1 /* getifaddrs -- get names and addresses of all network interfaces
2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 #include <netinet/in.h>
25 #include <netpacket/packet.h>
29 #include <sys/ioctl.h>
30 #include <sys/socket.h>
35 #include "netlinkaccess.h"
38 /* We don't know if we have NETLINK support compiled in in our
39 Kernel, so include the old implementation as fallback. */
40 #if __ASSUME_NETLINK_SUPPORT == 0
41 int __no_netlink_support attribute_hidden
;
43 # define getifaddrs fallback_getifaddrs
44 # include "sysdeps/gnu/ifaddrs.c"
49 /* struct to hold the data for one ifaddrs entry, so we can allocate
50 everything at once. */
51 struct ifaddrs_storage
56 /* Save space for the biggest of the four used sockaddr types and
57 avoid a lot of casts. */
59 struct sockaddr_ll sl
;
60 struct sockaddr_in s4
;
61 struct sockaddr_in6 s6
;
62 } addr
, netmask
, broadaddr
;
63 char name
[IF_NAMESIZE
+ 1];
68 __netlink_free_handle (struct netlink_handle
*h
)
70 struct netlink_res
*ptr
;
71 int saved_errno
= errno
;
76 struct netlink_res
*tmpptr
;
83 __set_errno (saved_errno
);
88 __netlink_sendreq (struct netlink_handle
*h
, int type
)
95 struct sockaddr_nl nladdr
;
100 req
.nlh
.nlmsg_len
= sizeof (req
);
101 req
.nlh
.nlmsg_type
= type
;
102 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
;
103 req
.nlh
.nlmsg_pid
= 0;
104 req
.nlh
.nlmsg_seq
= h
->seq
;
105 req
.g
.rtgen_family
= AF_UNSPEC
;
107 memset (&nladdr
, '\0', sizeof (nladdr
));
108 nladdr
.nl_family
= AF_NETLINK
;
110 return TEMP_FAILURE_RETRY (__sendto (h
->fd
, (void *) &req
, sizeof (req
), 0,
111 (struct sockaddr
*) &nladdr
,
117 __netlink_receive (struct netlink_handle
*h
)
119 struct netlink_res
*nlm_next
;
121 struct iovec iov
= { buf
, sizeof (buf
) };
122 struct sockaddr_nl nladdr
;
123 struct nlmsghdr
*nlmh
;
131 (void *) &nladdr
, sizeof (nladdr
),
137 read_len
= TEMP_FAILURE_RETRY (__recvmsg (h
->fd
, &msg
, 0));
141 if (msg
.msg_flags
& MSG_TRUNC
)
144 nlm_next
= (struct netlink_res
*) malloc (sizeof (struct netlink_res
)
146 if (nlm_next
== NULL
)
148 nlm_next
->next
= NULL
;
149 nlm_next
->nlh
= memcpy (nlm_next
+ 1, buf
, read_len
);
150 nlm_next
->size
= read_len
;
151 nlm_next
->seq
= h
->seq
;
152 if (h
->nlm_list
== NULL
)
153 h
->nlm_list
= nlm_next
;
155 h
->end_ptr
->next
= nlm_next
;
156 h
->end_ptr
= nlm_next
;
158 for (nlmh
= (struct nlmsghdr
*) buf
;
159 NLMSG_OK (nlmh
, (size_t) read_len
);
160 nlmh
= (struct nlmsghdr
*) NLMSG_NEXT (nlmh
, read_len
))
162 if (nladdr
.nl_pid
!= 0 || (pid_t
) nlmh
->nlmsg_pid
!= h
->pid
163 || nlmh
->nlmsg_seq
!= h
->seq
)
166 if (nlmh
->nlmsg_type
== NLMSG_DONE
)
168 /* We found the end, leave the loop. */
172 if (nlmh
->nlmsg_type
== NLMSG_ERROR
)
174 struct nlmsgerr
*nlerr
= (struct nlmsgerr
*) NLMSG_DATA (nlmh
);
175 if (nlmh
->nlmsg_len
< NLMSG_LENGTH (sizeof (struct nlmsgerr
)))
178 errno
= -nlerr
->error
;
188 __netlink_close (struct netlink_handle
*h
)
190 /* Don't modify errno. */
191 INTERNAL_SYSCALL_DECL (err
);
192 (void) INTERNAL_SYSCALL (close
, err
, 1, h
->fd
);
196 /* Open a NETLINK socket. */
198 __netlink_open (struct netlink_handle
*h
)
200 struct sockaddr_nl nladdr
;
202 h
->fd
= __socket (PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
206 memset (&nladdr
, '\0', sizeof (nladdr
));
207 nladdr
.nl_family
= AF_NETLINK
;
208 if (__bind (h
->fd
, (struct sockaddr
*) &nladdr
, sizeof (nladdr
)) < 0)
213 #if __ASSUME_NETLINK_SUPPORT == 0
214 __no_netlink_support
= 1;
218 /* Determine the ID the kernel assigned for this netlink connection.
219 It is not necessarily the PID if there is more than one socket
221 socklen_t addr_len
= sizeof (nladdr
);
222 if (__getsockname (h
->fd
, (struct sockaddr
*) &nladdr
, &addr_len
) < 0)
224 h
->pid
= nladdr
.nl_pid
;
229 /* We know the number of RTM_NEWLINK entries, so we reserve the first
230 # of entries for this type. All RTM_NEWADDR entries have an index
231 pointer to the RTM_NEWLINK entry. To find the entry, create
232 a table to map kernel index entries to our index numbers.
233 Since we get at first all RTM_NEWLINK entries, it can never happen
234 that a RTM_NEWADDR index is not known to this map. */
237 map_newlink (int index
, struct ifaddrs_storage
*ifas
, int *map
, int max
)
241 for (i
= 0; i
< max
; i
++)
247 ifas
[i
- 1].ifa
.ifa_next
= &ifas
[i
].ifa
;
250 else if (map
[i
] == index
)
253 /* This should never be reached. If this will be reached, we have
254 a very big problem. */
259 /* Create a linked list of `struct ifaddrs' structures, one for each
260 network interface on the host machine. If successful, store the
261 list in *IFAP and return 0. On errors, return -1 and set `errno'. */
263 getifaddrs (struct ifaddrs
**ifap
)
265 struct netlink_handle nh
= { 0, 0, 0, NULL
, NULL
};
266 struct netlink_res
*nlp
;
267 struct ifaddrs_storage
*ifas
;
268 unsigned int i
, newlink
, newaddr
, newaddr_idx
;
269 int *map_newlink_data
;
270 size_t ifa_data_size
= 0; /* Size to allocate for all ifa_data. */
271 char *ifa_data_ptr
; /* Pointer to the unused part of memory for
278 if (! __no_netlink_support
&& __netlink_open (&nh
) < 0)
280 #if __ASSUME_NETLINK_SUPPORT != 0
285 #if __ASSUME_NETLINK_SUPPORT == 0
286 if (__no_netlink_support
)
287 return fallback_getifaddrs (ifap
);
290 /* Tell the kernel that we wish to get a list of all
291 active interfaces. */
292 if (__netlink_sendreq (&nh
, RTM_GETLINK
) < 0)
297 /* Collect all data for every interface. */
298 if (__netlink_receive (&nh
) < 0)
305 /* Now ask the kernel for all addresses which are assigned
306 to an interface. Since we store the addresses after the
307 interfaces in the list, we will later always find the
308 interface before the corresponding addresses. */
310 if (__netlink_sendreq (&nh
, RTM_GETADDR
) < 0
311 /* Collect all data for every interface. */
312 || __netlink_receive (&nh
) < 0)
318 /* Count all RTM_NEWLINK and RTM_NEWADDR entries to allocate
320 newlink
= newaddr
= 0;
321 for (nlp
= nh
.nlm_list
; nlp
; nlp
= nlp
->next
)
323 struct nlmsghdr
*nlh
;
324 size_t size
= nlp
->size
;
326 if (nlp
->nlh
== NULL
)
329 /* Walk through all entries we got from the kernel and look, which
330 message type they contain. */
331 for (nlh
= nlp
->nlh
; NLMSG_OK (nlh
, size
); nlh
= NLMSG_NEXT (nlh
, size
))
333 /* Check if the message is what we want. */
334 if ((pid_t
) nlh
->nlmsg_pid
!= nh
.pid
|| nlh
->nlmsg_seq
!= nlp
->seq
)
337 if (nlh
->nlmsg_type
== NLMSG_DONE
)
340 if (nlh
->nlmsg_type
== RTM_NEWLINK
)
342 /* A RTM_NEWLINK message can have IFLA_STATS data. We need to
343 know the size before creating the list to allocate enough
345 struct ifinfomsg
*ifim
= (struct ifinfomsg
*) NLMSG_DATA (nlh
);
346 struct rtattr
*rta
= IFLA_RTA (ifim
);
347 size_t rtasize
= IFLA_PAYLOAD (nlh
);
349 while (RTA_OK (rta
, rtasize
))
351 size_t rta_payload
= RTA_PAYLOAD (rta
);
353 if (rta
->rta_type
== IFLA_STATS
)
355 ifa_data_size
+= rta_payload
;
359 rta
= RTA_NEXT (rta
, rtasize
);
363 else if (nlh
->nlmsg_type
== RTM_NEWADDR
)
368 /* Return if no interface is up. */
369 if ((newlink
+ newaddr
) == 0)
372 /* Allocate memory for all entries we have and initialize next
374 ifas
= (struct ifaddrs_storage
*) calloc (1,
376 * sizeof (struct ifaddrs_storage
)
384 /* Table for mapping kernel index to entry in our list. */
385 map_newlink_data
= alloca (newlink
* sizeof (int));
386 memset (map_newlink_data
, '\xff', newlink
* sizeof (int));
388 ifa_data_ptr
= (char *) &ifas
[newlink
+ newaddr
];
389 newaddr_idx
= 0; /* Counter for newaddr index. */
391 /* Walk through the list of data we got from the kernel. */
392 for (nlp
= nh
.nlm_list
; nlp
; nlp
= nlp
->next
)
394 struct nlmsghdr
*nlh
;
395 size_t size
= nlp
->size
;
397 if (nlp
->nlh
== NULL
)
400 /* Walk through one message and look at the type: If it is our
401 message, we need RTM_NEWLINK/RTM_NEWADDR and stop if we reach
402 the end or we find the end marker (in this case we ignore the
404 for (nlh
= nlp
->nlh
; NLMSG_OK (nlh
, size
); nlh
= NLMSG_NEXT (nlh
, size
))
408 /* Check if the message is the one we want */
409 if ((pid_t
) nlh
->nlmsg_pid
!= nh
.pid
|| nlh
->nlmsg_seq
!= nlp
->seq
)
412 if (nlh
->nlmsg_type
== NLMSG_DONE
)
415 if (nlh
->nlmsg_type
== RTM_NEWLINK
)
417 /* We found a new interface. Now extract everything from the
418 interface data we got and need. */
419 struct ifinfomsg
*ifim
= (struct ifinfomsg
*) NLMSG_DATA (nlh
);
420 struct rtattr
*rta
= IFLA_RTA (ifim
);
421 size_t rtasize
= IFLA_PAYLOAD (nlh
);
423 /* Interfaces are stored in the first "newlink" entries
424 of our list, starting in the order as we got from the
426 ifa_index
= map_newlink (ifim
->ifi_index
- 1, ifas
,
427 map_newlink_data
, newlink
);
428 ifas
[ifa_index
].ifa
.ifa_flags
= ifim
->ifi_flags
;
430 while (RTA_OK (rta
, rtasize
))
432 char *rta_data
= RTA_DATA (rta
);
433 size_t rta_payload
= RTA_PAYLOAD (rta
);
435 switch (rta
->rta_type
)
438 if (rta_payload
<= sizeof (ifas
[ifa_index
].addr
))
440 ifas
[ifa_index
].addr
.sl
.sll_family
= AF_PACKET
;
441 memcpy (ifas
[ifa_index
].addr
.sl
.sll_addr
,
442 (char *) rta_data
, rta_payload
);
443 ifas
[ifa_index
].addr
.sl
.sll_halen
= rta_payload
;
444 ifas
[ifa_index
].addr
.sl
.sll_ifindex
446 ifas
[ifa_index
].addr
.sl
.sll_hatype
= ifim
->ifi_type
;
448 ifas
[ifa_index
].ifa
.ifa_addr
449 = &ifas
[ifa_index
].addr
.sa
;
454 if (rta_payload
<= sizeof (ifas
[ifa_index
].broadaddr
))
456 ifas
[ifa_index
].broadaddr
.sl
.sll_family
= AF_PACKET
;
457 memcpy (ifas
[ifa_index
].broadaddr
.sl
.sll_addr
,
458 (char *) rta_data
, rta_payload
);
459 ifas
[ifa_index
].broadaddr
.sl
.sll_halen
= rta_payload
;
460 ifas
[ifa_index
].broadaddr
.sl
.sll_ifindex
462 ifas
[ifa_index
].broadaddr
.sl
.sll_hatype
465 ifas
[ifa_index
].ifa
.ifa_broadaddr
466 = &ifas
[ifa_index
].broadaddr
.sa
;
470 case IFLA_IFNAME
: /* Name of Interface */
471 if ((rta_payload
+ 1) <= sizeof (ifas
[ifa_index
].name
))
473 ifas
[ifa_index
].ifa
.ifa_name
= ifas
[ifa_index
].name
;
474 *(char *) __mempcpy (ifas
[ifa_index
].name
, rta_data
,
479 case IFLA_STATS
: /* Statistics of Interface */
480 ifas
[ifa_index
].ifa
.ifa_data
= ifa_data_ptr
;
481 ifa_data_ptr
+= rta_payload
;
482 memcpy (ifas
[ifa_index
].ifa
.ifa_data
, rta_data
,
498 rta
= RTA_NEXT (rta
, rtasize
);
501 else if (nlh
->nlmsg_type
== RTM_NEWADDR
)
503 struct ifaddrmsg
*ifam
= (struct ifaddrmsg
*) NLMSG_DATA (nlh
);
504 struct rtattr
*rta
= IFA_RTA (ifam
);
505 size_t rtasize
= IFA_PAYLOAD (nlh
);
507 /* New Addresses are stored in the order we got them from
508 the kernel after the interfaces. Theoretically it is possible
509 that we have holes in the interface part of the list,
510 but we always have already the interface for this address. */
511 ifa_index
= newlink
+ newaddr_idx
;
512 ifas
[ifa_index
].ifa
.ifa_flags
513 = ifas
[map_newlink (ifam
->ifa_index
- 1, ifas
,
514 map_newlink_data
, newlink
)].ifa
.ifa_flags
;
516 ifas
[ifa_index
- 1].ifa
.ifa_next
= &ifas
[ifa_index
].ifa
;
519 while (RTA_OK (rta
, rtasize
))
521 char *rta_data
= RTA_DATA (rta
);
522 size_t rta_payload
= RTA_PAYLOAD (rta
);
524 switch (rta
->rta_type
)
530 if (ifas
[ifa_index
].ifa
.ifa_addr
!= NULL
)
532 /* In a point-to-poing network IFA_ADDRESS
533 contains the destination address, local
534 address is supplied in IFA_LOCAL attribute.
535 destination address and broadcast address
536 are stored in an union, so it doesn't matter
537 which name we use. */
538 ifas
[ifa_index
].ifa
.ifa_broadaddr
539 = &ifas
[ifa_index
].broadaddr
.sa
;
540 sa
= &ifas
[ifa_index
].broadaddr
.sa
;
544 ifas
[ifa_index
].ifa
.ifa_addr
545 = &ifas
[ifa_index
].addr
.sa
;
546 sa
= &ifas
[ifa_index
].addr
.sa
;
549 sa
->sa_family
= ifam
->ifa_family
;
551 switch (ifam
->ifa_family
)
554 /* Size must match that of an address for IPv4. */
555 if (rta_payload
== 4)
556 memcpy (&((struct sockaddr_in
*) sa
)->sin_addr
,
557 rta_data
, rta_payload
);
561 /* Size must match that of an address for IPv6. */
562 if (rta_payload
== 16)
564 memcpy (&((struct sockaddr_in6
*) sa
)->sin6_addr
,
565 rta_data
, rta_payload
);
566 if (IN6_IS_ADDR_LINKLOCAL (rta_data
)
567 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data
))
568 ((struct sockaddr_in6
*) sa
)->sin6_scope_id
574 if (rta_payload
<= sizeof (ifas
[ifa_index
].addr
))
575 memcpy (sa
->sa_data
, rta_data
, rta_payload
);
582 if (ifas
[ifa_index
].ifa
.ifa_addr
!= NULL
)
584 /* If ifa_addr is set and we get IFA_LOCAL,
585 assume we have a point-to-point network.
586 Move address to correct field. */
587 ifas
[ifa_index
].broadaddr
= ifas
[ifa_index
].addr
;
588 ifas
[ifa_index
].ifa
.ifa_broadaddr
589 = &ifas
[ifa_index
].broadaddr
.sa
;
590 memset (&ifas
[ifa_index
].addr
, '\0',
591 sizeof (ifas
[ifa_index
].addr
));
594 ifas
[ifa_index
].ifa
.ifa_addr
= &ifas
[ifa_index
].addr
.sa
;
595 ifas
[ifa_index
].ifa
.ifa_addr
->sa_family
598 switch (ifam
->ifa_family
)
601 /* Size must match that of an address for IPv4. */
602 if (rta_payload
== 4)
603 memcpy (&ifas
[ifa_index
].addr
.s4
.sin_addr
,
604 rta_data
, rta_payload
);
608 /* Size must match that of an address for IPv6. */
609 if (rta_payload
== 16)
611 memcpy (&ifas
[ifa_index
].addr
.s6
.sin6_addr
,
612 rta_data
, rta_payload
);
613 if (IN6_IS_ADDR_LINKLOCAL (rta_data
)
614 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data
))
615 ifas
[ifa_index
].addr
.s6
.sin6_scope_id
=
621 if (rta_payload
<= sizeof (ifas
[ifa_index
].addr
))
622 memcpy (ifas
[ifa_index
].addr
.sa
.sa_data
,
623 rta_data
, rta_payload
);
629 /* We get IFA_BROADCAST, so IFA_LOCAL was too much. */
630 if (ifas
[ifa_index
].ifa
.ifa_broadaddr
!= NULL
)
631 memset (&ifas
[ifa_index
].broadaddr
, '\0',
632 sizeof (ifas
[ifa_index
].broadaddr
));
634 ifas
[ifa_index
].ifa
.ifa_broadaddr
635 = &ifas
[ifa_index
].broadaddr
.sa
;
636 ifas
[ifa_index
].ifa
.ifa_broadaddr
->sa_family
639 switch (ifam
->ifa_family
)
642 /* Size must match that of an address for IPv4. */
643 if (rta_payload
== 4)
644 memcpy (&ifas
[ifa_index
].broadaddr
.s4
.sin_addr
,
645 rta_data
, rta_payload
);
649 /* Size must match that of an address for IPv6. */
650 if (rta_payload
== 16)
652 memcpy (&ifas
[ifa_index
].broadaddr
.s6
.sin6_addr
,
653 rta_data
, rta_payload
);
654 if (IN6_IS_ADDR_LINKLOCAL (rta_data
)
655 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data
))
656 ifas
[ifa_index
].broadaddr
.s6
.sin6_scope_id
662 if (rta_payload
<= sizeof (ifas
[ifa_index
].addr
))
663 memcpy (&ifas
[ifa_index
].broadaddr
.sa
.sa_data
,
664 rta_data
, rta_payload
);
670 if (rta_payload
+ 1 <= sizeof (ifas
[ifa_index
].name
))
672 ifas
[ifa_index
].ifa
.ifa_name
= ifas
[ifa_index
].name
;
673 *(char *) __mempcpy (ifas
[ifa_index
].name
, rta_data
,
688 rta
= RTA_NEXT (rta
, rtasize
);
691 /* If we didn't get the interface name with the
692 address, use the name from the interface entry. */
693 if (ifas
[ifa_index
].ifa
.ifa_name
== NULL
)
694 ifas
[ifa_index
].ifa
.ifa_name
695 = ifas
[map_newlink (ifam
->ifa_index
- 1, ifas
,
696 map_newlink_data
, newlink
)].ifa
.ifa_name
;
698 /* Calculate the netmask. */
699 if (ifas
[ifa_index
].ifa
.ifa_addr
700 && ifas
[ifa_index
].ifa
.ifa_addr
->sa_family
!= AF_UNSPEC
701 && ifas
[ifa_index
].ifa
.ifa_addr
->sa_family
!= AF_PACKET
)
703 uint32_t max_prefixlen
= 0;
706 ifas
[ifa_index
].ifa
.ifa_netmask
707 = &ifas
[ifa_index
].netmask
.sa
;
709 switch (ifas
[ifa_index
].ifa
.ifa_addr
->sa_family
)
712 cp
= (char *) &ifas
[ifa_index
].netmask
.s4
.sin_addr
;
717 cp
= (char *) &ifas
[ifa_index
].netmask
.s6
.sin6_addr
;
722 ifas
[ifa_index
].ifa
.ifa_netmask
->sa_family
723 = ifas
[ifa_index
].ifa
.ifa_addr
->sa_family
;
728 unsigned int preflen
;
730 if ((max_prefixlen
> 0) &&
731 (ifam
->ifa_prefixlen
> max_prefixlen
))
732 preflen
= max_prefixlen
;
734 preflen
= ifam
->ifa_prefixlen
;
736 for (i
= 0; i
< (preflen
/ 8); i
++)
739 c
<<= (8 - (preflen
% 8));
747 assert (ifa_data_ptr
<= (char *) &ifas
[newlink
+ newaddr
] + ifa_data_size
);
751 for (i
= 0; i
< newlink
; ++i
)
752 if (map_newlink_data
[i
] == -1)
754 /* We have fewer links then we anticipated. Adjust the
755 forward pointer to the first address entry. */
756 ifas
[i
- 1].ifa
.ifa_next
= &ifas
[newlink
].ifa
;
759 if (i
== 0 && newlink
> 0)
760 /* No valid link, but we allocated memory. We have to
761 populate the first entry. */
762 memmove (ifas
, &ifas
[newlink
], sizeof (struct ifaddrs_storage
));
766 *ifap
= &ifas
[0].ifa
;
769 __netlink_free_handle (&nh
);
772 __netlink_close (&nh
);
776 libc_hidden_def (getifaddrs
)
779 #if __ASSUME_NETLINK_SUPPORT != 0
781 freeifaddrs (struct ifaddrs
*ifa
)
785 libc_hidden_def (freeifaddrs
)