Annotation of embedaddon/libnet/src/libnet_if_addr.c, revision 1.1.1.3
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:
1.1.1.3 ! misho 333: pcap_freealldevs(alldevs);
! 334:
1.1 misho 335: *ipaddrp = ifaddrlist;
336: return (nipaddr);
337: }
338: #endif /* __WIN32__ */
339:
340: int
341: libnet_select_device(libnet_t *l)
342: {
343: int c, i;
344: struct libnet_ifaddr_list *address_list, *al;
1.1.1.2 misho 345: uint32_t addr;
1.1 misho 346:
347:
348: if (l == NULL)
349: {
350: return (-1);
351: }
352:
353: if (l->device && !isdigit(l->device[0]))
354: {
355: #if !(__WIN32__)
356: if (libnet_check_iface(l) < 0)
357: {
358: /* err msg set in libnet_check_iface() */
359: return (-1);
360: }
361: #endif
362: return (1);
363: }
364:
365: /*
366: * Number of interfaces.
367: */
1.1.1.3 ! misho 368: c = libnet_ifaddrlist(&address_list, l->device, l->err_buf);
1.1 misho 369: if (c < 0)
370: {
371: /* err msg set in libnet_ifaddrlist() */
372: return (-1);
373: }
374: else if (c == 0)
375: {
376: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
377: "%s(): no network interface found\n", __func__);
378: return (-1);
379: }
380:
381: al = address_list;
382: if (l->device)
383: {
384: /*
385: * Then we have an IP address in l->device => do lookup
386: */
387: addr = libnet_name2addr4(l, l->device, 0);
388:
389: for (i = c; i; --i, ++address_list)
390: {
391: if (((addr == -1) && !(strncmp(l->device, address_list->device,
392: strlen(l->device)))) ||
393: (address_list->addr == addr))
394: {
395: /* free the "user supplied device" - see libnet_init() */
396: free(l->device);
397: l->device = strdup(address_list->device);
398: goto good;
399: }
400: }
401: if (i <= 0)
402: {
403: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
404: "%s(): can't find interface for IP %s\n", __func__,
405: l->device);
406: goto bad;
407: }
408: }
409: else
410: {
411: l->device = strdup(address_list->device);
412: }
413:
414: good:
415: for (i = 0; i < c; i++)
416: {
417: free(al[i].device);
1.1.1.2 misho 418: al[i].device = NULL;
1.1 misho 419: }
420: return (1);
421:
422: bad:
423: for (i = 0; i < c; i++)
424: {
425: free(al[i].device);
1.1.1.2 misho 426: al[i].device = NULL;
1.1 misho 427: }
428: return (-1);
429: }
430:
431: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>