Annotation of embedaddon/libnet/src/libnet_if_addr.c, revision 1.1.1.4
1.1 misho 1: /*
1.1.1.2 misho 2: * $Id: libnet_if_addr.c,v 1.23 2004/04/13 17:32:28 mike Exp $
1.1 misho 3: *
4: * libnet
5: * libnet_if_addr.c - interface selection code
6: *
7: * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
8: * All rights reserved.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: *
31: */
32:
1.1.1.4 ! misho 33: #include "common.h"
! 34:
1.1 misho 35: #ifdef HAVE_SYS_SOCKIO_H
36: #include <sys/sockio.h>
37: #endif
1.1.1.4 ! misho 38:
1.1 misho 39: #include "../include/ifaddrlist.h"
40:
41: #define MAX_IPADDR 512
42:
43: #if !(__WIN32__)
44:
45: /*
46: * By testing if we can retrieve the FLAGS of an iface
47: * we can know if it exists or not and if it is up.
48: */
49: int
50: libnet_check_iface(libnet_t *l)
51: {
52: struct ifreq ifr;
53: int fd, res;
54:
55: fd = socket(AF_INET, SOCK_DGRAM, 0);
56: if (fd < 0)
57: {
1.1.1.4 ! misho 58: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s() socket: %s", __func__,
1.1 misho 59: strerror(errno));
60: return (-1);
61: }
62:
63: strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) -1);
64: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
65:
66: res = ioctl(fd, SIOCGIFFLAGS, (int8_t *)&ifr);
67: if (res < 0)
68: {
1.1.1.4 ! misho 69: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s() ioctl: %s", __func__,
1.1 misho 70: strerror(errno));
71: }
72: else
73: {
74: if ((ifr.ifr_flags & IFF_UP) == 0)
75: {
1.1.1.4 ! misho 76: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): %s is down",
1.1 misho 77: __func__, l->device);
78: res = -1;
79: }
80: }
81: close(fd);
1.1.1.4 ! misho 82:
1.1 misho 83: return (res);
84: }
85:
1.1.1.4 ! misho 86: #endif
! 87:
! 88: #if defined(__OpenBSD__) || defined(__linux__)
! 89: #include <sys/types.h>
! 90: #ifdef __OpenBSD__
! 91: #include <sys/socket.h>
! 92: #endif
! 93: #include <ifaddrs.h>
! 94:
! 95: int
! 96: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev, register char *errbuf)
! 97: {
! 98: static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
! 99: struct ifaddrs *ifap, *ifa;
! 100: int i = 0;
! 101: memset (ifaddrlist, 0 , sizeof(ifaddrlist));
! 102:
! 103: if (getifaddrs(&ifap) != 0)
! 104: {
! 105: snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): getifaddrs: %s",
! 106: __func__, strerror(errno));
! 107: return 0;
! 108: }
! 109: for (ifa = ifap; ifa; ifa = ifa->ifa_next)
! 110: {
! 111: if (ifa->ifa_flags & IFF_LOOPBACK)
! 112: continue;
! 113:
! 114: if (ifa->ifa_addr->sa_family == AF_INET )
! 115: {
! 116: ifaddrlist[i].device = strdup(ifa->ifa_name);
! 117: if (ifaddrlist[i].device == NULL) {
! 118: snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): OOM", __func__);
! 119: continue;
! 120: }
! 121: ifaddrlist[i].addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
! 122: ++i;
! 123: }
! 124: }
! 125:
! 126: freeifaddrs(ifap);
! 127: *ipaddrp = ifaddrlist;
! 128: return (i);
! 129: }
! 130:
! 131:
! 132: #else
! 133: #if !(__WIN32__)
! 134:
1.1 misho 135:
136: /*
137: * Return the interface list
138: */
139:
140: #ifdef HAVE_SOCKADDR_SA_LEN
141: #define NEXTIFR(i) \
142: ((struct ifreq *)((u_char *)&i->ifr_addr + i->ifr_addr.sa_len))
143: #else
144: #define NEXTIFR(i) (i + 1)
145: #endif
146:
147: #ifndef BUFSIZE
148: #define BUFSIZE 2048
149: #endif
150:
151: #ifdef HAVE_LINUX_PROCFS
152: #define PROC_DEV_FILE "/proc/net/dev"
153: #endif
154:
155: int
1.1.1.4 ! misho 156: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev, register char *errbuf)
1.1 misho 157: {
158: register struct libnet_ifaddr_list *al;
159: struct ifreq *ifr, *lifr, *pifr, nifr;
1.1.1.2 misho 160: char device[sizeof(nifr.ifr_name)];
1.1 misho 161: static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
162:
163: char *p;
164: struct ifconf ifc;
165: struct ifreq ibuf[MAX_IPADDR];
166: register int fd, nipaddr;
167:
168: #ifdef HAVE_LINUX_PROCFS
169: FILE *fp;
170: char buf[2048];
171: #endif
172:
173: fd = socket(AF_INET, SOCK_DGRAM, 0);
174: if (fd < 0)
175: {
1.1.1.4 ! misho 176: snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): socket error: %s",
1.1 misho 177: __func__, strerror(errno));
178: return (-1);
179: }
180:
181: #ifdef HAVE_LINUX_PROCFS
1.1.1.4 ! misho 182: fp = fopen(PROC_DEV_FILE, "r");
! 183: if (!fp)
1.1 misho 184: {
185: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 186: "%s(): fopen(proc_dev_file) failed: %s", __func__,
1.1 misho 187: strerror(errno));
1.1.1.4 ! misho 188: goto bad;
1.1 misho 189: }
190: #endif
191:
192: memset(&ifc, 0, sizeof(ifc));
193: ifc.ifc_len = sizeof(ibuf);
194: ifc.ifc_buf = (caddr_t)ibuf;
195:
1.1.1.4 ! misho 196: if (ioctl(fd, SIOCGIFCONF, &ifc) < 0)
1.1 misho 197: {
198: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 199: "%s(): ioctl(SIOCGIFCONF) error: %s",
1.1 misho 200: __func__, strerror(errno));
1.1.1.4 ! misho 201: goto bad;
1.1 misho 202: }
203:
204: pifr = NULL;
205: lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
206:
207: al = ifaddrlist;
208: nipaddr = 0;
209:
210: #ifdef HAVE_LINUX_PROCFS
211: while (fgets(buf, sizeof(buf), fp))
212: {
1.1.1.4 ! misho 213: p = strchr(buf, ':');
! 214: if (!p)
1.1 misho 215: continue;
1.1.1.4 ! misho 216:
1.1 misho 217: *p = '\0';
1.1.1.4 ! misho 218: for (p = buf; *p == ' '; p++)
! 219: ;
1.1 misho 220:
221: strncpy(nifr.ifr_name, p, sizeof(nifr.ifr_name) - 1);
222: nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
223:
224: #else /* !HAVE_LINUX_PROCFS */
225:
226: for (ifr = ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr))
227: {
228: /* XXX LINUX SOLARIS ifalias */
1.1.1.4 ! misho 229: p = strchr(ifr->ifr_name, ':');
! 230: if (p)
! 231: *p = '\0';
! 232:
1.1 misho 233: if (pifr && strcmp(ifr->ifr_name, pifr->ifr_name) == 0)
234: continue;
1.1.1.4 ! misho 235:
1.1 misho 236: strncpy(nifr.ifr_name, ifr->ifr_name, sizeof(nifr.ifr_name) - 1);
237: nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
238: #endif
239:
240: /* save device name */
241: strncpy(device, nifr.ifr_name, sizeof(device) - 1);
242: device[sizeof(device) - 1] = '\0';
243:
244: if (ioctl(fd, SIOCGIFFLAGS, &nifr) < 0)
245: {
246: pifr = ifr;
247: continue;
248: }
249: if ((nifr.ifr_flags & IFF_UP) == 0)
250: {
251: pifr = ifr;
252: continue;
253: }
254:
255: if (dev == NULL && LIBNET_ISLOOPBACK(&nifr))
256: {
257: pifr = ifr;
258: continue;
259: }
260:
261: strncpy(nifr.ifr_name, device, sizeof(device) - 1);
262: nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
263: if (ioctl(fd, SIOCGIFADDR, (int8_t *)&nifr) < 0)
264: {
265: if (errno != EADDRNOTAVAIL)
266: {
267: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 268: "%s(): SIOCGIFADDR: dev=%s: %s", __func__, device,
1.1 misho 269: strerror(errno));
1.1.1.4 ! misho 270: goto bad;
1.1 misho 271: }
272: else /* device has no IP address => set to 0 */
273: {
274: al->addr = 0;
275: }
276: }
277: else
278: {
279: al->addr = ((struct sockaddr_in *)&nifr.ifr_addr)->sin_addr.s_addr;
280: }
1.1.1.2 misho 281:
282: free(al->device);
1.1 misho 283:
1.1.1.4 ! misho 284: al->device = strdup(device);
! 285: if (al->device == NULL)
1.1 misho 286: {
287: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 288: "%s(): strdup not enough memory", __func__);
! 289: goto bad;
1.1 misho 290: }
291:
292: ++al;
293: ++nipaddr;
294:
295: #ifndef HAVE_LINUX_PROCFS
296: pifr = ifr;
297: #endif
298:
299: } /* while|for */
300:
301: #ifdef HAVE_LINUX_PROCFS
302: if (ferror(fp))
303: {
304: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 305: "%s(): ferror: %s", __func__, strerror(errno));
! 306: goto bad;
1.1 misho 307: }
308: fclose(fp);
309: #endif
310:
1.1.1.4 ! misho 311: close(fd);
1.1 misho 312: *ipaddrp = ifaddrlist;
1.1.1.4 ! misho 313:
1.1 misho 314: return (nipaddr);
1.1.1.4 ! misho 315:
! 316: bad:
! 317: #ifdef HAVE_LINUX_PROCFS
! 318: if (fp)
! 319: fclose(fp);
! 320: #endif
! 321: close(fd);
! 322: return (-1);
1.1 misho 323: }
324: #else
1.1.1.4 ! misho 325: /* WIN32 support *
! 326: * TODO move win32 support into win32 specific source file */
! 327:
1.1 misho 328: /* From tcptraceroute, convert a numeric IP address to a string */
329: #define IPTOSBUFFERS 12
1.1.1.2 misho 330: static int8_t *iptos(uint32_t in)
1.1 misho 331: {
332: static int8_t output[IPTOSBUFFERS][ 3 * 4 + 3 + 1];
333: static int16_t which;
1.1.1.2 misho 334: uint8_t *p;
1.1 misho 335:
1.1.1.2 misho 336: p = (uint8_t *)∈
1.1 misho 337: which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
338: snprintf(output[which], IPTOSBUFFERS, "%d.%d.%d.%d",
339: p[0], p[1], p[2], p[3]);
340: return output[which];
341: }
342:
343: int
1.1.1.4 ! misho 344: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev_unused, register char *errbuf)
1.1 misho 345: {
1.1.1.4 ! misho 346: int nipaddr = 0;
! 347: int i = 0;
1.1 misho 348: static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
1.1.1.4 ! misho 349: pcap_if_t *devlist = NULL;
! 350: pcap_if_t *dev = NULL;
1.1 misho 351: int8_t err[PCAP_ERRBUF_SIZE];
352:
353: /* Retrieve the interfaces list */
1.1.1.4 ! misho 354: if (pcap_findalldevs(&devlist, err) == -1)
1.1 misho 355: {
356: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 357: "%s(): error in pcap_findalldevs: %s", __func__, err);
1.1 misho 358: return (-1);
359: }
360:
1.1.1.4 ! misho 361: for (dev = devlist; dev; dev = dev->next)
1.1 misho 362: {
1.1.1.4 ! misho 363: struct pcap_addr* pcapaddr;
! 364: for(pcapaddr = dev->addresses; pcapaddr; pcapaddr = pcapaddr->next) {
! 365: struct sockaddr* addr = pcapaddr->addr;
! 366: #if 0
! 367: printf("if name '%s' description '%s' loop? %d\n", dev->name, dev->description, dev->flags);
! 368: {
! 369: char p[NI_MAXHOST] = "";
! 370: int sz = sizeof(struct sockaddr_storage);
! 371: int r;
! 372: r = getnameinfo(addr, sz, p, sizeof(p), NULL,0, NI_NUMERICHOST);
! 373: printf(" addr %s\n", r ? gai_strerror(r) : p);
! 374: }
! 375: #endif
! 376:
! 377: if (dev->flags & PCAP_IF_LOOPBACK)
! 378: continue;
! 379:
! 380: /* this code ignores IPv6 addresses, a limitation of the libnet_ifaddr_list struct */
! 381:
! 382: if (addr->sa_family == AF_INET) {
! 383: ifaddrlist[i].device = strdup(dev->name);
! 384: ifaddrlist[i].addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
! 385: ++i;
! 386: ++nipaddr;
! 387: }
! 388: }
1.1 misho 389: }
390:
1.1.1.4 ! misho 391: pcap_freealldevs(devlist);
1.1.1.3 misho 392:
1.1 misho 393: *ipaddrp = ifaddrlist;
1.1.1.4 ! misho 394:
! 395: return nipaddr;
1.1 misho 396: }
397: #endif /* __WIN32__ */
398:
1.1.1.4 ! misho 399: #endif /* __OpenBSD__ */
! 400:
1.1 misho 401: int
402: libnet_select_device(libnet_t *l)
403: {
404: int c, i;
405: struct libnet_ifaddr_list *address_list, *al;
1.1.1.2 misho 406: uint32_t addr;
1.1 misho 407:
408:
409: if (l == NULL)
410: {
411: return (-1);
412: }
413:
414: if (l->device && !isdigit(l->device[0]))
415: {
416: #if !(__WIN32__)
417: if (libnet_check_iface(l) < 0)
418: {
419: /* err msg set in libnet_check_iface() */
420: return (-1);
421: }
422: #endif
423: return (1);
424: }
425:
426: /*
427: * Number of interfaces.
428: */
1.1.1.3 misho 429: c = libnet_ifaddrlist(&address_list, l->device, l->err_buf);
1.1 misho 430: if (c < 0)
431: {
432: return (-1);
433: }
434: else if (c == 0)
435: {
436: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 437: "%s(): no network interface found", __func__);
1.1 misho 438: return (-1);
439: }
440:
441: al = address_list;
442: if (l->device)
443: {
1.1.1.4 ! misho 444: addr = libnet_name2addr4(l, l->device, LIBNET_DONT_RESOLVE);
1.1 misho 445:
446: for (i = c; i; --i, ++address_list)
447: {
1.1.1.4 ! misho 448: if (
! 449: 0 == strcmp(l->device, address_list->device)
! 450: ||
! 451: address_list->addr == addr
! 452: )
1.1 misho 453: {
454: /* free the "user supplied device" - see libnet_init() */
455: free(l->device);
456: l->device = strdup(address_list->device);
457: goto good;
458: }
459: }
460: if (i <= 0)
461: {
462: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 463: "%s(): can't find interface for IP %s", __func__,
1.1 misho 464: l->device);
465: goto bad;
466: }
467: }
468: else
469: {
470: l->device = strdup(address_list->device);
471: }
472:
473: good:
474: for (i = 0; i < c; i++)
475: {
476: free(al[i].device);
1.1.1.2 misho 477: al[i].device = NULL;
1.1 misho 478: }
479: return (1);
480:
481: bad:
482: for (i = 0; i < c; i++)
483: {
484: free(al[i].device);
1.1.1.2 misho 485: al[i].device = NULL;
1.1 misho 486: }
487: return (-1);
488: }
489:
1.1.1.4 ! misho 490: /**
! 491: * Local Variables:
! 492: * indent-tabs-mode: nil
! 493: * c-file-style: "stroustrup"
! 494: * End:
! 495: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>