ioctl() Operation not permitted - android

I am developing an app in C for Android. I want to add a new tun interface and use the file descriptor to access the device. The way I am doing it is the same as described here: https://backreference.org/2010/03/26/tuntap-interface-tutorial/
However, I am getting Operation not permitted on ioctl() call. My device is rooted, I granted superuser rights to my app, set SELinux policy to permissive. But still, Android does not allow me to access /dev/net/tun. I created it by creating symbolic link from /dev/tun. I also didn't forget to set chmod 666 on /dev/tun. Calling open("/dev/net/tun", O_RDWR | O_NONBLOCK) returns a valid file descriptor, and I set the ifreq struct correctly. It is exactly ioctl() call that returns an error that is Operation not permitted.
Furthermore, if I separate the code and cross-compile it, and then push it to device via adb and run it - everything works. But if I do it as a part of my application, the Operation is not permitted.
Any advise on how to allow this system call inside application? Any tips on why it fails would be also appreciated.
Code:
int create_virtual_nic(char *device) {
struct ifreq ifr;
int fd_tunnel = -1;
int err = -1;
fd_tunnel = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
if(fd_tunnel < 0) {
fprintf(stderr, "Could not open TUN device!\n");
return fd_tunnel;
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
if (*device) {
strncpy(ifr.ifr_name, device, IFNAMSIZ);
}
// ERROR IS HERE
err = ioctl(fd_tunnel, TUNSETIFF, (void*) &ifr);
if(err < 0 ) {
close(fd_tunnel);
perror("ioctl()");
fprintf(stderr, "Device '%s' taken or not running as root!\n", device);
exit(EXIT_FAILURE);
} else {
fprintf(stdout, "Succesfullt ioctl() on %d\n", err);
}
fprintf(stdout, "Created interface '%s'...\n", device);
return fd_tunnel;
}

Related

Android NDK non-deterministic Socket connect() time out

I have problems with client/server application that is part of a bigger system for distributed computing. The clients are Android devices that run a native Android NDK application written in C. At some point the clients send registration messages to the server application, which is also written in C and runs on a windows machine.
The weird thing is, right after installing the Android application on the device everything works fine. However, after a while the Socket problem starts. All connect() function calls end with a time out on the client side. The error is not deterministic and occurs at different points in time. To make it work again, I have to uninstall the application in Android manually and reinstall it. After that I works for some time and then the error starts again. The same C code is used on clients that run on normal windows PCs and there the problem does not occur.
The network connection is fine and I checked, if the server ports are open and reachable with the Simple Socket Tester app from the client device. I also gave Android the permission for Internet use and the parameters of the connect() call are correct.
EDIT:
Sorry for the missing code. I thought the error is obvious and based on the different platforms, since it works on windows and I am not that experienced in Android NDK. Here is the code:
int pi_connect(SOCKET s, const SOCKADDR *name, int namelen)
{
int result = connect(s, name, namelen);
if (result < 0) {
ALOG("Socket connecting error!");
return -1;
}
return result;
}
SOCKET pi_socket(int af, int type, int protocol) {
SOCKET returnSocket = socket(af, type, protocol);
int yes = 1;
if (setsockopt(returnSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Server-setsockopt() error!");
exit(1);
}
if (returnSocket < 0) {
ALOG("Socket creation error!");
return -1;
}
return returnSocket;
}
SOCKET setupSendSocket(u_long host, int hostPort) {
SOCKET sendingSocket;
SOCKADDR_IN addr;
sendingSocket = pi_socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(SOCKADDR_IN));
addr.sin_family = AF_INET;
addr.sin_port = htons(hostPort);
addr.sin_addr.s_addr = host;
long rc = pi_connect(sendingSocket, (SOCKADDR*) &addr, sizeof(SOCKADDR));
if (rc < 0) {
return 0;
}
return sendingSocket;
}
void requestOwnIP() {
SOCKET connectedIPSocket = setupSendSocket(inet_addr(brokerIP), 34123);
if(connectedIPSocket==0)
return;
sendBHeartbeatMessage(connectedIPSocket);
myIP = receiveBIPMessage(connectedIPSocket);
pi_closesocket(connectedIPSocket);
}
The requestOwnIP() function is called in the main function of the NDK application.
EDIT 2 (some new remarks): After rebooting the device, the connect() is successful again and the system works for some time. Is there something stored in the process table of the operating system, that can cause this problem? I first though that it could be a high amount of sockets that are in the time_wait state, but I added SO_REUSEADDR and the problem is still occurring.
I would really appreciate some help. Thank you in advance!
Regards
Dominik

Communicating with android device from Windows PC via USB

I have android device and windows drivers for it.
I have to communicate using my own binary protocol in accessory mode.
Is it possible to send data to this device without writing custom USB driver?
USB is a complex protocol because it is 'universal' and can handle a large variety of devices (mass storage, cameras,...). So on your android device has to be implemented a basic USB structure to use standard libraries like libusb or something like that.
You can assume that this is the case, because android is in most cases used on processors with USB port.
See http://www.beyondlogic.org/usbnutshell/usb1.shtml.
You can get more information about the USB device classes, interfaces, configurations, endpoints ur android device impmenets by using libusb -v
Then if you know what the USB structure on your android device looks like you can use libusb or another library to write data to specific endpoints in the usb structure by e.g. libusb_bulk_transfer(), libusb_control_transfer()
http://libusb.sourceforge.net/api-1.0/io.html
If you want to program in java you can use usb4java however this is a bit flaky http://usb4java.org/quickstart/libusb.html
The general USB structure is device -> (configuration) -> interface -> endpoint
So the way to write data to an endpoint is:
libusb_init(NULL);
libusb_open_device_with_vid_pid(NULL, vendor_id, product_id);
libusb_claim_interface(devh, 0);
libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT), data,
4, &p, 0); //example
... release interface...
...
libusb_close(devh);
libusb_exit(NULL);
Here is C++ example copied from http://www.dreamincode.net/forums/topic/148707-introduction-to-using-libusb-10/
#include <iostream>
#include <libusb.h>
using namespace std;
int main() {
libusb_device **devs; //pointer to pointer of device, used to
retrieve a list of devices
libusb_device_handle *dev_handle; //a device handle
libusb_context *ctx = NULL; //a libusb session
int r; //for return values
ssize_t cnt; //holding number of devices in list
r = libusb_init(&ctx); //initialize the library for the session we
just declared
if(r < 0) {
cout<<"Init Error "<<r<<endl; //there was an error
return 1;
}
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in
the documentation
cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
if(cnt < 0) {
cout<<"Get Device Error"<<endl; //there was an error
return 1;
}
cout<<cnt<<" Devices in list."<<endl;
dev_handle = libusb_open_device_with_vid_pid(ctx, 5118, 7424);
//these are vendorID and productID I found for my usb device
if(dev_handle == NULL)
cout<<"Cannot open device"<<endl;
else
cout<<"Device Opened"<<endl;
libusb_free_device_list(devs, 1); //free the list, unref the devices
in it
unsigned char *data = new unsigned char[4]; //data to write
data[0]='a';data[1]='b';data[2]='c';data[3]='d'; //some dummy values
int actual; //used to find out how many bytes were written
if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if
kernel driver is attached
cout<<"Kernel Driver Active"<<endl;
if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
cout<<"Kernel Driver Detached!"<<endl;
}
r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the
first) of device (mine had jsut 1)
if(r < 0) {
cout<<"Cannot Claim Interface"<<endl;
return 1;
}
cout<<"Claimed Interface"<<endl;
cout<<"Data->"<<data<<"<-"<<endl; //just to see the data we want to
write : abcd
cout<<"Writing Data..."<<endl;
r = libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT_OUT), data,
4, &actual, 0); //my device's out endpoint was 2, found with trial-
the device had 2 endpoints: 2 and 129
if(r == 0 && actual == 4) //we wrote the 4 bytes successfully
cout<<"Writing Successful!"<<endl;
else
cout<<"Write Error"<<endl;
r = libusb_release_interface(dev_handle, 0); //release the claimed
interface
if(r!=0) {
cout<<"Cannot Release Interface"<<endl;
return 1;
}
cout<<"Released Interface"<<endl;
libusb_close(dev_handle); //close the device we opened
libusb_exit(ctx); //needs to be called to end the
delete[] data; //delete the allocated memory for data
return 0;
}
So as your device runs android it has a USB structure/functionality. To investigate the USB functionality of your device (device class like mass storage, RNDIS,...) use libusb -v and the see the code above to write custom data to one of the endpoints on the device.

