summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/if_nameindex.c
diff options
context:
space:
mode:
authormillert <>2002-03-07 22:40:23 +0000
committermillert <>2002-03-07 22:40:23 +0000
commitac55e95265194286ad7db771d95bd73b521e92b6 (patch)
treef13fe9b86c4ef03932d1e2d666076fea9acd6350 /src/lib/libc/net/if_nameindex.c
parent409c42a31740ca9da36e066b8f180e668520958c (diff)
downloadopenbsd-ac55e95265194286ad7db771d95bd73b521e92b6.tar.gz
openbsd-ac55e95265194286ad7db771d95bd73b521e92b6.tar.bz2
openbsd-ac55e95265194286ad7db771d95bd73b521e92b6.zip
Replace SIOCGIFCONF-using NRL versions with KAME versions that use
getifaddrs(3). Fixes problems on LP64 platforms.
Diffstat (limited to 'src/lib/libc/net/if_nameindex.c')
-rw-r--r--src/lib/libc/net/if_nameindex.c233
1 files changed, 103 insertions, 130 deletions
diff --git a/src/lib/libc/net/if_nameindex.c b/src/lib/libc/net/if_nameindex.c
index 2b85fbae95..3675a2a450 100644
--- a/src/lib/libc/net/if_nameindex.c
+++ b/src/lib/libc/net/if_nameindex.c
@@ -1,26 +1,20 @@
1/* 1/* $OpenBSD: if_nameindex.c,v 1.9 2002/03/07 22:40:23 millert Exp $ */
2 * Copyright (c) 1998-1999, Craig Metz, All rights reserved. 2/* $KAME: if_nameindex.c,v 1.7 2000/11/24 08:17:20 itojun Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. All rights reserved.
3 * 7 *
4 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
6 * are met: 10 * are met:
7 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Craig Metz and
15 * by other contributors.
16 * 4. Neither the name of the author nor the names of contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 * 13 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -28,140 +22,119 @@
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE. 24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
31 */ 27 */
32 28
33#include <stdlib.h>
34#include <sys/types.h> 29#include <sys/types.h>
35#include <sys/socket.h> 30#include <sys/socket.h>
36#include <sys/ioctl.h>
37#include <net/if.h>
38#include <net/if_dl.h> 31#include <net/if_dl.h>
39#include <errno.h> 32#include <net/if.h>
40#include <unistd.h> 33#include <ifaddrs.h>
34#include <stdlib.h>
41#include <string.h> 35#include <string.h>
42 36
37/*
38 * From RFC 2553:
39 *
40 * 4.3 Return All Interface Names and Indexes
41 *
42 * The if_nameindex structure holds the information about a single
43 * interface and is defined as a result of including the <net/if.h>
44 * header.
45 *
46 * struct if_nameindex {
47 * unsigned int if_index;
48 * char *if_name;
49 * };
50 *
51 * The final function returns an array of if_nameindex structures, one
52 * structure per interface.
53 *
54 * struct if_nameindex *if_nameindex(void);
55 *
56 * The end of the array of structures is indicated by a structure with
57 * an if_index of 0 and an if_name of NULL. The function returns a NULL
58 * pointer upon an error, and would set errno to the appropriate value.
59 *
60 * The memory used for this array of structures along with the interface
61 * names pointed to by the if_name members is obtained dynamically.
62 * This memory is freed by the next function.
63 *
64 * 4.4. Free Memory
65 *
66 * The following function frees the dynamic memory that was allocated by
67 * if_nameindex().
68 *
69 * #include <net/if.h>
70 *
71 * void if_freenameindex(struct if_nameindex *ptr);
72 *
73 * The argument to this function must be a pointer that was returned by
74 * if_nameindex().
75 */
76
43struct if_nameindex * 77struct if_nameindex *
44if_nameindex(void) 78if_nameindex(void)
45{ 79{
46 int i, j, fd = -1, extra, len = 0; 80 struct ifaddrs *ifaddrs, *ifa;
47 struct if_nameindex *nameindex = NULL; 81 unsigned int ni;
48 struct ifconf ifconf; 82 size_t nbytes;
49 char lastname[IFNAMSIZ], *c, *inbuf; 83 struct if_nameindex *ifni, *ifni2;
50 struct if_nameindex *n; 84 char *cp;
51 struct sockaddr *sa;
52 void *p;
53
54 ifconf.ifc_buf = NULL;
55 85
56 if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) 86 if (getifaddrs(&ifaddrs) < 0)
57 goto ret; 87 return(NULL);
58 88
59 /* 89 /*
60 * Try ifc_len == 0 hack first, to get the actual length. 90 * First, find out how many interfaces there are, and how
61 * If that fails, revert to a loop which grows the ifc_buf 91 * much space we need for the string names.
62 * until it is sufficiently large.
63 */ 92 */
64 extra = sizeof(struct ifreq); 93 ni = 0;
65 while (1) { 94 nbytes = 0;
66 ifconf.ifc_len = len; 95 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
67 if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf) == -1 && 96 if (ifa->ifa_addr &&
68 ifconf.ifc_buf) 97 ifa->ifa_addr->sa_family == AF_LINK) {
69 goto ret; 98 nbytes += strlen(ifa->ifa_name) + 1;
70 if (ifconf.ifc_buf && 99 ni++;
71 ifconf.ifc_len + extra < len)
72 break;
73 if (ifconf.ifc_buf) {
74 if (len == 0)
75 len = 4096;
76 ifconf.ifc_len = len *= 2;
77 } else {
78 len = ifconf.ifc_len;
79 extra = 0;
80 }
81 inbuf = realloc(ifconf.ifc_buf, ifconf.ifc_len);
82 if (inbuf == NULL)
83 goto ret;
84 ifconf.ifc_buf = inbuf;
85 }
86
87 i = sizeof(struct if_nameindex);
88 j = 0;
89 p = ifconf.ifc_buf;
90 len = ifconf.ifc_len;
91 lastname[0] = 0;
92 lastname[sizeof(lastname)-1] = 0;
93
94 while (len > 0) {
95 if (len < (IFNAMSIZ + sizeof(struct sockaddr)))
96 goto ret;
97 if (strncmp(lastname, p, IFNAMSIZ)) {
98 strlcpy(lastname, p, sizeof(lastname));
99 i += sizeof(struct if_nameindex);
100 j += strlen(lastname) + 1;
101 } 100 }
102 len -= IFNAMSIZ;
103 p += IFNAMSIZ;
104 sa = p;
105
106 if (sa->sa_len < sizeof(struct sockaddr))
107 sa->sa_len = sizeof(struct sockaddr);
108
109 if (len < sa->sa_len)
110 goto ret;
111 len -= sa->sa_len;
112 p += sa->sa_len;
113 }
114
115 nameindex = malloc(i + j);
116 if (nameindex == NULL) {
117 errno = ENOMEM;
118 goto ret;
119 } 101 }
120 memset(nameindex, 0, i + j);
121 102
122 n = nameindex; 103 /*
123 p = ifconf.ifc_buf; 104 * Next, allocate a chunk of memory, use the first part
124 c = (void *) nameindex + i; 105 * for the array of structures, and the last part for
125 i = 0; 106 * the strings.
126 len = ifconf.ifc_len; 107 */
127 lastname[0] = 0; 108 cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
128 109 ifni = (struct if_nameindex *)cp;
129 while (len > 0) { 110 if (ifni == NULL)
130 if (len < IFNAMSIZ + sizeof(struct sockaddr)) 111 goto out;
131 goto ret; 112 cp += (ni + 1) * sizeof(struct if_nameindex);
132 if (strncmp(lastname, p, IFNAMSIZ)) {
133 if (i) {
134 if (!n->if_index)
135 n->if_index = i;
136 n++;
137 }
138 i++;
139 memcpy(lastname, p, sizeof(lastname));
140 strlcpy(c, lastname, sizeof(lastname));
141 n->if_name = c;
142 c += strlen(c) + 1;
143 }
144 len -= IFNAMSIZ;
145 p += IFNAMSIZ;
146 sa = p;
147 113
148 if (len < sa->sa_len) 114 /*
149 goto ret; 115 * Now just loop through the list of interfaces again,
150 if (sa->sa_family == AF_LINK) { 116 * filling in the if_nameindex array and making copies
151 struct sockaddr_dl *sd = (struct sockaddr_dl *)sa; 117 * of all the strings.
152 n->if_index = sd->sdl_index; 118 */
119 ifni2 = ifni;
120 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
121 if (ifa->ifa_addr &&
122 ifa->ifa_addr->sa_family == AF_LINK) {
123 ifni2->if_index =
124 ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
125 ifni2->if_name = cp;
126 nbytes = strlen(ifa->ifa_name) + 1;
127 memcpy(cp, ifa->ifa_name, nbytes);
128 ifni2++;
129 cp += nbytes;
153 } 130 }
154 len -= sa->sa_len;
155 p += sa->sa_len;
156 } 131 }
157 132 /*
158 if (n->if_index == 0) 133 * Finally, don't forget to terminate the array.
159 n->if_index = i; 134 */
160 135 ifni2->if_index = 0;
161ret: 136 ifni2->if_name = NULL;
162 if (fd != -1) 137out:
163 close(fd); 138 freeifaddrs(ifaddrs);
164 if (ifconf.ifc_buf) 139 return(ifni);
165 free(ifconf.ifc_buf);
166 return (nameindex);
167} 140}