void AndroidGetAddr() { if (ifc_init()) { return; } in_addr_t addr; ifc_get_info("tiwlan0", &addr, 0, 0); myAddr = addr; ifc_close(); }
int ifc_reset_connections(const char *ifname, const int reset_mask) { #ifdef HAVE_ANDROID_OS int result = 0, success; in_addr_t myaddr = 0; struct ifreq ifr; struct in6_ifreq ifr6; int ctl_sock = -1; if (reset_mask & RESET_IPV4_ADDRESSES) { /* IPv4. Clear connections on the IP address. */ ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); if (ctl_sock >= 0) { if (!(reset_mask & RESET_IGNORE_INTERFACE_ADDRESS)) { ifc_get_info(ifname, &myaddr, NULL, NULL); } ifc_init_ifr(ifname, &ifr); init_sockaddr_in(&ifr.ifr_addr, myaddr); result = ioctl(ctl_sock, SIOCKILLADDR, &ifr); close(ctl_sock); } else { result = -1; } } if (reset_mask & RESET_IPV6_ADDRESSES) { /* * IPv6. On Linux, when an interface goes down it loses all its IPv6 * addresses, so we don't know which connections belonged to that interface * So we clear all unused IPv6 connections on the device by specifying an * empty IPv6 address. */ ctl_sock = socket(AF_INET6, SOCK_DGRAM, 0); // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets. memset(&ifr6, 0, sizeof(ifr6)); if (ctl_sock >= 0) { success = ioctl(ctl_sock, SIOCKILLADDR, &ifr6); if (result == 0) { result = success; } close(ctl_sock); } else { result = -1; } } return result; #else return 0; #endif }
int ifc_reset_connections(const char *ifname) { #ifdef HAVE_ANDROID_OS int result; in_addr_t myaddr; struct ifreq ifr; ifc_init(); ifc_get_info(ifname, &myaddr, NULL, NULL); ifc_init_ifr(ifname, &ifr); init_sockaddr_in(&ifr.ifr_addr, myaddr); result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); ifc_close(); return result; #else return 0; #endif }
int dump_interface(const char *name) { unsigned addr, flags; unsigned char hwbuf[ETH_ALEN]; int prefixLength; if(ifc_get_info(name, &addr, &prefixLength, &flags)) { return 0; } printf("%-8s %s ", name, flags & 1 ? "UP " : "DOWN"); printf("%40s", ipaddr(addr)); printf("/%-4d", prefixLength); printf("0x%08x ", flags); if (!ifc_get_hwaddr(name, hwbuf)) { int i; for(i=0; i < (ETH_ALEN-1); i++) printf("%02x:", hwbuf[i]); printf("%02x\n", hwbuf[i]); } else { printf("\n"); } return 0; }
void* SetupData(void* t) { //this should never happen but let's check if(pppd_pid!=0 ) { LOGD(" waiting pppd to die"); int status=0; kill(pppd_pid, SIGTERM); waitpid(pppd_pid, &status, 0); } //reset ppp.dns property_set("net.ppp0.dns1", "0.0.0.0"); property_set("net.ppp0.dns2", "0.0.0.0"); strcpy(current_addr, "255.255.255.255"); pthread_t thread; pthread_create(&thread, NULL, pppd_thread, NULL); //wait for pppd connect if(ifc_init()) { LOGE("%s: IFC failed to init", logtime()); sleep(7); } else { clock_t start=clock(); //loop till timeout or connected while(1) { //check if ppp0 interface is up, if true break loop, else record dnschange value unsigned addr, mask, flags; ifc_get_info("ppp0", &addr, &mask, &flags); if(flags & 1) { struct in_addr in_addr = {.s_addr=addr}; strcpy(current_addr, inet_ntoa(in_addr)); LOGD("%s: IP: %s", logtime(),current_addr); break; } //if timeout goto error if ( (clock()-start)/CLOCKS_PER_SEC > 60 ){ LOGE("%s: ppp0 connect timed out, giving up", logtime()); ifc_close(); goto error; } int status, pid=pppd_pid; if(pid==0 || waitpid(pid, &status, WNOHANG)>0){ LOGE("%s: ppp0 connect timed out, giving up", logtime()); ifc_close(); goto error; } msleep(100); } } ifc_close(); //if ip-up exists wait for dns change char dns1[PROPERTY_VALUE_MAX]; char dns2[PROPERTY_VALUE_MAX]; struct stat sts; if(stat("/etc/ppp/ip-up", &sts)==0 && (S_ISREG(sts.st_mode) || S_ISLNK(sts.st_mode))) { clock_t start=clock(); while(1) { //check if dnschange changed property_get("net.ppp0.dns1", dns1, "0.0.0.0"); property_get("net.ppp0.dns2", dns2, "0.0.0.0"); if(strcmp(dns1, "0.0.0.0")!=0 && strcmp(dns2, "0.0.0.0")!=0) break; if((clock()-start)/CLOCKS_PER_SEC > 2) { LOGE("%s: timeout waiting for dns change", logtime()); break; } msleep(100); } } //check ppp.dns values and set defaults if suspect wrong property_get("net.ppp0.dns1", dns1, ""); if(strlen(dns1)<7 || strcmp(dns1,"0.0.0.0")==0 || strcmp(dns1, "10.11.12.13")==0) { LOGD("%s: DNS1: %s wrong setting to 8.8.8.8", logtime(),dns1); property_set("net.ppp0.dns1", "8.8.8.8"); } else { LOGD("%s: DNS1: %s", logtime(),dns1); } property_get("net.ppp0.dns2", dns2, ""); if(strlen(dns2)<7 || strcmp(dns2, "0.0.0.0")==0 || strcmp(dns2, "10.11.12.14")==0) { LOGD("%s: DNS2: %s wrong setting to 8.8.4.4", logtime(),dns2); property_set("net.ppp0.dns2", "8.8.4.4"); } else { LOGD("%s: DNS2: %s", logtime(),dns2); } char *response[3] = { "1", "ppp0", current_addr }; dataConnectionState=DATA_STATE_CONNECTED; RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); return NULL; error: dataConnectionState=DATA_STATE_DISCONNECTED; RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); return NULL; }
int CommandListener::InterfaceCmd::runCommand(SocketClient *cli, int argc, char **argv) { if (argc < 2) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); return 0; } if (!strcmp(argv[1], "list")) { DIR *d; struct dirent *de; if (!(d = opendir("/sys/class/net"))) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true); return 0; } while((de = readdir(d))) { if (de->d_name[0] == '.') continue; cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false); } closedir(d); cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false); return 0; } else if (!strcmp(argv[1], "readrxcounter")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface readrxcounter <interface>", false); return 0; } unsigned long rx = 0, tx = 0; if (readInterfaceCounters(argv[2], &rx, &tx)) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true); return 0; } char *msg; asprintf(&msg, "%lu", rx); cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false); free(msg); return 0; } else if (!strcmp(argv[1], "readtxcounter")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface readtxcounter <interface>", false); return 0; } unsigned long rx = 0, tx = 0; if (readInterfaceCounters(argv[2], &rx, &tx)) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true); return 0; } char *msg = NULL; asprintf(&msg, "%lu", tx); cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false); free(msg); return 0; } else if (!strcmp(argv[1], "getthrottle")) { if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface getthrottle <interface> <rx|tx>", false); return 0; } int val = 0; int rc = 0; int voldRc = ResponseCode::InterfaceRxThrottleResult; if (!strcmp(argv[3], "rx")) { rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val); } else { rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val); voldRc = ResponseCode::InterfaceTxThrottleResult; } if (rc) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true); } else { char *msg = NULL; asprintf(&msg, "%u", val); cli->sendMsg(voldRc, msg, false); free(msg); return 0; } return 0; } else if (!strcmp(argv[1], "setthrottle")) { if (argc != 5) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false); return 0; } if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true); } else { cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false); } return 0; } else { /* * These commands take a minimum of 3 arguments */ if (argc < 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); return 0; } if (!strcmp(argv[1], "getcfg")) { struct in_addr addr, mask; unsigned char hwaddr[6]; unsigned flags = 0; ifc_init(); memset(hwaddr, 0, sizeof(hwaddr)); if (ifc_get_info(argv[2], &addr.s_addr, &mask.s_addr, &flags)) { cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true); return 0; } if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) { LOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno)); } char *addr_s = strdup(inet_ntoa(addr)); char *mask_s = strdup(inet_ntoa(mask)); const char *updown, *brdcst, *loopbk, *ppp, *running, *multi; updown = (flags & IFF_UP) ? "up" : "down"; brdcst = (flags & IFF_BROADCAST) ? " broadcast" : ""; loopbk = (flags & IFF_LOOPBACK) ? " loopback" : ""; ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : ""; running = (flags & IFF_RUNNING) ? " running" : ""; multi = (flags & IFF_MULTICAST) ? " multicast" : ""; char *flag_s; asprintf(&flag_s, "[%s%s%s%s%s%s]", updown, brdcst, loopbk, ppp, running, multi); char *msg = NULL; asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %s %s", hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5], addr_s, mask_s, flag_s); cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false); free(addr_s); free(mask_s); free(flag_s); free(msg); return 0; } else if (!strcmp(argv[1], "setcfg")) { // arglist: iface addr mask [flags] if (argc < 5) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); return 0; } LOGD("Setting iface cfg"); struct in_addr addr, mask; unsigned flags = 0; if (!inet_aton(argv[3], &addr)) { cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false); return 0; } if (!inet_aton(argv[4], &mask)) { cli->sendMsg(ResponseCode::CommandParameterError, "Invalid netmask", false); return 0; } ifc_init(); if (ifc_set_addr(argv[2], addr.s_addr)) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true); return 0; } if (ifc_set_mask(argv[2], mask.s_addr)) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to set netmask", true); return 0; } /* Process flags */ /* read from "[XX" arg to "YY]" arg */ bool bStarted = false; for (int i = 5; i < argc; i++) { char *flag = argv[i]; if (!bStarted) { if (*flag == '[') { flag++; bStarted = true; } else { continue; } } int len = strlen(flag); if (flag[len-1] == ']') { i = argc; // stop after this loop flag[len-1] = 0; } if (!strcmp(flag, "up")) { LOGD("Trying to bring up %s", argv[2]); if (ifc_up(argv[2])) { LOGE("Error upping interface"); cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true); return 0; } } else if (!strcmp(flag, "down")) { LOGD("Trying to bring down %s", argv[2]); if (ifc_down(argv[2])) { LOGE("Error downing interface"); cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true); return 0; } } else if (!strcmp(flag, "broadcast")) { LOGD("broadcast flag ignored"); } else if (!strcmp(flag, "multicast")) { LOGD("multicast flag ignored"); } else { cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false); return 0; } } cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false); return 0; } else { cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); return 0; } } return 0; }
int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) { int rc = 0; struct in_addr addr; if (argc < 2) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false); return 0; } if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>" if (argc == 3) { rc = sResolverCtrl->setDefaultInterface(argv[2]); } else { cli->sendMsg(ResponseCode::CommandSyntaxError, "Wrong number of arguments to resolver setdefaultif", false); return 0; } } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..." if (argc >= 4) { rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3); } else { cli->sendMsg(ResponseCode::CommandSyntaxError, "Wrong number of arguments to resolver setifdns", false); return 0; } // set the address of the interface to which the name servers // are bound. Required in order to bind to right interface when // doing the dns query. if (!rc) { ifc_init(); ifc_get_info(argv[2], &addr.s_addr, NULL, 0); rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr); } } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif" if (argc == 2) { rc = sResolverCtrl->flushDefaultDnsCache(); } else { cli->sendMsg(ResponseCode::CommandSyntaxError, "Wrong number of arguments to resolver flushdefaultif", false); return 0; } } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>" if (argc == 3) { rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]); } else { cli->sendMsg(ResponseCode::CommandSyntaxError, "Wrong number of arguments to resolver setdefaultif", false); return 0; } } else { cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false); return 0; } if (!rc) { cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false); } else { cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true); } return 0; }
int CommandListener::InterfaceCmd::runCommand(SocketClient *cli, int argc, char **argv) { if (argc < 2) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); return 0; } if (!strcmp(argv[1], "list")) { DIR *d; struct dirent *de; if (!(d = opendir("/sys/class/net"))) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true); return 0; } while((de = readdir(d))) { if (de->d_name[0] == '.') continue; cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false); } closedir(d); cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false); return 0; } else if (!strcmp(argv[1], "readrxcounter")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface readrxcounter <interface>", false); return 0; } unsigned long rx = 0, tx = 0; if (readInterfaceCounters(argv[2], &rx, &tx)) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true); return 0; } char *msg; asprintf(&msg, "%lu", rx); cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false); free(msg); return 0; } else if (!strcmp(argv[1], "readtxcounter")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface readtxcounter <interface>", false); return 0; } unsigned long rx = 0, tx = 0; if (readInterfaceCounters(argv[2], &rx, &tx)) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true); return 0; } char *msg = NULL; asprintf(&msg, "%lu", tx); cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false); free(msg); return 0; } else if (!strcmp(argv[1], "getthrottle")) { if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface getthrottle <interface> <rx|tx>", false); return 0; } int val = 0; int rc = 0; int voldRc = ResponseCode::InterfaceRxThrottleResult; if (!strcmp(argv[3], "rx")) { rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val); } else { rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val); voldRc = ResponseCode::InterfaceTxThrottleResult; } if (rc) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true); } else { char *msg = NULL; asprintf(&msg, "%u", val); cli->sendMsg(voldRc, msg, false); free(msg); return 0; } return 0; } else if (!strcmp(argv[1], "setthrottle")) { if (argc != 5) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false); return 0; } if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true); } else { cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false); } return 0; } else if (!strcmp(argv[1], "driver")) { int rc; char *rbuf; if (argc < 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface driver <interface> <cmd> <args>", false); return 0; } rc = sInterfaceCtrl->interfaceCommand(argc, argv, &rbuf); if (rc) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to execute command", true); } else { cli->sendMsg(ResponseCode::CommandOkay, rbuf, false); } return 0; } else { /* * These commands take a minimum of 3 arguments */ if (argc < 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); return 0; } // 0 1 2 3 4 5 6 7 // interface route add/remove iface default/secondary dest prefix gateway if (!strcmp(argv[1], "route")) { int prefix_length = 0; if (argc < 8) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); return 0; } if (sscanf(argv[6], "%d", &prefix_length) != 1) { cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false); return 0; } if (!strcmp(argv[2], "add")) { if (!strcmp(argv[4], "default")) { if (ifc_add_route(argv[3], argv[5], prefix_length, argv[7])) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to add route to default table", true); } else { cli->sendMsg(ResponseCode::CommandOkay, "Route added to default table", false); } } else if (!strcmp(argv[4], "secondary")) { return sSecondaryTableCtrl->addRoute(cli, argv[3], argv[5], prefix_length, argv[7]); } else { cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route type, expecting 'default' or 'secondary'", false); return 0; } } else if (!strcmp(argv[2], "remove")) { if (!strcmp(argv[4], "default")) { if (ifc_remove_route(argv[3], argv[5], prefix_length, argv[7])) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove route from default table", true); } else { cli->sendMsg(ResponseCode::CommandOkay, "Route removed from default table", false); } } else if (!strcmp(argv[4], "secondary")) { return sSecondaryTableCtrl->removeRoute(cli, argv[3], argv[5], prefix_length, argv[7]); } else { cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route type, expecting 'default' or 'secondary'", false); return 0; } } else { cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); } return 0; } if (!strcmp(argv[1], "getcfg")) { struct in_addr addr; int prefixLength; unsigned char hwaddr[6]; unsigned flags = 0; ifc_init(); memset(hwaddr, 0, sizeof(hwaddr)); if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) { cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true); ifc_close(); return 0; } if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) { ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno)); } char *addr_s = strdup(inet_ntoa(addr)); const char *updown, *brdcst, *loopbk, *ppp, *running, *multi; updown = (flags & IFF_UP) ? "up" : "down"; brdcst = (flags & IFF_BROADCAST) ? " broadcast" : ""; loopbk = (flags & IFF_LOOPBACK) ? " loopback" : ""; ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : ""; running = (flags & IFF_RUNNING) ? " running" : ""; multi = (flags & IFF_MULTICAST) ? " multicast" : ""; char *flag_s; asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi); char *msg = NULL; asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s", hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5], addr_s, prefixLength, flag_s); cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false); free(addr_s); free(flag_s); free(msg); ifc_close(); return 0; } else if (!strcmp(argv[1], "setcfg")) { // arglist: iface [addr prefixLength] flags if (argc < 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); return 0; } ALOGD("Setting iface cfg"); struct in_addr addr; unsigned flags = 0; int index = 5; ifc_init(); if (!inet_aton(argv[3], &addr)) { // Handle flags only case index = 3; } else { if (ifc_set_addr(argv[2], addr.s_addr)) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true); ifc_close(); return 0; } // Set prefix length on a non zero address if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) { cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true); ifc_close(); return 0; } } /* Process flags */ for (int i = index; i < argc; i++) { char *flag = argv[i]; if (!strcmp(flag, "up")) { ALOGD("Trying to bring up %s", argv[2]); if (ifc_up(argv[2])) { ALOGE("Error upping interface"); cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true); ifc_close(); return 0; } } else if (!strcmp(flag, "down")) { ALOGD("Trying to bring down %s", argv[2]); if (ifc_down(argv[2])) { ALOGE("Error downing interface"); cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true); ifc_close(); return 0; } } else if (!strcmp(flag, "broadcast")) { // currently ignored } else if (!strcmp(flag, "multicast")) { // currently ignored } else if (!strcmp(flag, "running")) { // currently ignored } else if (!strcmp(flag, "loopback")) { // currently ignored } else if (!strcmp(flag, "point-to-point")) { // currently ignored } else { cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false); ifc_close(); return 0; } } cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false); ifc_close(); return 0; } else if (!strcmp(argv[1], "clearaddrs")) { // arglist: iface ALOGD("Clearing all IP addresses on %s", argv[2]); ifc_clear_addresses(argv[2]); cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false); return 0; } else if (!strcmp(argv[1], "ipv6privacyextensions")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface ipv6privacyextensions <interface> <enable|disable>", false); return 0; } char *tmp; asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/use_tempaddr", argv[2]); if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "2" : "0", 1) < 0) { free(tmp); cli->sendMsg(ResponseCode::OperationFailed, "Failed to set ipv6 privacy extensions", true); return 0; } free(tmp); cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false); return 0; } else if (!strcmp(argv[1], "ipv6")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: interface ipv6 <interface> <enable|disable>", false); return 0; } char *tmp; asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", argv[2]); if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "0" : "1", 1) < 0) { free(tmp); cli->sendMsg(ResponseCode::OperationFailed, "Failed to change IPv6 state", true); return 0; } free(tmp); cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false); return 0; } else { cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false); return 0; } } return 0; }
struct ifaddrs *get_interface(const char *name, sa_family_t family) { unsigned addr, flags; int masklen; struct ifaddrs *ifa; struct sockaddr_in *saddr = NULL; struct sockaddr_in *smask = NULL; struct sockaddr_ll *hwaddr = NULL; unsigned char hwbuf[ETH_ALEN]; if (ifc_get_info(name, &addr, &masklen, &flags)) return NULL; if ((family == AF_INET) && (addr == 0)) return NULL; ifa = malloc(sizeof(struct ifaddrs)); if (!ifa) return NULL; memset(ifa, 0, sizeof(struct ifaddrs)); ifa->ifa_name = malloc(strlen(name)+1); if (!ifa->ifa_name) { free(ifa); return NULL; } strcpy(ifa->ifa_name, name); ifa->ifa_flags = flags; if (family == AF_INET) { saddr = malloc(sizeof(struct sockaddr_in)); if (saddr) { saddr->sin_addr.s_addr = addr; saddr->sin_family = family; } ifa->ifa_addr = (struct sockaddr *)saddr; if (masklen != 0) { smask = malloc(sizeof(struct sockaddr_in)); if (smask) { smask->sin_addr.s_addr = prefixLengthToIpv4Netmask(masklen); smask->sin_family = family; } } ifa->ifa_netmask = (struct sockaddr *)smask; } else if (family == AF_PACKET) { if (!ifc_get_hwaddr(name, hwbuf)) { hwaddr = malloc(sizeof(struct sockaddr_ll)); if (hwaddr) { memset(hwaddr, 0, sizeof(struct sockaddr_ll)); hwaddr->sll_family = family; /* hwaddr->sll_protocol = ETHERTYPE_IP; */ hwaddr->sll_hatype = ARPHRD_ETHER; hwaddr->sll_halen = ETH_ALEN; memcpy(hwaddr->sll_addr, hwbuf, ETH_ALEN); } } ifa->ifa_addr = (struct sockaddr *)hwaddr; ifa->ifa_netmask = (struct sockaddr *)smask; } return ifa; }