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