• 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 <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 ALOGD printf
50 #define ALOGW 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 
prefixLengthToIpv4Netmask(int prefix_length)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 
ipv4NetmaskToPrefixLength(in_addr_t mask)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 
ipaddr_to_string(in_addr_t addr)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 
string_to_ip(const char * string,struct sockaddr_storage * ss)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 
ifc_init(void)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 
ifc_init6(void)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 
ifc_close(void)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 
ifc_close6(void)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 
ifc_init_ifr(const char * name,struct ifreq * ifr)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 
ifc_get_hwaddr(const char * name,void * ptr)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 
ifc_get_ifindex(const char * name,int * if_indexp)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 
ifc_set_flags(const char * name,unsigned set,unsigned clr)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 
ifc_up(const char * name)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 
ifc_down(const char * name)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 
init_sockaddr_in(struct sockaddr * sa,in_addr_t addr)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 
ifc_set_addr(const char * name,in_addr_t addr)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  */
ifc_act_on_address(int action,const char * name,const char * address,int prefixlen)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 
ifc_add_address(const char * name,const char * address,int prefixlen)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 
ifc_del_address(const char * name,const char * address,int prefixlen)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  */
ifc_clear_ipv6_addresses(const char * name)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             ALOGE("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  */
ifc_clear_ipv4_addresses(const char * name)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  */
ifc_clear_addresses(const char * name)413 int ifc_clear_addresses(const char *name) {
414     ifc_clear_ipv4_addresses(name);
415     return ifc_clear_ipv6_addresses(name);
416 }
417 
ifc_set_hwaddr(const char * name,const void * ptr)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 
ifc_set_mask(const char * name,in_addr_t mask)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 
ifc_set_prefixLength(const char * name,int prefixLength)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 
ifc_get_addr(const char * name,in_addr_t * addr)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 
ifc_get_info(const char * name,in_addr_t * addr,int * prefixLength,unsigned * flags)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 
ifc_act_on_ipv4_route(int action,const char * ifname,struct in_addr dst,int prefix_length,struct in_addr gw)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 */
ifc_create_default_route(const char * name,in_addr_t gw)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 */
ifc_add_host_route(const char * name,in_addr_t dst)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 
ifc_enable(const char * ifname)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 
ifc_disable(const char * ifname)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 
ifc_reset_connections(const char * ifname,const int reset_mask)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  */
ifc_remove_host_routes(const char * name)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             ALOGD("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  */
ifc_get_default_route(const char * ifname)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  */
ifc_set_default_route(const char * ifname,in_addr_t gateway)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         ALOGD("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  */
ifc_remove_default_route(const char * ifname)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         ALOGD("failed to remove default route for %s: %s", ifname, strerror(errno));
777     }
778     ifc_close();
779     return result;
780 }
781 
782 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)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 
ifc_act_on_ipv6_route(int action,const char * ifname,struct in6_addr dst,int prefix_length,struct in6_addr gw)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 
ifc_act_on_route(int action,const char * ifname,const char * dst,int prefix_length,const char * gw)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  */
ifc_add_ipv4_route(const char * ifname,struct in_addr dst,int prefix_length,struct in_addr gw)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  */
ifc_add_ipv6_route(const char * ifname,struct in6_addr dst,int prefix_length,struct in6_addr gw)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 
ifc_add_route(const char * ifname,const char * dst,int prefix_length,const char * gw)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 
ifc_remove_route(const char * ifname,const char * dst,int prefix_length,const char * gw)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