]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/if_index.c
1 /* Copyright (C) 1997 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. */
24 #include <sys/socket.h>
25 #include <sys/ioctl.h>
26 #include <bits/libc-lock.h>
28 /* Try to get a socket to talk to the kernel. */
29 #if defined SIOGIFINDEX || defined SIOGIFNAME
34 /* Cache the last AF that worked, to avoid many redundant calls to
36 static int sock_af
= -1;
38 __libc_lock_define_initialized (static, lock
);
42 fd
= socket (sock_af
, SOCK_DGRAM
, 0);
47 __libc_lock_lock (lock
);
50 fd
= socket (sock_af
, SOCK_DGRAM
, 0);
54 fd
= socket (sock_af
= AF_INET6
, SOCK_DGRAM
, 0);
56 fd
= socket (sock_af
= AF_INET
, SOCK_DGRAM
, 0);
58 fd
= socket (sock_af
= AF_IPX
, SOCK_DGRAM
, 0);
60 fd
= socket (sock_af
= AF_AX25
, SOCK_DGRAM
, 0);
62 fd
= socket (sock_af
= AF_APPLETALK
, SOCK_DGRAM
, 0);
65 __libc_lock_unlock (lock
);
71 if_nametoindex (const char *ifname
)
83 strncpy (ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
84 if (ioctl (fd
, SIOGIFINDEX
, &ifr
) < 0)
86 int saved_errno
= errno
;
88 if (saved_errno
== EINVAL
)
93 return ifr
.ifr_ifindex
;
98 if_freenameindex (struct if_nameindex
*ifn
)
100 struct if_nameindex
*ptr
= ifn
;
101 while (ptr
->if_name
|| ptr
->if_index
)
110 struct if_nameindex
*
114 __set_errno (ENOSYS
);
117 int fd
= opensock ();
119 unsigned int rq_ifs
= 4, nifs
, i
;
121 struct if_nameindex
*idx
= NULL
;
123 static int siocgifcount_works
= 1;
130 /* We may be able to find out how many interfaces really exist, rather
131 than guessing. This ioctl is not present in kernels before version
133 if (siocgifcount_works
)
137 if (ioctl (fd
, SIOCGIFCOUNT
, &nifs
) < 0)
141 siocgifcount_works
= 0;
142 __set_errno (serrno
);
152 /* Read all the interfaces out of the kernel. */
155 rq_len
= ifc
.ifc_len
= rq_ifs
* sizeof (struct ifreq
);
156 ifc
.ifc_buf
= alloca (ifc
.ifc_len
);
157 if ((ifc
.ifc_buf
== NULL
) || (ioctl (fd
, SIOCGIFCONF
, &ifc
) < 0))
164 while (ifc
.ifc_len
== rq_len
);
166 nifs
= ifc
.ifc_len
/ sizeof (struct ifreq
);
168 idx
= malloc ((nifs
+ 1) * sizeof (struct if_nameindex
));
175 for (i
= 0; i
< nifs
; ++i
)
177 struct ifreq
*ifr
= &ifc
.ifc_req
[i
];
178 idx
[i
].if_name
= __strdup (ifr
->ifr_name
);
179 if (idx
[i
].if_name
== NULL
180 || ioctl (fd
, SIOGIFINDEX
, ifr
) < 0)
182 int saved_errno
= errno
;
185 for (j
= 0; j
< i
; ++j
)
186 free (idx
[j
].if_name
);
189 if (saved_errno
== EINVAL
)
190 __set_errno (ENOSYS
);
193 idx
[i
].if_index
= ifr
->ifr_ifindex
;
197 idx
[i
].if_name
= NULL
;
205 if_indextoname (unsigned int ifindex
, char *ifname
)
208 __set_errno (ENOSYS
);
211 struct if_nameindex
*idx
;
212 struct if_nameindex
*p
;
216 /* We may be able to do the conversion directly, rather than searching a
217 list. This ioctl is not present in kernels before version 2.1.50. */
220 static int siogifname_works
= 1;
222 if (siogifname_works
)
231 ifr
.ifr_ifindex
= ifindex
;
232 if (ioctl (fd
, SIOGIFNAME
, &ifr
) < 0)
235 siogifname_works
= 0; /* Don't make the same mistake twice. */
240 return strncpy (ifname
, ifr
.ifr_name
, IFNAMSIZ
);
245 __set_errno (serrno
);
249 idx
= if_nameindex ();
253 for (p
= idx
; p
->if_index
|| p
->if_name
; ++p
)
254 if (p
->if_index
== ifindex
)
256 result
= strncpy (ifname
, p
->if_name
, IFNAMSIZ
);
260 if_freenameindex (idx
);