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