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;
45 } NetlinkList;
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 }
netlink_send
static int netlink_send(int p_socket, int p_request)
Definition: android-ifaddrs.c:77
interpretAddrs
static int interpretAddrs(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
Definition: android-ifaddrs.c:625
AF_INET6
#define AF_INET6
Definition: ares_setup.h:208
memset
return memset(p, 0, total)
addToEnd
static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
Definition: android-ifaddrs.c:307
uv__malloc
void * uv__malloc(size_t size)
Definition: uv-common.c:75
uv-common.h
string.h
interpretLink
static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
Definition: android-ifaddrs.c:324
freeifaddrs
void freeifaddrs(struct ifaddrs *ifa)
Definition: android-ifaddrs.c:704
android-ifaddrs.h
interpretLinks
static int interpretLinks(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
Definition: android-ifaddrs.c:592
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
interpretAddr
static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
Definition: android-ifaddrs.c:444
netlink_socket
static int netlink_socket(pid_t *p_pid)
Definition: android-ifaddrs.c:47
NetlinkList
struct NetlinkList NetlinkList
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
calcAddrLen
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
Definition: android-ifaddrs.c:271
xds_interop_client.int
int
Definition: xds_interop_client.py:113
sockaddr_in6
Definition: ares_ipv6.h:25
ifaddrs::ifa_netmask
struct sockaddr * ifa_netmask
Definition: android-ifaddrs.h:34
ifaddrs::ifa_addr
struct sockaddr * ifa_addr
Definition: android-ifaddrs.h:33
ifaddrs::ifa_name
char * ifa_name
Definition: android-ifaddrs.h:31
netlink_recv
static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
Definition: android-ifaddrs.c:102
newListItem
static NetlinkList * newListItem(struct nlmsghdr *p_data, unsigned int p_size)
Definition: android-ifaddrs.c:193
close
#define close
Definition: test-fs.c:48
uv__free
void uv__free(void *ptr)
Definition: uv-common.c:81
getResultList
static NetlinkList * getResultList(int p_socket, int p_request, pid_t p_pid)
Definition: android-ifaddrs.c:219
getNetlinkResponse
static struct nlmsghdr * getNetlinkResponse(int p_socket, pid_t p_pid, int *p_size, int *p_done)
Definition: android-ifaddrs.c:141
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
findInterface
static struct ifaddrs * findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
Definition: android-ifaddrs.c:424
iovec
Definition: gsec.h:33
ifaddrs::ifa_dstaddr
struct sockaddr * ifa_dstaddr
Definition: android-ifaddrs.h:35
iovec::iov_len
size_t iov_len
Definition: gsec.h:35
ifaddrs::ifa_flags
unsigned int ifa_flags
Definition: android-ifaddrs.h:32
getifaddrs
int getifaddrs(struct ifaddrs **ifap)
Definition: android-ifaddrs.c:655
makeSockaddr
static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
Definition: android-ifaddrs.c:286
ifaddrs
Definition: android-ifaddrs.h:29
sockaddr_in6::sin6_addr
struct ares_in6_addr sin6_addr
Definition: ares_ipv6.h:30
test_server.socket
socket
Definition: test_server.py:65
freeResultList
static void freeResultList(NetlinkList *p_list)
Definition: android-ifaddrs.c:207
ifaddrs::ifa_next
struct ifaddrs * ifa_next
Definition: android-ifaddrs.h:30
iovec::iov_base
void * iov_base
Definition: gsec.h:34
errno.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
maxSize
static size_t maxSize(size_t a, size_t b)
Definition: android-ifaddrs.c:266
ifaddrs::ifa_data
void * ifa_data
Definition: android-ifaddrs.h:36


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:30