1 /* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
25 #include <sys/socket.h>
26 #include <sys/ioctl.h>
27 #include <bits/libc-lock.h>
29 /* Try to get a socket to talk to the kernel. */
30 #if defined SIOGIFINDEX || defined SIOGIFNAME
35 /* Cache the last AF that worked, to avoid many redundant calls to
37 static int sock_af
= -1;
39 __libc_lock_define_initialized (static, lock
);
43 fd
= __socket (sock_af
, SOCK_DGRAM
, 0);
48 __libc_lock_lock (lock
);
51 fd
= __socket (sock_af
, SOCK_DGRAM
, 0);
55 fd
= __socket (sock_af
= AF_INET6
, SOCK_DGRAM
, 0);
57 fd
= __socket (sock_af
= AF_INET
, SOCK_DGRAM
, 0);
59 fd
= __socket (sock_af
= AF_IPX
, SOCK_DGRAM
, 0);
61 fd
= __socket (sock_af
= AF_AX25
, SOCK_DGRAM
, 0);
63 fd
= __socket (sock_af
= AF_APPLETALK
, SOCK_DGRAM
, 0);
66 __libc_lock_unlock (lock
);
72 if_nametoindex (const char *ifname
)
84 strncpy (ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
85 if (__ioctl (fd
, SIOGIFINDEX
, &ifr
) < 0)
87 int saved_errno
= errno
;
89 if (saved_errno
== EINVAL
)
94 return ifr
.ifr_ifindex
;
99 if_freenameindex (struct if_nameindex
*ifn
)
101 struct if_nameindex
*ptr
= ifn
;
102 while (ptr
->if_name
|| ptr
->if_index
)
111 struct if_nameindex
*
115 __set_errno (ENOSYS
);
118 int fd
= opensock ();
120 unsigned int nifs
, i
;
122 struct if_nameindex
*idx
= NULL
;
123 static int new_siocgifconf
= 1;
131 /* We may be able to get the needed buffer size directly, rather than
137 if (__ioctl (fd
, SIOCGIFCONF
, &ifc
) < 0 || ifc
.ifc_len
== 0)
140 rq_len
= RQ_IFS
* sizeof (struct ifreq
);
143 rq_len
= ifc
.ifc_len
;
146 rq_len
= RQ_IFS
* sizeof (struct ifreq
);
148 /* Read all the interfaces out of the kernel. */
151 ifc
.ifc_buf
= alloca (ifc
.ifc_len
= rq_len
);
152 if (ifc
.ifc_buf
== NULL
|| __ioctl (fd
, SIOCGIFCONF
, &ifc
) < 0)
159 while (ifc
.ifc_len
== rq_len
&& new_siocgifconf
== 0);
161 nifs
= ifc
.ifc_len
/ sizeof (struct ifreq
);
163 idx
= malloc ((nifs
+ 1) * sizeof (struct if_nameindex
));
170 for (i
= 0; i
< nifs
; ++i
)
172 struct ifreq
*ifr
= &ifc
.ifc_req
[i
];
173 idx
[i
].if_name
= __strdup (ifr
->ifr_name
);
174 if (idx
[i
].if_name
== NULL
175 || __ioctl (fd
, SIOGIFINDEX
, ifr
) < 0)
177 int saved_errno
= errno
;
180 for (j
= 0; j
< i
; ++j
)
181 free (idx
[j
].if_name
);
184 if (saved_errno
== EINVAL
)
185 __set_errno (ENOSYS
);
188 idx
[i
].if_index
= ifr
->ifr_ifindex
;
192 idx
[i
].if_name
= NULL
;
200 if_indextoname (unsigned int ifindex
, char *ifname
)
203 __set_errno (ENOSYS
);
206 struct if_nameindex
*idx
;
207 struct if_nameindex
*p
;
211 /* We may be able to do the conversion directly, rather than searching a
212 list. This ioctl is not present in kernels before version 2.1.50. */
215 static int siogifname_works
= 1;
217 if (siogifname_works
)
226 ifr
.ifr_ifindex
= ifindex
;
227 if (__ioctl (fd
, SIOGIFNAME
, &ifr
) < 0)
230 siogifname_works
= 0; /* Don't make the same mistake twice. */
235 return strncpy (ifname
, ifr
.ifr_name
, IFNAMSIZ
);
240 __set_errno (serrno
);
244 idx
= if_nameindex ();
248 for (p
= idx
; p
->if_index
|| p
->if_name
; ++p
)
249 if (p
->if_index
== ifindex
)
251 result
= strncpy (ifname
, p
->if_name
, IFNAMSIZ
);
255 if_freenameindex (idx
);