1 /*
2 Copyright (c) 2011, The WebRTC project authors. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 
8   * Redistributions of source code must retain the above copyright
9     notice, this list of conditions and the following disclaimer.
10 
11   * Redistributions in binary form must reproduce the above copyright
12     notice, this list of conditions and the following disclaimer in
13     the documentation and/or other materials provided with the
14     distribution.
15 
16   * Neither the name of Google nor the names of its contributors may
17     be used to endorse or promote products derived from this software
18     without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 
33 #if defined(ANDROID)
34 #include "ifaddrs-android.h"
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/utsname.h>
40 #include <sys/ioctl.h>
41 #include <netinet/in.h>
42 #include <net/if.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #include <linux/netlink.h>
46 #include <linux/rtnetlink.h>
47 
48 struct netlinkrequest {
49   struct nlmsghdr header;
50   struct ifaddrmsg msg;
51 };
52 
53 static const int kMaxReadSize = 4096;
54 
set_ifname(struct ifaddrs * ifaddr,int interface)55 static int set_ifname(struct ifaddrs* ifaddr, int interface) {
56   char buf[IFNAMSIZ] = {0};
57   char* name = if_indextoname(interface, buf);
58   if (name == NULL) {
59     return -1;
60   }
61   ifaddr->ifa_name = malloc(strlen(name) + 1);
62   strncpy(ifaddr->ifa_name, name, strlen(name) + 1);
63   return 0;
64 }
65 
set_flags(struct ifaddrs * ifaddr)66 static int set_flags(struct ifaddrs* ifaddr) {
67   int fd = socket(AF_INET, SOCK_DGRAM, 0);
68   if (fd == -1) {
69     return -1;
70   }
71   struct ifreq ifr;
72   memset(&ifr, 0, sizeof(ifr));
73   strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1);
74   int rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
75   close(fd);
76   if (rc == -1) {
77     return -1;
78   }
79   ifaddr->ifa_flags = ifr.ifr_flags;
80   return 0;
81 }
82 
set_addresses(struct ifaddrs * ifaddr,struct ifaddrmsg * msg,void * data,size_t len)83 static int set_addresses(struct ifaddrs* ifaddr, struct ifaddrmsg* msg, void* data,
84                   size_t len) {
85   if (msg->ifa_family == AF_INET) {
86     struct sockaddr_in* sa = malloc(sizeof(struct sockaddr_in));
87     memset(sa, 0, sizeof(struct sockaddr_in));
88     sa->sin_family = AF_INET;
89     memcpy(&sa->sin_addr, data, len);
90     ifaddr->ifa_addr = (struct sockaddr*)sa;
91   } else if (msg->ifa_family == AF_INET6) {
92     struct sockaddr_in6* sa = malloc(sizeof(struct sockaddr_in6));
93     memset(sa, 0, sizeof(struct sockaddr_in6));
94     sa->sin6_family = AF_INET6;
95     sa->sin6_scope_id = msg->ifa_index;
96     memcpy(&sa->sin6_addr, data, len);
97     ifaddr->ifa_addr = (struct sockaddr*)sa;
98   } else {
99     return -1;
100   }
101   return 0;
102 }
103 
make_prefixes(struct ifaddrs * ifaddr,int family,int prefixlen)104 static int make_prefixes(struct ifaddrs* ifaddr, int family, int prefixlen) {
105   char* prefix = NULL;
106   if (family == AF_INET) {
107     struct sockaddr_in* mask = malloc(sizeof(struct sockaddr_in));
108     memset(mask, 0, sizeof(struct sockaddr_in));
109     mask->sin_family = AF_INET;
110     memset(&mask->sin_addr, 0, sizeof(struct in_addr));
111     ifaddr->ifa_netmask = (struct sockaddr*)mask;
112     if (prefixlen > 32) {
113       prefixlen = 32;
114     }
115     prefix = (char*)&mask->sin_addr;
116   } else if (family == AF_INET6) {
117     struct sockaddr_in6* mask = malloc(sizeof(struct sockaddr_in6));
118     memset(mask, 0, sizeof(struct sockaddr_in6));
119     mask->sin6_family = AF_INET6;
120     memset(&mask->sin6_addr, 0, sizeof(struct in6_addr));
121     ifaddr->ifa_netmask = (struct sockaddr*)mask;
122     if (prefixlen > 128) {
123       prefixlen = 128;
124     }
125     prefix = (char*)&mask->sin6_addr;
126   } else {
127     return -1;
128   }
129   for (int i = 0; i < (prefixlen / 8); i++) {
130     *prefix++ = 0xFF;
131   }
132   char remainder = 0xff;
133   remainder <<= (8 - prefixlen % 8);
134   *prefix = remainder;
135   return 0;
136 }
137 
populate_ifaddrs(struct ifaddrs * ifaddr,struct ifaddrmsg * msg,void * bytes,size_t len)138 static int populate_ifaddrs(struct ifaddrs* ifaddr, struct ifaddrmsg* msg, void* bytes,
139                      size_t len) {
140   if (set_ifname(ifaddr, msg->ifa_index) != 0) {
141     return -1;
142   }
143   if (set_flags(ifaddr) != 0) {
144     return -1;
145   }
146   if (set_addresses(ifaddr, msg, bytes, len) != 0) {
147     return -1;
148   }
149   if (make_prefixes(ifaddr, msg->ifa_family, msg->ifa_prefixlen) != 0) {
150     return -1;
151   }
152   return 0;
153 }
154 
android_getifaddrs(struct ifaddrs ** result)155 int android_getifaddrs(struct ifaddrs** result) {
156   int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
157   if (fd < 0) {
158     return -1;
159   }
160 
161   struct netlinkrequest ifaddr_request;
162   memset(&ifaddr_request, 0, sizeof(ifaddr_request));
163   ifaddr_request.header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
164   ifaddr_request.header.nlmsg_type = RTM_GETADDR;
165   ifaddr_request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
166 
167   ssize_t count = send(fd, &ifaddr_request, ifaddr_request.header.nlmsg_len, 0);
168   if ((size_t)count != ifaddr_request.header.nlmsg_len) {
169     close(fd);
170     return -1;
171   }
172   struct ifaddrs* start = NULL;
173   struct ifaddrs* current = NULL;
174   char buf[kMaxReadSize];
175   ssize_t amount_read = recv(fd, &buf, kMaxReadSize, 0);
176   while (amount_read > 0) {
177     struct nlmsghdr* header = (struct nlmsghdr*)&buf[0];
178     size_t header_size = (size_t)amount_read;
179     for ( ; NLMSG_OK(header, header_size);
180           header = NLMSG_NEXT(header, header_size)) {
181       switch (header->nlmsg_type) {
182         case NLMSG_DONE:
183           /* Success. Return. */
184           *result = start;
185           close(fd);
186           return 0;
187         case NLMSG_ERROR:
188           close(fd);
189           android_freeifaddrs(start);
190           return -1;
191         case RTM_NEWADDR: {
192           struct ifaddrmsg* address_msg =
193               (struct ifaddrmsg*)NLMSG_DATA(header);
194           struct rtattr* rta = IFA_RTA(address_msg);
195           ssize_t payload_len = IFA_PAYLOAD(header);
196           while (RTA_OK(rta, payload_len)) {
197             if (rta->rta_type == IFA_ADDRESS) {
198               int family = address_msg->ifa_family;
199               if (family == AF_INET || family == AF_INET6) {
200                 struct ifaddrs* newest = malloc(sizeof(struct ifaddrs));
201                 memset(newest, 0, sizeof(struct ifaddrs));
202                 if (current) {
203                   current->ifa_next = newest;
204                 } else {
205                   start = newest;
206                 }
207                 if (populate_ifaddrs(newest, address_msg, RTA_DATA(rta),
208                                      RTA_PAYLOAD(rta)) != 0) {
209                   android_freeifaddrs(start);
210                   *result = NULL;
211                   return -1;
212                 }
213                 current = newest;
214               }
215             }
216             rta = RTA_NEXT(rta, payload_len);
217           }
218           break;
219         }
220       }
221     }
222     amount_read = recv(fd, &buf, kMaxReadSize, 0);
223   }
224   close(fd);
225   android_freeifaddrs(start);
226   return -1;
227 }
228 
android_freeifaddrs(struct ifaddrs * addrs)229 void android_freeifaddrs(struct ifaddrs* addrs) {
230   struct ifaddrs* last = NULL;
231   struct ifaddrs* cursor = addrs;
232   while (cursor) {
233     free(cursor->ifa_name);
234     free(cursor->ifa_addr);
235     free(cursor->ifa_netmask);
236     last = cursor;
237     cursor = cursor->ifa_next;
238     free(last);
239   }
240 }
241 
242 #endif  /* defined(ANDROID) */
243