xref: /openbsd-src/lib/libpcap/fad-getad.c (revision 99d1c811e6ea66234bf110e32c73246e975f38bf)
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 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 
39 #include <net/if.h>
40 
41 #include <ctype.h>
42 #include <errno.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <ifaddrs.h>
47 #include <limits.h>
48 
49 #include "pcap-int.h"
50 
51 static struct sockaddr *
52 dup_sockaddr(struct sockaddr *sa, size_t sa_length)
53 {
54 	struct sockaddr *newsa;
55 
56 	if ((newsa = malloc(sa_length)) == NULL)
57 		return (NULL);
58 	return (memcpy(newsa, sa, sa_length));
59 }
60 
61 static int
62 get_instance(const char *name)
63 {
64 	const char *cp, *endcp, *errstr;
65 	int n;
66 
67 	if (strcmp(name, "any") == 0) {
68 		/*
69 		 * Give the "any" device an artificially high instance
70 		 * number, so it shows up after all other non-loopback
71 		 * interfaces.
72 		 */
73 		return INT_MAX;
74 	}
75 
76 	endcp = name + strlen(name);
77 	for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
78 		continue;
79 
80 	n = strtonum(cp, 0, INT_MAX, &errstr);
81 	if (errstr != NULL)
82 		return -1;
83 	return n;
84 }
85 
86 static int
87 add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
88     u_int flags, const char *description, char *errbuf)
89 {
90 	pcap_t *p;
91 	pcap_if_t *curdev, *prevdev, *nextdev;
92 	int this_instance;
93 	size_t len;
94 
95 	/*
96 	 * Can we open this interface for live capture?
97 	 *
98 	 * We do this check so that interfaces that are supplied
99 	 * by the interface enumeration mechanism we're using
100 	 * but that don't support packet capture aren't included
101 	 * in the list.  An example of this is loopback interfaces
102 	 * on Solaris; we don't just omit loopback interfaces
103 	 * because you *can* capture on loopback interfaces on some
104 	 * OSes.
105 	 */
106 	p = pcap_open_live(name, 68, 0, 0, errbuf);
107 	if (p == NULL) {
108 		/*
109 		 * No.  Don't bother including it.
110 		 * Don't treat this as an error, though.
111 		 */
112 		*curdev_ret = NULL;
113 		return (0);
114 	}
115 	pcap_close(p);
116 
117 	/*
118 	 * Is there already an entry in the list for this interface?
119 	 */
120 	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
121 		if (strcmp(name, curdev->name) == 0)
122 			break;	/* yes, we found it */
123 	}
124 	if (curdev == NULL) {
125 		/*
126 		 * No, we didn't find it.
127 		 * Allocate a new entry.
128 		 */
129 		curdev = calloc(1, sizeof(pcap_if_t));
130 		if (curdev == NULL) {
131 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
132 			    "calloc: %s", pcap_strerror(errno));
133 			goto fail;
134 		}
135 
136 		/*
137 		 * Fill in the entry.
138 		 */
139 		curdev->next = NULL;
140 		len = strlen(name) + 1;
141 		curdev->name = malloc(len);
142 		if (curdev->name == NULL) {
143 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
144 			    "malloc: %s", pcap_strerror(errno));
145 			goto fail;
146 		}
147 		strlcpy(curdev->name, name, len);
148 		if (description != NULL) {
149 			/*
150 			 * We have a description for this interface.
151 			 */
152 			len = strlen(description) + 1;
153 			curdev->description = malloc(len);
154 			if (curdev->description == NULL) {
155 				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
156 				    "malloc: %s", pcap_strerror(errno));
157 				goto fail;
158 			}
159 			strlcpy(curdev->description, description, len);
160 		}
161 		curdev->addresses = NULL;	/* list starts out as empty */
162 		curdev->flags = 0;
163 		if (ISLOOPBACK(name, flags))
164 			curdev->flags |= PCAP_IF_LOOPBACK;
165 
166 		/*
167 		 * Add it to the list, in the appropriate location.
168 		 * First, get the instance number of this interface.
169 		 */
170 		if ((this_instance = get_instance(name)) == -1) {
171 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
172 			    "malformed device name: %s", name);
173 			goto fail;
174 		}
175 
176 		/*
177 		 * Now look for the last interface with an instance number
178 		 * less than or equal to the new interface's instance
179 		 * number - except that non-loopback interfaces are
180 		 * arbitrarily treated as having interface numbers less
181 		 * than those of loopback interfaces, so the loopback
182 		 * interfaces are put at the end of the list.
183 		 *
184 		 * We start with "prevdev" being NULL, meaning we're before
185 		 * the first element in the list.
186 		 */
187 		prevdev = NULL;
188 		for (;;) {
189 			/*
190 			 * Get the interface after this one.
191 			 */
192 			if (prevdev == NULL) {
193 				/*
194 				 * The next element is the first element.
195 				 */
196 				nextdev = *alldevs;
197 			} else
198 				nextdev = prevdev->next;
199 
200 			/*
201 			 * Are we at the end of the list?
202 			 */
203 			if (nextdev == NULL) {
204 				/*
205 				 * Yes - we have to put the new entry
206 				 * after "prevdev".
207 				 */
208 				break;
209 			}
210 
211 			/*
212 			 * Is the new interface a non-loopback interface
213 			 * and the next interface a loopback interface?
214 			 */
215 			if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
216 			    (nextdev->flags & PCAP_IF_LOOPBACK)) {
217 				/*
218 				 * Yes, we should put the new entry
219 				 * before "nextdev", i.e. after "prevdev".
220 				 */
221 				break;
222 			}
223 
224 			/*
225 			 * Is the new interface's instance number less
226 			 * than the next interface's instance number,
227 			 * and is it the case that the new interface is a
228 			 * non-loopback interface or the next interface is
229 			 * a loopback interface?
230 			 *
231 			 * (The goal of both loopback tests is to make
232 			 * sure that we never put a loopback interface
233 			 * before any non-loopback interface and that we
234 			 * always put a non-loopback interface before all
235 			 * loopback interfaces.)
236 			 */
237 			if (this_instance < get_instance(nextdev->name) &&
238 			    (!(curdev->flags & PCAP_IF_LOOPBACK) ||
239 			       (nextdev->flags & PCAP_IF_LOOPBACK))) {
240 				/*
241 				 * Yes - we should put the new entry
242 				 * before "nextdev", i.e. after "prevdev".
243 				 */
244 				break;
245 			}
246 
247 			prevdev = nextdev;
248 		}
249 
250 		/*
251 		 * Insert before "nextdev".
252 		 */
253 		curdev->next = nextdev;
254 
255 		/*
256 		 * Insert after "prevdev" - unless "prevdev" is null,
257 		 * in which case this is the first interface.
258 		 */
259 		if (prevdev == NULL) {
260 			/*
261 			 * This is the first interface.  Pass back a
262 			 * pointer to it, and put "curdev" before
263 			 * "nextdev".
264 			 */
265 			*alldevs = curdev;
266 		} else
267 			prevdev->next = curdev;
268 	}
269 
270 	*curdev_ret = curdev;
271 	return (0);
272 
273 fail:
274 	if (curdev != NULL) {
275 		free(curdev->name);
276 		free(curdev->description);
277 		free(curdev);
278 	}
279 	return (-1);
280 }
281 
282 static int
283 add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
284     struct sockaddr *addr, size_t addr_size,
285     struct sockaddr *netmask, size_t netmask_size,
286     struct sockaddr *broadaddr, size_t broadaddr_size,
287     struct sockaddr *dstaddr, size_t dstaddr_size,
288     char *errbuf)
289 {
290 	pcap_if_t *curdev;
291 	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
292 
293 	if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
294 		/*
295 		 * Error - give up.
296 		 */
297 		return (-1);
298 	}
299 	if (curdev == NULL) {
300 		/*
301 		 * Device wasn't added because it can't be opened.
302 		 * Not a fatal error.
303 		 */
304 		return (0);
305 	}
306 
307 	/*
308 	 * "curdev" is an entry for this interface; add an entry for this
309 	 * address to its list of addresses.
310 	 *
311 	 * Allocate the new entry and fill it in.
312 	 */
313 	curaddr = calloc(1, sizeof(pcap_addr_t));
314 	if (curaddr == NULL) {
315 		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
316 		    "calloc: %s", pcap_strerror(errno));
317 		goto fail;
318 	}
319 
320 	curaddr->next = NULL;
321 	if (addr != NULL) {
322 		curaddr->addr = dup_sockaddr(addr, addr_size);
323 		if (curaddr->addr == NULL) {
324 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
325 			    "malloc: %s", pcap_strerror(errno));
326 			goto fail;
327 		}
328 	}
329 
330 	if (netmask != NULL) {
331 		curaddr->netmask = dup_sockaddr(netmask, netmask_size);
332 		if (curaddr->netmask == NULL) {
333 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
334 			    "malloc: %s", pcap_strerror(errno));
335 			goto fail;
336 		}
337 	}
338 
339 	if (broadaddr != NULL) {
340 		curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
341 		if (curaddr->broadaddr == NULL) {
342 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
343 			    "malloc: %s", pcap_strerror(errno));
344 			goto fail;
345 		}
346 	}
347 
348 	if (dstaddr != NULL) {
349 		curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
350 		if (curaddr->dstaddr == NULL) {
351 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
352 			    "malloc: %s", pcap_strerror(errno));
353 			goto fail;
354 		}
355 	}
356 
357 	/*
358 	 * Find the end of the list of addresses.
359 	 */
360 	for (prevaddr = curdev->addresses; prevaddr != NULL;
361 	    prevaddr = nextaddr) {
362 		nextaddr = prevaddr->next;
363 		if (nextaddr == NULL) {
364 			/*
365 			 * This is the end of the list.
366 			 */
367 			break;
368 		}
369 	}
370 
371 	if (prevaddr == NULL) {
372 		/*
373 		 * The list was empty; this is the first member.
374 		 */
375 		curdev->addresses = curaddr;
376 	} else {
377 		/*
378 		 * "prevaddr" is the last member of the list; append
379 		 * this member to it.
380 		 */
381 		prevaddr->next = curaddr;
382 	}
383 
384 	return (0);
385 
386 fail:
387 	if (curaddr != NULL) {
388 		free(curaddr->addr);
389 		free(curaddr->netmask);
390 		free(curaddr->broadaddr);
391 		free(curaddr->dstaddr);
392 		free(curaddr);
393 	}
394 	return (-1);
395 }
396 
397 /*
398  * Get a list of all interfaces that are up and that we can open.
399  * Returns -1 on error, 0 otherwise.
400  * The list, as returned through "alldevsp", may be null if no interfaces
401  * were up and could be opened.
402  *
403  * This is the implementation used on platforms that have "getifaddrs()".
404  */
405 int
406 pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
407 {
408 	pcap_if_t *devlist = NULL;
409 	struct ifaddrs *ifap, *ifa;
410 	struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
411 	size_t addr_size, broadaddr_size, dstaddr_size;
412 	int ret = 0;
413 
414 	/*
415 	 * Get the list of interface addresses.
416 	 *
417 	 * Note: this won't return information about interfaces
418 	 * with no addresses; are there any such interfaces
419 	 * that would be capable of receiving packets?
420 	 * (Interfaces incapable of receiving packets aren't
421 	 * very interesting from libpcap's point of view.)
422 	 *
423 	 * LAN interfaces will probably have link-layer
424 	 * addresses; I don't know whether all implementations
425 	 * of "getifaddrs()" now, or in the future, will return
426 	 * those.
427 	 */
428 	if (getifaddrs(&ifap) != 0) {
429 		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
430 		    "getifaddrs: %s", pcap_strerror(errno));
431 		return (-1);
432 	}
433 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
434 		/*
435 		 * Is this interface up?
436 		 */
437 		if (!(ifa->ifa_flags & IFF_UP)) {
438 			/*
439 			 * No, so don't add it to the list.
440 			 */
441 			continue;
442 		}
443 
444 		/*
445 		 * "ifa_addr" was apparently null on at least one
446 		 * interface on some system.
447 		 *
448 		 * "ifa_broadaddr" may be non-null even on
449 		 * non-broadcast interfaces, and was null on
450 		 * at least one OpenBSD 3.4 system on at least
451 		 * one interface with IFF_BROADCAST set.
452 		 *
453 		 * "ifa_dstaddr" was, on at least one FreeBSD 4.1
454 		 * system, non-null on a non-point-to-point
455 		 * interface.
456 		 *
457 		 * Therefore, we supply the address and netmask only
458 		 * if "ifa_addr" is non-null (if there's no address,
459 		 * there's obviously no netmask), and supply the
460 		 * broadcast and destination addresses if the appropriate
461 		 * flag is set *and* the appropriate "ifa_" entry doesn't
462 		 * evaluate to a null pointer.
463 		 */
464 		if (ifa->ifa_addr != NULL) {
465 			addr = ifa->ifa_addr;
466 			addr_size = SA_LEN(addr);
467 			netmask = ifa->ifa_netmask;
468 		} else {
469 			addr = NULL;
470 			addr_size = 0;
471 			netmask = NULL;
472 		}
473 		if (ifa->ifa_flags & IFF_BROADCAST &&
474 		    ifa->ifa_broadaddr != NULL) {
475 			broadaddr = ifa->ifa_broadaddr;
476 			broadaddr_size = SA_LEN(broadaddr);
477 		} else {
478 			broadaddr = NULL;
479 			broadaddr_size = 0;
480 		}
481 		if (ifa->ifa_flags & IFF_POINTOPOINT &&
482 		    ifa->ifa_dstaddr != NULL) {
483 			dstaddr = ifa->ifa_dstaddr;
484 			dstaddr_size = SA_LEN(ifa->ifa_dstaddr);
485 		} else {
486 			dstaddr = NULL;
487 			dstaddr_size = 0;
488 		}
489 
490 		/*
491 		 * Add information for this address to the list.
492 		 */
493 		if (add_addr_to_iflist(&devlist, ifa->ifa_name,
494 		    ifa->ifa_flags, addr, addr_size, netmask, addr_size,
495 		    broadaddr, broadaddr_size, dstaddr, dstaddr_size,
496 		    errbuf) < 0) {
497 			ret = -1;
498 			break;
499 		}
500 	}
501 
502 	freeifaddrs(ifap);
503 
504 	if (ret == -1) {
505 		/*
506 		 * We had an error; free the list we've been constructing.
507 		 */
508 		if (devlist != NULL) {
509 			pcap_freealldevs(devlist);
510 			devlist = NULL;
511 		}
512 	}
513 
514 	*alldevsp = devlist;
515 	return (ret);
516 }
517