1 //==========================================================================
5 //==========================================================================
6 //####BSDCOPYRIGHTBEGIN####
8 // -------------------------------------------
10 // Portions of this software may have been derived from OpenBSD,
11 // FreeBSD or other sources, and are covered by the appropriate
12 // copyright disclaimers included herein.
14 // Portions created by Red Hat are
15 // Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
17 // -------------------------------------------
19 //####BSDCOPYRIGHTEND####
20 //==========================================================================
23 // Adapted from KAME getifaddrs.c, if_nametoindex.c, if_indextoname.c
26 /* $KAME: getifaddrs.c,v 1.9 2001/08/20 02:31:20 itojun Exp $ */
27 /* $KAME: if_nametoindex.c,v 1.6 2000/11/24 08:18:54 itojun Exp $ */
28 /* $KAME: if_indextoname.c,v 1.7 2000/11/08 03:09:30 itojun Exp $ */
31 * Copyright (c) 1995, 1999
32 * Berkeley Software Design, Inc. All rights reserved.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
40 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
55 #include <cyg/infra/diag.h>
63 #include <sys/param.h>
64 #include <sys/types.h>
65 #include <sys/ioctl.h>
66 #include <sys/socket.h>
68 #include <net/if_dl.h>
69 #ifndef CYGPKG_NET_OPENBSD_STACK
70 #include <net/if_var.h>
73 #include <netinet/in.h>
74 #include <net/netdb.h>
76 #include <netinet/in_var.h>
80 #define SA_LEN(sa) sizeof(struct sockaddr)
84 #define SA_LEN(sa) (sa)->sa_len
87 #define SALIGN (sizeof(long) - 1)
88 #define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
92 * On systems with a routing socket, ALIGNBYTES should match the value
93 * that the kernel uses when building the messages.
95 #define ALIGNBYTES XXX
98 #define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
102 getifaddrs(struct ifaddrs **pif)
104 int icnt = 1; // Interface count
105 int dcnt = 0; // Data [length] count
106 int ncnt = 0; // Length of interface names
108 #define IF_WORK_SPACE_SZ 1024
110 #ifdef CYGPKG_NET_INET6
112 struct in6_ifreq ifrq6;
115 struct ifreq *ifr, *lifr;
118 struct ifaddrs *ifa, *ift;
120 buf = malloc(IF_WORK_SPACE_SZ);
124 ifc.ifc_len = IF_WORK_SPACE_SZ;
126 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
131 i = ioctl(sock, SIOCGIFCONF, (char *)&ifc);
140 lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
147 dcnt += SA_RLEN(sa) * 3; /* addr, mask, brdcst */
148 ncnt += sizeof(ifr->ifr_name) + 1;
150 if (SA_LEN(sa) < sizeof(*sa))
151 ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa));
153 ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
156 if (icnt + dcnt + ncnt == 1) {
163 data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
170 ifa = (struct ifaddrs *)(void *)data;
171 data += sizeof(struct ifaddrs) * icnt;
174 memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
179 #ifdef CYGPKG_NET_INET6
180 if ((sock6 = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
189 struct sockaddr * sa;
191 ift->ifa_name = names;
192 names[sizeof(ifr->ifr_name)] = 0;
193 strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name));
196 ift->ifa_addr = (struct sockaddr *)data;
198 memcpy(data, sa, SA_LEN(sa));
201 if ((sa->sa_family == AF_INET) || (sa->sa_family == AF_INET6)) {
202 struct sockaddr *sa_netmask = NULL;
203 struct sockaddr *sa_broadcast = NULL;
204 struct sockaddr *sa_dst = NULL;
206 memset(&ifrq,0,sizeof(ifrq));
207 strcpy(ifrq.ifr_name,ifr->ifr_name);
208 ioctl( sock, SIOCGIFFLAGS, &ifrq );
210 ift->ifa_flags = ifrq.ifr_flags;
212 memcpy(&ifrq.ifr_addr, ift->ifa_addr,sizeof(struct sockaddr));
213 if (sa->sa_family == AF_INET) {
214 ioctl(sock, SIOCGIFNETMASK, &ifrq);
215 sa_netmask = &ifrq.ifr_addr;
217 #ifdef CYGPKG_NET_INET6
218 if (sa->sa_family == AF_INET6) {
219 memset(&ifrq6,0,sizeof(ifrq));
220 strcpy(ifrq6.ifr_name,ifr->ifr_name);
221 memcpy(&ifrq6.ifr_addr, ift->ifa_addr,sizeof(struct sockaddr));
223 ioctl(sock6, SIOCGIFNETMASK_IN6, &ifrq6);
224 sa_netmask = (struct sockaddr *)&ifrq6.ifr_addr;
227 ift->ifa_netmask = (struct sockaddr *)data;
228 memcpy(data, sa_netmask, SA_LEN(sa_netmask));
229 data += SA_RLEN(sa_netmask);
231 memcpy(&ifrq.ifr_addr, ift->ifa_addr,sizeof(struct sockaddr));
232 if ((sa->sa_family == AF_INET) && (ift->ifa_flags & IFF_BROADCAST)) {
233 if (ioctl(sock, SIOCGIFBRDADDR, &ifrq) == 0) {
234 sa_broadcast = &ifrq.ifr_addr;
235 ift->ifa_broadaddr = (struct sockaddr *)data;
236 memcpy(data, sa_broadcast, SA_LEN(sa_broadcast));
237 data += SA_RLEN(sa_broadcast);
241 memcpy(&ifrq.ifr_addr, ift->ifa_addr,sizeof(struct sockaddr));
242 if ((sa->sa_family == AF_INET) &&
243 (ift->ifa_flags & IFF_POINTOPOINT)) {
244 if (ioctl(sock, SIOCGIFDSTADDR, &ifrq) == 0) {
245 sa_dst = &ifrq.ifr_addr;
246 ift->ifa_dstaddr = (struct sockaddr *)data;
247 memcpy(data, sa_dst, SA_LEN(sa_dst));
248 data += SA_RLEN(sa_dst);
253 if (SA_LEN(sa) < sizeof(*sa))
254 ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa));
256 ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
257 ift = (ift->ifa_next = ift + 1);
262 ift->ifa_next = NULL;
268 #ifdef CYGPKG_NET_INET6
276 freeifaddrs(struct ifaddrs *ifp)
282 _show_all_interfaces(void)
284 struct ifaddrs *iflist, *ifp;
288 if (getifaddrs(&iflist) < 0) {
289 diag_printf("Can't get interface information!!\n");
293 while (ifp != (struct ifaddrs *)NULL) {
294 if (ifp->ifa_addr->sa_family != AF_LINK) {
295 getnameinfo (ifp->ifa_addr, ifp->ifa_addr->sa_len, addr,
296 sizeof(addr), 0, 0, NI_NUMERICHOST);
297 diag_printf("%p - %s - %s\n", ifp, ifp->ifa_name, addr);
301 indx = if_nametoindex(iflist->ifa_name);
302 diag_printf("indx(%s) = %d\n", iflist->ifa_name, indx);
304 if (if_indextoname(indx, addr)) {
305 diag_printf("index(%s) = %d/%s\n", iflist->ifa_name, indx, addr);
307 diag_printf("index(%s) = %d: %s\n", iflist->ifa_name, indx, strerror(errno));
310 diag_printf("index(%s): %s\n", iflist->ifa_name, strerror(errno));
321 * The first function maps an interface name into its corresponding
324 * #include <net/if.h>
326 * unsigned int if_nametoindex(const char *ifname);
328 * If the specified interface name does not exist, the return value is
329 * 0, and errno is set to ENXIO. If there was a system error (such as
330 * running out of memory), the return value is 0 and errno is set to the
331 * proper value (e.g., ENOMEM).
335 if_nametoindex(const char *ifname)
337 struct ifaddrs *ifaddrs, *ifa;
340 if (getifaddrs(&ifaddrs) < 0)
345 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
347 ifa->ifa_addr->sa_family == AF_LINK &&
348 strcmp(ifa->ifa_name, ifname) == 0) {
349 ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
354 freeifaddrs(ifaddrs);
363 * The second function maps an interface index into its corresponding
366 * #include <net/if.h>
368 * char *if_indextoname(unsigned int ifindex, char *ifname);
370 * The ifname argument must point to a buffer of at least IF_NAMESIZE
371 * bytes into which the interface name corresponding to the specified
372 * index is returned. (IF_NAMESIZE is also defined in <net/if.h> and
373 * its value includes a terminating null byte at the end of the
374 * interface name.) This pointer is also the return value of the
375 * function. If there is no interface corresponding to the specified
376 * index, NULL is returned, and errno is set to ENXIO, if there was a
377 * system error (such as running out of memory), if_indextoname returns
378 * NULL and errno would be set to the proper value (e.g., ENOMEM).
382 if_indextoname(unsigned int ifindex, char *ifname)
384 struct ifaddrs *ifaddrs, *ifa;
387 if (getifaddrs(&ifaddrs) < 0)
388 return(NULL); /* getifaddrs properly set errno */
390 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
392 ifa->ifa_addr->sa_family == AF_LINK &&
393 ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
402 strncpy(ifname, ifa->ifa_name, IFNAMSIZ);
404 freeifaddrs(ifaddrs);