mc: multple fixes (#2367)
[termux-packages] / ndk-patches / ifaddrs.h
CommitLineData
42562d13
FF
1/*
2 * Copyright (c) 1995, 1999
3 * Berkeley Software Design, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
12 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
15 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
16 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
17 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
21 * SUCH DAMAGE.
22 *
23 * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
24 */
25/*
26Copyright (c) 2013, Kenneth MacKay
27All rights reserved.
28
29Redistribution and use in source and binary forms, with or without modification,
30are permitted provided that the following conditions are met:
31 * Redistributions of source code must retain the above copyright notice, this
32 list of conditions and the following disclaimer.
33 * Redistributions in binary form must reproduce the above copyright notice,
34 this list of conditions and the following disclaimer in the documentation
35 and/or other materials provided with the distribution.
36
37THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
38ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
41ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
44ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47*/
48
49#ifndef _IFADDRS_H_
50#define _IFADDRS_H_
51
52struct ifaddrs {
53 struct ifaddrs *ifa_next;
54 char *ifa_name;
55 unsigned int ifa_flags;
56 struct sockaddr *ifa_addr;
57 struct sockaddr *ifa_netmask;
58 struct sockaddr *ifa_dstaddr;
59 void *ifa_data;
60};
61
62/*
63 * This may have been defined in <net/if.h>. Note that if <net/if.h> is
64 * to be included it must be included before this header file.
65 */
66#ifndef ifa_broadaddr
67#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
68#endif
69
70#include <sys/cdefs.h>
71
72__BEGIN_DECLS
1197c15b
FF
73static int getifaddrs(struct ifaddrs **ifap);
74static void freeifaddrs(struct ifaddrs *ifa);
42562d13
FF
75__END_DECLS
76
77#endif
78
79
80#include <string.h>
81#include <stdlib.h>
82#include <stddef.h>
83#include <errno.h>
84#include <unistd.h>
85#include <sys/socket.h>
86#include <netpacket/packet.h>
87#include <net/if_arp.h>
88#include <netinet/in.h>
89#include <linux/netlink.h>
90#include <linux/rtnetlink.h>
91
92typedef struct NetlinkList {
93 struct NetlinkList *m_next;
94 struct nlmsghdr *m_data;
95 unsigned int m_size;
96} NetlinkList;
97
98static int netlink_socket(void)
99{
100 int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
101 if (l_socket < 0) return -1;
102
103 struct sockaddr_nl l_addr;
104 memset(&l_addr, 0, sizeof(l_addr));
105 l_addr.nl_family = AF_NETLINK;
106 if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) {
107 close(l_socket);
108 return -1;
109 }
110
111 return l_socket;
112}
113
114static int netlink_send(int p_socket, int p_request)
115{
116 struct {
117 struct nlmsghdr m_hdr;
118 struct rtgenmsg m_msg;
119 } l_data;
120
121 memset(&l_data, 0, sizeof(l_data));
122
123 l_data.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
124 l_data.m_hdr.nlmsg_type = p_request;
125 l_data.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
126 l_data.m_hdr.nlmsg_pid = 0;
127 l_data.m_hdr.nlmsg_seq = p_socket;
128 l_data.m_msg.rtgen_family = AF_UNSPEC;
129
130 struct sockaddr_nl l_addr;
131 memset(&l_addr, 0, sizeof(l_addr));
132 l_addr.nl_family = AF_NETLINK;
133 return (sendto(p_socket, &l_data.m_hdr, l_data.m_hdr.nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
134}
135
136static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
137{
138 struct msghdr l_msg;
139 struct iovec l_iov = { p_buffer, p_len };
140 struct sockaddr_nl l_addr;
141
142 for (;;) {
143 l_msg.msg_name = (void *)&l_addr;
144 l_msg.msg_namelen = sizeof(l_addr);
145 l_msg.msg_iov = &l_iov;
146 l_msg.msg_iovlen = 1;
147 l_msg.msg_control = NULL;
148 l_msg.msg_controllen = 0;
149 l_msg.msg_flags = 0;
150 int l_result = recvmsg(p_socket, &l_msg, 0);
151
152 if (l_result < 0) {
153 if (errno == EINTR) {
154 continue;
155 }
156 return -2;
157 }
158
159 if (l_msg.msg_flags & MSG_TRUNC) {
160 /* Buffer was too small. */
161 return -1;
162 }
163 return l_result;
164 }
165}
166
167static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
168{
169 size_t l_size = 4096;
170 void *l_buffer = NULL;
171
172 for(;;) {
173 free(l_buffer);
174 l_buffer = malloc(l_size);
175 if (l_buffer == NULL) return NULL;
176
177 int l_read = netlink_recv(p_socket, l_buffer, l_size);
178 *p_size = l_read;
179 if (l_read == -2) {
180 free(l_buffer);
181 return NULL;
182 }
183 if (l_read >= 0) {
184 pid_t l_pid = getpid();
185 struct nlmsghdr *l_hdr;
186 for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) {
187 if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) continue;
188
189 if(l_hdr->nlmsg_type == NLMSG_DONE) {
190 *p_done = 1;
191 break;
192 }
193
194 if(l_hdr->nlmsg_type == NLMSG_ERROR) {
195 free(l_buffer);
196 return NULL;
197 }
198 }
199 return (struct nlmsghdr*)l_buffer;
200 }
201
202 l_size *= 2;
203 }
204}
205
206static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
207{
208 NetlinkList *l_item = (NetlinkList*)malloc(sizeof(NetlinkList));
209 if (l_item == NULL) return NULL;
210
211 l_item->m_next = NULL;
212 l_item->m_data = p_data;
213 l_item->m_size = p_size;
214 return l_item;
215}
216
217static void freeResultList(NetlinkList *p_list)
218{
219 NetlinkList *l_cur;
220 while (p_list) {
221 l_cur = p_list;
222 p_list = p_list->m_next;
223 free(l_cur->m_data);
224 free(l_cur);
225 }
226}
227
228static NetlinkList *getResultList(int p_socket, int p_request)
229{
230 if (netlink_send(p_socket, p_request) < 0) return NULL;
231
232 NetlinkList *l_list = NULL;
233 NetlinkList *l_end = NULL;
234 int l_size;
235 int l_done = 0;
236 while (!l_done) {
237 struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
238 if (!l_hdr) {
239 freeResultList(l_list);
240 return NULL;
241 }
242
243 NetlinkList *l_item = newListItem(l_hdr, l_size);
244 if (!l_item) {
245 freeResultList(l_list);
246 return NULL;
247 }
248 if (!l_list) {
249 l_list = l_item;
250 } else {
251 l_end->m_next = l_item;
252 }
253 l_end = l_item;
254 }
255 return l_list;
256}
257
258static size_t maxSize(size_t a, size_t b)
259{
260 return (a > b ? a : b);
261}
262
263static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
264{
265 switch (p_family) {
266 case AF_INET:
267 return sizeof(struct sockaddr_in);
268 case AF_INET6:
269 return sizeof(struct sockaddr_in6);
270 case AF_PACKET:
271 return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
272 default:
273 return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
274 }
275}
276
277static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
278{
279 switch (p_family) {
280 case AF_INET:
281 memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
282 break;
283 case AF_INET6:
284 memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
285 break;
286 case AF_PACKET:
287 memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
288 ((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
289 break;
290 default:
291 memcpy(p_dest->sa_data, p_data, p_size);
292 break;
293 }
294 p_dest->sa_family = p_family;
295}
296
297static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
298{
299 if (!*p_resultList) {
300 *p_resultList = p_entry;
301 } else {
302 struct ifaddrs *l_cur = *p_resultList;
303 while(l_cur->ifa_next) {
304 l_cur = l_cur->ifa_next;
305 }
306 l_cur->ifa_next = p_entry;
307 }
308}
309
310static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
311{
312 struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
313
314 size_t l_nameSize = 0;
315 size_t l_addrSize = 0;
316 size_t l_dataSize = 0;
317
318 size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
319 struct rtattr *l_rta;
320 for (l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) {
321 void *l_rtaData = RTA_DATA(l_rta);
322 size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
323 switch (l_rta->rta_type) {
324 case IFLA_ADDRESS:
325 case IFLA_BROADCAST:
326 l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
327 break;
328 case IFLA_IFNAME:
329 l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
330 break;
331 case IFLA_STATS:
332 l_dataSize += NLMSG_ALIGN(l_rtaSize);
333 break;
334 default:
335 break;
336 }
337 }
338
339 struct ifaddrs *l_entry = (struct ifaddrs*)malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
340 if (l_entry == NULL) return -1;
341 memset(l_entry, 0, sizeof(struct ifaddrs));
342 l_entry->ifa_name = (char*)"";
343
344 char *l_index = ((char *)l_entry) + sizeof(struct ifaddrs);
345 char *l_name = l_index + sizeof(int);
346 char *l_addr = l_name + l_nameSize;
347 char *l_data = l_addr + l_addrSize;
348
349 /* Save the interface index so we can look it up when handling the addresses. */
350 memcpy(l_index, &l_info->ifi_index, sizeof(int));
351
352 l_entry->ifa_flags = l_info->ifi_flags;
353
354 l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
355 for (l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) {
356 void *l_rtaData = RTA_DATA(l_rta);
357 size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
358 switch (l_rta->rta_type) {
359 case IFLA_ADDRESS:
360 case IFLA_BROADCAST:
361 {
362 size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
363 makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
364 ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
365 ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
366 if (l_rta->rta_type == IFLA_ADDRESS) {
367 l_entry->ifa_addr = (struct sockaddr *)l_addr;
368 } else {
369 l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
370 }
371 l_addr += NLMSG_ALIGN(l_addrLen);
372 break;
373 }
374 case IFLA_IFNAME:
375 strncpy(l_name, (char*)l_rtaData, l_rtaDataSize);
376 l_name[l_rtaDataSize] = '\0';
377 l_entry->ifa_name = l_name;
378 break;
379 case IFLA_STATS:
380 memcpy(l_data, l_rtaData, l_rtaDataSize);
381 l_entry->ifa_data = l_data;
382 break;
383 default:
384 break;
385 }
386 }
387
388 addToEnd(p_resultList, l_entry);
389 return 0;
390}
391
392static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
393{
394 int l_num = 0;
395 struct ifaddrs *l_cur = *p_links;
396 while (l_cur && l_num < p_numLinks) {
397 char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs);
398 int l_index;
399 memcpy(&l_index, l_indexPtr, sizeof(int));
400 if(l_index == p_index) return l_cur;
401
402 l_cur = l_cur->ifa_next;
403 ++l_num;
404 }
405 return NULL;
406}
407
408static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
409{
410 struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
411 struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);
412
413 if (l_info->ifa_family == AF_PACKET) return 0;
414
415 size_t l_nameSize = 0;
416 size_t l_addrSize = 0;
417 int l_addedNetmask = 0;
418
419 size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
420 struct rtattr *l_rta;
421 for (l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) {
422 void *l_rtaData = RTA_DATA(l_rta);
423 size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
424
425 switch (l_rta->rta_type) {
426 case IFA_ADDRESS:
427 case IFA_LOCAL:
428 if ((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) {
429 /* Make room for netmask. */
430 l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
431 l_addedNetmask = 1;
432 }
433 case IFA_BROADCAST:
434 l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
435 break;
436 case IFA_LABEL:
437 l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
438 break;
439 default:
440 break;
441 }
442 }
443
444 struct ifaddrs *l_entry = (struct ifaddrs*)malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
445 if (l_entry == NULL) return -1;
446 memset(l_entry, 0, sizeof(struct ifaddrs));
447 l_entry->ifa_name = (l_interface ? l_interface->ifa_name : (char*)"");
448
449 char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
450 char *l_addr = l_name + l_nameSize;
451
452 l_entry->ifa_flags = l_info->ifa_flags;
453 if (l_interface) {
454 l_entry->ifa_flags |= l_interface->ifa_flags;
455 }
456
457 l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
458 for (l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) {
459 void *l_rtaData = RTA_DATA(l_rta);
460 size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
461 switch (l_rta->rta_type) {
462 case IFA_ADDRESS:
463 case IFA_BROADCAST:
464 case IFA_LOCAL:
465 {
466 size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
467 makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
468 if (l_info->ifa_family == AF_INET6) {
469 if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) {
470 ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
471 }
472 }
473
474 if (l_rta->rta_type == IFA_ADDRESS) {
475 /* Apparently in a point-to-point network IFA_ADDRESS contains
476 the dest address and IFA_LOCAL contains the local address. */
477 if(l_entry->ifa_addr) {
478 l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
479 } else {
480 l_entry->ifa_addr = (struct sockaddr *)l_addr;
481 }
482 } else if (l_rta->rta_type == IFA_LOCAL) {
483 if(l_entry->ifa_addr) {
484 l_entry->ifa_dstaddr = l_entry->ifa_addr;
485 }
486 l_entry->ifa_addr = (struct sockaddr *)l_addr;
487 } else {
488 l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
489 }
490 l_addr += NLMSG_ALIGN(l_addrLen);
491 break;
492 }
493 case IFA_LABEL:
494 strncpy(l_name, (char*)l_rtaData, l_rtaDataSize);
495 l_name[l_rtaDataSize] = '\0';
496 l_entry->ifa_name = l_name;
497 break;
498 default:
499 break;
500 }
501 }
502
503 if (l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) {
504 unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
505 unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
506 char l_mask[16] = {0};
507 unsigned i;
508 for (i=0; i<(l_prefix/8); ++i) {
509 l_mask[i] = 0xff;
510 }
511 if (l_prefix % 8) {
512 l_mask[i] = 0xff << (8 - (l_prefix % 8));
513 }
514
515 makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
516 l_entry->ifa_netmask = (struct sockaddr *)l_addr;
517 }
518
519 addToEnd(p_resultList, l_entry);
520 return 0;
521}
522
523static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
524{
525 int l_numLinks = 0;
526 pid_t l_pid = getpid();
527 for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) {
528 unsigned int l_nlsize = p_netlinkList->m_size;
529 struct nlmsghdr *l_hdr;
530 for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
531 {
532 if ((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) continue;
533
534 if (l_hdr->nlmsg_type == NLMSG_DONE) break;
535
536 if (l_hdr->nlmsg_type == RTM_NEWLINK) {
537 if(interpretLink(l_hdr, p_resultList) == -1) return -1;
538 ++l_numLinks;
539 }
540 }
541 }
542 return l_numLinks;
543}
544
545static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
546{
547 pid_t l_pid = getpid();
548 for (; p_netlinkList; p_netlinkList = p_netlinkList->m_next) {
549 unsigned int l_nlsize = p_netlinkList->m_size;
550 struct nlmsghdr *l_hdr;
551 for (l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) {
552 if ((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) continue;
553
554 if (l_hdr->nlmsg_type == NLMSG_DONE) break;
555
556 if (l_hdr->nlmsg_type == RTM_NEWADDR) {
557 if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1) return -1;
558 }
559 }
560 }
561 return 0;
562}
563
59a1174c 564static int getifaddrs(struct ifaddrs **ifap)
42562d13
FF
565{
566 if (!ifap) return -1;
567 *ifap = NULL;
568
569 int l_socket = netlink_socket();
570 if (l_socket < 0) {
571 return -1;
572 }
573
574 NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
575 if (!l_linkResults) {
576 close(l_socket);
577 return -1;
578 }
579
580 NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
581 if (!l_addrResults) {
582 close(l_socket);
583 freeResultList(l_linkResults);
584 return -1;
585 }
586
587 int l_result = 0;
588 int l_numLinks = interpretLinks(l_socket, l_linkResults, ifap);
589 if (l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1) {
590 l_result = -1;
591 }
592
593 freeResultList(l_linkResults);
594 freeResultList(l_addrResults);
595 close(l_socket);
596 return l_result;
597}
598
59a1174c 599static void freeifaddrs(struct ifaddrs *ifa)
42562d13
FF
600{
601 struct ifaddrs *l_cur;
602 while (ifa) {
603 l_cur = ifa;
604 ifa = ifa->ifa_next;
605 free(l_cur);
606 }
607}