]> The Tcpdump Group git mirrors - libpcap/blob - fad-helpers.c
ea9011fe90f8f08ff500ab821ee4fa0e620273ef
[libpcap] / fad-helpers.c
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 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #ifdef _WIN32
40 #include <pcap-stdinc.h>
41 #else /* _WIN32 */
42
43 #include <sys/param.h>
44 #ifndef MSDOS
45 #include <sys/file.h>
46 #endif
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
49 #ifdef HAVE_SYS_SOCKIO_H
50 #include <sys/sockio.h>
51 #endif
52
53 struct mbuf; /* Squelch compiler warnings on some platforms for */
54 struct rtentry; /* declarations in <net/if.h> */
55 #include <net/if.h>
56 #include <netinet/in.h>
57 #endif /* _WIN32 */
58
59 #include <ctype.h>
60 #include <errno.h>
61 #include <memory.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #if !defined(_WIN32) && !defined(__BORLANDC__)
66 #include <unistd.h>
67 #endif /* !_WIN32 && !__BORLANDC__ */
68 #ifdef HAVE_LIMITS_H
69 #include <limits.h>
70 #else
71 #define INT_MAX 2147483647
72 #endif
73
74 #include "pcap-int.h"
75
76 #ifdef HAVE_OS_PROTO_H
77 #include "os-proto.h"
78 #endif
79
80 #ifndef _WIN32
81 /* Not all systems have IFF_LOOPBACK */
82 #ifdef IFF_LOOPBACK
83 #define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
84 #else
85 #define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
86 (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
87 #endif
88
89 #ifdef IFF_UP
90 #define ISUP(flags) ((flags) & IFF_UP)
91 #else
92 #define ISUP(flags) 0
93 #endif
94
95 #ifdef IFF_RUNNING
96 #define ISRUNNING(flags) ((flags) & IFF_RUNNING)
97 #else
98 #define ISRUNNING(flags) 0
99 #endif
100
101 /*
102 * Map UN*X-style interface flags to libpcap flags.
103 */
104 bpf_u_int32
105 if_flags_to_pcap_flags(const char *name _U_, u_int if_flags)
106 {
107 bpf_u_int32 pcap_flags;
108
109 pcap_flags = 0;
110 if (ISLOOPBACK(name, if_flags))
111 pcap_flags |= PCAP_IF_LOOPBACK;
112 if (ISUP(if_flags))
113 pcap_flags |= PCAP_IF_UP;
114 if (ISRUNNING(if_flags))
115 pcap_flags |= PCAP_IF_RUNNING;
116 return (pcap_flags);
117 }
118 #endif
119
120 static struct sockaddr *
121 dup_sockaddr(struct sockaddr *sa, size_t sa_length)
122 {
123 struct sockaddr *newsa;
124
125 if ((newsa = malloc(sa_length)) == NULL)
126 return (NULL);
127 return (memcpy(newsa, sa, sa_length));
128 }
129
130 /*
131 * Construct a "figure of merit" for an interface, for use when sorting
132 * the list of interfaces, in which interfaces that are up are superior
133 * to interfaces that aren't up, interfaces that are up and running are
134 * superior to interfaces that are up but not running, and non-loopback
135 * interfaces that are up and running are superior to loopback interfaces,
136 * and interfaces with the same flags have a figure of merit that's higher
137 * the lower the instance number.
138 *
139 * The goal is to try to put the interfaces most likely to be useful for
140 * capture at the beginning of the list.
141 *
142 * The figure of merit, which is lower the "better" the interface is,
143 * has the uppermost bit set if the interface isn't running, the bit
144 * below that set if the interface isn't up, the bit below that set
145 * if the interface is a loopback interface, and the interface index
146 * in the 29 bits below that. (Yes, we assume u_int is 32 bits.)
147 */
148 static u_int
149 get_figure_of_merit(pcap_if_t *dev)
150 {
151 const char *cp;
152 u_int n;
153
154 if (strcmp(dev->name, "any") == 0) {
155 /*
156 * Give the "any" device an artificially high instance
157 * number, so it shows up after all other non-loopback
158 * interfaces.
159 */
160 n = 0x1FFFFFFF; /* 29 all-1 bits */
161 } else {
162 /*
163 * A number at the end of the device name string is
164 * assumed to be an instance number. Add 1 to the
165 * instance number, and use 0 for "no instance
166 * number", so we don't put "no instance number"
167 * devices and "instance 0" devices together.
168 */
169 cp = dev->name + strlen(dev->name) - 1;
170 while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
171 cp--;
172 if (*cp >= '0' && *cp <= '9')
173 n = atoi(cp) + 1;
174 else
175 n = 0;
176 }
177 if (!(dev->flags & PCAP_IF_RUNNING))
178 n |= 0x80000000;
179 if (!(dev->flags & PCAP_IF_UP))
180 n |= 0x40000000;
181 if (dev->flags & PCAP_IF_LOOPBACK)
182 n |= 0x20000000;
183 return (n);
184 }
185
186 #ifndef _WIN32
187 /*
188 * Try to get a description for a given device.
189 * Returns a mallocated description if it could and NULL if it couldn't.
190 *
191 * XXX - on FreeBSDs that support it, should it get the sysctl named
192 * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
193 * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
194 * with my Cisco 350 card, so the name isn't entirely descriptive. The
195 * "dev.an.0.%pnpinfo" has a better description, although one might argue
196 * that the problem is really a driver bug - if it can find out that it's
197 * a Cisco 340 or 350, rather than an old Aironet card, it should use
198 * that in the description.
199 *
200 * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? FreeBSD
201 * and OpenBSD let you get a description, but it's not generated by the OS,
202 * it's set with another ioctl that ifconfig supports; we use that to get
203 * a description in FreeBSD and OpenBSD, but if there is no such
204 * description available, it still might be nice to get some description
205 * string based on the device type or something such as that.
206 *
207 * In OS X, the System Configuration framework can apparently return
208 * names in 10.4 and later.
209 *
210 * It also appears that freedesktop.org's HAL offers an "info.product"
211 * string, but the HAL specification says it "should not be used in any
212 * UI" and "subsystem/capability specific properties" should be used
213 * instead and, in any case, I think HAL is being deprecated in
214 * favor of other stuff such as DeviceKit. DeviceKit doesn't appear
215 * to have any obvious product information for devices, but maybe
216 * I haven't looked hard enough.
217 *
218 * Using the System Configuration framework, or HAL, or DeviceKit, or
219 * whatever, would require that libpcap applications be linked with
220 * the frameworks/libraries in question. That shouldn't be a problem
221 * for programs linking with the shared version of libpcap (unless
222 * you're running on AIX - which I think is the only UN*X that doesn't
223 * support linking a shared library with other libraries on which it
224 * depends, and having an executable linked only with the first shared
225 * library automatically pick up the other libraries when started -
226 * and using HAL or whatever). Programs linked with the static
227 * version of libpcap would have to use pcap-config with the --static
228 * flag in order to get the right linker flags in order to pick up
229 * the additional libraries/frameworks; those programs need that anyway
230 * for libpcap 1.1 and beyond on Linux, as, by default, it requires
231 * -lnl.
232 *
233 * Do any other UN*Xes, or desktop environments support getting a
234 * description?
235 */
236 static char *
237 get_if_description(const char *name)
238 {
239 #ifdef SIOCGIFDESCR
240 char *description = NULL;
241 int s;
242 struct ifreq ifrdesc;
243 #ifndef IFDESCRSIZE
244 size_t descrlen = 64;
245 #else
246 size_t descrlen = IFDESCRSIZE;
247 #endif /* IFDESCRSIZE */
248
249 /*
250 * Get the description for the interface.
251 */
252 memset(&ifrdesc, 0, sizeof ifrdesc);
253 strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
254 s = socket(AF_INET, SOCK_DGRAM, 0);
255 if (s >= 0) {
256 #ifdef __FreeBSD__
257 /*
258 * On FreeBSD, if the buffer isn't big enough for the
259 * description, the ioctl succeeds, but the description
260 * isn't copied, ifr_buffer.length is set to the description
261 * length, and ifr_buffer.buffer is set to NULL.
262 */
263 for (;;) {
264 free(description);
265 if ((description = malloc(descrlen)) != NULL) {
266 ifrdesc.ifr_buffer.buffer = description;
267 ifrdesc.ifr_buffer.length = descrlen;
268 if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
269 if (ifrdesc.ifr_buffer.buffer ==
270 description)
271 break;
272 else
273 descrlen = ifrdesc.ifr_buffer.length;
274 } else {
275 /*
276 * Failed to get interface description.
277 */
278 free(description);
279 description = NULL;
280 break;
281 }
282 } else
283 break;
284 }
285 #else /* __FreeBSD__ */
286 /*
287 * The only other OS that currently supports
288 * SIOCGIFDESCR is OpenBSD, and it has no way
289 * to get the description length - it's clamped
290 * to a maximum of IFDESCRSIZE.
291 */
292 if ((description = malloc(descrlen)) != NULL) {
293 ifrdesc.ifr_data = (caddr_t)description;
294 if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
295 /*
296 * Failed to get interface description.
297 */
298 free(description);
299 description = NULL;
300 }
301 }
302 #endif /* __FreeBSD__ */
303 close(s);
304 if (description != NULL && strlen(description) == 0) {
305 /*
306 * Description is empty, so discard it.
307 */
308 free(description);
309 description = NULL;
310 }
311 }
312
313 #ifdef __FreeBSD__
314 /*
315 * For FreeBSD, if we didn't get a description, and this is
316 * a device with a name of the form usbusN, label it as a USB
317 * bus.
318 */
319 if (description == NULL) {
320 if (strncmp(name, "usbus", 5) == 0) {
321 /*
322 * OK, it begins with "usbus".
323 */
324 long busnum;
325 char *p;
326
327 errno = 0;
328 busnum = strtol(name + 5, &p, 10);
329 if (errno == 0 && p != name + 5 && *p == '\0' &&
330 busnum >= 0 && busnum <= INT_MAX) {
331 /*
332 * OK, it's a valid number that's not
333 * bigger than INT_MAX. Construct
334 * a description from it.
335 */
336 static const char descr_prefix[] = "USB bus number ";
337 size_t descr_size;
338
339 /*
340 * Allow enough room for a 32-bit bus number.
341 * sizeof (descr_prefix) includes the
342 * terminating NUL.
343 */
344 descr_size = sizeof (descr_prefix) + 10;
345 description = malloc(descr_size);
346 if (description != NULL) {
347 pcap_snprintf(description, descr_size,
348 "%s%ld", descr_prefix, busnum);
349 }
350 }
351 }
352 }
353 #endif
354 return (description);
355 #else /* SIOCGIFDESCR */
356 return (NULL);
357 #endif /* SIOCGIFDESCR */
358 }
359
360 /*
361 * Look for a given device in the specified list of devices.
362 *
363 * If we find it, then, if the specified address isn't null, add it to
364 * the list of addresses for the device and return 0.
365 *
366 * If we don't find it, attempt to add an entry for it, with the specified
367 * flags and description, and, if that succeeds, add the specified
368 * address to its list of addresses if that address is non-null, and
369 * return 0, otherwise return -1 and set errbuf to an error message.
370 *
371 * (We can get called with a null address because we might get a list
372 * of interface name/address combinations from the underlying OS, with
373 * the address being absent in some cases, rather than a list of
374 * interfaces with each interface having a list of addresses, so this
375 * call may be the only call made to add to the list, and we want to
376 * add interfaces even if they have no addresses.)
377 */
378 int
379 add_addr_to_iflist(pcap_if_t **alldevs, const char *name, bpf_u_int32 flags,
380 struct sockaddr *addr, size_t addr_size,
381 struct sockaddr *netmask, size_t netmask_size,
382 struct sockaddr *broadaddr, size_t broadaddr_size,
383 struct sockaddr *dstaddr, size_t dstaddr_size,
384 char *errbuf)
385 {
386 pcap_if_t *curdev;
387
388 /*
389 * Attempt to find an entry for this device; if we don't find one,
390 * attempt to add one.
391 */
392 curdev = find_or_add_dev(alldevs, name, flags, get_if_description(name),
393 errbuf);
394 if (curdev == NULL) {
395 /*
396 * Error - give up.
397 */
398 return (-1);
399 }
400
401 if (addr == NULL) {
402 /*
403 * There's no address to add; this entry just meant
404 * "here's a new interface".
405 */
406 return (0);
407 }
408
409 /*
410 * "curdev" is an entry for this interface, and we have an
411 * address for it; add an entry for that address to the
412 * interface's list of addresses.
413 *
414 * Allocate the new entry and fill it in.
415 */
416 return (add_addr_to_dev(curdev, addr, addr_size, netmask,
417 netmask_size, broadaddr, broadaddr_size, dstaddr,
418 dstaddr_size, errbuf));
419 }
420 #endif /* _WIN32 */
421
422 /*
423 * Add an entry to the list of addresses for an interface.
424 * "curdev" is the entry for that interface.
425 * If this is the first IP address added to the interface, move it
426 * in the list as appropriate.
427 */
428 int
429 add_addr_to_dev(pcap_if_t *curdev,
430 struct sockaddr *addr, size_t addr_size,
431 struct sockaddr *netmask, size_t netmask_size,
432 struct sockaddr *broadaddr, size_t broadaddr_size,
433 struct sockaddr *dstaddr, size_t dstaddr_size,
434 char *errbuf)
435 {
436 pcap_addr_t *curaddr, *prevaddr, *nextaddr;
437
438 curaddr = malloc(sizeof(pcap_addr_t));
439 if (curaddr == NULL) {
440 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
441 "malloc: %s", pcap_strerror(errno));
442 return (-1);
443 }
444
445 curaddr->next = NULL;
446 if (addr != NULL) {
447 curaddr->addr = dup_sockaddr(addr, addr_size);
448 if (curaddr->addr == NULL) {
449 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
450 "malloc: %s", pcap_strerror(errno));
451 free(curaddr);
452 return (-1);
453 }
454 } else
455 curaddr->addr = NULL;
456
457 if (netmask != NULL) {
458 curaddr->netmask = dup_sockaddr(netmask, netmask_size);
459 if (curaddr->netmask == NULL) {
460 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
461 "malloc: %s", pcap_strerror(errno));
462 if (curaddr->addr != NULL)
463 free(curaddr->addr);
464 free(curaddr);
465 return (-1);
466 }
467 } else
468 curaddr->netmask = NULL;
469
470 if (broadaddr != NULL) {
471 curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
472 if (curaddr->broadaddr == NULL) {
473 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
474 "malloc: %s", pcap_strerror(errno));
475 if (curaddr->netmask != NULL)
476 free(curaddr->netmask);
477 if (curaddr->addr != NULL)
478 free(curaddr->addr);
479 free(curaddr);
480 return (-1);
481 }
482 } else
483 curaddr->broadaddr = NULL;
484
485 if (dstaddr != NULL) {
486 curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
487 if (curaddr->dstaddr == NULL) {
488 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
489 "malloc: %s", pcap_strerror(errno));
490 if (curaddr->broadaddr != NULL)
491 free(curaddr->broadaddr);
492 if (curaddr->netmask != NULL)
493 free(curaddr->netmask);
494 if (curaddr->addr != NULL)
495 free(curaddr->addr);
496 free(curaddr);
497 return (-1);
498 }
499 } else
500 curaddr->dstaddr = NULL;
501
502 /*
503 * Find the end of the list of addresses.
504 */
505 for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
506 nextaddr = prevaddr->next;
507 if (nextaddr == NULL) {
508 /*
509 * This is the end of the list.
510 */
511 break;
512 }
513 }
514
515 if (prevaddr == NULL) {
516 /*
517 * The list was empty; this is the first member.
518 */
519 curdev->addresses = curaddr;
520 } else {
521 /*
522 * "prevaddr" is the last member of the list; append
523 * this member to it.
524 */
525 prevaddr->next = curaddr;
526 }
527
528 return (0);
529 }
530
531 /*
532 * Look for a given device in the specified list of devices.
533 *
534 * If we find it, return 0 and set *curdev_ret to point to it.
535 *
536 * If we don't find it, attempt to add an entry for it, with the specified
537 * flags and description, and, if that succeeds, return 0, otherwise
538 * return -1 and set errbuf to an error message.
539 */
540 pcap_if_t *
541 find_or_add_dev(pcap_if_t **alldevs, const char *name, bpf_u_int32 flags,
542 const char *description, char *errbuf)
543 {
544 pcap_if_t *curdev;
545
546 /*
547 * Is there already an entry in the list for this interface?
548 */
549 curdev = find_dev(alldevs, name);
550 if (curdev != NULL) {
551 /*
552 * Yes, return it.
553 */
554 return (curdev);
555 }
556
557 /*
558 * No, we didn't find it. Try to add it to the list of devices.
559 */
560 return (add_dev(alldevs, name, flags, description, errbuf));
561 }
562
563 /*
564 * Look for a given device in the specified list of devices, and return
565 * the entry for it if we find it or NULL if we don't.
566 */
567 pcap_if_t *
568 find_dev(pcap_if_t **alldevs, const char *name)
569 {
570 pcap_if_t *curdev;
571
572 /*
573 * Is there an entry in the list for this device?
574 */
575 for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
576 if (strcmp(name, curdev->name) == 0) {
577 /*
578 * We found it, so, yes, there is. No need to
579 * add it. Provide the entry we found to our
580 * caller.
581 */
582 return (curdev);
583 }
584 }
585
586 /*
587 * No.
588 */
589 return (NULL);
590 }
591
592 /*
593 * Attempt to add an entry for a device, with the specified flags
594 * and description, and, if that succeeds, return 0 and return a pointer
595 * to the new entry, otherwise return NULL and set errbuf to an error
596 * message.
597 *
598 * If we weren't given a description, try to get one.
599 */
600 pcap_if_t *
601 add_dev(pcap_if_t **alldevs, const char *name, bpf_u_int32 flags,
602 const char *description, char *errbuf)
603 {
604 pcap_if_t *curdev, *prevdev, *nextdev;
605 u_int this_figure_of_merit, nextdev_figure_of_merit;
606
607 curdev = malloc(sizeof(pcap_if_t));
608 if (curdev == NULL) {
609 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
610 "malloc: %s", pcap_strerror(errno));
611 return (NULL);
612 }
613
614 /*
615 * Fill in the entry.
616 */
617 curdev->next = NULL;
618 curdev->name = strdup(name);
619 if (curdev->name == NULL) {
620 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
621 "malloc: %s", pcap_strerror(errno));
622 free(curdev);
623 return (NULL);
624 }
625 if (description == NULL) {
626 /*
627 * We weren't handed a description for the interface.
628 */
629 curdev->description = NULL;
630 } else {
631 /*
632 * We were handed a description; make a copy.
633 */
634 curdev->description = strdup(description);
635 if (curdev->description == NULL) {
636 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
637 "malloc: %s", pcap_strerror(errno));
638 free(curdev->name);
639 free(curdev);
640 return (NULL);
641 }
642 }
643 curdev->addresses = NULL; /* list starts out as empty */
644 curdev->flags = flags;
645
646 /*
647 * Add it to the list, in the appropriate location.
648 * First, get the "figure of merit" for this interface.
649 */
650 this_figure_of_merit = get_figure_of_merit(curdev);
651
652 /*
653 * Now look for the last interface with an figure of merit
654 * less than or equal to the new interface's figure of merit.
655 *
656 * We start with "prevdev" being NULL, meaning we're before
657 * the first element in the list.
658 */
659 prevdev = NULL;
660 for (;;) {
661 /*
662 * Get the interface after this one.
663 */
664 if (prevdev == NULL) {
665 /*
666 * The next element is the first element.
667 */
668 nextdev = *alldevs;
669 } else
670 nextdev = prevdev->next;
671
672 /*
673 * Are we at the end of the list?
674 */
675 if (nextdev == NULL) {
676 /*
677 * Yes - we have to put the new entry after "prevdev".
678 */
679 break;
680 }
681
682 /*
683 * Is the new interface's figure of merit less
684 * than the next interface's figure of merit,
685 * meaning that the new interface is better
686 * than the next interface?
687 */
688 nextdev_figure_of_merit = get_figure_of_merit(nextdev);
689 if (this_figure_of_merit < nextdev_figure_of_merit) {
690 /*
691 * Yes - we should put the new entry
692 * before "nextdev", i.e. after "prevdev".
693 */
694 break;
695 }
696
697 prevdev = nextdev;
698 }
699
700 /*
701 * Insert before "nextdev".
702 */
703 curdev->next = nextdev;
704
705 /*
706 * Insert after "prevdev" - unless "prevdev" is null,
707 * in which case this is the first interface.
708 */
709 if (prevdev == NULL) {
710 /*
711 * This is the first interface. Pass back a
712 * pointer to it, and put "curdev" before
713 * "nextdev".
714 */
715 *alldevs = curdev;
716 } else
717 prevdev->next = curdev;
718 return (curdev);
719 }
720
721 /*
722 * Free a list of interfaces.
723 */
724 void
725 pcap_freealldevs(pcap_if_t *alldevs)
726 {
727 pcap_if_t *curdev, *nextdev;
728 pcap_addr_t *curaddr, *nextaddr;
729
730 for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
731 nextdev = curdev->next;
732
733 /*
734 * Free all addresses.
735 */
736 for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
737 nextaddr = curaddr->next;
738 if (curaddr->addr)
739 free(curaddr->addr);
740 if (curaddr->netmask)
741 free(curaddr->netmask);
742 if (curaddr->broadaddr)
743 free(curaddr->broadaddr);
744 if (curaddr->dstaddr)
745 free(curaddr->dstaddr);
746 free(curaddr);
747 }
748
749 /*
750 * Free the name string.
751 */
752 free(curdev->name);
753
754 /*
755 * Free the description string, if any.
756 */
757 if (curdev->description != NULL)
758 free(curdev->description);
759
760 /*
761 * Free the interface.
762 */
763 free(curdev);
764 }
765 }