inet.c revision 127664
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 36static const char rcsid[] _U_ = 37 "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.58.2.1 2003/11/15 23:26:41 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 57struct mbuf; /* Squelch compiler warnings on some platforms for */ 58struct 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 95struct sockaddr * 96dup_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 105static int 106get_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 131int 132add_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 284int 285add_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 396int 397pcap_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 */ 410void 411pcap_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 */ 460char * 461pcap_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 502int 503pcap_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 */ 584char * 585pcap_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 654int 655pcap_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 */ 694