• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <arpa/inet.h>
18  #include <errno.h>
19  #include <linux/if.h>
20  #include <linux/if_ether.h>
21  #include <linux/if_arp.h>
22  #include <linux/netlink.h>
23  #include <linux/route.h>
24  #include <linux/ipv6_route.h>
25  #include <linux/rtnetlink.h>
26  #include <linux/sockios.h>
27  #include <net/if.h>
28  #include <netdb.h>
29  #include <netinet/in.h>
30  #include <pthread.h>
31  #include <stdio.h>
32  #include <stdlib.h>
33  #include <string.h>
34  #include <sys/select.h>
35  #include <sys/socket.h>
36  #include <sys/types.h>
37  #include <unistd.h>
38  
39  #ifdef ANDROID
40  #define LOG_TAG "NetUtils"
41  #include <cutils/properties.h>
42  #include <log/log.h>
43  #else
44  #define ALOGD printf
45  #define ALOGW printf
46  #endif
47  
48  #include "netutils/ifc.h"
49  
50  #if defined(__ANDROID__)
51  /* SIOCKILLADDR is an Android extension. */
52  #define SIOCKILLADDR 0x8939
53  #endif
54  
55  static int ifc_ctl_sock = -1;
56  static int ifc_ctl_sock6 = -1;
57  static pthread_mutex_t ifc_sock_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
58  static pthread_mutex_t ifc_sock6_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
59  void printerr(char *fmt, ...);
60  
61  #define DBG 0
62  #define INET_ADDRLEN 4
63  #define INET6_ADDRLEN 16
64  
prefixLengthToIpv4Netmask(int prefix_length)65  in_addr_t prefixLengthToIpv4Netmask(int prefix_length)
66  {
67      in_addr_t mask = 0;
68  
69      // C99 (6.5.7): shifts of 32 bits have undefined results
70      if (prefix_length <= 0 || prefix_length > 32) {
71          return 0;
72      }
73  
74      mask = ~mask << (32 - prefix_length);
75      mask = htonl(mask);
76  
77      return mask;
78  }
79  
ipv4NetmaskToPrefixLength(in_addr_t mask)80  int ipv4NetmaskToPrefixLength(in_addr_t mask)
81  {
82      int prefixLength = 0;
83      uint32_t m = (uint32_t)ntohl(mask);
84      while (m & 0x80000000) {
85          prefixLength++;
86          m = m << 1;
87      }
88      return prefixLength;
89  }
90  
ipaddr_to_string(in_addr_t addr)91  static const char *ipaddr_to_string(in_addr_t addr)
92  {
93      struct in_addr in_addr;
94  
95      in_addr.s_addr = addr;
96      return inet_ntoa(in_addr);
97  }
98  
string_to_ip(const char * string,struct sockaddr_storage * ss)99  int string_to_ip(const char *string, struct sockaddr_storage *ss) {
100      struct addrinfo hints, *ai;
101      int ret;
102  
103      if (ss == NULL) {
104          return -EFAULT;
105      }
106  
107      memset(&hints, 0, sizeof(hints));
108      hints.ai_family = AF_UNSPEC;
109      hints.ai_flags = AI_NUMERICHOST;
110      hints.ai_socktype = SOCK_DGRAM;
111  
112      ret = getaddrinfo(string, NULL, &hints, &ai);
113      if (ret == 0) {
114          memcpy(ss, ai->ai_addr, ai->ai_addrlen);
115          freeaddrinfo(ai);
116      }
117  
118      return ret;
119  }
120  
ifc_init(void)121  int ifc_init(void)
122  {
123      int ret;
124  
125      pthread_mutex_lock(&ifc_sock_mutex);
126      if (ifc_ctl_sock == -1) {
127          ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
128          if (ifc_ctl_sock < 0) {
129              printerr("socket() failed: %s\n", strerror(errno));
130          }
131      }
132  
133      ret = ifc_ctl_sock < 0 ? -1 : 0;
134      if (DBG) printerr("ifc_init_returning %d", ret);
135      return ret;
136  }
137  
ifc_init6(void)138  int ifc_init6(void)
139  {
140      pthread_mutex_lock(&ifc_sock6_mutex);
141      if (ifc_ctl_sock6 == -1) {
142          ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
143          if (ifc_ctl_sock6 < 0) {
144              printerr("socket() failed: %s\n", strerror(errno));
145          }
146      }
147      return ifc_ctl_sock6 < 0 ? -1 : 0;
148  }
149  
ifc_close(void)150  void ifc_close(void)
151  {
152      if (DBG) printerr("ifc_close");
153      if (ifc_ctl_sock != -1) {
154          (void)close(ifc_ctl_sock);
155          ifc_ctl_sock = -1;
156      }
157      pthread_mutex_unlock(&ifc_sock_mutex);
158  }
159  
ifc_close6(void)160  void ifc_close6(void)
161  {
162      if (ifc_ctl_sock6 != -1) {
163          (void)close(ifc_ctl_sock6);
164          ifc_ctl_sock6 = -1;
165      }
166      pthread_mutex_unlock(&ifc_sock6_mutex);
167  }
168  
ifc_init_ifr(const char * name,struct ifreq * ifr)169  static void ifc_init_ifr(const char *name, struct ifreq *ifr)
170  {
171      memset(ifr, 0, sizeof(struct ifreq));
172      strncpy(ifr->ifr_name, name, IFNAMSIZ);
173      ifr->ifr_name[IFNAMSIZ - 1] = 0;
174  }
175  
ifc_get_hwaddr(const char * name,void * ptr)176  int ifc_get_hwaddr(const char *name, void *ptr)
177  {
178      int r;
179      struct ifreq ifr;
180      ifc_init_ifr(name, &ifr);
181  
182      r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr);
183      if(r < 0) return -1;
184  
185      memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
186      return 0;
187  }
188  
ifc_get_ifindex(const char * name,int * if_indexp)189  int ifc_get_ifindex(const char *name, int *if_indexp)
190  {
191      int r;
192      struct ifreq ifr;
193      ifc_init_ifr(name, &ifr);
194  
195      r = ioctl(ifc_ctl_sock, SIOCGIFINDEX, &ifr);
196      if(r < 0) return -1;
197  
198      *if_indexp = ifr.ifr_ifindex;
199      return 0;
200  }
201  
ifc_set_flags(const char * name,unsigned set,unsigned clr)202  static int ifc_set_flags(const char *name, unsigned set, unsigned clr)
203  {
204      struct ifreq ifr;
205      ifc_init_ifr(name, &ifr);
206  
207      if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) return -1;
208      ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set;
209      return ioctl(ifc_ctl_sock, SIOCSIFFLAGS, &ifr);
210  }
211  
ifc_up(const char * name)212  int ifc_up(const char *name)
213  {
214      int ret = ifc_set_flags(name, IFF_UP, 0);
215      if (DBG) printerr("ifc_up(%s) = %d", name, ret);
216      return ret;
217  }
218  
ifc_down(const char * name)219  int ifc_down(const char *name)
220  {
221      int ret = ifc_set_flags(name, 0, IFF_UP);
222      if (DBG) printerr("ifc_down(%s) = %d", name, ret);
223      return ret;
224  }
225  
init_sockaddr_in(struct sockaddr * sa,in_addr_t addr)226  static void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr)
227  {
228      struct sockaddr_in *sin = (struct sockaddr_in *) sa;
229      sin->sin_family = AF_INET;
230      sin->sin_port = 0;
231      sin->sin_addr.s_addr = addr;
232  }
233  
ifc_set_addr(const char * name,in_addr_t addr)234  int ifc_set_addr(const char *name, in_addr_t addr)
235  {
236      struct ifreq ifr;
237      int ret;
238  
239      ifc_init_ifr(name, &ifr);
240      init_sockaddr_in(&ifr.ifr_addr, addr);
241  
242      ret = ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr);
243      if (DBG) printerr("ifc_set_addr(%s, xx) = %d", name, ret);
244      return ret;
245  }
246  
247  /*
248   * Adds or deletes an IP address on an interface.
249   *
250   * Action is one of:
251   * - RTM_NEWADDR (to add a new address)
252   * - RTM_DELADDR (to delete an existing address)
253   *
254   * Returns zero on success and negative errno on failure.
255   */
ifc_act_on_address(int action,const char * name,const char * address,int prefixlen)256  int ifc_act_on_address(int action, const char *name, const char *address,
257                         int prefixlen) {
258      int ifindex, s, len, ret;
259      struct sockaddr_storage ss;
260      int saved_errno;
261      void *addr;
262      size_t addrlen;
263      struct {
264          struct nlmsghdr n;
265          struct ifaddrmsg r;
266          // Allow for IPv6 address, headers, IPv4 broadcast addr and padding.
267          char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
268                       NLMSG_ALIGN(sizeof(struct rtattr)) +
269                       NLMSG_ALIGN(INET6_ADDRLEN) +
270                       NLMSG_ALIGN(sizeof(struct rtattr)) +
271                       NLMSG_ALIGN(INET_ADDRLEN)];
272      } req;
273      struct rtattr *rta;
274      struct nlmsghdr *nh;
275      struct nlmsgerr *err;
276      char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
277               NLMSG_ALIGN(sizeof(struct nlmsgerr)) +
278               NLMSG_ALIGN(sizeof(struct nlmsghdr))];
279  
280      // Get interface ID.
281      ifindex = if_nametoindex(name);
282      if (ifindex == 0) {
283          return -errno;
284      }
285  
286      // Convert string representation to sockaddr_storage.
287      ret = string_to_ip(address, &ss);
288      if (ret) {
289          return ret;
290      }
291  
292      // Determine address type and length.
293      if (ss.ss_family == AF_INET) {
294          struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
295          addr = &sin->sin_addr;
296          addrlen = INET_ADDRLEN;
297      } else if (ss.ss_family == AF_INET6) {
298          struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
299          addr = &sin6->sin6_addr;
300          addrlen = INET6_ADDRLEN;
301      } else {
302          return -EAFNOSUPPORT;
303      }
304  
305      // Fill in netlink structures.
306      memset(&req, 0, sizeof(req));
307  
308      // Netlink message header.
309      req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
310      req.n.nlmsg_type = action;
311      req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
312      req.n.nlmsg_pid = getpid();
313  
314      // Interface address message header.
315      req.r.ifa_family = ss.ss_family;
316      req.r.ifa_prefixlen = prefixlen;
317      req.r.ifa_index = ifindex;
318  
319      // Routing attribute. Contains the actual IP address.
320      rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len));
321      rta->rta_type = IFA_LOCAL;
322      rta->rta_len = RTA_LENGTH(addrlen);
323      req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen);
324      memcpy(RTA_DATA(rta), addr, addrlen);
325  
326      // Add an explicit IFA_BROADCAST for IPv4 RTM_NEWADDRs.
327      if (ss.ss_family == AF_INET && action == RTM_NEWADDR) {
328          rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len));
329          rta->rta_type = IFA_BROADCAST;
330          rta->rta_len = RTA_LENGTH(addrlen);
331          req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen);
332          ((struct in_addr *)addr)->s_addr |= htonl((1<<(32-prefixlen))-1);
333          memcpy(RTA_DATA(rta), addr, addrlen);
334      }
335  
336      s = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
337      if (s < 0) {
338          return -errno;
339      }
340  
341      if (send(s, &req, req.n.nlmsg_len, 0) < 0) {
342          saved_errno = errno;
343          close(s);
344          return -saved_errno;
345      }
346  
347      len = recv(s, buf, sizeof(buf), 0);
348      saved_errno = errno;
349      close(s);
350      if (len < 0) {
351          return -saved_errno;
352      }
353  
354      // Parse the acknowledgement to find the return code.
355      nh = (struct nlmsghdr *) buf;
356      if (!NLMSG_OK(nh, (unsigned) len) || nh->nlmsg_type != NLMSG_ERROR) {
357          return -EINVAL;
358      }
359      err = NLMSG_DATA(nh);
360  
361      // Return code is negative errno.
362      return err->error;
363  }
364  
ifc_add_address(const char * name,const char * address,int prefixlen)365  int ifc_add_address(const char *name, const char *address, int prefixlen) {
366      return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen);
367  }
368  
ifc_del_address(const char * name,const char * address,int prefixlen)369  int ifc_del_address(const char *name, const char * address, int prefixlen) {
370      return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen);
371  }
372  
373  /*
374   * Clears IPv6 addresses on the specified interface.
375   */
ifc_clear_ipv6_addresses(const char * name)376  int ifc_clear_ipv6_addresses(const char *name) {
377      char rawaddrstr[INET6_ADDRSTRLEN], addrstr[INET6_ADDRSTRLEN];
378      unsigned int prefixlen;
379      int lasterror = 0, i, j, ret;
380      char ifname[64];  // Currently, IFNAMSIZ = 16.
381      FILE *f = fopen("/proc/net/if_inet6", "r");
382      if (!f) {
383          return -errno;
384      }
385  
386      // Format:
387      // 20010db8000a0001fc446aa4b5b347ed 03 40 00 01    wlan0
388      while (fscanf(f, "%32s %*02x %02x %*02x %*02x %63s\n",
389                    rawaddrstr, &prefixlen, ifname) == 3) {
390          // Is this the interface we're looking for?
391          if (strcmp(name, ifname)) {
392              continue;
393          }
394  
395          // Put the colons back into the address.
396          for (i = 0, j = 0; i < 32; i++, j++) {
397              addrstr[j] = rawaddrstr[i];
398              if (i % 4 == 3) {
399                  addrstr[++j] = ':';
400              }
401          }
402          addrstr[j - 1] = '\0';
403  
404          // Don't delete the link-local address as well, or it will disable IPv6
405          // on the interface.
406          if (strncmp(addrstr, "fe80:", 5) == 0) {
407              continue;
408          }
409  
410          ret = ifc_del_address(ifname, addrstr, prefixlen);
411          if (ret) {
412              ALOGE("Deleting address %s/%d on %s: %s", addrstr, prefixlen, ifname,
413                   strerror(-ret));
414              lasterror = ret;
415          }
416      }
417  
418      fclose(f);
419      return lasterror;
420  }
421  
422  /*
423   * Clears IPv4 addresses on the specified interface.
424   */
ifc_clear_ipv4_addresses(const char * name)425  void ifc_clear_ipv4_addresses(const char *name) {
426      unsigned count, addr;
427      ifc_init();
428      for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
429          if (ifc_get_addr(name, &addr) < 0)
430              break;
431          if (addr)
432              ifc_set_addr(name, 0);
433      }
434      ifc_close();
435  }
436  
437  /*
438   * Clears all IP addresses on the specified interface.
439   */
ifc_clear_addresses(const char * name)440  int ifc_clear_addresses(const char *name) {
441      ifc_clear_ipv4_addresses(name);
442      return ifc_clear_ipv6_addresses(name);
443  }
444  
ifc_set_hwaddr(const char * name,const void * ptr)445  int ifc_set_hwaddr(const char *name, const void *ptr)
446  {
447      struct ifreq ifr;
448      ifc_init_ifr(name, &ifr);
449  
450      ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
451      memcpy(&ifr.ifr_hwaddr.sa_data, ptr, ETH_ALEN);
452      return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr);
453  }
454  
ifc_set_mask(const char * name,in_addr_t mask)455  int ifc_set_mask(const char *name, in_addr_t mask)
456  {
457      struct ifreq ifr;
458      int ret;
459  
460      ifc_init_ifr(name, &ifr);
461      init_sockaddr_in(&ifr.ifr_addr, mask);
462  
463      ret = ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
464      if (DBG) printerr("ifc_set_mask(%s, xx) = %d", name, ret);
465      return ret;
466  }
467  
ifc_set_prefixLength(const char * name,int prefixLength)468  int ifc_set_prefixLength(const char *name, int prefixLength)
469  {
470      struct ifreq ifr;
471      // TODO - support ipv6
472      if (prefixLength > 32 || prefixLength < 0) return -1;
473  
474      in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength);
475      ifc_init_ifr(name, &ifr);
476      init_sockaddr_in(&ifr.ifr_addr, mask);
477  
478      return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
479  }
480  
ifc_get_addr(const char * name,in_addr_t * addr)481  int ifc_get_addr(const char *name, in_addr_t *addr)
482  {
483      struct ifreq ifr;
484      int ret = 0;
485  
486      ifc_init_ifr(name, &ifr);
487      if (addr != NULL) {
488          ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr);
489          if (ret < 0) {
490              *addr = 0;
491          } else {
492              *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
493          }
494      }
495      return ret;
496  }
497  
ifc_get_info(const char * name,in_addr_t * addr,int * prefixLength,unsigned * flags)498  int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags)
499  {
500      struct ifreq ifr;
501      ifc_init_ifr(name, &ifr);
502  
503      if (addr != NULL) {
504          if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) {
505              *addr = 0;
506          } else {
507              *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
508          }
509      }
510  
511      if (prefixLength != NULL) {
512          if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) {
513              *prefixLength = 0;
514          } else {
515              *prefixLength = ipv4NetmaskToPrefixLength(
516                      ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr);
517          }
518      }
519  
520      if (flags != NULL) {
521          if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) {
522              *flags = 0;
523          } else {
524              *flags = ifr.ifr_flags;
525          }
526      }
527  
528      return 0;
529  }
530  
ifc_act_on_ipv4_route(int action,const char * ifname,struct in_addr dst,int prefix_length,struct in_addr gw)531  int ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, int prefix_length,
532        struct in_addr gw)
533  {
534      struct rtentry rt;
535      int result;
536      in_addr_t netmask;
537  
538      memset(&rt, 0, sizeof(rt));
539  
540      rt.rt_dst.sa_family = AF_INET;
541      rt.rt_dev = (void*) ifname;
542  
543      netmask = prefixLengthToIpv4Netmask(prefix_length);
544      init_sockaddr_in(&rt.rt_genmask, netmask);
545      init_sockaddr_in(&rt.rt_dst, dst.s_addr);
546      rt.rt_flags = RTF_UP;
547  
548      if (prefix_length == 32) {
549          rt.rt_flags |= RTF_HOST;
550      }
551  
552      if (gw.s_addr != 0) {
553          rt.rt_flags |= RTF_GATEWAY;
554          init_sockaddr_in(&rt.rt_gateway, gw.s_addr);
555      }
556  
557      ifc_init();
558  
559      if (ifc_ctl_sock < 0) {
560          ifc_close();
561          return -errno;
562      }
563  
564      result = ioctl(ifc_ctl_sock, action, &rt);
565      if (result < 0) {
566          if (errno == EEXIST) {
567              result = 0;
568          } else {
569              result = -errno;
570          }
571      }
572      ifc_close();
573      return result;
574  }
575  
576  /* deprecated - v4 only */
ifc_create_default_route(const char * name,in_addr_t gw)577  int ifc_create_default_route(const char *name, in_addr_t gw)
578  {
579      struct in_addr in_dst, in_gw;
580  
581      in_dst.s_addr = 0;
582      in_gw.s_addr = gw;
583  
584      int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw);
585      if (DBG) printerr("ifc_create_default_route(%s, %d) = %d", name, gw, ret);
586      return ret;
587  }
588  
589  // Needed by code in hidden partner repositories / branches, so don't delete.
ifc_enable(const char * ifname)590  int ifc_enable(const char *ifname)
591  {
592      int result;
593  
594      ifc_init();
595      result = ifc_up(ifname);
596      ifc_close();
597      return result;
598  }
599  
600  // Needed by code in hidden partner repositories / branches, so don't delete.
ifc_disable(const char * ifname)601  int ifc_disable(const char *ifname)
602  {
603      unsigned addr, count;
604      int result;
605  
606      ifc_init();
607      result = ifc_down(ifname);
608  
609      ifc_set_addr(ifname, 0);
610      for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
611         if (ifc_get_addr(ifname, &addr) < 0)
612              break;
613         if (addr)
614            ifc_set_addr(ifname, 0);
615      }
616  
617      ifc_close();
618      return result;
619  }
620  
ifc_reset_connections(const char * ifname,const int reset_mask)621  int ifc_reset_connections(const char *ifname, const int reset_mask)
622  {
623  #if defined(__ANDROID__)
624      int result, success;
625      in_addr_t myaddr = 0;
626      struct ifreq ifr;
627      struct in6_ifreq ifr6;
628  
629      if (reset_mask & RESET_IPV4_ADDRESSES) {
630          /* IPv4. Clear connections on the IP address. */
631          ifc_init();
632          if (!(reset_mask & RESET_IGNORE_INTERFACE_ADDRESS)) {
633              ifc_get_info(ifname, &myaddr, NULL, NULL);
634          }
635          ifc_init_ifr(ifname, &ifr);
636          init_sockaddr_in(&ifr.ifr_addr, myaddr);
637          result = ioctl(ifc_ctl_sock, SIOCKILLADDR,  &ifr);
638          ifc_close();
639      } else {
640          result = 0;
641      }
642  
643      if (reset_mask & RESET_IPV6_ADDRESSES) {
644          /*
645           * IPv6. On Linux, when an interface goes down it loses all its IPv6
646           * addresses, so we don't know which connections belonged to that interface
647           * So we clear all unused IPv6 connections on the device by specifying an
648           * empty IPv6 address.
649           */
650          ifc_init6();
651          // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets.
652          memset(&ifr6, 0, sizeof(ifr6));
653          success = ioctl(ifc_ctl_sock6, SIOCKILLADDR,  &ifr6);
654          if (result == 0) {
655              result = success;
656          }
657          ifc_close6();
658      }
659  
660      return result;
661  #else
662      return 0;
663  #endif
664  }
665  
666  /*
667   * Removes the default route for the named interface.
668   */
ifc_remove_default_route(const char * ifname)669  int ifc_remove_default_route(const char *ifname)
670  {
671      struct rtentry rt;
672      int result;
673  
674      ifc_init();
675      memset(&rt, 0, sizeof(rt));
676      rt.rt_dev = (void *)ifname;
677      rt.rt_flags = RTF_UP|RTF_GATEWAY;
678      init_sockaddr_in(&rt.rt_dst, 0);
679      if ((result = ioctl(ifc_ctl_sock, SIOCDELRT, &rt)) < 0) {
680          ALOGD("failed to remove default route for %s: %s", ifname, strerror(errno));
681      }
682      ifc_close();
683      return result;
684  }
685  
686  int
ifc_configure(const char * ifname,in_addr_t address,uint32_t prefixLength,in_addr_t gateway,in_addr_t dns1,in_addr_t dns2)687  ifc_configure(const char *ifname,
688          in_addr_t address,
689          uint32_t prefixLength,
690          in_addr_t gateway,
691          in_addr_t dns1,
692          in_addr_t dns2) {
693  
694      char dns_prop_name[PROPERTY_KEY_MAX];
695  
696      ifc_init();
697  
698      if (ifc_up(ifname)) {
699          printerr("failed to turn on interface %s: %s\n", ifname, strerror(errno));
700          ifc_close();
701          return -1;
702      }
703      if (ifc_set_addr(ifname, address)) {
704          printerr("failed to set ipaddr %s: %s\n", ipaddr_to_string(address), strerror(errno));
705          ifc_close();
706          return -1;
707      }
708      if (ifc_set_prefixLength(ifname, prefixLength)) {
709          printerr("failed to set prefixLength %d: %s\n", prefixLength, strerror(errno));
710          ifc_close();
711          return -1;
712      }
713      if (ifc_create_default_route(ifname, gateway)) {
714          printerr("failed to set default route %s: %s\n", ipaddr_to_string(gateway), strerror(errno));
715          ifc_close();
716          return -1;
717      }
718  
719      ifc_close();
720  
721      snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname);
722      property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : "");
723      snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname);
724      property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : "");
725  
726      return 0;
727  }
728