inet.c revision 127664
1/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
2/*
3 * Copyright (c) 1994, 1995, 1996, 1997, 1998
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by the Computer Systems
17 *	Engineering Group at Lawrence Berkeley Laboratory.
18 * 4. Neither the name of the University nor of the Laboratory may be used
19 *    to endorse or promote products derived from this software without
20 *    specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#ifndef lint
36static const char rcsid[] _U_ =
37    "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.58.2.1 2003/11/15 23:26:41 guy Exp $ (LBL)";
38#endif
39
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#ifdef WIN32
45#include <pcap-stdinc.h>
46#else /* WIN32 */
47
48#include <sys/param.h>
49#include <sys/file.h>
50#include <sys/ioctl.h>
51#include <sys/socket.h>
52#ifdef HAVE_SYS_SOCKIO_H
53#include <sys/sockio.h>
54#endif
55#include <sys/time.h>				/* concession to AIX */
56
57struct mbuf;		/* Squelch compiler warnings on some platforms for */
58struct rtentry;		/* declarations in <net/if.h> */
59#include <net/if.h>
60#include <netinet/in.h>
61#endif /* WIN32 */
62
63#include <ctype.h>
64#include <errno.h>
65#include <memory.h>
66#include <stdio.h>
67#include <stdlib.h>
68#include <string.h>
69#ifndef WIN32
70#include <unistd.h>
71#endif /* WIN32 */
72#ifdef HAVE_LIMITS_H
73#include <limits.h>
74#else
75#define INT_MAX		2147483647
76#endif
77#ifdef HAVE_IFADDRS_H
78#include <ifaddrs.h>
79#endif
80
81#include "pcap-int.h"
82
83#ifdef HAVE_OS_PROTO_H
84#include "os-proto.h"
85#endif
86
87/* Not all systems have IFF_LOOPBACK */
88#ifdef IFF_LOOPBACK
89#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
90#else
91#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
92    (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
93#endif
94
95struct sockaddr *
96dup_sockaddr(struct sockaddr *sa, size_t sa_length)
97{
98	struct sockaddr *newsa;
99
100	if ((newsa = malloc(sa_length)) == NULL)
101		return (NULL);
102	return (memcpy(newsa, sa, sa_length));
103}
104
105static int
106get_instance(const char *name)
107{
108	const char *cp, *endcp;
109	int n;
110
111	if (strcmp(name, "any") == 0) {
112		/*
113		 * Give the "any" device an artificially high instance
114		 * number, so it shows up after all other non-loopback
115		 * interfaces.
116		 */
117		return INT_MAX;
118	}
119
120	endcp = name + strlen(name);
121	for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
122		continue;
123
124	if (isdigit((unsigned char)*cp))
125		n = atoi(cp);
126	else
127		n = 0;
128	return (n);
129}
130
131int
132add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
133    u_int flags, const char *description, char *errbuf)
134{
135	pcap_if_t *curdev, *prevdev, *nextdev;
136	int this_instance;
137
138	/*
139	 * Is there already an entry in the list for this interface?
140	 */
141	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
142		if (strcmp(name, curdev->name) == 0)
143			break;	/* yes, we found it */
144	}
145	if (curdev == NULL) {
146		/*
147		 * No, we didn't find it.
148		 * Allocate a new entry.
149		 */
150		curdev = malloc(sizeof(pcap_if_t));
151		if (curdev == NULL) {
152			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
153			    "malloc: %s", pcap_strerror(errno));
154			return (-1);
155		}
156
157		/*
158		 * Fill in the entry.
159		 */
160		curdev->next = NULL;
161		curdev->name = malloc(strlen(name) + 1);
162		strcpy(curdev->name, name);
163		if (description != NULL) {
164			/*
165			 * We have a description for this interface.
166			 */
167			curdev->description = malloc(strlen(description) + 1);
168			strcpy(curdev->description, description);
169		} else {
170			/*
171			 * We don't.
172			 */
173			curdev->description = NULL;
174		}
175		curdev->addresses = NULL;	/* list starts out as empty */
176		curdev->flags = 0;
177		if (ISLOOPBACK(name, flags))
178			curdev->flags |= PCAP_IF_LOOPBACK;
179
180		/*
181		 * Add it to the list, in the appropriate location.
182		 * First, get the instance number of this interface.
183		 */
184		this_instance = get_instance(name);
185
186		/*
187		 * Now look for the last interface with an instance number
188		 * less than or equal to the new interface's instance
189		 * number - except that non-loopback interfaces are
190		 * arbitrarily treated as having interface numbers less
191		 * than those of loopback interfaces, so the loopback
192		 * interfaces are put at the end of the list.
193		 *
194		 * We start with "prevdev" being NULL, meaning we're before
195		 * the first element in the list.
196		 */
197		prevdev = NULL;
198		for (;;) {
199			/*
200			 * Get the interface after this one.
201			 */
202			if (prevdev == NULL) {
203				/*
204				 * The next element is the first element.
205				 */
206				nextdev = *alldevs;
207			} else
208				nextdev = prevdev->next;
209
210			/*
211			 * Are we at the end of the list?
212			 */
213			if (nextdev == NULL) {
214				/*
215				 * Yes - we have to put the new entry
216				 * after "prevdev".
217				 */
218				break;
219			}
220
221			/*
222			 * Is the new interface a non-loopback interface
223			 * and the next interface a loopback interface?
224			 */
225			if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
226			    (nextdev->flags & PCAP_IF_LOOPBACK)) {
227				/*
228				 * Yes, we should put the new entry
229				 * before "nextdev", i.e. after "prevdev".
230				 */
231				break;
232			}
233
234			/*
235			 * Is the new interface's instance number less
236			 * than the next interface's instance number,
237			 * and is it the case that the new interface is a
238			 * non-loopback interface or the next interface is
239			 * a loopback interface?
240			 *
241			 * (The goal of both loopback tests is to make
242			 * sure that we never put a loopback interface
243			 * before any non-loopback interface and that we
244			 * always put a non-loopback interface before all
245			 * loopback interfaces.)
246			 */
247			if (this_instance < get_instance(nextdev->name) &&
248			    (!(curdev->flags & PCAP_IF_LOOPBACK) ||
249			       (nextdev->flags & PCAP_IF_LOOPBACK))) {
250				/*
251				 * Yes - we should put the new entry
252				 * before "nextdev", i.e. after "prevdev".
253				 */
254				break;
255			}
256
257			prevdev = nextdev;
258		}
259
260		/*
261		 * Insert before "nextdev".
262		 */
263		curdev->next = nextdev;
264
265		/*
266		 * Insert after "prevdev" - unless "prevdev" is null,
267		 * in which case this is the first interface.
268		 */
269		if (prevdev == NULL) {
270			/*
271			 * This is the first interface.  Pass back a
272			 * pointer to it, and put "curdev" before
273			 * "nextdev".
274			 */
275			*alldevs = curdev;
276		} else
277			prevdev->next = curdev;
278	}
279
280	*curdev_ret = curdev;
281	return (0);
282}
283
284int
285add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags,
286    struct sockaddr *addr, size_t addr_size,
287    struct sockaddr *netmask, size_t netmask_size,
288    struct sockaddr *broadaddr, size_t broadaddr_size,
289    struct sockaddr *dstaddr, size_t dstaddr_size,
290    char *errbuf)
291{
292	pcap_if_t *curdev;
293	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
294
295	if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
296		/*
297		 * Error - give up.
298		 */
299		return (-1);
300	}
301	if (curdev == NULL) {
302		/*
303		 * Device wasn't added because it can't be opened.
304		 * Not a fatal error.
305		 */
306		return (0);
307	}
308
309	/*
310	 * "curdev" is an entry for this interface; add an entry for this
311	 * address to its list of addresses.
312	 *
313	 * Allocate the new entry and fill it in.
314	 */
315	curaddr = malloc(sizeof(pcap_addr_t));
316	if (curaddr == NULL) {
317		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
318		    "malloc: %s", pcap_strerror(errno));
319		return (-1);
320	}
321
322	curaddr->next = NULL;
323	if (addr != NULL) {
324		curaddr->addr = dup_sockaddr(addr, addr_size);
325		if (curaddr->addr == NULL) {
326			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
327			    "malloc: %s", pcap_strerror(errno));
328			free(curaddr);
329			return (-1);
330		}
331	} else
332		curaddr->addr = NULL;
333
334	if (netmask != NULL) {
335		curaddr->netmask = dup_sockaddr(netmask, netmask_size);
336		if (curaddr->netmask == NULL) {
337			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
338			    "malloc: %s", pcap_strerror(errno));
339			free(curaddr);
340			return (-1);
341		}
342	} else
343		curaddr->netmask = NULL;
344
345	if (broadaddr != NULL) {
346		curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
347		if (curaddr->broadaddr == NULL) {
348			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
349			    "malloc: %s", pcap_strerror(errno));
350			free(curaddr);
351			return (-1);
352		}
353	} else
354		curaddr->broadaddr = NULL;
355
356	if (dstaddr != NULL) {
357		curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
358		if (curaddr->dstaddr == NULL) {
359			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
360			    "malloc: %s", pcap_strerror(errno));
361			free(curaddr);
362			return (-1);
363		}
364	} else
365		curaddr->dstaddr = NULL;
366
367	/*
368	 * Find the end of the list of addresses.
369	 */
370	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
371		nextaddr = prevaddr->next;
372		if (nextaddr == NULL) {
373			/*
374			 * This is the end of the list.
375			 */
376			break;
377		}
378	}
379
380	if (prevaddr == NULL) {
381		/*
382		 * The list was empty; this is the first member.
383		 */
384		curdev->addresses = curaddr;
385	} else {
386		/*
387		 * "prevaddr" is the last member of the list; append
388		 * this member to it.
389		 */
390		prevaddr->next = curaddr;
391	}
392
393	return (0);
394}
395
396int
397pcap_add_if(pcap_if_t **devlist, char *name, u_int flags,
398    const char *description, char *errbuf)
399{
400	pcap_if_t *curdev;
401
402	return (add_or_find_if(&curdev, devlist, name, flags, description,
403	    errbuf));
404}
405
406
407/*
408 * Free a list of interfaces.
409 */
410void
411pcap_freealldevs(pcap_if_t *alldevs)
412{
413	pcap_if_t *curdev, *nextdev;
414	pcap_addr_t *curaddr, *nextaddr;
415
416	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
417		nextdev = curdev->next;
418
419		/*
420		 * Free all addresses.
421		 */
422		for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
423			nextaddr = curaddr->next;
424			if (curaddr->addr)
425				free(curaddr->addr);
426			if (curaddr->netmask)
427				free(curaddr->netmask);
428			if (curaddr->broadaddr)
429				free(curaddr->broadaddr);
430			if (curaddr->dstaddr)
431				free(curaddr->dstaddr);
432			free(curaddr);
433		}
434
435		/*
436		 * Free the name string.
437		 */
438		free(curdev->name);
439
440		/*
441		 * Free the description string, if any.
442		 */
443		if (curdev->description != NULL)
444			free(curdev->description);
445
446		/*
447		 * Free the interface.
448		 */
449		free(curdev);
450	}
451}
452
453#ifndef WIN32
454
455/*
456 * Return the name of a network interface attached to the system, or NULL
457 * if none can be found.  The interface must be configured up; the
458 * lowest unit number is preferred; loopback is ignored.
459 */
460char *
461pcap_lookupdev(errbuf)
462	register char *errbuf;
463{
464	pcap_if_t *alldevs;
465/* for old BSD systems, including bsdi3 */
466#ifndef IF_NAMESIZE
467#define IF_NAMESIZE IFNAMSIZ
468#endif
469	static char device[IF_NAMESIZE + 1];
470	char *ret;
471
472	if (pcap_findalldevs(&alldevs, errbuf) == -1)
473		return (NULL);
474
475	if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
476		/*
477		 * There are no devices on the list, or the first device
478		 * on the list is a loopback device, which means there
479		 * are no non-loopback devices on the list.  This means
480		 * we can't return any device.
481		 *
482		 * XXX - why not return a loopback device?  If we can't
483		 * capture on it, it won't be on the list, and if it's
484		 * on the list, there aren't any non-loopback devices,
485		 * so why not just supply it as the default device?
486		 */
487		(void)strlcpy(errbuf, "no suitable device found",
488		    PCAP_ERRBUF_SIZE);
489		ret = NULL;
490	} else {
491		/*
492		 * Return the name of the first device on the list.
493		 */
494		(void)strlcpy(device, alldevs->name, sizeof(device));
495		ret = device;
496	}
497
498	pcap_freealldevs(alldevs);
499	return (ret);
500}
501
502int
503pcap_lookupnet(device, netp, maskp, errbuf)
504	register const char *device;
505	register bpf_u_int32 *netp, *maskp;
506	register char *errbuf;
507{
508	register int fd;
509	register struct sockaddr_in *sin;
510	struct ifreq ifr;
511
512	/*
513	 * The pseudo-device "any" listens on all interfaces and therefore
514	 * has the network address and -mask "0.0.0.0" therefore catching
515	 * all traffic. Using NULL for the interface is the same as "any".
516	 */
517	if (!device || strcmp(device, "any") == 0
518#ifdef HAVE_DAG_API
519	    || strstr(device, "dag") != NULL
520#endif
521	    ) {
522		*netp = *maskp = 0;
523		return 0;
524	}
525
526	fd = socket(AF_INET, SOCK_DGRAM, 0);
527	if (fd < 0) {
528		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
529		    pcap_strerror(errno));
530		return (-1);
531	}
532	memset(&ifr, 0, sizeof(ifr));
533#ifdef linux
534	/* XXX Work around Linux kernel bug */
535	ifr.ifr_addr.sa_family = AF_INET;
536#endif
537	(void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
538	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
539		if (errno == EADDRNOTAVAIL) {
540			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
541			    "%s: no IPv4 address assigned", device);
542		} else {
543			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
544			    "SIOCGIFADDR: %s: %s",
545			    device, pcap_strerror(errno));
546		}
547		(void)close(fd);
548		return (-1);
549	}
550	sin = (struct sockaddr_in *)&ifr.ifr_addr;
551	*netp = sin->sin_addr.s_addr;
552	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
553		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
554		    "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
555		(void)close(fd);
556		return (-1);
557	}
558	(void)close(fd);
559	*maskp = sin->sin_addr.s_addr;
560	if (*maskp == 0) {
561		if (IN_CLASSA(*netp))
562			*maskp = IN_CLASSA_NET;
563		else if (IN_CLASSB(*netp))
564			*maskp = IN_CLASSB_NET;
565		else if (IN_CLASSC(*netp))
566			*maskp = IN_CLASSC_NET;
567		else {
568			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
569			    "inet class for 0x%x unknown", *netp);
570			return (-1);
571		}
572	}
573	*netp &= *maskp;
574	return (0);
575}
576
577#else /* WIN32 */
578
579/*
580 * Return the name of a network interface attached to the system, or NULL
581 * if none can be found.  The interface must be configured up; the
582 * lowest unit number is preferred; loopback is ignored.
583 */
584char *
585pcap_lookupdev(errbuf)
586	register char *errbuf;
587{
588	DWORD dwVersion;
589	DWORD dwWindowsMajorVersion;
590	dwVersion = GetVersion();	/* get the OS version */
591	dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
592
593	if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
594		/*
595		 * Windows 95, 98, ME.
596		 */
597		ULONG NameLength = 8192;
598		static char AdaptersName[8192];
599
600		PacketGetAdapterNames(AdaptersName,&NameLength);
601
602		return (AdaptersName);
603	} else {
604		/*
605		 * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
606		 */
607		ULONG NameLength = 8192;
608		static WCHAR AdaptersName[8192];
609		char *tAstr;
610		WCHAR *tUstr;
611		WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
612		int NAdapts = 0;
613
614		if(TAdaptersName == NULL)
615		{
616			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
617			return NULL;
618		}
619
620		PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength);
621
622		tAstr = (char*)TAdaptersName;
623		tUstr = (WCHAR*)AdaptersName;
624
625		/*
626		 * Convert and copy the device names
627		 */
628		while(sscanf(tAstr, "%S", tUstr) > 0)
629		{
630			tAstr += strlen(tAstr) + 1;
631			tUstr += wcslen(tUstr) + 1;
632			NAdapts ++;
633		}
634
635		tAstr++;
636		*tUstr = 0;
637		tUstr++;
638
639		/*
640		 * Copy the descriptions
641		 */
642		while(NAdapts--)
643		{
644			strcpy((char*)tUstr, tAstr);
645			(char*)tUstr += strlen(tAstr) + 1;;
646			tAstr += strlen(tAstr) + 1;
647		}
648
649		return (char *)(AdaptersName);
650	}
651}
652
653
654int
655pcap_lookupnet(device, netp, maskp, errbuf)
656	const register char *device;
657	register bpf_u_int32 *netp, *maskp;
658	register char *errbuf;
659{
660	/*
661	 * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
662	 * in order to skip non IPv4 (i.e. IPv6 addresses)
663	 */
664	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
665	LONG if_addr_size = 1;
666	struct sockaddr_in *t_addr;
667	unsigned int i;
668
669	if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
670		*netp = *maskp = 0;
671		return (0);
672	}
673
674	for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
675	{
676		if(if_addrs[i].IPAddress.ss_family == AF_INET)
677		{
678			t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
679			*netp = t_addr->sin_addr.S_un.S_addr;
680			t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
681			*maskp = t_addr->sin_addr.S_un.S_addr;
682
683			*netp &= *maskp;
684			return (0);
685		}
686
687	}
688
689	*netp = *maskp = 0;
690	return (0);
691}
692
693#endif /* WIN32 */
694