Home | History | Annotate | Download | only in libnetutils
      1 /*
      2  * Copyright 2008, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <unistd.h>
     20 #include <string.h>
     21 #include <errno.h>
     22 
     23 #include <sys/socket.h>
     24 #include <sys/select.h>
     25 #include <sys/types.h>
     26 #include <netinet/in.h>
     27 #include <arpa/inet.h>
     28 #include <net/if.h>
     29 #include <netdb.h>
     30 
     31 #include <linux/if.h>
     32 #include <linux/if_ether.h>
     33 #include <linux/if_arp.h>
     34 #include <linux/netlink.h>
     35 #include <linux/route.h>
     36 #include <linux/ipv6_route.h>
     37 #include <linux/rtnetlink.h>
     38 #include <linux/sockios.h>
     39 
     40 #include "netutils/ifc.h"
     41 
     42 #ifdef ANDROID
     43 #define LOG_TAG "NetUtils"
     44 #include <cutils/log.h>
     45 #include <cutils/properties.h>
     46 #else
     47 #include <stdio.h>
     48 #include <string.h>
     49 #define LOGD printf
     50 #define LOGW printf
     51 #endif
     52 
     53 static int ifc_ctl_sock = -1;
     54 static int ifc_ctl_sock6 = -1;
     55 void printerr(char *fmt, ...);
     56 
     57 #define DBG 0
     58 #define INET_ADDRLEN 4
     59 #define INET6_ADDRLEN 16
     60 
     61 in_addr_t prefixLengthToIpv4Netmask(int prefix_length)
     62 {
     63     in_addr_t mask = 0;
     64 
     65     // C99 (6.5.7): shifts of 32 bits have undefined results
     66     if (prefix_length <= 0 || prefix_length > 32) {
     67         return 0;
     68     }
     69 
     70     mask = ~mask << (32 - prefix_length);
     71     mask = htonl(mask);
     72 
     73     return mask;
     74 }
     75 
     76 int ipv4NetmaskToPrefixLength(in_addr_t mask)
     77 {
     78     mask = ntohl(mask);
     79     int prefixLength = 0;
     80     uint32_t m = (uint32_t)mask;
     81     while (m & 0x80000000) {
     82         prefixLength++;
     83         m = m << 1;
     84     }
     85     return prefixLength;
     86 }
     87 
     88 static const char *ipaddr_to_string(in_addr_t addr)
     89 {
     90     struct in_addr in_addr;
     91 
     92     in_addr.s_addr = addr;
     93     return inet_ntoa(in_addr);
     94 }
     95 
     96 int string_to_ip(const char *string, struct sockaddr_storage *ss) {
     97     struct addrinfo hints, *ai;
     98     int ret;
     99 
    100     if (ss == NULL) {
    101         return -EFAULT;
    102     }
    103 
    104     memset(&hints, 0, sizeof(hints));
    105     hints.ai_family = AF_UNSPEC;
    106     hints.ai_flags = AI_NUMERICHOST;
    107     hints.ai_socktype = SOCK_DGRAM;
    108 
    109     ret = getaddrinfo(string, NULL, &hints, &ai);
    110     if (ret == 0) {
    111         memcpy(ss, ai->ai_addr, ai->ai_addrlen);
    112         freeaddrinfo(ai);
    113     }
    114 
    115     return ret;
    116 }
    117 
    118 int ifc_init(void)
    119 {
    120     int ret;
    121     if (ifc_ctl_sock == -1) {
    122         ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
    123         if (ifc_ctl_sock < 0) {
    124             printerr("socket() failed: %s\n", strerror(errno));
    125         }
    126     }
    127 
    128     ret = ifc_ctl_sock < 0 ? -1 : 0;
    129     if (DBG) printerr("ifc_init_returning %d", ret);
    130     return ret;
    131 }
    132 
    133 int ifc_init6(void)
    134 {
    135     if (ifc_ctl_sock6 == -1) {
    136         ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
    137         if (ifc_ctl_sock6 < 0) {
    138             printerr("socket() failed: %s\n", strerror(errno));
    139         }
    140     }
    141     return ifc_ctl_sock6 < 0 ? -1 : 0;
    142 }
    143 
    144 void ifc_close(void)
    145 {
    146     if (DBG) printerr("ifc_close");
    147     if (ifc_ctl_sock != -1) {
    148         (void)close(ifc_ctl_sock);
    149         ifc_ctl_sock = -1;
    150     }
    151 }
    152 
    153 void ifc_close6(void)
    154 {
    155     if (ifc_ctl_sock6 != -1) {
    156         (void)close(ifc_ctl_sock6);
    157         ifc_ctl_sock6 = -1;
    158     }
    159 }
    160 
    161 static void ifc_init_ifr(const char *name, struct ifreq *ifr)
    162 {
    163     memset(ifr, 0, sizeof(struct ifreq));
    164     strncpy(ifr->ifr_name, name, IFNAMSIZ);
    165     ifr->ifr_name[IFNAMSIZ - 1] = 0;
    166 }
    167 
    168 int ifc_get_hwaddr(const char *name, void *ptr)
    169 {
    170     int r;
    171     struct ifreq ifr;
    172     ifc_init_ifr(name, &ifr);
    173 
    174     r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr);
    175     if(r < 0) return -1;
    176 
    177     memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    178     return 0;
    179 }
    180 
    181 int ifc_get_ifindex(const char *name, int *if_indexp)
    182 {
    183     int r;
    184     struct ifreq ifr;
    185     ifc_init_ifr(name, &ifr);
    186 
    187     r = ioctl(ifc_ctl_sock, SIOCGIFINDEX, &ifr);
    188     if(r < 0) return -1;
    189 
    190     *if_indexp = ifr.ifr_ifindex;
    191     return 0;
    192 }
    193 
    194 static int ifc_set_flags(const char *name, unsigned set, unsigned clr)
    195 {
    196     struct ifreq ifr;
    197     ifc_init_ifr(name, &ifr);
    198 
    199     if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) return -1;
    200     ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set;
    201     return ioctl(ifc_ctl_sock, SIOCSIFFLAGS, &ifr);
    202 }
    203 
    204 int ifc_up(const char *name)
    205 {
    206     int ret = ifc_set_flags(name, IFF_UP, 0);
    207     if (DBG) printerr("ifc_up(%s) = %d", name, ret);
    208     return ret;
    209 }
    210 
    211 int ifc_down(const char *name)
    212 {
    213     int ret = ifc_set_flags(name, 0, IFF_UP);
    214     if (DBG) printerr("ifc_down(%s) = %d", name, ret);
    215     return ret;
    216 }
    217 
    218 static void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr)
    219 {
    220     struct sockaddr_in *sin = (struct sockaddr_in *) sa;
    221     sin->sin_family = AF_INET;
    222     sin->sin_port = 0;
    223     sin->sin_addr.s_addr = addr;
    224 }
    225 
    226 int ifc_set_addr(const char *name, in_addr_t addr)
    227 {
    228     struct ifreq ifr;
    229     int ret;
    230 
    231     ifc_init_ifr(name, &ifr);
    232     init_sockaddr_in(&ifr.ifr_addr, addr);
    233 
    234     ret = ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr);
    235     if (DBG) printerr("ifc_set_addr(%s, xx) = %d", name, ret);
    236     return ret;
    237 }
    238 
    239 /*
    240  * Adds or deletes an IP address on an interface.
    241  *
    242  * Action is one of:
    243  * - RTM_NEWADDR (to add a new address)
    244  * - RTM_DELADDR (to delete an existing address)
    245  *
    246  * Returns zero on success and negative errno on failure.
    247  */
    248 int ifc_act_on_address(int action, const char *name, const char *address,
    249                        int prefixlen) {
    250     int ifindex, s, len, ret;
    251     struct sockaddr_storage ss;
    252     void *addr;
    253     size_t addrlen;
    254     struct {
    255         struct nlmsghdr n;
    256         struct ifaddrmsg r;
    257         // Allow for IPv6 address, headers, and padding.
    258         char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
    259                      NLMSG_ALIGN(sizeof(struct rtattr)) +
    260                      NLMSG_ALIGN(INET6_ADDRLEN)];
    261     } req;
    262     struct rtattr *rta;
    263     struct nlmsghdr *nh;
    264     struct nlmsgerr *err;
    265     char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
    266              NLMSG_ALIGN(sizeof(struct nlmsgerr)) +
    267              NLMSG_ALIGN(sizeof(struct nlmsghdr))];
    268 
    269     // Get interface ID.
    270     ifindex = if_nametoindex(name);
    271     if (ifindex == 0) {
    272         return -errno;
    273     }
    274 
    275     // Convert string representation to sockaddr_storage.
    276     ret = string_to_ip(address, &ss);
    277     if (ret) {
    278         return ret;
    279     }
    280 
    281     // Determine address type and length.
    282     if (ss.ss_family == AF_INET) {
    283         struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
    284         addr = &sin->sin_addr;
    285         addrlen = INET_ADDRLEN;
    286     } else if (ss.ss_family == AF_INET6) {
    287         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
    288         addr = &sin6->sin6_addr;
    289         addrlen = INET6_ADDRLEN;
    290     } else {
    291         return -EAFNOSUPPORT;
    292     }
    293 
    294     // Fill in netlink structures.
    295     memset(&req, 0, sizeof(req));
    296 
    297     // Netlink message header.
    298     req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
    299     req.n.nlmsg_type = action;
    300     req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    301     req.n.nlmsg_pid = getpid();
    302 
    303     // Interface address message header.
    304     req.r.ifa_family = ss.ss_family;
    305     req.r.ifa_prefixlen = prefixlen;
    306     req.r.ifa_index = ifindex;
    307 
    308     // Routing attribute. Contains the actual IP address.
    309     rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len));
    310     rta->rta_type = IFA_LOCAL;
    311     rta->rta_len = RTA_LENGTH(addrlen);
    312     req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen);
    313     memcpy(RTA_DATA(rta), addr, addrlen);
    314 
    315     s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    316     if (send(s, &req, req.n.nlmsg_len, 0) < 0) {
    317         close(s);
    318         return -errno;
    319     }
    320 
    321     len = recv(s, buf, sizeof(buf), 0);
    322     close(s);
    323     if (len < 0) {
    324         return -errno;
    325     }
    326 
    327     // Parse the acknowledgement to find the return code.
    328     nh = (struct nlmsghdr *) buf;
    329     if (!NLMSG_OK(nh, (unsigned) len) || nh->nlmsg_type != NLMSG_ERROR) {
    330         return -EINVAL;
    331     }
    332     err = NLMSG_DATA(nh);
    333 
    334     // Return code is negative errno.
    335     return err->error;
    336 }
    337 
    338 int ifc_add_address(const char *name, const char *address, int prefixlen) {
    339     return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen);
    340 }
    341 
    342 int ifc_del_address(const char *name, const char * address, int prefixlen) {
    343     return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen);
    344 }
    345 
    346 /*
    347  * Clears IPv6 addresses on the specified interface.
    348  */
    349 int ifc_clear_ipv6_addresses(const char *name) {
    350     char rawaddrstr[INET6_ADDRSTRLEN], addrstr[INET6_ADDRSTRLEN];
    351     unsigned int prefixlen;
    352     int lasterror = 0, i, j, ret;
    353     char ifname[64];  // Currently, IFNAMSIZ = 16.
    354     FILE *f = fopen("/proc/net/if_inet6", "r");
    355     if (!f) {
    356         return -errno;
    357     }
    358 
    359     // Format:
    360     // 20010db8000a0001fc446aa4b5b347ed 03 40 00 01    wlan0
    361     while (fscanf(f, "%32s %*02x %02x %*02x %*02x %63s\n",
    362                   rawaddrstr, &prefixlen, ifname) == 3) {
    363         // Is this the interface we're looking for?
    364         if (strcmp(name, ifname)) {
    365             continue;
    366         }
    367 
    368         // Put the colons back into the address.
    369         for (i = 0, j = 0; i < 32; i++, j++) {
    370             addrstr[j] = rawaddrstr[i];
    371             if (i % 4 == 3) {
    372                 addrstr[++j] = ':';
    373             }
    374         }
    375         addrstr[j - 1] = '\0';
    376 
    377         // Don't delete the link-local address as well, or it will disable IPv6
    378         // on the interface.
    379         if (strncmp(addrstr, "fe80:", 5) == 0) {
    380             continue;
    381         }
    382 
    383         ret = ifc_del_address(ifname, addrstr, prefixlen);
    384         if (ret) {
    385             LOGE("Deleting address %s/%d on %s: %s", addrstr, prefixlen, ifname,
    386                  strerror(-ret));
    387             lasterror = ret;
    388         }
    389     }
    390 
    391     fclose(f);
    392     return lasterror;
    393 }
    394 
    395 /*
    396  * Clears IPv4 addresses on the specified interface.
    397  */
    398 void ifc_clear_ipv4_addresses(const char *name) {
    399     unsigned count, addr;
    400     ifc_init();
    401     for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
    402         if (ifc_get_addr(name, &addr) < 0)
    403             break;
    404         if (addr)
    405             ifc_set_addr(name, 0);
    406     }
    407     ifc_close();
    408 }
    409 
    410 /*
    411  * Clears all IP addresses on the specified interface.
    412  */
    413 int ifc_clear_addresses(const char *name) {
    414     ifc_clear_ipv4_addresses(name);
    415     return ifc_clear_ipv6_addresses(name);
    416 }
    417 
    418 int ifc_set_hwaddr(const char *name, const void *ptr)
    419 {
    420     int r;
    421     struct ifreq ifr;
    422     ifc_init_ifr(name, &ifr);
    423 
    424     ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
    425     memcpy(&ifr.ifr_hwaddr.sa_data, ptr, ETH_ALEN);
    426     return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr);
    427 }
    428 
    429 int ifc_set_mask(const char *name, in_addr_t mask)
    430 {
    431     struct ifreq ifr;
    432     int ret;
    433 
    434     ifc_init_ifr(name, &ifr);
    435     init_sockaddr_in(&ifr.ifr_addr, mask);
    436 
    437     ret = ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
    438     if (DBG) printerr("ifc_set_mask(%s, xx) = %d", name, ret);
    439     return ret;
    440 }
    441 
    442 int ifc_set_prefixLength(const char *name, int prefixLength)
    443 {
    444     struct ifreq ifr;
    445     // TODO - support ipv6
    446     if (prefixLength > 32 || prefixLength < 0) return -1;
    447 
    448     in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength);
    449     ifc_init_ifr(name, &ifr);
    450     init_sockaddr_in(&ifr.ifr_addr, mask);
    451 
    452     return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
    453 }
    454 
    455 int ifc_get_addr(const char *name, in_addr_t *addr)
    456 {
    457     struct ifreq ifr;
    458     int ret = 0;
    459 
    460     ifc_init_ifr(name, &ifr);
    461     if (addr != NULL) {
    462         ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr);
    463         if (ret < 0) {
    464             *addr = 0;
    465         } else {
    466             *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
    467         }
    468     }
    469     return ret;
    470 }
    471 
    472 int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags)
    473 {
    474     struct ifreq ifr;
    475     ifc_init_ifr(name, &ifr);
    476 
    477     if (addr != NULL) {
    478         if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) {
    479             *addr = 0;
    480         } else {
    481             *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
    482         }
    483     }
    484 
    485     if (prefixLength != NULL) {
    486         if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) {
    487             *prefixLength = 0;
    488         } else {
    489             *prefixLength = ipv4NetmaskToPrefixLength((int)
    490                     ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr);
    491         }
    492     }
    493 
    494     if (flags != NULL) {
    495         if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) {
    496             *flags = 0;
    497         } else {
    498             *flags = ifr.ifr_flags;
    499         }
    500     }
    501 
    502     return 0;
    503 }
    504 
    505 int ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, int prefix_length,
    506       struct in_addr gw)
    507 {
    508     struct rtentry rt;
    509     int result;
    510     in_addr_t netmask;
    511 
    512     memset(&rt, 0, sizeof(rt));
    513 
    514     rt.rt_dst.sa_family = AF_INET;
    515     rt.rt_dev = (void*) ifname;
    516 
    517     netmask = prefixLengthToIpv4Netmask(prefix_length);
    518     init_sockaddr_in(&rt.rt_genmask, netmask);
    519     init_sockaddr_in(&rt.rt_dst, dst.s_addr);
    520     rt.rt_flags = RTF_UP;
    521 
    522     if (prefix_length == 32) {
    523         rt.rt_flags |= RTF_HOST;
    524     }
    525 
    526     if (gw.s_addr != 0) {
    527         rt.rt_flags |= RTF_GATEWAY;
    528         init_sockaddr_in(&rt.rt_gateway, gw.s_addr);
    529     }
    530 
    531     ifc_init();
    532 
    533     if (ifc_ctl_sock < 0) {
    534         return -errno;
    535     }
    536 
    537     result = ioctl(ifc_ctl_sock, action, &rt);
    538     if (result < 0) {
    539         if (errno == EEXIST) {
    540             result = 0;
    541         } else {
    542             result = -errno;
    543         }
    544     }
    545     ifc_close();
    546     return result;
    547 }
    548 
    549 /* deprecated - v4 only */
    550 int ifc_create_default_route(const char *name, in_addr_t gw)
    551 {
    552     struct in_addr in_dst, in_gw;
    553 
    554     in_dst.s_addr = 0;
    555     in_gw.s_addr = gw;
    556 
    557     int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw);
    558     if (DBG) printerr("ifc_create_default_route(%s, %d) = %d", name, gw, ret);
    559     return ret;
    560 }
    561 
    562 /* deprecated v4-only */
    563 int ifc_add_host_route(const char *name, in_addr_t dst)
    564 {
    565     struct in_addr in_dst, in_gw;
    566 
    567     in_dst.s_addr = dst;
    568     in_gw.s_addr = 0;
    569 
    570     return ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 32, in_gw);
    571 }
    572 
    573 int ifc_enable(const char *ifname)
    574 {
    575     int result;
    576 
    577     ifc_init();
    578     result = ifc_up(ifname);
    579     ifc_close();
    580     return result;
    581 }
    582 
    583 int ifc_disable(const char *ifname)
    584 {
    585     unsigned addr, count;
    586     int result;
    587 
    588     ifc_init();
    589     result = ifc_down(ifname);
    590 
    591     ifc_set_addr(ifname, 0);
    592     for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
    593        if (ifc_get_addr(ifname, &addr) < 0)
    594             break;
    595        if (addr)
    596           ifc_set_addr(ifname, 0);
    597     }
    598 
    599     ifc_close();
    600     return result;
    601 }
    602 
    603 #define RESET_IPV4_ADDRESSES 0x01
    604 #define RESET_IPV6_ADDRESSES 0x02
    605 #define RESET_ALL_ADDRESSES  (RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES)
    606 
    607 int ifc_reset_connections(const char *ifname, const int reset_mask)
    608 {
    609 #ifdef HAVE_ANDROID_OS
    610     int result, success;
    611     in_addr_t myaddr;
    612     struct ifreq ifr;
    613     struct in6_ifreq ifr6;
    614 
    615     if (reset_mask & RESET_IPV4_ADDRESSES) {
    616         /* IPv4. Clear connections on the IP address. */
    617         ifc_init();
    618         ifc_get_info(ifname, &myaddr, NULL, NULL);
    619         ifc_init_ifr(ifname, &ifr);
    620         init_sockaddr_in(&ifr.ifr_addr, myaddr);
    621         result = ioctl(ifc_ctl_sock, SIOCKILLADDR,  &ifr);
    622         ifc_close();
    623     } else {
    624         result = 0;
    625     }
    626 
    627     if (reset_mask & RESET_IPV6_ADDRESSES) {
    628         /*
    629          * IPv6. On Linux, when an interface goes down it loses all its IPv6
    630          * addresses, so we don't know which connections belonged to that interface
    631          * So we clear all unused IPv6 connections on the device by specifying an
    632          * empty IPv6 address.
    633          */
    634         ifc_init6();
    635         // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets.
    636         memset(&ifr6, 0, sizeof(ifr6));
    637         success = ioctl(ifc_ctl_sock6, SIOCKILLADDR,  &ifr6);
    638         if (result == 0) {
    639             result = success;
    640         }
    641         ifc_close6();
    642     }
    643 
    644     return result;
    645 #else
    646     return 0;
    647 #endif
    648 }
    649 
    650 /*
    651  * Remove the routes associated with the named interface.
    652  */
    653 int ifc_remove_host_routes(const char *name)
    654 {
    655     char ifname[64];
    656     in_addr_t dest, gway, mask;
    657     int flags, refcnt, use, metric, mtu, win, irtt;
    658     struct rtentry rt;
    659     FILE *fp;
    660     struct in_addr addr;
    661 
    662     fp = fopen("/proc/net/route", "r");
    663     if (fp == NULL)
    664         return -1;
    665     /* Skip the header line */
    666     if (fscanf(fp, "%*[^\n]\n") < 0) {
    667         fclose(fp);
    668         return -1;
    669     }
    670     ifc_init();
    671     for (;;) {
    672         int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n",
    673                            ifname, &dest, &gway, &flags, &refcnt, &use, &metric, &mask,
    674                            &mtu, &win, &irtt);
    675         if (nread != 11) {
    676             break;
    677         }
    678         if ((flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST)
    679                 || strcmp(ifname, name) != 0) {
    680             continue;
    681         }
    682         memset(&rt, 0, sizeof(rt));
    683         rt.rt_dev = (void *)name;
    684         init_sockaddr_in(&rt.rt_dst, dest);
    685         init_sockaddr_in(&rt.rt_gateway, gway);
    686         init_sockaddr_in(&rt.rt_genmask, mask);
    687         addr.s_addr = dest;
    688         if (ioctl(ifc_ctl_sock, SIOCDELRT, &rt) < 0) {
    689             LOGD("failed to remove route for %s to %s: %s",
    690                  ifname, inet_ntoa(addr), strerror(errno));
    691         }
    692     }
    693     fclose(fp);
    694     ifc_close();
    695     return 0;
    696 }
    697 
    698 /*
    699  * Return the address of the default gateway
    700  *
    701  * TODO: factor out common code from this and remove_host_routes()
    702  * so that we only scan /proc/net/route in one place.
    703  *
    704  * DEPRECATED
    705  */
    706 int ifc_get_default_route(const char *ifname)
    707 {
    708     char name[64];
    709     in_addr_t dest, gway, mask;
    710     int flags, refcnt, use, metric, mtu, win, irtt;
    711     int result;
    712     FILE *fp;
    713 
    714     fp = fopen("/proc/net/route", "r");
    715     if (fp == NULL)
    716         return 0;
    717     /* Skip the header line */
    718     if (fscanf(fp, "%*[^\n]\n") < 0) {
    719         fclose(fp);
    720         return 0;
    721     }
    722     ifc_init();
    723     result = 0;
    724     for (;;) {
    725         int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n",
    726                            name, &dest, &gway, &flags, &refcnt, &use, &metric, &mask,
    727                            &mtu, &win, &irtt);
    728         if (nread != 11) {
    729             break;
    730         }
    731         if ((flags & (RTF_UP|RTF_GATEWAY)) == (RTF_UP|RTF_GATEWAY)
    732                 && dest == 0
    733                 && strcmp(ifname, name) == 0) {
    734             result = gway;
    735             break;
    736         }
    737     }
    738     fclose(fp);
    739     ifc_close();
    740     return result;
    741 }
    742 
    743 /*
    744  * Sets the specified gateway as the default route for the named interface.
    745  * DEPRECATED
    746  */
    747 int ifc_set_default_route(const char *ifname, in_addr_t gateway)
    748 {
    749     struct in_addr addr;
    750     int result;
    751 
    752     ifc_init();
    753     addr.s_addr = gateway;
    754     if ((result = ifc_create_default_route(ifname, gateway)) < 0) {
    755         LOGD("failed to add %s as default route for %s: %s",
    756              inet_ntoa(addr), ifname, strerror(errno));
    757     }
    758     ifc_close();
    759     return result;
    760 }
    761 
    762 /*
    763  * Removes the default route for the named interface.
    764  */
    765 int ifc_remove_default_route(const char *ifname)
    766 {
    767     struct rtentry rt;
    768     int result;
    769 
    770     ifc_init();
    771     memset(&rt, 0, sizeof(rt));
    772     rt.rt_dev = (void *)ifname;
    773     rt.rt_flags = RTF_UP|RTF_GATEWAY;
    774     init_sockaddr_in(&rt.rt_dst, 0);
    775     if ((result = ioctl(ifc_ctl_sock, SIOCDELRT, &rt)) < 0) {
    776         LOGD("failed to remove default route for %s: %s", ifname, strerror(errno));
    777     }
    778     ifc_close();
    779     return result;
    780 }
    781 
    782 int
    783 ifc_configure(const char *ifname,
    784         in_addr_t address,
    785         uint32_t prefixLength,
    786         in_addr_t gateway,
    787         in_addr_t dns1,
    788         in_addr_t dns2) {
    789 
    790     char dns_prop_name[PROPERTY_KEY_MAX];
    791 
    792     ifc_init();
    793 
    794     if (ifc_up(ifname)) {
    795         printerr("failed to turn on interface %s: %s\n", ifname, strerror(errno));
    796         ifc_close();
    797         return -1;
    798     }
    799     if (ifc_set_addr(ifname, address)) {
    800         printerr("failed to set ipaddr %s: %s\n", ipaddr_to_string(address), strerror(errno));
    801         ifc_close();
    802         return -1;
    803     }
    804     if (ifc_set_prefixLength(ifname, prefixLength)) {
    805         printerr("failed to set prefixLength %d: %s\n", prefixLength, strerror(errno));
    806         ifc_close();
    807         return -1;
    808     }
    809     if (ifc_create_default_route(ifname, gateway)) {
    810         printerr("failed to set default route %s: %s\n", ipaddr_to_string(gateway), strerror(errno));
    811         ifc_close();
    812         return -1;
    813     }
    814 
    815     ifc_close();
    816 
    817     snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname);
    818     property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : "");
    819     snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname);
    820     property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : "");
    821 
    822     return 0;
    823 }
    824 
    825 int ifc_act_on_ipv6_route(int action, const char *ifname, struct in6_addr dst, int prefix_length,
    826       struct in6_addr gw)
    827 {
    828     struct in6_rtmsg rtmsg;
    829     int result;
    830     int ifindex;
    831 
    832     memset(&rtmsg, 0, sizeof(rtmsg));
    833 
    834     ifindex = if_nametoindex(ifname);
    835     if (ifindex == 0) {
    836         printerr("if_nametoindex() failed: interface %s\n", ifname);
    837         return -ENXIO;
    838     }
    839 
    840     rtmsg.rtmsg_ifindex = ifindex;
    841     rtmsg.rtmsg_dst = dst;
    842     rtmsg.rtmsg_dst_len = prefix_length;
    843     rtmsg.rtmsg_flags = RTF_UP;
    844 
    845     if (prefix_length == 128) {
    846         rtmsg.rtmsg_flags |= RTF_HOST;
    847     }
    848 
    849     if (memcmp(&gw, &in6addr_any, sizeof(in6addr_any))) {
    850         rtmsg.rtmsg_flags |= RTF_GATEWAY;
    851         rtmsg.rtmsg_gateway = gw;
    852     }
    853 
    854     ifc_init6();
    855 
    856     if (ifc_ctl_sock6 < 0) {
    857         return -errno;
    858     }
    859 
    860     result = ioctl(ifc_ctl_sock6, action, &rtmsg);
    861     if (result < 0) {
    862         if (errno == EEXIST) {
    863             result = 0;
    864         } else {
    865             result = -errno;
    866         }
    867     }
    868     ifc_close6();
    869     return result;
    870 }
    871 
    872 int ifc_act_on_route(int action, const char *ifname, const char *dst, int prefix_length,
    873         const char *gw)
    874 {
    875     int ret = 0;
    876     struct sockaddr_in ipv4_dst, ipv4_gw;
    877     struct sockaddr_in6 ipv6_dst, ipv6_gw;
    878     struct addrinfo hints, *addr_ai, *gw_ai;
    879 
    880     memset(&hints, 0, sizeof(hints));
    881     hints.ai_family = AF_UNSPEC;  /* Allow IPv4 or IPv6 */
    882     hints.ai_flags = AI_NUMERICHOST;
    883 
    884     ret = getaddrinfo(dst, NULL, &hints, &addr_ai);
    885 
    886     if (ret != 0) {
    887         printerr("getaddrinfo failed: invalid address %s\n", dst);
    888         return -EINVAL;
    889     }
    890 
    891     if (gw == NULL || (strlen(gw) == 0)) {
    892         if (addr_ai->ai_family == AF_INET6) {
    893             gw = "::";
    894         } else if (addr_ai->ai_family == AF_INET) {
    895             gw = "0.0.0.0";
    896         }
    897     }
    898 
    899     if (((addr_ai->ai_family == AF_INET6) && (prefix_length < 0 || prefix_length > 128)) ||
    900             ((addr_ai->ai_family == AF_INET) && (prefix_length < 0 || prefix_length > 32))) {
    901         printerr("ifc_add_route: invalid prefix length");
    902         freeaddrinfo(addr_ai);
    903         return -EINVAL;
    904     }
    905 
    906     ret = getaddrinfo(gw, NULL, &hints, &gw_ai);
    907     if (ret != 0) {
    908         printerr("getaddrinfo failed: invalid gateway %s\n", gw);
    909         freeaddrinfo(addr_ai);
    910         return -EINVAL;
    911     }
    912 
    913     if (addr_ai->ai_family != gw_ai->ai_family) {
    914         printerr("ifc_add_route: different address families: %s and %s\n", dst, gw);
    915         freeaddrinfo(addr_ai);
    916         freeaddrinfo(gw_ai);
    917         return -EINVAL;
    918     }
    919 
    920     if (addr_ai->ai_family == AF_INET6) {
    921         memcpy(&ipv6_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in6));
    922         memcpy(&ipv6_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in6));
    923         ret = ifc_act_on_ipv6_route(action, ifname, ipv6_dst.sin6_addr,
    924                 prefix_length, ipv6_gw.sin6_addr);
    925     } else if (addr_ai->ai_family == AF_INET) {
    926         memcpy(&ipv4_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in));
    927         memcpy(&ipv4_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in));
    928         ret = ifc_act_on_ipv4_route(action, ifname, ipv4_dst.sin_addr,
    929                 prefix_length, ipv4_gw.sin_addr);
    930     } else {
    931         printerr("ifc_add_route: getaddrinfo returned un supported address family %d\n",
    932                   addr_ai->ai_family);
    933         ret = -EAFNOSUPPORT;
    934     }
    935 
    936     freeaddrinfo(addr_ai);
    937     freeaddrinfo(gw_ai);
    938     return ret;
    939 }
    940 
    941 /*
    942  * DEPRECATED
    943  */
    944 int ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length,
    945       struct in_addr gw)
    946 {
    947     int i =ifc_act_on_ipv4_route(SIOCADDRT, ifname, dst, prefix_length, gw);
    948     if (DBG) printerr("ifc_add_ipv4_route(%s, xx, %d, xx) = %d", ifname, prefix_length, i);
    949     return i;
    950 }
    951 
    952 /*
    953  * DEPRECATED
    954  */
    955 int ifc_add_ipv6_route(const char *ifname, struct in6_addr dst, int prefix_length,
    956       struct in6_addr gw)
    957 {
    958     return ifc_act_on_ipv6_route(SIOCADDRT, ifname, dst, prefix_length, gw);
    959 }
    960 
    961 int ifc_add_route(const char *ifname, const char *dst, int prefix_length, const char *gw)
    962 {
    963     int i = ifc_act_on_route(SIOCADDRT, ifname, dst, prefix_length, gw);
    964     if (DBG) printerr("ifc_add_route(%s, %s, %d, %s) = %d", ifname, dst, prefix_length, gw, i);
    965     return i;
    966 }
    967 
    968 int ifc_remove_route(const char *ifname, const char*dst, int prefix_length, const char *gw)
    969 {
    970     return ifc_act_on_route(SIOCDELRT, ifname, dst, prefix_length, gw);
    971 }
    972