1/* Find network interface names and index numbers. Hurd version.
2 Copyright (C) 2000-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
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.
9
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.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <error.h>
20#include <net/if.h>
21#include <string.h>
22#include <sys/ioctl.h>
23#include <unistd.h>
24
25#include <hurd.h>
26#include <hurd/ioctl.h>
27#include <hurd/pfinet.h>
28
29/* Return the interface index corresponding to interface IFNAME.
30 On error, return 0. */
31unsigned int
32__if_nametoindex (const char *ifname)
33{
34 struct ifreq ifr;
35 int fd = __socket (AF_INET, SOCK_DGRAM, 0);
36
37 if (fd < 0)
38 return 0;
39
40 if (strlen (ifname) >= IFNAMSIZ)
41 {
42 __set_errno (ENODEV);
43 return 0;
44 }
45
46 strncpy (ifr.ifr_name, ifname, IFNAMSIZ);
47 if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0)
48 {
49 int saved_errno = errno;
50 __close (fd);
51 if (saved_errno == EINVAL || saved_errno == ENOTTY)
52 __set_errno (ENOSYS);
53 return 0;
54 }
55 __close (fd);
56 return ifr.ifr_ifindex;
57}
58libc_hidden_def (__if_nametoindex)
59weak_alias (__if_nametoindex, if_nametoindex)
60libc_hidden_weak (if_nametoindex)
61
62/* Free the structure IFN returned by if_nameindex. */
63void
64__if_freenameindex (struct if_nameindex *ifn)
65{
66 struct if_nameindex *ptr = ifn;
67 while (ptr->if_name || ptr->if_index)
68 {
69 free (ptr->if_name);
70 ++ptr;
71 }
72 free (ifn);
73}
74libc_hidden_def (__if_freenameindex)
75weak_alias (__if_freenameindex, if_freenameindex)
76libc_hidden_weak (if_freenameindex)
77
78/* Return an array of if_nameindex structures, one for each network
79 interface present, plus one indicating the end of the array. On
80 error, return NULL. */
81struct if_nameindex *
82__if_nameindex (void)
83{
84 error_t err = 0;
85 char data[2048];
86 file_t server;
87 int fd = __socket (AF_INET, SOCK_DGRAM, 0);
88 struct ifconf ifc;
89 unsigned int nifs, i;
90 struct if_nameindex *idx = NULL;
91
92 ifc.ifc_buf = data;
93
94 if (fd < 0)
95 return NULL;
96
97 server = _hurd_socket_server (PF_INET, 0);
98 if (server == MACH_PORT_NULL)
99 nifs = 0;
100 else
101 {
102 size_t len = sizeof data;
103 err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len);
104 if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED)
105 {
106 /* On the first use of the socket server during the operation,
107 allow for the old server port dying. */
108 server = _hurd_socket_server (PF_INET, 1);
109 if (server == MACH_PORT_NULL)
110 goto out;
111 err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len);
112 }
113 if (err)
114 goto out;
115
116 ifc.ifc_len = len;
117 nifs = len / sizeof (struct ifreq);
118 }
119
120 idx = malloc ((nifs + 1) * sizeof (struct if_nameindex));
121 if (idx == NULL)
122 {
123 err = ENOBUFS;
124 goto out;
125 }
126
127 for (i = 0; i < nifs; ++i)
128 {
129 struct ifreq *ifr = &ifc.ifc_req[i];
130 idx[i].if_name = __strdup (ifr->ifr_name);
131 if (idx[i].if_name == NULL
132 || __ioctl (fd, SIOCGIFINDEX, ifr) < 0)
133 {
134 unsigned int j;
135 err = errno;
136
137 for (j = 0; j < i; ++j)
138 free (idx[j].if_name);
139 free (idx);
140 idx = NULL;
141
142 if (err == EINVAL)
143 err = ENOSYS;
144 else if (err == ENOMEM)
145 err = ENOBUFS;
146 goto out;
147 }
148 idx[i].if_index = ifr->ifr_ifindex;
149 }
150
151 idx[i].if_index = 0;
152 idx[i].if_name = NULL;
153
154 out:
155 __close (fd);
156 if (data != ifc.ifc_buf)
157 __vm_deallocate (__mach_task_self (), (vm_address_t) ifc.ifc_buf,
158 ifc.ifc_len);
159 __set_errno (err);
160 return idx;
161}
162weak_alias (__if_nameindex, if_nameindex)
163libc_hidden_weak (if_nameindex)
164
165/* Store the name of the interface corresponding to index IFINDEX in
166 IFNAME (which has space for at least IFNAMSIZ characters). Return
167 IFNAME, or NULL on error. */
168char *
169__if_indextoname (unsigned int ifindex, char ifname[IF_NAMESIZE])
170{
171 struct ifreq ifr;
172 int fd = __socket (AF_INET, SOCK_DGRAM, 0);
173
174 if (fd < 0)
175 return NULL;
176
177 ifr.ifr_ifindex = ifindex;
178 if (__ioctl (fd, SIOCGIFNAME, &ifr) < 0)
179 {
180 int saved_errno = errno;
181 __close (fd);
182 if (saved_errno == EINVAL || saved_errno == ENOTTY)
183 __set_errno (ENOSYS);
184 else if (saved_errno == ENODEV)
185 __set_errno (ENXIO);
186 return NULL;
187 }
188 __close (fd);
189 return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
190}
191weak_alias (__if_indextoname, if_indextoname)
192libc_hidden_weak (if_indextoname)
193
194#if 0
195void
196__protocol_available (int *have_inet, int *have_inet6)
197{
198 *have_inet = _hurd_socket_server (PF_INET, 0) != MACH_PORT_NULL;
199 *have_inet6 = _hurd_socket_server (PF_INET6, 0) != MACH_PORT_NULL;
200}
201#endif
202

source code of glibc/sysdeps/mach/hurd/if_index.c