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/fad-gifc.c,v 1.8.2.2 2005/06/29 06:43:31 guy Exp $ (LBL)";
38#endif
39
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#include <sys/param.h>
45#include <sys/file.h>
46#include <sys/ioctl.h>
47#include <sys/socket.h>
48#ifdef HAVE_SYS_SOCKIO_H
49#include <sys/sockio.h>
50#endif
51#include <sys/time.h>				/* concession to AIX */
52
53struct mbuf;		/* Squelch compiler warnings on some platforms for */
54struct rtentry;		/* declarations in <net/if.h> */
55#include <net/if.h>
56#include <netinet/in.h>
57
58#include <ctype.h>
59#include <errno.h>
60#include <memory.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <unistd.h>
65
66#include "pcap-int.h"
67
68#ifdef HAVE_OS_PROTO_H
69#include "os-proto.h"
70#endif
71
72/*
73 * This is fun.
74 *
75 * In older BSD systems, socket addresses were fixed-length, and
76 * "sizeof (struct sockaddr)" gave the size of the structure.
77 * All addresses fit within a "struct sockaddr".
78 *
79 * In newer BSD systems, the socket address is variable-length, and
80 * there's an "sa_len" field giving the length of the structure;
81 * this allows socket addresses to be longer than 2 bytes of family
82 * and 14 bytes of data.
83 *
84 * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
85 * variant of the old BSD scheme (with "struct sockaddr_storage" rather
86 * than "struct sockaddr"), and some use the new BSD scheme.
87 *
88 * Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
89 * macro that determines the size based on the address family.  Other
90 * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
91 * but not in the final version).
92 *
93 * We assume that a UNIX that doesn't have "getifaddrs()" and doesn't have
94 * SIOCGLIFCONF, but has SIOCGIFCONF, uses "struct sockaddr" for the
95 * address in an entry returned by SIOCGIFCONF.
96 */
97#ifndef SA_LEN
98#ifdef HAVE_SOCKADDR_SA_LEN
99#define SA_LEN(addr)	((addr)->sa_len)
100#else /* HAVE_SOCKADDR_SA_LEN */
101#define SA_LEN(addr)	(sizeof (struct sockaddr))
102#endif /* HAVE_SOCKADDR_SA_LEN */
103#endif /* SA_LEN */
104
105/*
106 * This is also fun.
107 *
108 * There is no ioctl that returns the amount of space required for all
109 * the data that SIOCGIFCONF could return, and if a buffer is supplied
110 * that's not large enough for all the data SIOCGIFCONF could return,
111 * on at least some platforms it just returns the data that'd fit with
112 * no indication that there wasn't enough room for all the data, much
113 * less an indication of how much more room is required.
114 *
115 * The only way to ensure that we got all the data is to pass a buffer
116 * large enough that the amount of space in the buffer *not* filled in
117 * is greater than the largest possible entry.
118 *
119 * We assume that's "sizeof(ifreq.ifr_name)" plus 255, under the assumption
120 * that no address is more than 255 bytes (on systems where the "sa_len"
121 * field in a "struct sockaddr" is 1 byte, e.g. newer BSDs, that's the
122 * case, and addresses are unlikely to be bigger than that in any case).
123 */
124#define MAX_SA_LEN	255
125
126#ifdef HAVE_PROC_NET_DEV
127/*
128 * Get from "/proc/net/dev" all interfaces listed there; if they're
129 * already in the list of interfaces we have, that won't add another
130 * instance, but if they're not, that'll add them.
131 *
132 * We don't bother getting any addresses for them; it appears you can't
133 * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and,
134 * although some other types of addresses can be fetched with SIOCGIFADDR,
135 * we don't bother with them for now.
136 *
137 * We also don't fail if we couldn't open "/proc/net/dev"; we just leave
138 * the list of interfaces as is.
139 */
140static int
141scan_proc_net_dev(pcap_if_t **devlistp, int fd, char *errbuf)
142{
143	FILE *proc_net_f;
144	char linebuf[512];
145	int linenum;
146	unsigned char *p;
147	char name[512];	/* XXX - pick a size */
148	char *q, *saveq;
149	struct ifreq ifrflags;
150	int ret = 0;
151
152	proc_net_f = fopen("/proc/net/dev", "r");
153	if (proc_net_f == NULL)
154		return (0);
155
156	for (linenum = 1;
157	    fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) {
158		/*
159		 * Skip the first two lines - they're headers.
160		 */
161		if (linenum <= 2)
162			continue;
163
164		p = &linebuf[0];
165
166		/*
167		 * Skip leading white space.
168		 */
169		while (*p != '\0' && isspace(*p))
170			p++;
171		if (*p == '\0' || *p == '\n')
172			continue;	/* blank line */
173
174		/*
175		 * Get the interface name.
176		 */
177		q = &name[0];
178		while (*p != '\0' && !isspace(*p)) {
179			if (*p == ':') {
180				/*
181				 * This could be the separator between a
182				 * name and an alias number, or it could be
183				 * the separator between a name with no
184				 * alias number and the next field.
185				 *
186				 * If there's a colon after digits, it
187				 * separates the name and the alias number,
188				 * otherwise it separates the name and the
189				 * next field.
190				 */
191				saveq = q;
192				while (isdigit(*p))
193					*q++ = *p++;
194				if (*p != ':') {
195					/*
196					 * That was the next field,
197					 * not the alias number.
198					 */
199					q = saveq;
200				}
201				break;
202			} else
203				*q++ = *p++;
204		}
205		*q = '\0';
206
207		/*
208		 * Get the flags for this interface, and skip it if
209		 * it's not up.
210		 */
211		strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
212		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
213			if (errno == ENXIO)
214				continue;
215			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
216			    "SIOCGIFFLAGS: %.*s: %s",
217			    (int)sizeof(ifrflags.ifr_name),
218			    ifrflags.ifr_name,
219			    pcap_strerror(errno));
220			ret = -1;
221			break;
222		}
223		if (!(ifrflags.ifr_flags & IFF_UP))
224			continue;
225
226		/*
227		 * Add an entry for this interface, with no addresses.
228		 */
229		if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
230		    errbuf) == -1) {
231			/*
232			 * Failure.
233			 */
234			ret = -1;
235			break;
236		}
237	}
238	if (ret != -1) {
239		/*
240		 * Well, we didn't fail for any other reason; did we
241		 * fail due to an error reading the file?
242		 */
243		if (ferror(proc_net_f)) {
244			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
245			    "Error reading /proc/net/dev: %s",
246			    pcap_strerror(errno));
247			ret = -1;
248		}
249	}
250
251	(void)fclose(proc_net_f);
252	return (ret);
253}
254#endif /* HAVE_PROC_NET_DEV */
255
256/*
257 * Get a list of all interfaces that are up and that we can open.
258 * Returns -1 on error, 0 otherwise.
259 * The list, as returned through "alldevsp", may be null if no interfaces
260 * were up and could be opened.
261 *
262 * This is the implementation used on platforms that have SIOCGIFCONF but
263 * don't have any other mechanism for getting a list of interfaces.
264 *
265 * XXX - or platforms that have other, better mechanisms but for which
266 * we don't yet have code to use that mechanism; I think there's a better
267 * way on Linux, for example.
268 */
269int
270pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
271{
272	pcap_if_t *devlist = NULL;
273	register int fd;
274	register struct ifreq *ifrp, *ifend, *ifnext;
275	int n;
276	struct ifconf ifc;
277	char *buf = NULL;
278	unsigned buf_size;
279#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
280	char *p, *q;
281#endif
282	struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
283	struct sockaddr *netmask, *broadaddr, *dstaddr;
284	size_t netmask_size, broadaddr_size, dstaddr_size;
285	int ret = 0;
286
287	/*
288	 * Create a socket from which to fetch the list of interfaces.
289	 */
290	fd = socket(AF_INET, SOCK_DGRAM, 0);
291	if (fd < 0) {
292		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
293		    "socket: %s", pcap_strerror(errno));
294		return (-1);
295	}
296
297	/*
298	 * Start with an 8K buffer, and keep growing the buffer until
299	 * we have more than "sizeof(ifrp->ifr_name) + MAX_SA_LEN"
300	 * bytes left over in the buffer or we fail to get the
301	 * interface list for some reason other than EINVAL (which is
302	 * presumed here to mean "buffer is too small").
303	 */
304	buf_size = 8192;
305	for (;;) {
306		buf = malloc(buf_size);
307		if (buf == NULL) {
308			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
309			    "malloc: %s", pcap_strerror(errno));
310			(void)close(fd);
311			return (-1);
312		}
313
314		ifc.ifc_len = buf_size;
315		ifc.ifc_buf = buf;
316		memset(buf, 0, buf_size);
317		if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
318		    && errno != EINVAL) {
319			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
320			    "SIOCGIFCONF: %s", pcap_strerror(errno));
321			(void)close(fd);
322			free(buf);
323			return (-1);
324		}
325		if (ifc.ifc_len < buf_size &&
326		    (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN)
327			break;
328		free(buf);
329		buf_size *= 2;
330	}
331
332	ifrp = (struct ifreq *)buf;
333	ifend = (struct ifreq *)(buf + ifc.ifc_len);
334
335	for (; ifrp < ifend; ifrp = ifnext) {
336		/*
337		 * XXX - what if this isn't an IPv4 address?  Can
338		 * we still get the netmask, etc. with ioctls on
339		 * an IPv4 socket?
340		 *
341		 * The answer is probably platform-dependent, and
342		 * if the answer is "no" on more than one platform,
343		 * the way you work around it is probably platform-
344		 * dependent as well.
345		 */
346		n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name);
347		if (n < sizeof(*ifrp))
348			ifnext = ifrp + 1;
349		else
350			ifnext = (struct ifreq *)((char *)ifrp + n);
351
352		/*
353		 * XXX - The 32-bit compatibility layer for Linux on IA-64
354		 * is slightly broken. It correctly converts the structures
355		 * to and from kernel land from 64 bit to 32 bit but
356		 * doesn't update ifc.ifc_len, leaving it larger than the
357		 * amount really used. This means we read off the end
358		 * of the buffer and encounter an interface with an
359		 * "empty" name. Since this is highly unlikely to ever
360		 * occur in a valid case we can just finish looking for
361		 * interfaces if we see an empty name.
362		 */
363		if (!(*ifrp->ifr_name))
364			break;
365
366		/*
367		 * Skip entries that begin with "dummy".
368		 * XXX - what are these?  Is this Linux-specific?
369		 * Are there platforms on which we shouldn't do this?
370		 */
371		if (strncmp(ifrp->ifr_name, "dummy", 5) == 0)
372			continue;
373
374		/*
375		 * Get the flags for this interface, and skip it if it's
376		 * not up.
377		 */
378		strncpy(ifrflags.ifr_name, ifrp->ifr_name,
379		    sizeof(ifrflags.ifr_name));
380		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
381			if (errno == ENXIO)
382				continue;
383			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
384			    "SIOCGIFFLAGS: %.*s: %s",
385			    (int)sizeof(ifrflags.ifr_name),
386			    ifrflags.ifr_name,
387			    pcap_strerror(errno));
388			ret = -1;
389			break;
390		}
391		if (!(ifrflags.ifr_flags & IFF_UP))
392			continue;
393
394		/*
395		 * Get the netmask for this address on this interface.
396		 */
397		strncpy(ifrnetmask.ifr_name, ifrp->ifr_name,
398		    sizeof(ifrnetmask.ifr_name));
399		memcpy(&ifrnetmask.ifr_addr, &ifrp->ifr_addr,
400		    sizeof(ifrnetmask.ifr_addr));
401		if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifrnetmask) < 0) {
402			if (errno == EADDRNOTAVAIL) {
403				/*
404				 * Not available.
405				 */
406				netmask = NULL;
407				netmask_size = 0;
408			} else {
409				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
410				    "SIOCGIFNETMASK: %.*s: %s",
411				    (int)sizeof(ifrnetmask.ifr_name),
412				    ifrnetmask.ifr_name,
413				    pcap_strerror(errno));
414				ret = -1;
415				break;
416			}
417		} else {
418			netmask = &ifrnetmask.ifr_addr;
419			netmask_size = SA_LEN(netmask);
420		}
421
422		/*
423		 * Get the broadcast address for this address on this
424		 * interface (if any).
425		 */
426		if (ifrflags.ifr_flags & IFF_BROADCAST) {
427			strncpy(ifrbroadaddr.ifr_name, ifrp->ifr_name,
428			    sizeof(ifrbroadaddr.ifr_name));
429			memcpy(&ifrbroadaddr.ifr_addr, &ifrp->ifr_addr,
430			    sizeof(ifrbroadaddr.ifr_addr));
431			if (ioctl(fd, SIOCGIFBRDADDR,
432			    (char *)&ifrbroadaddr) < 0) {
433				if (errno == EADDRNOTAVAIL) {
434					/*
435					 * Not available.
436					 */
437					broadaddr = NULL;
438					broadaddr_size = 0;
439				} else {
440					(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
441					    "SIOCGIFBRDADDR: %.*s: %s",
442					    (int)sizeof(ifrbroadaddr.ifr_name),
443					    ifrbroadaddr.ifr_name,
444					    pcap_strerror(errno));
445					ret = -1;
446					break;
447				}
448			} else {
449				broadaddr = &ifrbroadaddr.ifr_broadaddr;
450				broadaddr_size = SA_LEN(broadaddr);
451			}
452		} else {
453			/*
454			 * Not a broadcast interface, so no broadcast
455			 * address.
456			 */
457			broadaddr = NULL;
458			broadaddr_size = 0;
459		}
460
461		/*
462		 * Get the destination address for this address on this
463		 * interface (if any).
464		 */
465		if (ifrflags.ifr_flags & IFF_POINTOPOINT) {
466			strncpy(ifrdstaddr.ifr_name, ifrp->ifr_name,
467			    sizeof(ifrdstaddr.ifr_name));
468			memcpy(&ifrdstaddr.ifr_addr, &ifrp->ifr_addr,
469			    sizeof(ifrdstaddr.ifr_addr));
470			if (ioctl(fd, SIOCGIFDSTADDR,
471			    (char *)&ifrdstaddr) < 0) {
472				if (errno == EADDRNOTAVAIL) {
473					/*
474					 * Not available.
475					 */
476					dstaddr = NULL;
477					dstaddr_size = 0;
478				} else {
479					(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
480					    "SIOCGIFDSTADDR: %.*s: %s",
481					    (int)sizeof(ifrdstaddr.ifr_name),
482					    ifrdstaddr.ifr_name,
483					    pcap_strerror(errno));
484					ret = -1;
485					break;
486				}
487			} else {
488				dstaddr = &ifrdstaddr.ifr_dstaddr;
489				dstaddr_size = SA_LEN(dstaddr);
490			}
491		} else {
492			/*
493			 * Not a point-to-point interface, so no destination
494			 * address.
495			 */
496			dstaddr = NULL;
497			dstaddr_size = 0;
498		}
499
500#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
501		/*
502		 * If this entry has a colon followed by a number at
503		 * the end, it's a logical interface.  Those are just
504		 * the way you assign multiple IP addresses to a real
505		 * interface, so an entry for a logical interface should
506		 * be treated like the entry for the real interface;
507		 * we do that by stripping off the ":" and the number.
508		 */
509		p = strchr(ifrp->ifr_name, ':');
510		if (p != NULL) {
511			/*
512			 * We have a ":"; is it followed by a number?
513			 */
514			q = p + 1;
515			while (isdigit((unsigned char)*q))
516				q++;
517			if (*q == '\0') {
518				/*
519				 * All digits after the ":" until the end.
520				 * Strip off the ":" and everything after
521				 * it.
522				 */
523				*p = '\0';
524			}
525		}
526#endif
527
528		/*
529		 * Add information for this address to the list.
530		 */
531		if (add_addr_to_iflist(&devlist, ifrp->ifr_name,
532		    ifrflags.ifr_flags, &ifrp->ifr_addr,
533		    SA_LEN(&ifrp->ifr_addr), netmask, netmask_size,
534		    broadaddr, broadaddr_size, dstaddr, dstaddr_size,
535		    errbuf) < 0) {
536			ret = -1;
537			break;
538		}
539	}
540	free(buf);
541
542#ifdef HAVE_PROC_NET_DEV
543	if (ret != -1) {
544		/*
545		 * We haven't had any errors yet; now read "/proc/net/dev",
546		 * and add to the list of interfaces all interfaces listed
547		 * there that we don't already have, because, on Linux,
548		 * SIOCGIFCONF reports only interfaces with IPv4 addresses,
549		 * so you need to read "/proc/net/dev" to get the names of
550		 * the rest of the interfaces.
551		 */
552		ret = scan_proc_net_dev(&devlist, fd, errbuf);
553	}
554#endif
555	(void)close(fd);
556
557	if (ret != -1) {
558		/*
559		 * We haven't had any errors yet; do any platform-specific
560		 * operations to add devices.
561		 */
562		if (pcap_platform_finddevs(&devlist, errbuf) < 0)
563			ret = -1;
564	}
565
566	if (ret == -1) {
567		/*
568		 * We had an error; free the list we've been constructing.
569		 */
570		if (devlist != NULL) {
571			pcap_freealldevs(devlist);
572			devlist = NULL;
573		}
574	}
575
576	*alldevsp = devlist;
577	return (ret);
578}
579