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