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