summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoritojun <>2000-02-23 06:55:58 +0000
committeritojun <>2000-02-23 06:55:58 +0000
commitebd32d3382e8e38694e45f4ca5a83fed5ad68d76 (patch)
tree235e1152d86e47ae8e43f416157de66f99ec1883
parent662c66429e022b4e3dcfe1b7060ce13da066bd8b (diff)
downloadopenbsd-ebd32d3382e8e38694e45f4ca5a83fed5ad68d76.tar.gz
openbsd-ebd32d3382e8e38694e45f4ca5a83fed5ad68d76.tar.bz2
openbsd-ebd32d3382e8e38694e45f4ca5a83fed5ad68d76.zip
add getifaddrs(3), from bsdi4.
this will help future apps from complexity of SIOCGIFCONF. NOTE: getifaddrs(3) uses sysctl interface, not SIOCGIFCONF.
-rw-r--r--src/lib/libc/net/Makefile.inc10
-rw-r--r--src/lib/libc/net/getifaddrs.3161
-rw-r--r--src/lib/libc/net/getifaddrs.c373
3 files changed, 539 insertions, 5 deletions
diff --git a/src/lib/libc/net/Makefile.inc b/src/lib/libc/net/Makefile.inc
index 7174d68220..7504a3e195 100644
--- a/src/lib/libc/net/Makefile.inc
+++ b/src/lib/libc/net/Makefile.inc
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile.inc,v 1.28 2000/01/27 05:18:46 itojun Exp $ 1# $OpenBSD: Makefile.inc,v 1.29 2000/02/23 06:55:58 itojun Exp $
2 2
3# net sources 3# net sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net
@@ -6,7 +6,7 @@
6CFLAGS+=-DRESOLVSORT 6CFLAGS+=-DRESOLVSORT
7 7
8SRCS+= base64.c freeaddrinfo.c gai_strerror.c getaddrinfo.c gethostnamadr.c \ 8SRCS+= base64.c freeaddrinfo.c gai_strerror.c getaddrinfo.c gethostnamadr.c \
9 getnameinfo.c getnetbyaddr.c getnetbyname.c getnetent.c \ 9 getifaddrs.c getnameinfo.c getnetbyaddr.c getnetbyname.c getnetent.c \
10 getnetnamadr.c getproto.c getprotoent.c getprotoname.c \ 10 getnetnamadr.c getproto.c getprotoent.c getprotoname.c \
11 getservbyname.c getservbyport.c getservent.c herror.c \ 11 getservbyname.c getservbyport.c getservent.c herror.c \
12 if_indextoname.c if_nameindex.c if_nametoindex.c inet_addr.c \ 12 if_indextoname.c if_nameindex.c if_nametoindex.c inet_addr.c \
@@ -28,9 +28,9 @@ SRCS+= ip6opt.c rthdr.c vars6.c
28 28
29.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc" 29.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc"
30 30
31MAN+= byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 getnameinfo.3 \ 31MAN+= byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 getifaddrs.3 \
32 getnetent.3 getprotoent.3 getservent.3 inet.3 if_indextoname.3 \ 32 getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 inet.3 \
33 inet_net.3 iso_addr.3 link_addr.3 ns.3 ipx.3 \ 33 if_indextoname.3 inet_net.3 iso_addr.3 link_addr.3 ns.3 ipx.3 \
34 rcmd.3 rcmdsh.3 resolver.3 net_addrcmp.3 \ 34 rcmd.3 rcmdsh.3 resolver.3 net_addrcmp.3 \
35 inet6_option_space.3 inet6_rthdr_space.3 35 inet6_option_space.3 inet6_rthdr_space.3
36 36
diff --git a/src/lib/libc/net/getifaddrs.3 b/src/lib/libc/net/getifaddrs.3
new file mode 100644
index 0000000000..68c12b552a
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.3
@@ -0,0 +1,161 @@
1.\" $OpenBSD: getifaddrs.3,v 1.1 2000/02/23 06:55:58 itojun Exp $
2.\" BSDI getifaddrs.3,v 2.4 1999/03/15 20:57:20 jch Exp
3.\"
4.\" Copyright (c) 1995, 1999
5.\" Berkeley Software Design, Inc. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\"
13.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16.\" ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23.\" SUCH DAMAGE.
24.Dd "October 12, 1995"
25.Dt GETIFADDRS 3
26.Sh NAME
27.Nm getifaddrs
28.Nd get interface addresses
29.Sh SYNOPSIS
30.Fd #include <sys/types.h>
31.Fd #include <sys/socket.h>
32.Fd #include <ifaddrs.h>
33.Ft int
34.Fn getifaddrs "struct ifaddrs **ifap"
35.Sh DESCRIPTION
36The
37.Fn getifaddrs
38function stores a reference to a linked list of the network interfaces
39on the local machine in the memory referenced by
40.Fa ifap .
41The list consists of
42.Nm ifaddrs
43structures, as defined in the include file
44.Aq Pa ifaddrs.h .
45The
46.Nm ifaddrs
47structure contains at least the following entries:
48.Bd -literal
49 struct ifaddrs *ifa_next; /* Pointer to next struct */
50 char *ifa_name; /* Interface name */
51 u_int ifa_flags; /* Interface flags */
52 struct sockaddr *ifa_addr; /* Interface address */
53 struct sockaddr *ifa_netmask; /* Interface netmask */
54 struct sockaddr *ifa_broadaddr; /* Interface broadcast address */
55 struct sockaddr *ifa_dstaddr; /* P2P interface destination */
56 void *ifa_data; /* Address specific data */
57.Ed
58.Pp
59The
60.Li ifa_next
61field contains a pointer to the next structure on the list.
62This field is
63.Dv NULL
64in last structure on the list.
65.Pp
66The
67.Li ifa_name
68field contains the interface name.
69.Pp
70The
71.Li ifa_flags
72field contains the interface flags, as set by
73.Xr ifconfig 8
74utility.
75.Pp
76The
77.Li ifa_addr
78field references either the address of the interface or the link level
79address of the interface, if one exists, otherwise it is NULL.
80(The
81.Li sa_family
82field of the
83.Li ifa_addr
84field should be consulted to determine the format of the
85.Li ifa_addr
86address.)
87.Pp
88The
89.Li ifa_netmask
90field references the netmask associated with
91.Li ifa_addr ,
92if one is set, otherwise it is NULL.
93.Pp
94The
95.Li ifa_broadaddr
96field,
97which should only be referenced for non-P2P interfaces,
98references the broadcast address associated with
99.Li ifa_addr ,
100if one exists, otherwise it is NULL.
101.Pp
102The
103.Li ifa_dstaddr
104field references the destination address on a P2P interface,
105if one exists, otherwise it is NULL.
106.Pp
107The
108.Li ifa_data
109field references address family specific data. For
110.Dv AF_LINK
111addresses it contains a pointer to the
112.Fa struct if_data
113.Pq as defined in include file Aq Pa net/if.h
114which contains various interface attributes and statistics.
115For all other address families, it contains a pointer to the
116.Fa struct ifa_data
117.Pq as defined in include file Aq Pa net/if.h
118which contains per-address interface statistics.
119.Pp
120The data returned by
121.Fn getifaddrs
122is dynamically allocated and should be freed using
123.Fn free
124.Pq see Xr free 3
125when no longer needed.
126.Sh RETURN VALUES
127Upon successful completion, a value of 0 is returned.
128Otherwise, a value of -1 is returned and
129.Va errno
130is set to indicate the error.
131.Sh ERRORS
132The
133.Fn getifaddrs
134may fail and set
135.Va errno
136for any of the errors specified for the library routines
137.Xr ioctl 2 ,
138.Xr socket 2 ,
139.Xr malloc 3
140or
141.Xr sysctl 3 .
142.Sh BUGS
143If both
144.Aq Pa net/if.h
145and
146.Aq Pa ifaddrs.h
147are being included,
148.Aq Pa net/if.h
149.Em must
150be included before
151.Aq Pa ifaddrs.h .
152.Sh SEE ALSO
153.Xr ioctl 2 ,
154.Xr socket 2 ,
155.Xr sysctl 3 ,
156.Xr networking 4 ,
157.Xr ifconfig 8
158.Sh HISTORY
159The
160.Nm
161implementation first appeared in BSDI BSD/OS.
diff --git a/src/lib/libc/net/getifaddrs.c b/src/lib/libc/net/getifaddrs.c
new file mode 100644
index 0000000000..9537405667
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.c
@@ -0,0 +1,373 @@
1/* $OpenBSD: getifaddrs.c,v 1.1 2000/02/23 06:55:58 itojun Exp $ */
2
3/*
4 * Copyright (c) 1995, 1999
5 * Berkeley Software Design, Inc. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * BSDI getifaddrs.c,v 2.11 1999/03/15 20:57:20 jch Exp
26 */
27/*
28 * NOTE: SIOCGIFCONF case is not LP64 friendly. it also does not perform
29 * try-and-error for region size.
30 */
31#include <sys/types.h>
32#include <sys/ioctl.h>
33#include <sys/socket.h>
34#include <net/if.h>
35#ifdef NET_RT_IFLIST
36#include <sys/param.h>
37#include <net/route.h>
38#include <sys/sysctl.h>
39#include <net/if_dl.h>
40#endif
41
42#include <errno.h>
43#include <ifaddrs.h>
44#include <stdlib.h>
45#include <string.h>
46
47#if !defined(AF_LINK)
48#define SA_LEN(sa) sizeof(struct sockaddr)
49#endif
50
51#if !defined(SA_LEN)
52#define SA_LEN(sa) (sa)->sa_len
53#endif
54
55#define SALIGN (sizeof(long) - 1)
56#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
57
58#ifndef ALIGNBYTES
59/*
60 * On systems with a routing socket, ALIGNBYTES should match the value
61 * that the kernel uses when building the messages.
62 */
63#define ALIGNBYTES XXX
64#endif
65#ifndef ALIGN
66#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
67#endif
68
69#if _BSDI_VERSION >= 199701
70#define HAVE_IFM_DATA
71#endif
72
73#if _BSDI_VERSION >= 199802
74#define HAVE_IFAM_DATA
75#endif
76
77int
78getifaddrs(struct ifaddrs **pif)
79{
80 int icnt = 1;
81 int dcnt = 0;
82 int ncnt = 0;
83#ifdef NET_RT_IFLIST
84 int mib[6];
85 size_t needed;
86 char *buf;
87 char *next;
88 struct ifaddrs *cif = 0;
89 char *p, *p0;
90 struct rt_msghdr *rtm;
91 struct if_msghdr *ifm;
92 struct ifa_msghdr *ifam;
93 struct sockaddr_dl *dl;
94 struct sockaddr *sa;
95 struct ifaddrs *ifa, *ift;
96 u_short index = 0;
97#else /* NET_RT_IFLIST */
98 char buf[1024];
99 int m, sock;
100 struct ifconf ifc;
101 struct ifreq *ifr;
102 struct ifreq *lifr;
103#endif /* NET_RT_IFLIST */
104 int i;
105 size_t len, alen;
106 char *data;
107 char *names;
108
109#ifdef NET_RT_IFLIST
110 mib[0] = CTL_NET;
111 mib[1] = PF_ROUTE;
112 mib[2] = 0; /* protocol */
113 mib[3] = 0; /* wildcard address family */
114 mib[4] = NET_RT_IFLIST;
115 mib[5] = 0; /* no flags */
116 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
117 return (-1);
118 if ((buf = malloc(needed)) == NULL)
119 return (-1);
120 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
121 free(buf);
122 return (-1);
123 }
124
125 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
126 rtm = (struct rt_msghdr *)next;
127 if (rtm->rtm_version != RTM_VERSION)
128 continue;
129 switch (rtm->rtm_type) {
130 case RTM_IFINFO:
131 ifm = (struct if_msghdr *)rtm;
132 if (ifm->ifm_addrs & RTA_IFP) {
133 index = ifm->ifm_index;
134 ++icnt;
135 dl = (struct sockaddr_dl *)(ifm + 1);
136 dcnt += SA_RLEN((struct sockaddr *)dl) +
137 ALIGNBYTES;
138#ifdef HAVE_IFM_DATA
139 dcnt += sizeof(ifm->ifm_data);
140#endif /* HAVE_IFM_DATA */
141 ncnt += dl->sdl_nlen + 1;
142 } else
143 index = 0;
144 break;
145
146 case RTM_NEWADDR:
147 ifam = (struct ifa_msghdr *)rtm;
148 if (index && ifam->ifam_index != index)
149 abort(); /* this cannot happen */
150
151#define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
152 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
153 break;
154 p = (char *)(ifam + 1);
155 ++icnt;
156#ifdef HAVE_IFAM_DATA
157 dcnt += sizeof(ifam->ifam_data) + ALIGNBYTES;
158#endif /* HAVE_IFAM_DATA */
159 /* Scan to look for length of address */
160 alen = 0;
161 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
162 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
163 == 0)
164 continue;
165 sa = (struct sockaddr *)p;
166 len = SA_RLEN(sa);
167 if (i == RTAX_IFA) {
168 alen = len;
169 break;
170 }
171 p += len;
172 }
173 for (p = p0, i = 0; i < RTAX_MAX; i++) {
174 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
175 == 0)
176 continue;
177 sa = (struct sockaddr *)p;
178 len = SA_RLEN(sa);
179 if (i == RTAX_NETMASK && SA_LEN(sa) == 0)
180 dcnt += alen;
181 else
182 dcnt += len;
183 p += len;
184 }
185 break;
186 }
187 }
188#else /* NET_RT_IFLIST */
189 ifc.ifc_buf = buf;
190 ifc.ifc_len = sizeof(buf);
191
192 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
193 return (-1);
194 i = ioctl(sock, SIOCGIFCONF, (char *)&ifc);
195 close(sock);
196 if (i < 0)
197 return (-1);
198
199 ifr = ifc.ifc_req;
200 lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
201
202 while (ifr < lifr) {
203 struct sockaddr *sa;
204
205 sa = &ifr->ifr_addr;
206 ++icnt;
207 dcnt += SA_RLEN(sa);
208 ncnt += sizeof(ifr->ifr_name) + 1;
209
210 ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
211 }
212#endif /* NET_RT_IFLIST */
213
214 if (icnt + dcnt + ncnt == 1) {
215 *pif = NULL;
216 free(buf);
217 return (0);
218 }
219 data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
220 if (data == NULL) {
221 free(buf);
222 return(-1);
223 }
224
225 ifa = (struct ifaddrs *)data;
226 data += sizeof(struct ifaddrs) * icnt;
227 names = data + dcnt;
228
229 memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
230 ift = ifa;
231
232#ifdef NET_RT_IFLIST
233 index = 0;
234 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
235 rtm = (struct rt_msghdr *)next;
236 if (rtm->rtm_version != RTM_VERSION)
237 continue;
238 switch (rtm->rtm_type) {
239 case RTM_IFINFO:
240 ifm = (struct if_msghdr *)rtm;
241 if (ifm->ifm_addrs & RTA_IFP) {
242 index = ifm->ifm_index;
243 dl = (struct sockaddr_dl *)(ifm + 1);
244
245 cif = ift;
246 ift->ifa_name = names;
247 ift->ifa_flags = (int)ifm->ifm_flags;
248 memcpy(names, dl->sdl_data, dl->sdl_nlen);
249 names[dl->sdl_nlen] = 0;
250 names += dl->sdl_nlen + 1;
251
252 ift->ifa_addr = (struct sockaddr *)data;
253 memcpy(data, dl, SA_LEN((struct sockaddr *)dl));
254 data += SA_RLEN((struct sockaddr *)dl);
255
256#ifdef HAVE_IFM_DATA
257 /* ifm_data needs to be aligned */
258 ift->ifa_data = data = (void *)ALIGN(data);
259 memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data));
260 data += sizeof(ifm->ifm_data);
261#else /* HAVE_IFM_DATA */
262 ift->ifa_data = NULL;
263#endif /* HAVE_IFM_DATA */
264
265 ift = (ift->ifa_next = ift + 1);
266 } else
267 index = 0;
268 break;
269
270 case RTM_NEWADDR:
271 ifam = (struct ifa_msghdr *)rtm;
272 if (index && ifam->ifam_index != index)
273 abort(); /* this cannot happen */
274
275 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
276 break;
277 ift->ifa_name = cif->ifa_name;
278 ift->ifa_flags = cif->ifa_flags;
279 ift->ifa_data = NULL;
280 p = (char *)(ifam + 1);
281 /* Scan to look for length of address */
282 alen = 0;
283 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
284 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
285 == 0)
286 continue;
287 sa = (struct sockaddr *)p;
288 len = SA_RLEN(sa);
289 if (i == RTAX_IFA) {
290 alen = len;
291 break;
292 }
293 p += len;
294 }
295 for (p = p0, i = 0; i < RTAX_MAX; i++) {
296 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
297 == 0)
298 continue;
299 sa = (struct sockaddr *)p;
300 len = SA_RLEN(sa);
301 switch (i) {
302 case RTAX_IFA:
303 ift->ifa_addr = (struct sockaddr *)data;
304 memcpy(data, p, len);
305 data += len;
306 break;
307
308 case RTAX_NETMASK:
309 ift->ifa_netmask =
310 (struct sockaddr *)data;
311 if (SA_LEN(sa) == 0) {
312 memset(data, 0, alen);
313 data += alen;
314 break;
315 }
316 memcpy(data, p, len);
317 data += len;
318 break;
319
320 case RTAX_BRD:
321 ift->ifa_broadaddr =
322 (struct sockaddr *)data;
323 memcpy(data, p, len);
324 data += len;
325 break;
326 }
327 p += len;
328 }
329
330#ifdef HAVE_IFAM_DATA
331 /* ifam_data needs to be aligned */
332 ift->ifa_data = data = (void *)ALIGN(data);
333 memcpy(data, &ifam->ifam_data, sizeof(ifam->ifam_data));
334 data += sizeof(ifam->ifam_data);
335#endif /* HAVE_IFAM_DATA */
336
337 ift = (ift->ifa_next = ift + 1);
338 break;
339 }
340 }
341
342 free(buf);
343#else /* NET_RT_IFLIST */
344 ifr = ifc.ifc_req;
345 lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
346
347 while (ifr < lifr) {
348 struct sockaddr *sa;
349
350 ift->ifa_name = names;
351 names[sizeof(ifr->ifr_name)] = 0;
352 strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name));
353 while (*names++)
354 ;
355
356 ift->ifa_addr = (struct sockaddr *)data;
357 sa = &ifr->ifr_addr;
358 memcpy(data, sa, SA_LEN(sa));
359 data += SA_RLEN(sa);
360
361 ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
362 ift = (ift->ifa_next = ift + 1);
363 }
364#endif /* NET_RT_IFLIST */
365 if (--ift >= ifa) {
366 ift->ifa_next = NULL;
367 *pif = ifa;
368 } else {
369 *pif = NULL;
370 free(ifa);
371 }
372 return (0);
373}