Annotation of embedaddon/libnet/src/libnet_if_addr.c, revision 1.1.1.2
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:
33: #if (HAVE_CONFIG_H)
34: #include "../include/config.h"
35: #endif
36: #if (!(_WIN32) || (__CYGWIN__))
37: #include "../include/libnet.h"
38: #else
39: #include "../include/win32/libnet.h"
40: #endif
41: #ifdef HAVE_SYS_SOCKIO_H
42: #include <sys/sockio.h>
43: #endif
44: #include "../include/ifaddrlist.h"
45:
46: #define MAX_IPADDR 512
47:
48: #if !(__WIN32__)
49:
50: /*
51: * By testing if we can retrieve the FLAGS of an iface
52: * we can know if it exists or not and if it is up.
53: */
54: int
55: libnet_check_iface(libnet_t *l)
56: {
57: struct ifreq ifr;
58: int fd, res;
59:
60: fd = socket(AF_INET, SOCK_DGRAM, 0);
61: if (fd < 0)
62: {
63: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s() socket: %s\n", __func__,
64: strerror(errno));
65: return (-1);
66: }
67:
68: strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) -1);
69: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
70:
71: res = ioctl(fd, SIOCGIFFLAGS, (int8_t *)&ifr);
72:
73: if (res < 0)
74: {
75: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s() ioctl: %s\n", __func__,
76: strerror(errno));
77: }
78: else
79: {
80: if ((ifr.ifr_flags & IFF_UP) == 0)
81: {
82: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): %s is down\n",
83: __func__, l->device);
84: res = -1;
85: }
86: }
87: close(fd);
88: return (res);
89: }
90:
91:
92: /*
93: * Return the interface list
94: */
95:
96: #ifdef HAVE_SOCKADDR_SA_LEN
97: #define NEXTIFR(i) \
98: ((struct ifreq *)((u_char *)&i->ifr_addr + i->ifr_addr.sa_len))
99: #else
100: #define NEXTIFR(i) (i + 1)
101: #endif
102:
103: #ifndef BUFSIZE
104: #define BUFSIZE 2048
105: #endif
106:
107: #ifdef HAVE_LINUX_PROCFS
108: #define PROC_DEV_FILE "/proc/net/dev"
109: #endif
110:
111: int
1.1.1.2 ! misho 112: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev,
! 113: register char *errbuf)
1.1 misho 114: {
115: register struct libnet_ifaddr_list *al;
116: struct ifreq *ifr, *lifr, *pifr, nifr;
1.1.1.2 ! misho 117: char device[sizeof(nifr.ifr_name)];
1.1 misho 118: static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
119:
120: char *p;
121: struct ifconf ifc;
122: struct ifreq ibuf[MAX_IPADDR];
123: register int fd, nipaddr;
124:
125: #ifdef HAVE_LINUX_PROCFS
126: FILE *fp;
127: char buf[2048];
128: #endif
129:
130: fd = socket(AF_INET, SOCK_DGRAM, 0);
131: if (fd < 0)
132: {
133: snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): socket error: %s\n",
134: __func__, strerror(errno));
135: return (-1);
136: }
137:
138: #ifdef HAVE_LINUX_PROCFS
139: if ((fp = fopen(PROC_DEV_FILE, "r")) == NULL)
140: {
141: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
142: "%s(): fopen(proc_dev_file) failed: %s\n", __func__,
143: strerror(errno));
144: return (-1);
145: }
146: #endif
147:
148: memset(&ifc, 0, sizeof(ifc));
149: ifc.ifc_len = sizeof(ibuf);
150: ifc.ifc_buf = (caddr_t)ibuf;
151:
152: if(ioctl(fd, SIOCGIFCONF, &ifc) < 0)
153: {
154: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
155: "%s(): ioctl(SIOCGIFCONF) error: %s\n",
156: __func__, strerror(errno));
1.1.1.2 ! misho 157: #ifdef HAVE_LINUX_PROCFS
! 158: fclose(fp);
! 159: #endif
1.1 misho 160: return(-1);
161: }
162:
163: pifr = NULL;
164: lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
165:
166: al = ifaddrlist;
167: nipaddr = 0;
168:
169: #ifdef HAVE_LINUX_PROCFS
170: while (fgets(buf, sizeof(buf), fp))
171: {
172: if ((p = strchr(buf, ':')) == NULL)
173: {
174: continue;
175: }
176: *p = '\0';
177: for(p = buf; *p == ' '; p++) ;
178:
179: strncpy(nifr.ifr_name, p, sizeof(nifr.ifr_name) - 1);
180: nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
181:
182: #else /* !HAVE_LINUX_PROCFS */
183:
184: for (ifr = ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr))
185: {
186: /* XXX LINUX SOLARIS ifalias */
187: if((p = strchr(ifr->ifr_name, ':')))
188: {
189: *p='\0';
190: }
191: if (pifr && strcmp(ifr->ifr_name, pifr->ifr_name) == 0)
192: {
193: continue;
194: }
195: strncpy(nifr.ifr_name, ifr->ifr_name, sizeof(nifr.ifr_name) - 1);
196: nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
197: #endif
198:
199: /* save device name */
200: strncpy(device, nifr.ifr_name, sizeof(device) - 1);
201: device[sizeof(device) - 1] = '\0';
202:
203: if (ioctl(fd, SIOCGIFFLAGS, &nifr) < 0)
204: {
205: pifr = ifr;
206: continue;
207: }
208: if ((nifr.ifr_flags & IFF_UP) == 0)
209: {
210: pifr = ifr;
211: continue;
212: }
213:
214: if (dev == NULL && LIBNET_ISLOOPBACK(&nifr))
215: {
216: pifr = ifr;
217: continue;
218: }
219:
220: strncpy(nifr.ifr_name, device, sizeof(device) - 1);
221: nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
222: if (ioctl(fd, SIOCGIFADDR, (int8_t *)&nifr) < 0)
223: {
224: if (errno != EADDRNOTAVAIL)
225: {
226: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
227: "%s(): SIOCGIFADDR: dev=%s: %s\n", __func__, device,
228: strerror(errno));
229: close(fd);
1.1.1.2 ! misho 230: #ifdef HAVE_LINUX_PROCFS
! 231: fclose(fp);
! 232: #endif
1.1 misho 233: return (-1);
234: }
235: else /* device has no IP address => set to 0 */
236: {
237: al->addr = 0;
238: }
239: }
240: else
241: {
242: al->addr = ((struct sockaddr_in *)&nifr.ifr_addr)->sin_addr.s_addr;
243: }
1.1.1.2 ! misho 244:
! 245: free(al->device);
! 246: al->device = NULL;
1.1 misho 247:
248: if ((al->device = strdup(device)) == NULL)
249: {
250: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
251: "%s(): strdup not enough memory\n", __func__);
1.1.1.2 ! misho 252: #ifdef HAVE_LINUX_PROCFS
! 253: fclose(fp);
! 254: #endif
1.1 misho 255: return(-1);
256: }
257:
258: ++al;
259: ++nipaddr;
260:
261: #ifndef HAVE_LINUX_PROCFS
262: pifr = ifr;
263: #endif
264:
265: } /* while|for */
266:
267: #ifdef HAVE_LINUX_PROCFS
268: if (ferror(fp))
269: {
270: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
271: "%s(): ferror: %s\n", __func__, strerror(errno));
1.1.1.2 ! misho 272: fclose(fp);
1.1 misho 273: return (-1);
274: }
275: fclose(fp);
276: #endif
277:
278: *ipaddrp = ifaddrlist;
279: return (nipaddr);
280: }
281: #else
282: /* From tcptraceroute, convert a numeric IP address to a string */
283: #define IPTOSBUFFERS 12
1.1.1.2 ! misho 284: static int8_t *iptos(uint32_t in)
1.1 misho 285: {
286: static int8_t output[IPTOSBUFFERS][ 3 * 4 + 3 + 1];
287: static int16_t which;
1.1.1.2 ! misho 288: uint8_t *p;
1.1 misho 289:
1.1.1.2 ! misho 290: p = (uint8_t *)∈
1.1 misho 291: which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
292: snprintf(output[which], IPTOSBUFFERS, "%d.%d.%d.%d",
293: p[0], p[1], p[2], p[3]);
294: return output[which];
295: }
296:
297: int
1.1.1.2 ! misho 298: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev,
! 299: register char *errbuf)
1.1 misho 300: {
301: int nipaddr = 0; int i = 0;
302:
303: static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
304: pcap_if_t *alldevs;
305: pcap_if_t *d;
306: int8_t err[PCAP_ERRBUF_SIZE];
307:
308: /* Retrieve the interfaces list */
309: if (pcap_findalldevs(&alldevs, err) == -1)
310: {
311: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
312: "%s(): error in pcap_findalldevs: %s\n", __func__, err);
313: return (-1);
314: }
315:
316: /* Scan the list printing every entry */
317: for (d = alldevs; d; d = d->next)
318: {
319: if((!d->addresses) || (d->addresses->addr->sa_family != AF_INET))
320: continue;
321: if(d->flags & PCAP_IF_LOOPBACK)
322: continue;
323:
324: /* XXX - strdup */
325: ifaddrlist[i].device = strdup(d->name);
1.1.1.2 ! misho 326: ifaddrlist[i].addr = (uint32_t)
1.1 misho 327: strdup(iptos(((struct sockaddr_in *)
328: d->addresses->addr)->sin_addr.s_addr));
329: ++i;
330: ++nipaddr;
331: }
332:
333: *ipaddrp = ifaddrlist;
334: return (nipaddr);
335: }
336: #endif /* __WIN32__ */
337:
338: int
339: libnet_select_device(libnet_t *l)
340: {
341: int c, i;
1.1.1.2 ! misho 342: char err_buf[LIBNET_ERRBUF_SIZE];
1.1 misho 343: struct libnet_ifaddr_list *address_list, *al;
1.1.1.2 ! misho 344: uint32_t addr;
1.1 misho 345:
346:
347: if (l == NULL)
348: {
349: return (-1);
350: }
351:
352: if (l->device && !isdigit(l->device[0]))
353: {
354: #if !(__WIN32__)
355: if (libnet_check_iface(l) < 0)
356: {
357: /* err msg set in libnet_check_iface() */
358: return (-1);
359: }
360: #endif
361: return (1);
362: }
363:
364: /*
365: * Number of interfaces.
366: */
367: c = libnet_ifaddrlist(&address_list, l->device, err_buf);
368: if (c < 0)
369: {
370: /* err msg set in libnet_ifaddrlist() */
371: return (-1);
372: }
373: else if (c == 0)
374: {
375: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
376: "%s(): no network interface found\n", __func__);
377: return (-1);
378: }
379:
380: al = address_list;
381: if (l->device)
382: {
383: /*
384: * Then we have an IP address in l->device => do lookup
385: */
386: addr = libnet_name2addr4(l, l->device, 0);
387:
388: for (i = c; i; --i, ++address_list)
389: {
390: if (((addr == -1) && !(strncmp(l->device, address_list->device,
391: strlen(l->device)))) ||
392: (address_list->addr == addr))
393: {
394: /* free the "user supplied device" - see libnet_init() */
395: free(l->device);
396: l->device = strdup(address_list->device);
397: goto good;
398: }
399: }
400: if (i <= 0)
401: {
402: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
403: "%s(): can't find interface for IP %s\n", __func__,
404: l->device);
405: goto bad;
406: }
407: }
408: else
409: {
410: l->device = strdup(address_list->device);
411: }
412:
413: good:
414: for (i = 0; i < c; i++)
415: {
416: free(al[i].device);
1.1.1.2 ! misho 417: al[i].device = NULL;
1.1 misho 418: }
419: return (1);
420:
421: bad:
422: for (i = 0; i < c; i++)
423: {
424: free(al[i].device);
1.1.1.2 ! misho 425: al[i].device = NULL;
1.1 misho 426: }
427: return (-1);
428: }
429:
430: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>