GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libpcap/fad-getad.c Lines: 0 145 0.0 %
Date: 2017-11-07 Branches: 0 92 0.0 %

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