‘Permission denied’ while connecting to abstract unix socket

OS: Android L
Server: an native level system server, service through abstract socket.
Client: jni in normal 3rd APK
Get a 'permission denied' while using APK to connect the socket.
I thought abstract socket has no permissions!
And, the same code works when running in a adb shell, rooted shell.
The question is: where is the permisson set?
the code:
char *target_socket_name = "#mobilelogd";
int sock_id = 0;
struct sockaddr_un sun;
int address_len;
sock_id = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock_id < 0) {
LOG("in %s: Unable to create socket: %s\n", __func__, strerror(errno));
return -1;
} else {
LOG("socket created!\n");
}
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
strncpy(sun.sun_path, target_socket_name, strlen(target_socket_name));
sun.sun_path[0] = 0;
address_len = offsetof(struct sockaddr_un, sun_path) + strlen(target_socket_name);
if (connect(sock_id, (struct sockaddr *)&sun, address_len) == -1)
{
LOG("in %s: Connect to socket failed: (%d),%s\n", __func__, errno, strerror(errno));
close(sock_id);
return -1;
}
--- EDIT 1 ---: add some initialise code,and change '0' to 0. Same result.
Okay, here is the scoop it changed on L by a bug introduced..the bug fix is the pipeline:
https://android.googlesource.com/device/moto/shamu/+/b2db40f
Until than do java pipes or native pipes instead
Since Android manipulated the Linux kernel and added Paranoid networking to it, So you should add the following permission to your manifest file.
<uses-permission android:name="android.permission.INTERNET" />
Android adds a "paranoid network" option to the Linux kernel, which restricts access to some networking features depending on the group of the calling process.
So, your app's uid (user id; each app is assigned an unique uid once it is installed) must be granted that permission in order to do networking tasks.

