Remove *xattr syscalls.
[glibc.git] / sysdeps / unix / sysv / linux / if_index.c
blob46f8b1ec1121d6465b8362e143f8511aa5fa8308
1 /* Copyright (C) 1997,98,99,2000,02 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 Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
19 #include <errno.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <net/if.h>
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;
34 #else
35 # define old_siocgifconf 0
36 #endif
39 unsigned int
40 if_nametoindex (const char *ifname)
42 #ifndef SIOCGIFINDEX
43 __set_errno (ENOSYS);
44 return 0;
45 #else
46 struct ifreq ifr;
47 int fd = __opensock ();
49 if (fd < 0)
50 return 0;
52 strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
53 if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0)
55 int saved_errno = errno;
56 __close (fd);
57 if (saved_errno == EINVAL)
58 __set_errno (ENOSYS);
59 return 0;
61 __close (fd);
62 return ifr.ifr_ifindex;
63 #endif
65 libc_hidden_def (if_nametoindex)
68 void
69 if_freenameindex (struct if_nameindex *ifn)
71 struct if_nameindex *ptr = ifn;
72 while (ptr->if_name || ptr->if_index)
74 if (ptr->if_name)
75 free (ptr->if_name);
76 ++ptr;
78 free (ifn);
81 struct if_nameindex *
82 if_nameindex (void)
84 #ifndef SIOCGIFINDEX
85 __set_errno (ENOSYS);
86 return NULL;
87 #else
88 int fd = __opensock ();
89 struct ifconf ifc;
90 unsigned int nifs, i;
91 int rq_len;
92 struct if_nameindex *idx = NULL;
93 # define RQ_IFS 4
95 if (fd < 0)
96 return NULL;
98 ifc.ifc_buf = NULL;
100 /* We may be able to get the needed buffer size directly, rather than
101 guessing. */
102 if (! old_siocgifconf)
104 ifc.ifc_buf = NULL;
105 ifc.ifc_len = 0;
106 if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
108 # if __ASSUME_SIOCGIFNAME == 0
109 old_siocgifconf = 1;
110 # endif
111 rq_len = RQ_IFS * sizeof (struct ifreq);
113 else
114 rq_len = ifc.ifc_len;
116 else
117 rq_len = RQ_IFS * sizeof (struct ifreq);
119 /* Read all the interfaces out of the kernel. */
122 ifc.ifc_buf = alloca (ifc.ifc_len = rq_len);
123 if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
125 __close (fd);
126 return NULL;
128 rq_len *= 2;
130 while (ifc.ifc_len == rq_len && old_siocgifconf);
132 nifs = ifc.ifc_len / sizeof (struct ifreq);
134 idx = malloc ((nifs + 1) * sizeof (struct if_nameindex));
135 if (idx == NULL)
137 __close (fd);
138 __set_errno (ENOBUFS);
139 return NULL;
142 for (i = 0; i < nifs; ++i)
144 struct ifreq *ifr = &ifc.ifc_req[i];
145 idx[i].if_name = __strdup (ifr->ifr_name);
146 if (idx[i].if_name == NULL
147 || __ioctl (fd, SIOCGIFINDEX, ifr) < 0)
149 int saved_errno = errno;
150 unsigned int j;
152 for (j = 0; j < i; ++j)
153 free (idx[j].if_name);
154 free (idx);
155 __close (fd);
156 if (saved_errno == EINVAL)
157 saved_errno = ENOSYS;
158 else if (saved_errno == ENOMEM)
159 saved_errno = ENOBUFS;
160 __set_errno (saved_errno);
161 return NULL;
163 idx[i].if_index = ifr->ifr_ifindex;
166 idx[i].if_index = 0;
167 idx[i].if_name = NULL;
169 __close (fd);
170 return idx;
171 #endif
174 char *
175 if_indextoname (unsigned int ifindex, char *ifname)
177 #if !defined SIOCGIFINDEX && __ASSUME_SIOCGIFNAME == 0
178 __set_errno (ENOSYS);
179 return NULL;
180 #else
181 # if __ASSUME_SIOCGIFNAME == 0
182 struct if_nameindex *idx;
183 struct if_nameindex *p;
184 char *result = NULL;
185 # endif
187 # if defined SIOCGIFNAME || __ASSUME_SIOCGIFNAME > 0
188 /* We may be able to do the conversion directly, rather than searching a
189 list. This ioctl is not present in kernels before version 2.1.50. */
190 struct ifreq ifr;
191 int fd;
192 # if __ASSUME_SIOCGIFNAME == 0
193 static int siocgifname_works_not;
195 if (!siocgifname_works_not)
196 # endif
198 # if __ASSUME_SIOCGIFNAME == 0
199 int serrno = errno;
200 # endif
201 int status;
203 fd = __opensock ();
205 if (fd < 0)
206 return NULL;
208 ifr.ifr_ifindex = ifindex;
209 status = __ioctl (fd, SIOCGIFNAME, &ifr);
211 __close (fd);
213 # if __ASSUME_SIOCGIFNAME == 0
214 if (status < 0)
216 if (errno == EINVAL)
217 siocgifname_works_not = 1; /* Don't make the same mistake twice. */
219 else
220 return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
222 __set_errno (serrno);
223 # else
224 return status < 0 ? NULL : strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
225 # endif
227 # endif
229 # if __ASSUME_SIOCGIFNAME == 0
230 idx = if_nameindex ();
232 if (idx != NULL)
234 for (p = idx; p->if_index || p->if_name; ++p)
235 if (p->if_index == ifindex)
237 result = strncpy (ifname, p->if_name, IFNAMSIZ);
238 break;
241 if_freenameindex (idx);
243 return result;
244 # endif
245 #endif
247 libc_hidden_def (if_indextoname)
249 #if 0
250 void
251 internal_function
252 __protocol_available (int *have_inet, int *have_inet6)
254 int fd = __opensock ();
255 unsigned int nifs;
256 int rq_len;
257 struct ifconf ifc;
258 # define RQ_IFS 4
260 /* Wirst case assumption. */
261 *have_inet = 0;
262 *have_inet6 = 0;
264 if (fd < 0)
265 /* We cannot open the socket. No networking at all? */
266 return;
268 /* We may be able to get the needed buffer size directly, rather than
269 guessing. */
270 if (! old_siocgifconf)
272 ifc.ifc_buf = NULL;
273 ifc.ifc_len = 0;
274 if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
276 # if __ASSUME_SIOCGIFNAME == 0
277 old_siocgifconf = 1;
278 # endif
279 rq_len = RQ_IFS * sizeof (struct ifreq);
281 else
282 rq_len = ifc.ifc_len;
284 else
285 rq_len = RQ_IFS * sizeof (struct ifreq);
287 /* Read all the interfaces out of the kernel. */
290 ifc.ifc_buf = alloca (ifc.ifc_len = rq_len);
291 if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
293 __close (fd);
294 return;
296 rq_len *= 2;
298 while (ifc.ifc_len == rq_len && old_siocgifconf);
300 nifs = ifc.ifc_len / sizeof (struct ifreq);
302 /* Go through all the interfaces and get the address. */
303 while (nifs-- > 0)
304 if (__ioctl (fd, SIOCGIFADDR, &ifc.ifc_req[nifs]) >= 0)
306 /* We successfully got information about this interface. Now
307 test whether it is an IPv4 or IPv6 address. */
308 if (ifc.ifc_req[nifs].ifr_addr.sa_family == AF_INET)
309 *have_inet = 1;
310 else if (ifc.ifc_req[nifs].ifr_addr.sa_family == AF_INET6)
311 *have_inet6 = 1;
313 /* Note, this is & not &&. It works since the values are always
314 0 or 1. */
315 if (*have_inet & *have_inet6)
316 /* We can stop early. */
317 break;
320 __close (fd);
322 #endif