From 98ea86bde0e2f2eee127643c22159fd00cf83e1a Mon Sep 17 00:00:00 2001 From: gardners Date: Thu, 3 May 2012 22:46:00 +0930 Subject: [PATCH] added new /proc/net/route method to find interfaces on android (would you believe that using ifconfig to READ about interfaces requires ROOT on android). should also help for interfaces with multiple addresses. --- lsif.c | 44 ++++++++++++++++++++++++++++++- overlay_interface.c | 64 +++++++++++++++++++++++++-------------------- serval.h | 4 ++- 3 files changed, 82 insertions(+), 30 deletions(-) diff --git a/lsif.c b/lsif.c index bfc9764d..77346202 100644 --- a/lsif.c +++ b/lsif.c @@ -59,6 +59,47 @@ #define SIOCGIFBRDADDR OSIOCGIFBRDADDR #endif +int overlay_interface_register(unsigned char *name, + struct sockaddr_in local, + struct sockaddr_in broadcast); + +/* for when all other options fail, as can happen on Android, + if the permissions for the socket-based method are broken. + Down side is that it while it gets the interface name and + broadcast, it doesn't get the local address for that + interface. +*/ +int scrapeProcNetRoute() +{ + FILE *f=fopen("/proc/net/route","r"); + if (!f) return fprintf(stderr,"Can't read from /proc/net/route\n"); + + char line[1024],name[1024],dest[1024],mask[1024]; + + /* skip header line */ + line[0]=0; fgets(line,1024,f); + + line[0]=0; fgets(line,1024,f); + while(line[0]) { + int r; + if ((r=sscanf(line,"%s %s %*s %*s %*s %*s %*s %s",name,dest,mask))==3) + { + unsigned int d = strtol(dest,NULL,16); + unsigned int m = strtol(mask,NULL,16); + struct sockaddr_in local,broadcast; + if (!(d&(~m))) { + local.sin_addr.s_addr=d; + broadcast.sin_addr.s_addr=d|~m; + overlay_interface_register((unsigned char *)name,local,broadcast); + } + } + + line[0]=0; fgets(line,1024,f); + } + fclose(f); + return 0; +} + #ifdef ANDROID int lsif(void) { @@ -74,7 +115,8 @@ int lsif(void) /* Get a socket handle. */ sck = socket(PF_INET, SOCK_DGRAM, 0); if(sck < 0) { - fprintf(stderr,"Failed to gt socket handle to list addresses\n"); + fprintf(stderr,"Failed to gt socket handle to list addresses, errno=%d\n", + errno); return 1; } diff --git a/overlay_interface.c b/overlay_interface.c index 6ff0c19c..77007469 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -178,7 +178,7 @@ int overlay_interface_args(char *arg) int overlay_interface_init_socket(int interface,struct sockaddr_in src_addr,struct sockaddr_in broadcast) { #define I(X) overlay_interfaces[interface].X - I(local_address)=src_addr; + // I(local_address)=src_addr; I(broadcast_address)=broadcast; I(fileP)=0; @@ -502,29 +502,36 @@ int overlay_interface_register(unsigned char *name, int i; for(i=0;inext; } +#ifdef ANDROID + /* Use alternative linux-only method to find and register interfaces. */ + lsif(); +#endif + /* /proc based approach */ + scrapeProcNetRoute(); + #ifdef HAVE_IFADDRS_H struct ifaddrs *ifaddr,*ifa; int family; @@ -607,16 +625,6 @@ int overlay_interface_discover() } freeifaddrs(ifaddr); #endif -#ifdef ANDROID - /* Use alternative linux-only method to find and register interfaces. */ - lsif(); -#else -#ifdef HAVE_IFADDRS_H -#else -#error Don't know how to get interface list on this platform -#endif -#endif - return 0; } diff --git a/serval.h b/serval.h index 8e10403b..7249a487 100755 --- a/serval.h +++ b/serval.h @@ -601,7 +601,9 @@ typedef struct overlay_interface { int sequence_number; /* Broadcast address and netmask, if known */ - struct sockaddr_in local_address; + /* We really only case about distinct broadcast addresses on interfaces. + Also simplifies aliases on interfaces. + struct sockaddr_in local_address; */ struct sockaddr_in broadcast_address; /* Not necessarily the real MTU, but the largest frame size we are willing to TX on this interface.