]> The Tcpdump Group git mirrors - libpcap/blob - inet.c
We don't call "getifaddrs()" in inet.c, so we don't need to include
[libpcap] / inet.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 #ifndef lint
36 static const char rcsid[] _U_ =
37 "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.61 2004-12-16 22:07:28 guy Exp $ (LBL)";
38 #endif
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #ifdef WIN32
45 #include <pcap-stdinc.h>
46 #else /* WIN32 */
47
48 #include <sys/param.h>
49 #include <sys/file.h>
50 #include <sys/ioctl.h>
51 #include <sys/socket.h>
52 #ifdef HAVE_SYS_SOCKIO_H
53 #include <sys/sockio.h>
54 #endif
55 #include <sys/time.h> /* concession to AIX */
56
57 struct mbuf; /* Squelch compiler warnings on some platforms for */
58 struct rtentry; /* declarations in <net/if.h> */
59 #include <net/if.h>
60 #include <netinet/in.h>
61 #endif /* WIN32 */
62
63 #include <ctype.h>
64 #include <errno.h>
65 #include <memory.h>
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #ifndef WIN32
70 #include <unistd.h>
71 #endif /* WIN32 */
72 #ifdef HAVE_LIMITS_H
73 #include <limits.h>
74 #else
75 #define INT_MAX 2147483647
76 #endif
77
78 #include "pcap-int.h"
79
80 #ifdef HAVE_OS_PROTO_H
81 #include "os-proto.h"
82 #endif
83
84 /* Not all systems have IFF_LOOPBACK */
85 #ifdef IFF_LOOPBACK
86 #define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
87 #else
88 #define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
89 (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
90 #endif
91
92 struct sockaddr *
93 dup_sockaddr(struct sockaddr *sa, size_t sa_length)
94 {
95 struct sockaddr *newsa;
96
97 if ((newsa = malloc(sa_length)) == NULL)
98 return (NULL);
99 return (memcpy(newsa, sa, sa_length));
100 }
101
102 static int
103 get_instance(const char *name)
104 {
105 const char *cp, *endcp;
106 int n;
107
108 if (strcmp(name, "any") == 0) {
109 /*
110 * Give the "any" device an artificially high instance
111 * number, so it shows up after all other non-loopback
112 * interfaces.
113 */
114 return INT_MAX;
115 }
116
117 endcp = name + strlen(name);
118 for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
119 continue;
120
121 if (isdigit((unsigned char)*cp))
122 n = atoi(cp);
123 else
124 n = 0;
125 return (n);
126 }
127
128 int
129 add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
130 u_int flags, const char *description, char *errbuf)
131 {
132 pcap_if_t *curdev, *prevdev, *nextdev;
133 int this_instance;
134
135 /*
136 * Is there already an entry in the list for this interface?
137 */
138 for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
139 if (strcmp(name, curdev->name) == 0)
140 break; /* yes, we found it */
141 }
142 if (curdev == NULL) {
143 /*
144 * No, we didn't find it.
145 * Allocate a new entry.
146 */
147 curdev = malloc(sizeof(pcap_if_t));
148 if (curdev == NULL) {
149 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
150 "malloc: %s", pcap_strerror(errno));
151 return (-1);
152 }
153
154 /*
155 * Fill in the entry.
156 */
157 curdev->next = NULL;
158 curdev->name = malloc(strlen(name) + 1);
159 strcpy(curdev->name, name);
160 if (description != NULL) {
161 /*
162 * We have a description for this interface.
163 */
164 curdev->description = malloc(strlen(description) + 1);
165 strcpy(curdev->description, description);
166 } else {
167 /*
168 * We don't.
169 */
170 curdev->description = NULL;
171 }
172 curdev->addresses = NULL; /* list starts out as empty */
173 curdev->flags = 0;
174 if (ISLOOPBACK(name, flags))
175 curdev->flags |= PCAP_IF_LOOPBACK;
176
177 /*
178 * Add it to the list, in the appropriate location.
179 * First, get the instance number of this interface.
180 */
181 this_instance = get_instance(name);
182
183 /*
184 * Now look for the last interface with an instance number
185 * less than or equal to the new interface's instance
186 * number - except that non-loopback interfaces are
187 * arbitrarily treated as having interface numbers less
188 * than those of loopback interfaces, so the loopback
189 * interfaces are put at the end of the list.
190 *
191 * We start with "prevdev" being NULL, meaning we're before
192 * the first element in the list.
193 */
194 prevdev = NULL;
195 for (;;) {
196 /*
197 * Get the interface after this one.
198 */
199 if (prevdev == NULL) {
200 /*
201 * The next element is the first element.
202 */
203 nextdev = *alldevs;
204 } else
205 nextdev = prevdev->next;
206
207 /*
208 * Are we at the end of the list?
209 */
210 if (nextdev == NULL) {
211 /*
212 * Yes - we have to put the new entry
213 * after "prevdev".
214 */
215 break;
216 }
217
218 /*
219 * Is the new interface a non-loopback interface
220 * and the next interface a loopback interface?
221 */
222 if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
223 (nextdev->flags & PCAP_IF_LOOPBACK)) {
224 /*
225 * Yes, we should put the new entry
226 * before "nextdev", i.e. after "prevdev".
227 */
228 break;
229 }
230
231 /*
232 * Is the new interface's instance number less
233 * than the next interface's instance number,
234 * and is it the case that the new interface is a
235 * non-loopback interface or the next interface is
236 * a loopback interface?
237 *
238 * (The goal of both loopback tests is to make
239 * sure that we never put a loopback interface
240 * before any non-loopback interface and that we
241 * always put a non-loopback interface before all
242 * loopback interfaces.)
243 */
244 if (this_instance < get_instance(nextdev->name) &&
245 (!(curdev->flags & PCAP_IF_LOOPBACK) ||
246 (nextdev->flags & PCAP_IF_LOOPBACK))) {
247 /*
248 * Yes - we should put the new entry
249 * before "nextdev", i.e. after "prevdev".
250 */
251 break;
252 }
253
254 prevdev = nextdev;
255 }
256
257 /*
258 * Insert before "nextdev".
259 */
260 curdev->next = nextdev;
261
262 /*
263 * Insert after "prevdev" - unless "prevdev" is null,
264 * in which case this is the first interface.
265 */
266 if (prevdev == NULL) {
267 /*
268 * This is the first interface. Pass back a
269 * pointer to it, and put "curdev" before
270 * "nextdev".
271 */
272 *alldevs = curdev;
273 } else
274 prevdev->next = curdev;
275 }
276
277 *curdev_ret = curdev;
278 return (0);
279 }
280
281 int
282 add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags,
283 struct sockaddr *addr, size_t addr_size,
284 struct sockaddr *netmask, size_t netmask_size,
285 struct sockaddr *broadaddr, size_t broadaddr_size,
286 struct sockaddr *dstaddr, size_t dstaddr_size,
287 char *errbuf)
288 {
289 pcap_if_t *curdev;
290 pcap_addr_t *curaddr, *prevaddr, *nextaddr;
291
292 if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
293 /*
294 * Error - give up.
295 */
296 return (-1);
297 }
298 if (curdev == NULL) {
299 /*
300 * Device wasn't added because it can't be opened.
301 * Not a fatal error.
302 */
303 return (0);
304 }
305
306 /*
307 * "curdev" is an entry for this interface; add an entry for this
308 * address to its list of addresses.
309 *
310 * Allocate the new entry and fill it in.
311 */
312 curaddr = malloc(sizeof(pcap_addr_t));
313 if (curaddr == NULL) {
314 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
315 "malloc: %s", pcap_strerror(errno));
316 return (-1);
317 }
318
319 curaddr->next = NULL;
320 if (addr != NULL) {
321 curaddr->addr = dup_sockaddr(addr, addr_size);
322 if (curaddr->addr == NULL) {
323 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
324 "malloc: %s", pcap_strerror(errno));
325 free(curaddr);
326 return (-1);
327 }
328 } else
329 curaddr->addr = NULL;
330
331 if (netmask != NULL) {
332 curaddr->netmask = dup_sockaddr(netmask, netmask_size);
333 if (curaddr->netmask == NULL) {
334 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
335 "malloc: %s", pcap_strerror(errno));
336 free(curaddr);
337 return (-1);
338 }
339 } else
340 curaddr->netmask = NULL;
341
342 if (broadaddr != NULL) {
343 curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
344 if (curaddr->broadaddr == NULL) {
345 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
346 "malloc: %s", pcap_strerror(errno));
347 free(curaddr);
348 return (-1);
349 }
350 } else
351 curaddr->broadaddr = NULL;
352
353 if (dstaddr != NULL) {
354 curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
355 if (curaddr->dstaddr == NULL) {
356 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
357 "malloc: %s", pcap_strerror(errno));
358 free(curaddr);
359 return (-1);
360 }
361 } else
362 curaddr->dstaddr = NULL;
363
364 /*
365 * Find the end of the list of addresses.
366 */
367 for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
368 nextaddr = prevaddr->next;
369 if (nextaddr == NULL) {
370 /*
371 * This is the end of the list.
372 */
373 break;
374 }
375 }
376
377 if (prevaddr == NULL) {
378 /*
379 * The list was empty; this is the first member.
380 */
381 curdev->addresses = curaddr;
382 } else {
383 /*
384 * "prevaddr" is the last member of the list; append
385 * this member to it.
386 */
387 prevaddr->next = curaddr;
388 }
389
390 return (0);
391 }
392
393 int
394 pcap_add_if(pcap_if_t **devlist, char *name, u_int flags,
395 const char *description, char *errbuf)
396 {
397 pcap_if_t *curdev;
398
399 return (add_or_find_if(&curdev, devlist, name, flags, description,
400 errbuf));
401 }
402
403
404 /*
405 * Free a list of interfaces.
406 */
407 void
408 pcap_freealldevs(pcap_if_t *alldevs)
409 {
410 pcap_if_t *curdev, *nextdev;
411 pcap_addr_t *curaddr, *nextaddr;
412
413 for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
414 nextdev = curdev->next;
415
416 /*
417 * Free all addresses.
418 */
419 for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
420 nextaddr = curaddr->next;
421 if (curaddr->addr)
422 free(curaddr->addr);
423 if (curaddr->netmask)
424 free(curaddr->netmask);
425 if (curaddr->broadaddr)
426 free(curaddr->broadaddr);
427 if (curaddr->dstaddr)
428 free(curaddr->dstaddr);
429 free(curaddr);
430 }
431
432 /*
433 * Free the name string.
434 */
435 free(curdev->name);
436
437 /*
438 * Free the description string, if any.
439 */
440 if (curdev->description != NULL)
441 free(curdev->description);
442
443 /*
444 * Free the interface.
445 */
446 free(curdev);
447 }
448 }
449
450 #ifndef WIN32
451
452 /*
453 * Return the name of a network interface attached to the system, or NULL
454 * if none can be found. The interface must be configured up; the
455 * lowest unit number is preferred; loopback is ignored.
456 */
457 char *
458 pcap_lookupdev(errbuf)
459 register char *errbuf;
460 {
461 pcap_if_t *alldevs;
462 /* for old BSD systems, including bsdi3 */
463 #ifndef IF_NAMESIZE
464 #define IF_NAMESIZE IFNAMSIZ
465 #endif
466 static char device[IF_NAMESIZE + 1];
467 char *ret;
468
469 if (pcap_findalldevs(&alldevs, errbuf) == -1)
470 return (NULL);
471
472 if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
473 /*
474 * There are no devices on the list, or the first device
475 * on the list is a loopback device, which means there
476 * are no non-loopback devices on the list. This means
477 * we can't return any device.
478 *
479 * XXX - why not return a loopback device? If we can't
480 * capture on it, it won't be on the list, and if it's
481 * on the list, there aren't any non-loopback devices,
482 * so why not just supply it as the default device?
483 */
484 (void)strlcpy(errbuf, "no suitable device found",
485 PCAP_ERRBUF_SIZE);
486 ret = NULL;
487 } else {
488 /*
489 * Return the name of the first device on the list.
490 */
491 (void)strlcpy(device, alldevs->name, sizeof(device));
492 ret = device;
493 }
494
495 pcap_freealldevs(alldevs);
496 return (ret);
497 }
498
499 int
500 pcap_lookupnet(device, netp, maskp, errbuf)
501 register const char *device;
502 register bpf_u_int32 *netp, *maskp;
503 register char *errbuf;
504 {
505 register int fd;
506 register struct sockaddr_in *sin;
507 struct ifreq ifr;
508
509 /*
510 * The pseudo-device "any" listens on all interfaces and therefore
511 * has the network address and -mask "0.0.0.0" therefore catching
512 * all traffic. Using NULL for the interface is the same as "any".
513 */
514 if (!device || strcmp(device, "any") == 0
515 #ifdef HAVE_DAG_API
516 || strstr(device, "dag") != NULL
517 #endif
518 ) {
519 *netp = *maskp = 0;
520 return 0;
521 }
522
523 fd = socket(AF_INET, SOCK_DGRAM, 0);
524 if (fd < 0) {
525 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
526 pcap_strerror(errno));
527 return (-1);
528 }
529 memset(&ifr, 0, sizeof(ifr));
530 #ifdef linux
531 /* XXX Work around Linux kernel bug */
532 ifr.ifr_addr.sa_family = AF_INET;
533 #endif
534 (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
535 if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
536 if (errno == EADDRNOTAVAIL) {
537 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
538 "%s: no IPv4 address assigned", device);
539 } else {
540 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
541 "SIOCGIFADDR: %s: %s",
542 device, pcap_strerror(errno));
543 }
544 (void)close(fd);
545 return (-1);
546 }
547 sin = (struct sockaddr_in *)&ifr.ifr_addr;
548 *netp = sin->sin_addr.s_addr;
549 if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
550 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
551 "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
552 (void)close(fd);
553 return (-1);
554 }
555 (void)close(fd);
556 *maskp = sin->sin_addr.s_addr;
557 if (*maskp == 0) {
558 if (IN_CLASSA(*netp))
559 *maskp = IN_CLASSA_NET;
560 else if (IN_CLASSB(*netp))
561 *maskp = IN_CLASSB_NET;
562 else if (IN_CLASSC(*netp))
563 *maskp = IN_CLASSC_NET;
564 else {
565 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
566 "inet class for 0x%x unknown", *netp);
567 return (-1);
568 }
569 }
570 *netp &= *maskp;
571 return (0);
572 }
573
574 #else /* WIN32 */
575
576 /*
577 * Return the name of a network interface attached to the system, or NULL
578 * if none can be found. The interface must be configured up; the
579 * lowest unit number is preferred; loopback is ignored.
580 */
581 char *
582 pcap_lookupdev(errbuf)
583 register char *errbuf;
584 {
585 DWORD dwVersion;
586 DWORD dwWindowsMajorVersion;
587 dwVersion = GetVersion(); /* get the OS version */
588 dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
589
590 if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
591 /*
592 * Windows 95, 98, ME.
593 */
594 ULONG NameLength = 8192;
595 static char AdaptersName[8192];
596
597 if (PacketGetAdapterNames(AdaptersName,&NameLength) )
598 return (AdaptersName);
599 else
600 return NULL;
601 } else {
602 /*
603 * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
604 */
605 ULONG NameLength = 8192;
606 static WCHAR AdaptersName[8192];
607 char *tAstr;
608 WCHAR *tUstr;
609 WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
610 int NAdapts = 0;
611
612 if(TAdaptersName == NULL)
613 {
614 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
615 return NULL;
616 }
617
618 if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
619 {
620 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
621 "PacketGetAdapterNames: %s",
622 pcap_win32strerror());
623 free(TAdaptersName);
624 return NULL;
625 }
626
627
628 tAstr = (char*)TAdaptersName;
629 tUstr = (WCHAR*)AdaptersName;
630
631 /*
632 * Convert and copy the device names
633 */
634 while(sscanf(tAstr, "%S", tUstr) > 0)
635 {
636 tAstr += strlen(tAstr) + 1;
637 tUstr += wcslen(tUstr) + 1;
638 NAdapts ++;
639 }
640
641 tAstr++;
642 *tUstr = 0;
643 tUstr++;
644
645 /*
646 * Copy the descriptions
647 */
648 while(NAdapts--)
649 {
650 strcpy((char*)tUstr, tAstr);
651 (char*)tUstr += strlen(tAstr) + 1;;
652 tAstr += strlen(tAstr) + 1;
653 }
654
655 free(TAdaptersName);
656 return (char *)(AdaptersName);
657 }
658 }
659
660
661 int
662 pcap_lookupnet(device, netp, maskp, errbuf)
663 const register char *device;
664 register bpf_u_int32 *netp, *maskp;
665 register char *errbuf;
666 {
667 /*
668 * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
669 * in order to skip non IPv4 (i.e. IPv6 addresses)
670 */
671 npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
672 LONG if_addr_size = 1;
673 struct sockaddr_in *t_addr;
674 unsigned int i;
675
676 if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
677 *netp = *maskp = 0;
678 return (0);
679 }
680
681 for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
682 {
683 if(if_addrs[i].IPAddress.ss_family == AF_INET)
684 {
685 t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
686 *netp = t_addr->sin_addr.S_un.S_addr;
687 t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
688 *maskp = t_addr->sin_addr.S_un.S_addr;
689
690 *netp &= *maskp;
691 return (0);
692 }
693
694 }
695
696 *netp = *maskp = 0;
697 return (0);
698 }
699
700 #endif /* WIN32 */