2 * $Id: libnet_if_addr.c,v 1.1.1.1 2000/05/25 00:28:49 route Exp $
5 * libnet_if_addr.c - interface selection code
7 * Copyright (c) 1998 - 2001 Mike D. Schiffman <mike@infonexus.com>
8 * Originally pulled from traceroute sources.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include "../include/config.h"
37 #include "../include/libnet.h"
38 #ifdef HAVE_SYS_SOCKIO_H
39 #include <sys/sockio.h>
45 * Return the interface list
49 libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp,
50 register char *errbuf)
52 register int fd, nipaddr;
53 #ifdef HAVE_SOCKADDR_SA_LEN
56 register struct ifreq *ifrp, *ifend, *ifnext, *mp;
57 register struct sockaddr_in *sin;
58 register struct libnet_ifaddr_list *al;
60 struct ifreq ibuf[MAX_IPADDR], ifr;
61 char device[sizeof(ifr.ifr_name) + 1];
62 static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
64 fd = socket(AF_INET, SOCK_DGRAM, 0);
67 sprintf(errbuf, "socket: %s", strerror(errno));
70 ifc.ifc_len = sizeof(ibuf);
71 ifc.ifc_buf = (caddr_t)ibuf;
75 (char *)&ifc) < 0 || ifc.ifc_len < sizeof(struct ifreq))
77 sprintf(errbuf, "SIOCGIFCONF: %s", strerror(errno));
82 ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
87 for (; ifrp < ifend; ifrp = ifnext)
89 #ifdef HAVE_SOCKADDR_SA_LEN
90 n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
91 if (n < sizeof(*ifrp))
97 ifnext = (struct ifreq *)((char *)ifrp + n);
99 if (ifrp->ifr_addr.sa_family != AF_INET) continue;
104 * Need a template to preserve address info that is
105 * used below to locate the next entry. (Otherwise,
106 * SIOCGIFFLAGS stomps over it because the requests
107 * are returned in a union.)
109 strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
110 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0)
112 if (errno == ENXIO) continue;
114 "SIOCGIFFLAGS: %.*s: %s",
115 (int)sizeof(ifr.ifr_name),
122 /* Must be up and not the loopback */
123 if ((ifr.ifr_flags & IFF_UP) == 0 || LIBNET_ISLOOPBACK(&ifr))
128 strncpy(device, ifr.ifr_name, sizeof(ifr.ifr_name));
129 device[sizeof(device) - 1] = '\0';
130 if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0)
132 sprintf(errbuf, "SIOCGIFADDR: %s: %s", device, strerror(errno));
137 sin = (struct sockaddr_in *)&ifr.ifr_addr;
138 al->addr = sin->sin_addr.s_addr;
140 * Replaced savestr() with strdup(). -- MDS
142 al->device = strdup(device);
148 *ipaddrp = ifaddrlist;
151 #endif /* !__solaris__ */
154 libnet_select_device(struct sockaddr_in *sin, char **device, char *errbuf)
157 char err_buf[BUFSIZ];
158 struct libnet_ifaddr_list *address_list;
162 * XXX - this is temporary and needs to be better documented.
168 * Number of interfaces.
170 c = libnet_ifaddrlist(&address_list, err_buf);
173 sprintf(errbuf, "ifaddrlist : %s\n", err_buf);
178 sprintf(errbuf, "No network interfaces found.\n");
183 for (i = c; i; --i, ++address_list)
185 if (!(strncmp(*device, address_list->device, strlen(address_list->device))))
192 sprintf(errbuf, "Can't find interface %s\n", *device);
196 sin->sin_family = AF_INET;
197 sin->sin_addr.s_addr = address_list->addr;
200 * Do we need to assign a name to device?
208 "Multiple interfaces found, using %s @ %s.\n",
209 libnet_host_lookup(sin->sin_addr.s_addr, 0),
210 address_list->device);
213 *device = address_list->device;
217 #endif /* __solaris__ */