1
/* Copyright (C) 2002 Free Software Foundation, Inc.
2
This file is part of the GNU C Library.
3
Contributed by Bruno Haible <bruno@clisp.org>, 2002.
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
21
#include <sys/sysctl.h>
22
#include <sys/socket.h>
23
#include <net/route.h>
24
#include <net/if_dl.h>
31
typedef int (*if_fn) (void *private, unsigned int index, const char *name);
33
/* Iterate through all present interfaces.
34
Call FN once for every interface, returning immediately if FN returns
37
if_iterate (if_fn fn, void *private)
39
int request[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
45
/* Call the kernel function sysctl_iflist() in /usr/src/sys/net/rtsock.c. */
48
buf = alloca (bufsize);
49
if (__sysctl (request, 6, buf, &bufsize, NULL, 0) >= 0)
56
bufend = buf + bufsize;
57
for (p = buf; p < bufend; )
59
struct if_msghdr *msg = (struct if_msghdr *) p;
61
if (msg->ifm_version != RTM_VERSION)
64
switch (msg->ifm_type)
67
if (msg->ifm_addrs & RTA_IFP)
70
struct sockaddr_dl *sdl;
71
char namebuf[IFNAMSIZ + 1];
74
index = msg->ifm_index;
78
/* FIXME: 'struct if_msghdr' contains a 'struct if_data' which in turns
79
contains 'unsigned long' values. Their size therefore depends on
80
the running kernel (32 or 64 bits). This should be fixed in the
81
compat layer of the kernel. Meanwhile just workaround the bug here/ */
83
sdl = (struct sockaddr_dl *) (msg + 1);
85
sdl = (struct sockaddr_dl *) (p + msg->ifm_msglen - sizeof(struct sockaddr_dl) - 2);
87
namelen = sdl->sdl_nlen;
88
/* Avoid overflowing namebuf[]. */
89
if (namelen > IFNAMSIZ)
91
memcpy (namebuf, sdl->sdl_data, namelen);
92
namebuf[namelen] = '\0';
95
if (fn (private, index, namebuf))
107
p += msg->ifm_msglen;
111
/* ------------------------------------------------------------------------- */
113
struct nametoindex_locals
120
nametoindex_aux (void *private, unsigned int index, const char *name)
122
struct nametoindex_locals *l = (struct nametoindex_locals *) private;
123
if (strcmp (name, l->name) == 0)
131
/* Return the index of an interface given by name. */
133
if_nametoindex (const char *ifname)
135
struct nametoindex_locals l;
139
if_iterate (nametoindex_aux, &l);
143
libc_hidden_def (if_nametoindex)
145
/* ------------------------------------------------------------------------- */
147
struct indextoname_locals
155
indextoname_aux (void *private, unsigned int index, const char *name)
157
struct indextoname_locals *l = (struct indextoname_locals *) private;
158
if (index == l->index)
160
strncpy (l->name, name, IF_NAMESIZE);
168
/* Return the name of an interface given by name. */
170
if_indextoname (unsigned int ifindex, char *ifname)
172
struct indextoname_locals l;
177
if_iterate (indextoname_aux, &l);
180
libc_hidden_def (if_indextoname)
182
/* ------------------------------------------------------------------------- */
184
struct nameindex_locals
186
/* Resizable array of 'struct if_nameindex'. */
187
struct if_nameindex *s_array;
190
/* Resizable array of char. */
194
/* Out-of-memory indicator. */
199
add_s (struct nameindex_locals *l, unsigned int index, char *name)
201
if (l->s_len == l->s_allocated)
203
size_t new_allocated = 2 * l->s_allocated + 1;
204
struct if_nameindex *new_array =
205
(struct if_nameindex *)
206
realloc (l->s_array, new_allocated * sizeof (struct if_nameindex));
207
if (new_array == NULL)
212
l->s_array = new_array;
213
l->s_allocated = new_allocated;
215
/* Now l->s_len < l->s_allocated. */
216
l->s_array[l->s_len].if_index = index;
217
l->s_array[l->s_len].if_name = name;
221
static __inline size_t
222
add_c (struct nameindex_locals *l, const char *name)
224
size_t n = strlen (name) + 1;
225
size_t result_offset;
226
if (l->c_len + n > l->c_allocated)
228
size_t new_allocated =
229
(l->c_len + n < 2 * l->c_allocated + 1
230
? 2 * l->c_allocated + 1
232
char *new_array = (char *) realloc (l->c_array, new_allocated);
233
if (new_array == NULL)
238
l->c_array = new_array;
239
l->c_allocated = new_allocated;
241
/* Now l->c_len + n <= l->c_allocated. */
242
result_offset = l->c_len;
243
memcpy (l->c_array + l->c_len, name, n);
245
return result_offset;
249
nameindex_aux (void *private, unsigned int index, const char *name)
251
struct nameindex_locals *l = (struct nameindex_locals *) private;
253
size_t name_offset = add_c (l, name);
256
add_s (l, index, (char *) NULL + name_offset);
263
/* Return an array of 'struct if_nameindex', one for each present
265
struct if_nameindex *
268
struct nameindex_locals l;
270
l.s_array = NULL; l.s_len = 0; l.s_allocated = 0;
271
l.c_array = NULL; l.c_len = 0; l.c_allocated = 0;
273
if_iterate (nameindex_aux, &l);
276
/* Convert all offsets to real pointers. */
277
struct if_nameindex *p;
278
struct if_nameindex *p_end;
280
for (p = l.s_array, p_end = p + l.s_len; p < p_end; p++)
281
p->if_name = l.c_array + (p->if_name - (char *) NULL);
283
/* Add a terminating entry. */
290
__set_errno (ENOMEM);
295
libc_hidden_def (if_nameindex)
297
/* ------------------------------------------------------------------------- */
299
/* Free an array returned by if_nameindex(). */
301
if_freenameindex (struct if_nameindex *ifn)
306
free (ifn[0].if_name);
311
libc_hidden_def (if_freenameindex)