Annotation of embedaddon/libnet/src/libnet_if_addr.c, revision 1.1.1.1
1.1 misho 1: /*
2: * $Id: libnet_if_addr.c,v 1.22 2004/03/04 20:51:07 kkuehl Exp $
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
112: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, int8_t *dev,
113: register int8_t *errbuf)
114: {
115: register struct libnet_ifaddr_list *al;
116: struct ifreq *ifr, *lifr, *pifr, nifr;
117: int8_t device[sizeof(nifr.ifr_name)];
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));
157: return(-1);
158: }
159:
160: pifr = NULL;
161: lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
162:
163: al = ifaddrlist;
164: nipaddr = 0;
165:
166: #ifdef HAVE_LINUX_PROCFS
167: while (fgets(buf, sizeof(buf), fp))
168: {
169: if ((p = strchr(buf, ':')) == NULL)
170: {
171: continue;
172: }
173: *p = '\0';
174: for(p = buf; *p == ' '; p++) ;
175:
176: strncpy(nifr.ifr_name, p, sizeof(nifr.ifr_name) - 1);
177: nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
178:
179: #else /* !HAVE_LINUX_PROCFS */
180:
181: for (ifr = ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr))
182: {
183: /* XXX LINUX SOLARIS ifalias */
184: if((p = strchr(ifr->ifr_name, ':')))
185: {
186: *p='\0';
187: }
188: if (pifr && strcmp(ifr->ifr_name, pifr->ifr_name) == 0)
189: {
190: continue;
191: }
192: strncpy(nifr.ifr_name, ifr->ifr_name, sizeof(nifr.ifr_name) - 1);
193: nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
194: #endif
195:
196: /* save device name */
197: strncpy(device, nifr.ifr_name, sizeof(device) - 1);
198: device[sizeof(device) - 1] = '\0';
199:
200: if (ioctl(fd, SIOCGIFFLAGS, &nifr) < 0)
201: {
202: pifr = ifr;
203: continue;
204: }
205: if ((nifr.ifr_flags & IFF_UP) == 0)
206: {
207: pifr = ifr;
208: continue;
209: }
210:
211: if (dev == NULL && LIBNET_ISLOOPBACK(&nifr))
212: {
213: pifr = ifr;
214: continue;
215: }
216:
217: strncpy(nifr.ifr_name, device, sizeof(device) - 1);
218: nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
219: if (ioctl(fd, SIOCGIFADDR, (int8_t *)&nifr) < 0)
220: {
221: if (errno != EADDRNOTAVAIL)
222: {
223: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
224: "%s(): SIOCGIFADDR: dev=%s: %s\n", __func__, device,
225: strerror(errno));
226: close(fd);
227: return (-1);
228: }
229: else /* device has no IP address => set to 0 */
230: {
231: al->addr = 0;
232: }
233: }
234: else
235: {
236: al->addr = ((struct sockaddr_in *)&nifr.ifr_addr)->sin_addr.s_addr;
237: }
238:
239: if ((al->device = strdup(device)) == NULL)
240: {
241: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
242: "%s(): strdup not enough memory\n", __func__);
243: return(-1);
244: }
245:
246: ++al;
247: ++nipaddr;
248:
249: #ifndef HAVE_LINUX_PROCFS
250: pifr = ifr;
251: #endif
252:
253: } /* while|for */
254:
255: #ifdef HAVE_LINUX_PROCFS
256: if (ferror(fp))
257: {
258: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
259: "%s(): ferror: %s\n", __func__, strerror(errno));
260: return (-1);
261: }
262: fclose(fp);
263: #endif
264:
265: *ipaddrp = ifaddrlist;
266: return (nipaddr);
267: }
268: #else
269: /* From tcptraceroute, convert a numeric IP address to a string */
270: #define IPTOSBUFFERS 12
271: static int8_t *iptos(u_int32_t in)
272: {
273: static int8_t output[IPTOSBUFFERS][ 3 * 4 + 3 + 1];
274: static int16_t which;
275: u_int8_t *p;
276:
277: p = (u_int8_t *)∈
278: which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
279: snprintf(output[which], IPTOSBUFFERS, "%d.%d.%d.%d",
280: p[0], p[1], p[2], p[3]);
281: return output[which];
282: }
283:
284: int
285: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, int8_t *dev,
286: register int8_t *errbuf)
287: {
288: int nipaddr = 0; int i = 0;
289:
290: static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
291: pcap_if_t *alldevs;
292: pcap_if_t *d;
293: int8_t err[PCAP_ERRBUF_SIZE];
294:
295: /* Retrieve the interfaces list */
296: if (pcap_findalldevs(&alldevs, err) == -1)
297: {
298: snprintf(errbuf, LIBNET_ERRBUF_SIZE,
299: "%s(): error in pcap_findalldevs: %s\n", __func__, err);
300: return (-1);
301: }
302:
303: /* Scan the list printing every entry */
304: for (d = alldevs; d; d = d->next)
305: {
306: if((!d->addresses) || (d->addresses->addr->sa_family != AF_INET))
307: continue;
308: if(d->flags & PCAP_IF_LOOPBACK)
309: continue;
310:
311: /* XXX - strdup */
312: ifaddrlist[i].device = strdup(d->name);
313: ifaddrlist[i].addr = (u_int32_t)
314: strdup(iptos(((struct sockaddr_in *)
315: d->addresses->addr)->sin_addr.s_addr));
316: ++i;
317: ++nipaddr;
318: }
319:
320: *ipaddrp = ifaddrlist;
321: return (nipaddr);
322: }
323: #endif /* __WIN32__ */
324:
325: int
326: libnet_select_device(libnet_t *l)
327: {
328: int c, i;
329: int8_t err_buf[LIBNET_ERRBUF_SIZE];
330: struct libnet_ifaddr_list *address_list, *al;
331: u_int32_t addr;
332:
333:
334: if (l == NULL)
335: {
336: return (-1);
337: }
338:
339: if (l->device && !isdigit(l->device[0]))
340: {
341: #if !(__WIN32__)
342: if (libnet_check_iface(l) < 0)
343: {
344: /* err msg set in libnet_check_iface() */
345: return (-1);
346: }
347: #endif
348: return (1);
349: }
350:
351: /*
352: * Number of interfaces.
353: */
354: c = libnet_ifaddrlist(&address_list, l->device, err_buf);
355: if (c < 0)
356: {
357: /* err msg set in libnet_ifaddrlist() */
358: return (-1);
359: }
360: else if (c == 0)
361: {
362: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
363: "%s(): no network interface found\n", __func__);
364: return (-1);
365: }
366:
367: al = address_list;
368: if (l->device)
369: {
370: /*
371: * Then we have an IP address in l->device => do lookup
372: */
373: addr = libnet_name2addr4(l, l->device, 0);
374:
375: for (i = c; i; --i, ++address_list)
376: {
377: if (((addr == -1) && !(strncmp(l->device, address_list->device,
378: strlen(l->device)))) ||
379: (address_list->addr == addr))
380: {
381: /* free the "user supplied device" - see libnet_init() */
382: free(l->device);
383: l->device = strdup(address_list->device);
384: goto good;
385: }
386: }
387: if (i <= 0)
388: {
389: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
390: "%s(): can't find interface for IP %s\n", __func__,
391: l->device);
392: goto bad;
393: }
394: }
395: else
396: {
397: l->device = strdup(address_list->device);
398: }
399:
400: good:
401: for (i = 0; i < c; i++)
402: {
403: free(al[i].device);
404: }
405: return (1);
406:
407: bad:
408: for (i = 0; i < c; i++)
409: {
410: free(al[i].device);
411: }
412: return (-1);
413: }
414:
415: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>