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 *
dup_sockaddr(struct sockaddr * sa,size_t sa_length)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
get_instance(const char * name)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
add_or_find_if(pcap_if_t ** curdev_ret,pcap_if_t ** alldevs,const char * name,u_int flags,const char * description,char * errbuf)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
add_addr_to_iflist(pcap_if_t ** alldevs,const char * name,u_int flags,struct sockaddr * addr,size_t addr_size,struct sockaddr * netmask,size_t netmask_size,struct sockaddr * broadaddr,size_t broadaddr_size,struct sockaddr * dstaddr,size_t dstaddr_size,char * errbuf)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
pcap_findalldevs(pcap_if_t ** alldevsp,char * errbuf)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 }
514