bind error in android socket in a sample executable binary

I have made an executable binary built through android ndk. I put the binary in /data/local/tmp.
In the binary I try to bind a socket which I later on want to listen through my android app. I have got root permissions still the bind shows 30 as error which means read only file system. Can anyone tell me what else do I need to do bind a socket?
My code in brief:
int serv_sock = -1, len;
struct sockaddr_un serv_soc_addr;
if ((serv_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
printf( "socket error:%d\n", errno);
return -1; // Terminatie DR
}
bzero(&serv_soc_addr, sizeof(serv_soc_addr));
serv_soc_addr.sun_family = AF_UNIX;
strcpy(serv_soc_addr.sun_path, "iptable_socket");
unlink(serv_soc_addr.sun_path);
len = strlen(serv_soc_addr.sun_path) + sizeof(serv_soc_addr.sun_family);
if (0 != bind(serv_sock, (struct sockaddr*) &serv_soc_addr, len)) {
printf( "bind error:%d\n", errno);
close(serv_sock);
return -1; //Terminate DR
}
root#android:/ # /data/local/tmp/hello-jni
bind error:30
I was able to solve this one myself. Probably someone else looking for this might find helpful.
I changed the type of socket from Abstract type to FileSystem type.
I put the unlink statement at the end of the function after the accept system call breaks rather than just after strcpy as above.
Lastly I ran chmod on my binary.
Any other pointers would be helpful. Thanks.

android ndk sockets Network Unreachable

I don't know if this is in the way I'm handling Android, or a problem with my native code, or both.
I am setting up a udp socket in C++ (wrappers generated by swig):
udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (udpSocket < 0)
{
pthread_mutex_unlock(&csOpenCloseUdp);
throw IOException("Failed to open socket");
}
char bAllowMultiple = true;
setsockopt(udpSocket, SOL_SOCKET, SO_REUSEADDR, &bAllowMultiple, sizeof(bAllowMultiple));
setsockopt(udpSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&hopLimit, sizeof(hopLimit));
setsockopt(udpSocket, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localAddr, sizeof(localAddr));
// Set to non-blocking mode
unsigned long bMode = 1;
ioctl( udpSocket, FIONBIO, &bMode );
// Create the local endpoint
sockaddr_in localEndPoint;
localEndPoint.sin_family = AF_INET;
localEndPoint.sin_addr.s_addr = localAddr.s_addr;
localEndPoint.sin_port = groupEndPoint.sin_port;
// Bind the socket to the port
int r = bind(udpSocket, (sockaddr*)&localEndPoint, sizeof(localEndPoint));
if (r == SOCKET_ERROR)
{
//LeaveCriticalSection(&csOpenCloseUdp);
pthread_mutex_unlock(&csOpenCloseUdp);
close();
throw IOException("Failed to bind port");
}
// Join the multicast group
struct ip_mreq imr;
imr.imr_multiaddr = groupEndPoint.sin_addr;
imr.imr_interface.s_addr = localAddr.s_addr;
setsockopt(udpSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&imr, sizeof(imr));
The socket is not throwing any exceptions, and after this it has some value not INVALID_SOCKET.
When I try to send a packet though,
int r = sendto(udpSocket, (char*)dataToSend, (size_t)length, 0, (sockaddr*)&groupEndPoint, (socklen_t)sizeof(groupEndPoint));
I get errno 101: Network is unreachable.
I'm quite new to socket programming, and I know sockets in Android is a bad way to start, but the fact is I have to get this done and have very little time. Does anyone here know of a likely reason to get Network Unreachable? Has anyone tried playing with UDP on Android and can shed some light?
Is there a requirement to use C++ sockets? If possible, in the interests of time, and pretty much
in the interests of everything, I'd recommend the Java API instead. Here is an example of how to use it: http://android-er.blogspot.com/2011/01/simple-communication-using.html . I like C, but I would recommend against using it here.
SOLVED:
I just had to monkey with the ethernet settings on the device to get it to talk to my laptop. for some reason it didn't like using the dedicated link, so I'm going through the local network router and it's working. now getting different issues, but this one's done

Categories

Resources