1 /* getifaddrs -- get names and addresses of all network interfaces
2 Copyright (C) 2002-2023 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, see
17 <https://www.gnu.org/licenses/>. */
21 #include <sys/socket.h>
22 #include <sys/ioctl.h>
27 #include <netinet/in.h>
31 /* Create a linked list of `struct ifaddrs' structures, one for each
32 network interface on the host machine. If successful, store the
33 list in *IFAP and return 0. On errors, return -1 and set `errno'. */
35 __getifaddrs (struct ifaddrs
**ifap
)
37 /* This implementation handles only IPv4 interfaces.
38 The various ioctls below will only work on an AF_INET socket.
39 Some different mechanism entirely must be used for IPv6. */
40 int fd
= __socket (AF_INET
, SOCK_DGRAM
, 0);
47 __ifreq (&ifreqs
, &nifs
, fd
);
48 if (ifreqs
== NULL
) /* XXX doesn't distinguish error vs none */
54 /* Now we have the list of interfaces and each one's address.
55 Put it into the expected format and fill in the remaining details. */
63 struct sockaddr addr
, netmask
, broadaddr
;
64 char name
[IF_NAMESIZE
];
69 storage
= malloc (nifs
* sizeof storage
[0]);
73 __if_freereq (ifreqs
, nifs
);
81 /* Fill in pointers to the storage we've already allocated. */
82 storage
[i
].ia
.ifa_next
= &storage
[i
+ 1].ia
;
83 storage
[i
].ia
.ifa_addr
= &storage
[i
].addr
;
85 /* Now copy the information we already have from SIOCGIFCONF. */
86 storage
[i
].ia
.ifa_name
= strncpy (storage
[i
].name
, ifr
->ifr_name
,
87 sizeof storage
[i
].name
);
88 storage
[i
].addr
= ifr
->ifr_addr
;
90 /* The SIOCGIFCONF call filled in only the name and address.
91 Now we must also ask for the other information we need. */
93 if (__ioctl (fd
, SIOCGIFFLAGS
, ifr
) < 0)
95 storage
[i
].ia
.ifa_flags
= ifr
->ifr_flags
;
97 ifr
->ifr_addr
= storage
[i
].addr
;
99 if (__ioctl (fd
, SIOCGIFNETMASK
, ifr
) < 0)
100 storage
[i
].ia
.ifa_netmask
= NULL
;
103 storage
[i
].ia
.ifa_netmask
= &storage
[i
].netmask
;
104 storage
[i
].netmask
= ifr
->ifr_netmask
;
107 if (ifr
->ifr_flags
& IFF_BROADCAST
)
109 ifr
->ifr_addr
= storage
[i
].addr
;
110 if (__ioctl (fd
, SIOCGIFBRDADDR
, ifr
) < 0)
111 storage
[i
].ia
.ifa_broadaddr
= NULL
;
113 storage
[i
].ia
.ifa_broadaddr
= &storage
[i
].broadaddr
;
114 storage
[i
].broadaddr
= ifr
->ifr_broadaddr
;
117 else if (ifr
->ifr_flags
& IFF_POINTOPOINT
)
119 ifr
->ifr_addr
= storage
[i
].addr
;
120 if (__ioctl (fd
, SIOCGIFDSTADDR
, ifr
) < 0)
121 storage
[i
].ia
.ifa_broadaddr
= NULL
;
124 storage
[i
].ia
.ifa_broadaddr
= &storage
[i
].broadaddr
;
125 storage
[i
].broadaddr
= ifr
->ifr_dstaddr
;
129 storage
[i
].ia
.ifa_broadaddr
= NULL
;
131 storage
[i
].ia
.ifa_data
= NULL
; /* Nothing here for now. */
133 ifr
= __if_nextreq (ifr
);
134 } while (++i
< nifs
);
135 if (i
< nifs
) /* Broke out early on error. */
139 __if_freereq (ifreqs
, nifs
);
143 storage
[i
- 1].ia
.ifa_next
= NULL
;
145 *ifap
= &storage
[0].ia
;
148 __if_freereq (ifreqs
, nifs
);
153 weak_alias (__getifaddrs
, getifaddrs
)
154 libc_hidden_def (__getifaddrs
)
156 libc_hidden_weak (getifaddrs
)
160 __freeifaddrs (struct ifaddrs
*ifa
)
164 weak_alias (__freeifaddrs
, freeifaddrs
)
165 libc_hidden_def (__freeifaddrs
)
166 libc_hidden_weak (freeifaddrs
)