]>
sourceware.org Git - glibc.git/blob - sysdeps/unix/sysv/linux/if_index.c
1 /* Copyright (C) 1997, 1998, 1999 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 #include "kernel-features.h"
31 /* Variable to signal whether SIOCGIFCONF is not available. */
32 #if __ASSUME_SIOCGIFNAME == 0
33 static int old_siocgifconf
;
35 # define old_siocgifconf 0
38 /* Try to get a socket to talk to the kernel. */
39 #if defined SIOCGIFINDEX || defined SIOCGIFNAME
44 /* Cache the last AF that worked, to avoid many redundant calls to
46 static int sock_af
= -1;
48 __libc_lock_define_initialized (static, lock
);
52 fd
= __socket (sock_af
, SOCK_DGRAM
, 0);
57 __libc_lock_lock (lock
);
60 fd
= __socket (sock_af
, SOCK_DGRAM
, 0);
64 fd
= __socket (sock_af
= AF_INET
, SOCK_DGRAM
, 0);
66 fd
= __socket (sock_af
= AF_INET6
, SOCK_DGRAM
, 0);
68 fd
= __socket (sock_af
= AF_IPX
, SOCK_DGRAM
, 0);
70 fd
= __socket (sock_af
= AF_AX25
, SOCK_DGRAM
, 0);
72 fd
= __socket (sock_af
= AF_APPLETALK
, SOCK_DGRAM
, 0);
75 __libc_lock_unlock (lock
);
81 if_nametoindex (const char *ifname
)
93 strncpy (ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
94 if (__ioctl (fd
, SIOCGIFINDEX
, &ifr
) < 0)
96 int saved_errno
= errno
;
98 if (saved_errno
== EINVAL
)
103 return ifr
.ifr_ifindex
;
108 if_freenameindex (struct if_nameindex
*ifn
)
110 struct if_nameindex
*ptr
= ifn
;
111 while (ptr
->if_name
|| ptr
->if_index
)
120 struct if_nameindex
*
124 __set_errno (ENOSYS
);
127 int fd
= opensock ();
129 unsigned int nifs
, i
;
131 struct if_nameindex
*idx
= NULL
;
139 /* We may be able to get the needed buffer size directly, rather than
141 if (! old_siocgifconf
)
145 if (__ioctl (fd
, SIOCGIFCONF
, &ifc
) < 0 || ifc
.ifc_len
== 0)
147 # if __ASSUME_SIOCGIFNAME == 0
150 rq_len
= RQ_IFS
* sizeof (struct ifreq
);
153 rq_len
= ifc
.ifc_len
;
156 rq_len
= RQ_IFS
* sizeof (struct ifreq
);
158 /* Read all the interfaces out of the kernel. */
161 ifc
.ifc_buf
= alloca (ifc
.ifc_len
= rq_len
);
162 if (ifc
.ifc_buf
== NULL
|| __ioctl (fd
, SIOCGIFCONF
, &ifc
) < 0)
169 while (ifc
.ifc_len
== rq_len
&& old_siocgifconf
);
171 nifs
= ifc
.ifc_len
/ sizeof (struct ifreq
);
173 idx
= malloc ((nifs
+ 1) * sizeof (struct if_nameindex
));
180 for (i
= 0; i
< nifs
; ++i
)
182 struct ifreq
*ifr
= &ifc
.ifc_req
[i
];
183 idx
[i
].if_name
= __strdup (ifr
->ifr_name
);
184 if (idx
[i
].if_name
== NULL
185 || __ioctl (fd
, SIOCGIFINDEX
, ifr
) < 0)
187 int saved_errno
= errno
;
190 for (j
= 0; j
< i
; ++j
)
191 free (idx
[j
].if_name
);
194 if (saved_errno
== EINVAL
)
195 __set_errno (ENOSYS
);
198 idx
[i
].if_index
= ifr
->ifr_ifindex
;
202 idx
[i
].if_name
= NULL
;
210 if_indextoname (unsigned int ifindex
, char *ifname
)
212 #if !defined SIOCGIFINDEX && __ASSUME_SIOCGIFNAME == 0
213 __set_errno (ENOSYS
);
216 # if __ASSUME_SIOCGIFNAME == 0
217 struct if_nameindex
*idx
;
218 struct if_nameindex
*p
;
222 # if defined SIOCGIFNAME || __ASSUME_SIOCGIFNAME > 0
223 /* We may be able to do the conversion directly, rather than searching a
224 list. This ioctl is not present in kernels before version 2.1.50. */
227 # if __ASSUME_SIOCGIFNAME == 0
228 static int siocgifname_works_not
;
230 if (!siocgifname_works_not
)
233 # if __ASSUME_SIOCGIFNAME == 0
243 ifr
.ifr_ifindex
= ifindex
;
244 status
= __ioctl (fd
, SIOCGIFNAME
, &ifr
);
248 # if __ASSUME_SIOCGIFNAME == 0
252 siocgifname_works_not
= 1; /* Don't make the same mistake twice. */
255 return strncpy (ifname
, ifr
.ifr_name
, IFNAMSIZ
);
257 __set_errno (serrno
);
259 return status
< 0 ? NULL
: strncpy (ifname
, ifr
.ifr_name
, IFNAMSIZ
);
264 # if __ASSUME_SIOCGIFNAME == 0
265 idx
= if_nameindex ();
269 for (p
= idx
; p
->if_index
|| p
->if_name
; ++p
)
270 if (p
->if_index
== ifindex
)
272 result
= strncpy (ifname
, p
->if_name
, IFNAMSIZ
);
276 if_freenameindex (idx
);
286 __protocol_available (int *have_inet
, int *have_inet6
)
288 int fd
= opensock ();
294 /* Wirst case assumption. */
299 /* We cannot open the socket. No networking at all? */
302 /* We may be able to get the needed buffer size directly, rather than
304 if (! old_siocgifconf
)
308 if (__ioctl (fd
, SIOCGIFCONF
, &ifc
) < 0 || ifc
.ifc_len
== 0)
310 # if __ASSUME_SIOCGIFNAME == 0
313 rq_len
= RQ_IFS
* sizeof (struct ifreq
);
316 rq_len
= ifc
.ifc_len
;
319 rq_len
= RQ_IFS
* sizeof (struct ifreq
);
321 /* Read all the interfaces out of the kernel. */
324 ifc
.ifc_buf
= alloca (ifc
.ifc_len
= rq_len
);
325 if (ifc
.ifc_buf
== NULL
|| __ioctl (fd
, SIOCGIFCONF
, &ifc
) < 0)
332 while (ifc
.ifc_len
== rq_len
&& old_siocgifconf
);
334 nifs
= ifc
.ifc_len
/ sizeof (struct ifreq
);
336 /* Go through all the interfaces and get the address. */
338 if (__ioctl (fd
, SIOCGIFADDR
, &ifc
.ifc_req
[nifs
]) >= 0)
340 /* We successfully got information about this interface. Now
341 test whether it is an IPv4 or IPv6 address. */
342 if (ifc
.ifc_req
[nifs
].ifr_addr
.sa_family
== AF_INET
)
344 else if (ifc
.ifc_req
[nifs
].ifr_addr
.sa_family
== AF_INET6
)
347 /* Note, this is & not &&. It works since the values are always
349 if (*have_inet
& *have_inet6
)
350 /* We can stop early. */
This page took 0.053019 seconds and 5 git commands to generate.