xref: /openbsd-src/lib/libpcap/fad-getad.c (revision 99d1c811e6ea66234bf110e32c73246e975f38bf)
1a878b819Sdjm /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
2a878b819Sdjm /*
3a878b819Sdjm  * Copyright (c) 1994, 1995, 1996, 1997, 1998
4a878b819Sdjm  *	The Regents of the University of California.  All rights reserved.
5a878b819Sdjm  *
6a878b819Sdjm  * Redistribution and use in source and binary forms, with or without
7a878b819Sdjm  * modification, are permitted provided that the following conditions
8a878b819Sdjm  * are met:
9a878b819Sdjm  * 1. Redistributions of source code must retain the above copyright
10a878b819Sdjm  *    notice, this list of conditions and the following disclaimer.
11a878b819Sdjm  * 2. Redistributions in binary form must reproduce the above copyright
12a878b819Sdjm  *    notice, this list of conditions and the following disclaimer in the
13a878b819Sdjm  *    documentation and/or other materials provided with the distribution.
14a878b819Sdjm  * 3. All advertising materials mentioning features or use of this software
15a878b819Sdjm  *    must display the following acknowledgement:
16a878b819Sdjm  *	This product includes software developed by the Computer Systems
17a878b819Sdjm  *	Engineering Group at Lawrence Berkeley Laboratory.
18a878b819Sdjm  * 4. Neither the name of the University nor of the Laboratory may be used
19a878b819Sdjm  *    to endorse or promote products derived from this software without
20a878b819Sdjm  *    specific prior written permission.
21a878b819Sdjm  *
22a878b819Sdjm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23a878b819Sdjm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24a878b819Sdjm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25a878b819Sdjm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26a878b819Sdjm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27a878b819Sdjm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28a878b819Sdjm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29a878b819Sdjm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30a878b819Sdjm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31a878b819Sdjm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32a878b819Sdjm  * SUCH DAMAGE.
33a878b819Sdjm  */
34a878b819Sdjm 
35a878b819Sdjm #include <sys/types.h>
36a878b819Sdjm #include <sys/socket.h>
37a878b819Sdjm #include <netinet/in.h>
38a878b819Sdjm 
39a878b819Sdjm #include <net/if.h>
40a878b819Sdjm 
41a878b819Sdjm #include <ctype.h>
42a878b819Sdjm #include <errno.h>
43a878b819Sdjm #include <stdio.h>
44a878b819Sdjm #include <stdlib.h>
45a878b819Sdjm #include <string.h>
46a878b819Sdjm #include <ifaddrs.h>
47a878b819Sdjm #include <limits.h>
48a878b819Sdjm 
49a878b819Sdjm #include "pcap-int.h"
50a878b819Sdjm 
51a878b819Sdjm static struct sockaddr *
52a878b819Sdjm dup_sockaddr(struct sockaddr *sa, size_t sa_length)
53a878b819Sdjm {
54a878b819Sdjm 	struct sockaddr *newsa;
55a878b819Sdjm 
56a878b819Sdjm 	if ((newsa = malloc(sa_length)) == NULL)
57a878b819Sdjm 		return (NULL);
58a878b819Sdjm 	return (memcpy(newsa, sa, sa_length));
59a878b819Sdjm }
60a878b819Sdjm 
61a878b819Sdjm static int
62a878b819Sdjm get_instance(const char *name)
63a878b819Sdjm {
64*99d1c811Sop 	const char *cp, *endcp, *errstr;
65a878b819Sdjm 	int n;
66a878b819Sdjm 
67a878b819Sdjm 	if (strcmp(name, "any") == 0) {
68a878b819Sdjm 		/*
69a878b819Sdjm 		 * Give the "any" device an artificially high instance
70a878b819Sdjm 		 * number, so it shows up after all other non-loopback
71a878b819Sdjm 		 * interfaces.
72a878b819Sdjm 		 */
73a878b819Sdjm 		return INT_MAX;
74a878b819Sdjm 	}
75a878b819Sdjm 
76a878b819Sdjm 	endcp = name + strlen(name);
77a878b819Sdjm 	for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
78a878b819Sdjm 		continue;
79a878b819Sdjm 
80*99d1c811Sop 	n = strtonum(cp, 0, INT_MAX, &errstr);
81*99d1c811Sop 	if (errstr != NULL)
82*99d1c811Sop 		return -1;
83*99d1c811Sop 	return n;
84a878b819Sdjm }
85a878b819Sdjm 
86a878b819Sdjm static int
87a878b819Sdjm add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
88a878b819Sdjm     u_int flags, const char *description, char *errbuf)
89a878b819Sdjm {
90a878b819Sdjm 	pcap_t *p;
91a878b819Sdjm 	pcap_if_t *curdev, *prevdev, *nextdev;
92a878b819Sdjm 	int this_instance;
93a878b819Sdjm 	size_t len;
94a878b819Sdjm 
95a878b819Sdjm 	/*
96a878b819Sdjm 	 * Can we open this interface for live capture?
97a878b819Sdjm 	 *
98a878b819Sdjm 	 * We do this check so that interfaces that are supplied
99a878b819Sdjm 	 * by the interface enumeration mechanism we're using
100a878b819Sdjm 	 * but that don't support packet capture aren't included
101a878b819Sdjm 	 * in the list.  An example of this is loopback interfaces
102a878b819Sdjm 	 * on Solaris; we don't just omit loopback interfaces
1032c53affbSjmc 	 * because you *can* capture on loopback interfaces on some
104a878b819Sdjm 	 * OSes.
105a878b819Sdjm 	 */
106a878b819Sdjm 	p = pcap_open_live(name, 68, 0, 0, errbuf);
107a878b819Sdjm 	if (p == NULL) {
108a878b819Sdjm 		/*
109a878b819Sdjm 		 * No.  Don't bother including it.
110a878b819Sdjm 		 * Don't treat this as an error, though.
111a878b819Sdjm 		 */
112a878b819Sdjm 		*curdev_ret = NULL;
113a878b819Sdjm 		return (0);
114a878b819Sdjm 	}
115a878b819Sdjm 	pcap_close(p);
116a878b819Sdjm 
117a878b819Sdjm 	/*
118a878b819Sdjm 	 * Is there already an entry in the list for this interface?
119a878b819Sdjm 	 */
120a878b819Sdjm 	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
121a878b819Sdjm 		if (strcmp(name, curdev->name) == 0)
122a878b819Sdjm 			break;	/* yes, we found it */
123a878b819Sdjm 	}
124a878b819Sdjm 	if (curdev == NULL) {
125a878b819Sdjm 		/*
126a878b819Sdjm 		 * No, we didn't find it.
127a878b819Sdjm 		 * Allocate a new entry.
128a878b819Sdjm 		 */
1291492bed3Sjaredy 		curdev = calloc(1, sizeof(pcap_if_t));
130a878b819Sdjm 		if (curdev == NULL) {
131a878b819Sdjm 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
1321492bed3Sjaredy 			    "calloc: %s", pcap_strerror(errno));
1331492bed3Sjaredy 			goto fail;
134a878b819Sdjm 		}
135a878b819Sdjm 
136a878b819Sdjm 		/*
137a878b819Sdjm 		 * Fill in the entry.
138a878b819Sdjm 		 */
139a878b819Sdjm 		curdev->next = NULL;
140a878b819Sdjm 		len = strlen(name) + 1;
141a878b819Sdjm 		curdev->name = malloc(len);
1421492bed3Sjaredy 		if (curdev->name == NULL) {
1431492bed3Sjaredy 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
1441492bed3Sjaredy 			    "malloc: %s", pcap_strerror(errno));
1451492bed3Sjaredy 			goto fail;
1461492bed3Sjaredy 		}
147a878b819Sdjm 		strlcpy(curdev->name, name, len);
148a878b819Sdjm 		if (description != NULL) {
149a878b819Sdjm 			/*
150a878b819Sdjm 			 * We have a description for this interface.
151a878b819Sdjm 			 */
152a878b819Sdjm 			len = strlen(description) + 1;
153a878b819Sdjm 			curdev->description = malloc(len);
1541492bed3Sjaredy 			if (curdev->description == NULL) {
1551492bed3Sjaredy 				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
1561492bed3Sjaredy 				    "malloc: %s", pcap_strerror(errno));
1571492bed3Sjaredy 				goto fail;
1581492bed3Sjaredy 			}
159a878b819Sdjm 			strlcpy(curdev->description, description, len);
160a878b819Sdjm 		}
161a878b819Sdjm 		curdev->addresses = NULL;	/* list starts out as empty */
162a878b819Sdjm 		curdev->flags = 0;
163a878b819Sdjm 		if (ISLOOPBACK(name, flags))
164a878b819Sdjm 			curdev->flags |= PCAP_IF_LOOPBACK;
165a878b819Sdjm 
166a878b819Sdjm 		/*
167a878b819Sdjm 		 * Add it to the list, in the appropriate location.
168a878b819Sdjm 		 * First, get the instance number of this interface.
169a878b819Sdjm 		 */
170*99d1c811Sop 		if ((this_instance = get_instance(name)) == -1) {
171*99d1c811Sop 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
172*99d1c811Sop 			    "malformed device name: %s", name);
173*99d1c811Sop 			goto fail;
174*99d1c811Sop 		}
175a878b819Sdjm 
176a878b819Sdjm 		/*
177a878b819Sdjm 		 * Now look for the last interface with an instance number
178a878b819Sdjm 		 * less than or equal to the new interface's instance
179a878b819Sdjm 		 * number - except that non-loopback interfaces are
180a878b819Sdjm 		 * arbitrarily treated as having interface numbers less
181a878b819Sdjm 		 * than those of loopback interfaces, so the loopback
182a878b819Sdjm 		 * interfaces are put at the end of the list.
183a878b819Sdjm 		 *
184a878b819Sdjm 		 * We start with "prevdev" being NULL, meaning we're before
185a878b819Sdjm 		 * the first element in the list.
186a878b819Sdjm 		 */
187a878b819Sdjm 		prevdev = NULL;
188a878b819Sdjm 		for (;;) {
189a878b819Sdjm 			/*
190a878b819Sdjm 			 * Get the interface after this one.
191a878b819Sdjm 			 */
192a878b819Sdjm 			if (prevdev == NULL) {
193a878b819Sdjm 				/*
194a878b819Sdjm 				 * The next element is the first element.
195a878b819Sdjm 				 */
196a878b819Sdjm 				nextdev = *alldevs;
197a878b819Sdjm 			} else
198a878b819Sdjm 				nextdev = prevdev->next;
199a878b819Sdjm 
200a878b819Sdjm 			/*
201a878b819Sdjm 			 * Are we at the end of the list?
202a878b819Sdjm 			 */
203a878b819Sdjm 			if (nextdev == NULL) {
204a878b819Sdjm 				/*
205a878b819Sdjm 				 * Yes - we have to put the new entry
206a878b819Sdjm 				 * after "prevdev".
207a878b819Sdjm 				 */
208a878b819Sdjm 				break;
209a878b819Sdjm 			}
210a878b819Sdjm 
211a878b819Sdjm 			/*
212a878b819Sdjm 			 * Is the new interface a non-loopback interface
213a878b819Sdjm 			 * and the next interface a loopback interface?
214a878b819Sdjm 			 */
215a878b819Sdjm 			if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
216a878b819Sdjm 			    (nextdev->flags & PCAP_IF_LOOPBACK)) {
217a878b819Sdjm 				/*
218a878b819Sdjm 				 * Yes, we should put the new entry
219a878b819Sdjm 				 * before "nextdev", i.e. after "prevdev".
220a878b819Sdjm 				 */
221a878b819Sdjm 				break;
222a878b819Sdjm 			}
223a878b819Sdjm 
224a878b819Sdjm 			/*
225a878b819Sdjm 			 * Is the new interface's instance number less
226a878b819Sdjm 			 * than the next interface's instance number,
227a878b819Sdjm 			 * and is it the case that the new interface is a
228a878b819Sdjm 			 * non-loopback interface or the next interface is
229a878b819Sdjm 			 * a loopback interface?
230a878b819Sdjm 			 *
231a878b819Sdjm 			 * (The goal of both loopback tests is to make
232a878b819Sdjm 			 * sure that we never put a loopback interface
233a878b819Sdjm 			 * before any non-loopback interface and that we
234a878b819Sdjm 			 * always put a non-loopback interface before all
235a878b819Sdjm 			 * loopback interfaces.)
236a878b819Sdjm 			 */
237a878b819Sdjm 			if (this_instance < get_instance(nextdev->name) &&
238a878b819Sdjm 			    (!(curdev->flags & PCAP_IF_LOOPBACK) ||
239a878b819Sdjm 			       (nextdev->flags & PCAP_IF_LOOPBACK))) {
240a878b819Sdjm 				/*
241a878b819Sdjm 				 * Yes - we should put the new entry
242a878b819Sdjm 				 * before "nextdev", i.e. after "prevdev".
243a878b819Sdjm 				 */
244a878b819Sdjm 				break;
245a878b819Sdjm 			}
246a878b819Sdjm 
247a878b819Sdjm 			prevdev = nextdev;
248a878b819Sdjm 		}
249a878b819Sdjm 
250a878b819Sdjm 		/*
251a878b819Sdjm 		 * Insert before "nextdev".
252a878b819Sdjm 		 */
253a878b819Sdjm 		curdev->next = nextdev;
254a878b819Sdjm 
255a878b819Sdjm 		/*
256a878b819Sdjm 		 * Insert after "prevdev" - unless "prevdev" is null,
257a878b819Sdjm 		 * in which case this is the first interface.
258a878b819Sdjm 		 */
259a878b819Sdjm 		if (prevdev == NULL) {
260a878b819Sdjm 			/*
261a878b819Sdjm 			 * This is the first interface.  Pass back a
262a878b819Sdjm 			 * pointer to it, and put "curdev" before
263a878b819Sdjm 			 * "nextdev".
264a878b819Sdjm 			 */
265a878b819Sdjm 			*alldevs = curdev;
266a878b819Sdjm 		} else
267a878b819Sdjm 			prevdev->next = curdev;
268a878b819Sdjm 	}
269a878b819Sdjm 
270a878b819Sdjm 	*curdev_ret = curdev;
271a878b819Sdjm 	return (0);
2721492bed3Sjaredy 
2731492bed3Sjaredy fail:
2741492bed3Sjaredy 	if (curdev != NULL) {
2751492bed3Sjaredy 		free(curdev->name);
2761492bed3Sjaredy 		free(curdev->description);
2771492bed3Sjaredy 		free(curdev);
2781492bed3Sjaredy 	}
2791492bed3Sjaredy 	return (-1);
280a878b819Sdjm }
281a878b819Sdjm 
282a878b819Sdjm static int
283a878b819Sdjm add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
284a878b819Sdjm     struct sockaddr *addr, size_t addr_size,
285a878b819Sdjm     struct sockaddr *netmask, size_t netmask_size,
286a878b819Sdjm     struct sockaddr *broadaddr, size_t broadaddr_size,
287a878b819Sdjm     struct sockaddr *dstaddr, size_t dstaddr_size,
288a878b819Sdjm     char *errbuf)
289a878b819Sdjm {
290a878b819Sdjm 	pcap_if_t *curdev;
291a878b819Sdjm 	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
292a878b819Sdjm 
293a878b819Sdjm 	if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
294a878b819Sdjm 		/*
295a878b819Sdjm 		 * Error - give up.
296a878b819Sdjm 		 */
297a878b819Sdjm 		return (-1);
298a878b819Sdjm 	}
299a878b819Sdjm 	if (curdev == NULL) {
300a878b819Sdjm 		/*
301a878b819Sdjm 		 * Device wasn't added because it can't be opened.
302a878b819Sdjm 		 * Not a fatal error.
303a878b819Sdjm 		 */
304a878b819Sdjm 		return (0);
305a878b819Sdjm 	}
306a878b819Sdjm 
307a878b819Sdjm 	/*
308a878b819Sdjm 	 * "curdev" is an entry for this interface; add an entry for this
309a878b819Sdjm 	 * address to its list of addresses.
310a878b819Sdjm 	 *
311a878b819Sdjm 	 * Allocate the new entry and fill it in.
312a878b819Sdjm 	 */
3131492bed3Sjaredy 	curaddr = calloc(1, sizeof(pcap_addr_t));
314a878b819Sdjm 	if (curaddr == NULL) {
315a878b819Sdjm 		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
3161492bed3Sjaredy 		    "calloc: %s", pcap_strerror(errno));
3171492bed3Sjaredy 		goto fail;
318a878b819Sdjm 	}
319a878b819Sdjm 
320a878b819Sdjm 	curaddr->next = NULL;
321a878b819Sdjm 	if (addr != NULL) {
322a878b819Sdjm 		curaddr->addr = dup_sockaddr(addr, addr_size);
323a878b819Sdjm 		if (curaddr->addr == NULL) {
324a878b819Sdjm 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
325a878b819Sdjm 			    "malloc: %s", pcap_strerror(errno));
3261492bed3Sjaredy 			goto fail;
327a878b819Sdjm 		}
3281492bed3Sjaredy 	}
329a878b819Sdjm 
330a878b819Sdjm 	if (netmask != NULL) {
331a878b819Sdjm 		curaddr->netmask = dup_sockaddr(netmask, netmask_size);
332a878b819Sdjm 		if (curaddr->netmask == NULL) {
333a878b819Sdjm 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
334a878b819Sdjm 			    "malloc: %s", pcap_strerror(errno));
3351492bed3Sjaredy 			goto fail;
336a878b819Sdjm 		}
3371492bed3Sjaredy 	}
338a878b819Sdjm 
339a878b819Sdjm 	if (broadaddr != NULL) {
340a878b819Sdjm 		curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
341a878b819Sdjm 		if (curaddr->broadaddr == NULL) {
342a878b819Sdjm 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
343a878b819Sdjm 			    "malloc: %s", pcap_strerror(errno));
3441492bed3Sjaredy 			goto fail;
345a878b819Sdjm 		}
3461492bed3Sjaredy 	}
347a878b819Sdjm 
348a878b819Sdjm 	if (dstaddr != NULL) {
349a878b819Sdjm 		curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
350a878b819Sdjm 		if (curaddr->dstaddr == NULL) {
351a878b819Sdjm 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
352a878b819Sdjm 			    "malloc: %s", pcap_strerror(errno));
3531492bed3Sjaredy 			goto fail;
354a878b819Sdjm 		}
3551492bed3Sjaredy 	}
356a878b819Sdjm 
357a878b819Sdjm 	/*
358a878b819Sdjm 	 * Find the end of the list of addresses.
359a878b819Sdjm 	 */
360a878b819Sdjm 	for (prevaddr = curdev->addresses; prevaddr != NULL;
361a878b819Sdjm 	    prevaddr = nextaddr) {
362a878b819Sdjm 		nextaddr = prevaddr->next;
363a878b819Sdjm 		if (nextaddr == NULL) {
364a878b819Sdjm 			/*
365a878b819Sdjm 			 * This is the end of the list.
366a878b819Sdjm 			 */
367a878b819Sdjm 			break;
368a878b819Sdjm 		}
369a878b819Sdjm 	}
370a878b819Sdjm 
371a878b819Sdjm 	if (prevaddr == NULL) {
372a878b819Sdjm 		/*
373a878b819Sdjm 		 * The list was empty; this is the first member.
374a878b819Sdjm 		 */
375a878b819Sdjm 		curdev->addresses = curaddr;
376a878b819Sdjm 	} else {
377a878b819Sdjm 		/*
378a878b819Sdjm 		 * "prevaddr" is the last member of the list; append
379a878b819Sdjm 		 * this member to it.
380a878b819Sdjm 		 */
381a878b819Sdjm 		prevaddr->next = curaddr;
382a878b819Sdjm 	}
383a878b819Sdjm 
384a878b819Sdjm 	return (0);
3851492bed3Sjaredy 
3861492bed3Sjaredy fail:
3871492bed3Sjaredy 	if (curaddr != NULL) {
3881492bed3Sjaredy 		free(curaddr->addr);
3891492bed3Sjaredy 		free(curaddr->netmask);
3901492bed3Sjaredy 		free(curaddr->broadaddr);
3911492bed3Sjaredy 		free(curaddr->dstaddr);
3921492bed3Sjaredy 		free(curaddr);
3931492bed3Sjaredy 	}
3941492bed3Sjaredy 	return (-1);
395a878b819Sdjm }
396a878b819Sdjm 
397a878b819Sdjm /*
398a878b819Sdjm  * Get a list of all interfaces that are up and that we can open.
399a878b819Sdjm  * Returns -1 on error, 0 otherwise.
400a878b819Sdjm  * The list, as returned through "alldevsp", may be null if no interfaces
401a878b819Sdjm  * were up and could be opened.
402a878b819Sdjm  *
403a878b819Sdjm  * This is the implementation used on platforms that have "getifaddrs()".
404a878b819Sdjm  */
405a878b819Sdjm int
406a878b819Sdjm pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
407a878b819Sdjm {
408a878b819Sdjm 	pcap_if_t *devlist = NULL;
409a878b819Sdjm 	struct ifaddrs *ifap, *ifa;
410a878b819Sdjm 	struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
411a878b819Sdjm 	size_t addr_size, broadaddr_size, dstaddr_size;
412a878b819Sdjm 	int ret = 0;
413a878b819Sdjm 
414a878b819Sdjm 	/*
415a878b819Sdjm 	 * Get the list of interface addresses.
416a878b819Sdjm 	 *
417a878b819Sdjm 	 * Note: this won't return information about interfaces
418a878b819Sdjm 	 * with no addresses; are there any such interfaces
419a878b819Sdjm 	 * that would be capable of receiving packets?
420a878b819Sdjm 	 * (Interfaces incapable of receiving packets aren't
421a878b819Sdjm 	 * very interesting from libpcap's point of view.)
422a878b819Sdjm 	 *
423a878b819Sdjm 	 * LAN interfaces will probably have link-layer
424a878b819Sdjm 	 * addresses; I don't know whether all implementations
425a878b819Sdjm 	 * of "getifaddrs()" now, or in the future, will return
426a878b819Sdjm 	 * those.
427a878b819Sdjm 	 */
428a878b819Sdjm 	if (getifaddrs(&ifap) != 0) {
429a878b819Sdjm 		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
430a878b819Sdjm 		    "getifaddrs: %s", pcap_strerror(errno));
431a878b819Sdjm 		return (-1);
432a878b819Sdjm 	}
433a878b819Sdjm 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
434a878b819Sdjm 		/*
435a878b819Sdjm 		 * Is this interface up?
436a878b819Sdjm 		 */
437a878b819Sdjm 		if (!(ifa->ifa_flags & IFF_UP)) {
438a878b819Sdjm 			/*
439a878b819Sdjm 			 * No, so don't add it to the list.
440a878b819Sdjm 			 */
441a878b819Sdjm 			continue;
442a878b819Sdjm 		}
443a878b819Sdjm 
444a878b819Sdjm 		/*
445a878b819Sdjm 		 * "ifa_addr" was apparently null on at least one
446a878b819Sdjm 		 * interface on some system.
447a878b819Sdjm 		 *
448a878b819Sdjm 		 * "ifa_broadaddr" may be non-null even on
449a878b819Sdjm 		 * non-broadcast interfaces, and was null on
450a878b819Sdjm 		 * at least one OpenBSD 3.4 system on at least
451a878b819Sdjm 		 * one interface with IFF_BROADCAST set.
452a878b819Sdjm 		 *
453a878b819Sdjm 		 * "ifa_dstaddr" was, on at least one FreeBSD 4.1
454a878b819Sdjm 		 * system, non-null on a non-point-to-point
455a878b819Sdjm 		 * interface.
456a878b819Sdjm 		 *
457a878b819Sdjm 		 * Therefore, we supply the address and netmask only
458a878b819Sdjm 		 * if "ifa_addr" is non-null (if there's no address,
459a878b819Sdjm 		 * there's obviously no netmask), and supply the
460a878b819Sdjm 		 * broadcast and destination addresses if the appropriate
461a878b819Sdjm 		 * flag is set *and* the appropriate "ifa_" entry doesn't
462a878b819Sdjm 		 * evaluate to a null pointer.
463a878b819Sdjm 		 */
464a878b819Sdjm 		if (ifa->ifa_addr != NULL) {
465a878b819Sdjm 			addr = ifa->ifa_addr;
466a878b819Sdjm 			addr_size = SA_LEN(addr);
467a878b819Sdjm 			netmask = ifa->ifa_netmask;
468a878b819Sdjm 		} else {
469a878b819Sdjm 			addr = NULL;
470a878b819Sdjm 			addr_size = 0;
471a878b819Sdjm 			netmask = NULL;
472a878b819Sdjm 		}
473a878b819Sdjm 		if (ifa->ifa_flags & IFF_BROADCAST &&
474a878b819Sdjm 		    ifa->ifa_broadaddr != NULL) {
475a878b819Sdjm 			broadaddr = ifa->ifa_broadaddr;
476a878b819Sdjm 			broadaddr_size = SA_LEN(broadaddr);
477a878b819Sdjm 		} else {
478a878b819Sdjm 			broadaddr = NULL;
479a878b819Sdjm 			broadaddr_size = 0;
480a878b819Sdjm 		}
481a878b819Sdjm 		if (ifa->ifa_flags & IFF_POINTOPOINT &&
482a878b819Sdjm 		    ifa->ifa_dstaddr != NULL) {
483a878b819Sdjm 			dstaddr = ifa->ifa_dstaddr;
484a878b819Sdjm 			dstaddr_size = SA_LEN(ifa->ifa_dstaddr);
485a878b819Sdjm 		} else {
486a878b819Sdjm 			dstaddr = NULL;
487a878b819Sdjm 			dstaddr_size = 0;
488a878b819Sdjm 		}
489a878b819Sdjm 
490a878b819Sdjm 		/*
491a878b819Sdjm 		 * Add information for this address to the list.
492a878b819Sdjm 		 */
493a878b819Sdjm 		if (add_addr_to_iflist(&devlist, ifa->ifa_name,
494a878b819Sdjm 		    ifa->ifa_flags, addr, addr_size, netmask, addr_size,
495a878b819Sdjm 		    broadaddr, broadaddr_size, dstaddr, dstaddr_size,
496a878b819Sdjm 		    errbuf) < 0) {
497a878b819Sdjm 			ret = -1;
498a878b819Sdjm 			break;
499a878b819Sdjm 		}
500a878b819Sdjm 	}
501a878b819Sdjm 
502a878b819Sdjm 	freeifaddrs(ifap);
503a878b819Sdjm 
504a878b819Sdjm 	if (ret == -1) {
505a878b819Sdjm 		/*
506a878b819Sdjm 		 * We had an error; free the list we've been constructing.
507a878b819Sdjm 		 */
508a878b819Sdjm 		if (devlist != NULL) {
509a878b819Sdjm 			pcap_freealldevs(devlist);
510a878b819Sdjm 			devlist = NULL;
511a878b819Sdjm 		}
512a878b819Sdjm 	}
513a878b819Sdjm 
514a878b819Sdjm 	*alldevsp = devlist;
515a878b819Sdjm 	return (ret);
516a878b819Sdjm }
517