1 /* $NetBSD: nametoaddr.c,v 1.6 2023/08/17 15:18:12 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 * 23 * Name to id translation routines used by the scanner. 24 * These functions are not time critical. 25 */ 26 27 #include <sys/cdefs.h> 28 __RCSID("$NetBSD: nametoaddr.c,v 1.6 2023/08/17 15:18:12 christos Exp $"); 29 30 #ifdef HAVE_CONFIG_H 31 #include <config.h> 32 #endif 33 34 #ifdef DECNETLIB 35 #include <sys/types.h> 36 #include <netdnet/dnetdb.h> 37 #endif 38 39 #ifdef _WIN32 40 #include <winsock2.h> 41 #include <ws2tcpip.h> 42 43 #ifdef INET6 44 /* 45 * To quote the MSDN page for getaddrinfo() at 46 * 47 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx 48 * 49 * "Support for getaddrinfo on Windows 2000 and older versions 50 * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and 51 * later. To execute an application that uses this function on earlier 52 * versions of Windows, then you need to include the Ws2tcpip.h and 53 * Wspiapi.h files. When the Wspiapi.h include file is added, the 54 * getaddrinfo function is defined to the WspiapiGetAddrInfo inline 55 * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo 56 * function is implemented in such a way that if the Ws2_32.dll or the 57 * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology 58 * Preview for Windows 2000) does not include getaddrinfo, then a 59 * version of getaddrinfo is implemented inline based on code in the 60 * Wspiapi.h header file. This inline code will be used on older Windows 61 * platforms that do not natively support the getaddrinfo function." 62 * 63 * We use getaddrinfo(), so we include Wspiapi.h here. 64 */ 65 #include <wspiapi.h> 66 #endif /* INET6 */ 67 #else /* _WIN32 */ 68 #include <sys/param.h> 69 #include <sys/types.h> 70 #include <sys/socket.h> 71 #include <sys/time.h> 72 73 #include <netinet/in.h> 74 75 #ifdef HAVE_ETHER_HOSTTON 76 #if defined(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON) 77 /* 78 * OK, just include <net/ethernet.h>. 79 */ 80 #include <net/ethernet.h> 81 #elif defined(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON) 82 /* 83 * OK, just include <netinet/ether.h> 84 */ 85 #include <netinet/ether.h> 86 #elif defined(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON) 87 /* 88 * OK, just include <sys/ethernet.h> 89 */ 90 #include <sys/ethernet.h> 91 #elif defined(ARPA_INET_H_DECLARES_ETHER_HOSTTON) 92 /* 93 * OK, just include <arpa/inet.h> 94 */ 95 #include <arpa/inet.h> 96 #elif defined(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON) 97 /* 98 * OK, include <netinet/if_ether.h>, after all the other stuff we 99 * need to include or define for its benefit. 100 */ 101 #define NEED_NETINET_IF_ETHER_H 102 #else 103 /* 104 * We'll have to declare it ourselves. 105 * If <netinet/if_ether.h> defines struct ether_addr, include 106 * it. Otherwise, define it ourselves. 107 */ 108 #ifdef HAVE_STRUCT_ETHER_ADDR 109 #define NEED_NETINET_IF_ETHER_H 110 #else /* HAVE_STRUCT_ETHER_ADDR */ 111 struct ether_addr { 112 unsigned char ether_addr_octet[6]; 113 }; 114 #endif /* HAVE_STRUCT_ETHER_ADDR */ 115 #endif /* what declares ether_hostton() */ 116 117 #ifdef NEED_NETINET_IF_ETHER_H 118 #include <net/if.h> /* Needed on some platforms */ 119 #include <netinet/in.h> /* Needed on some platforms */ 120 #include <netinet/if_ether.h> 121 #endif /* NEED_NETINET_IF_ETHER_H */ 122 123 #ifndef HAVE_DECL_ETHER_HOSTTON 124 /* 125 * No header declares it, so declare it ourselves. 126 */ 127 extern int ether_hostton(const char *, struct ether_addr *); 128 #endif /* !defined(HAVE_DECL_ETHER_HOSTTON) */ 129 #endif /* HAVE_ETHER_HOSTTON */ 130 131 #include <arpa/inet.h> 132 #include <netdb.h> 133 #endif /* _WIN32 */ 134 135 #include <errno.h> 136 #include <stdlib.h> 137 #include <string.h> 138 #include <stdio.h> 139 140 #include "pcap-int.h" 141 142 #include "diag-control.h" 143 144 #include "gencode.h" 145 #include <pcap/namedb.h> 146 #include "nametoaddr.h" 147 148 #ifdef HAVE_OS_PROTO_H 149 #include "os-proto.h" 150 #endif 151 152 #ifndef NTOHL 153 #define NTOHL(x) (x) = ntohl(x) 154 #define NTOHS(x) (x) = ntohs(x) 155 #endif 156 157 /* 158 * Convert host name to internet address. 159 * Return 0 upon failure. 160 * XXX - not thread-safe; don't use it inside libpcap. 161 */ 162 bpf_u_int32 ** 163 pcap_nametoaddr(const char *name) 164 { 165 #ifndef h_addr 166 static bpf_u_int32 *hlist[2]; 167 #endif 168 bpf_u_int32 **p; 169 struct hostent *hp; 170 171 /* 172 * gethostbyname() is deprecated on Windows, perhaps because 173 * it's not thread-safe, or because it doesn't support IPv6, 174 * or both. 175 * 176 * We deprecate pcap_nametoaddr() on all platforms because 177 * it's not thread-safe; we supply it for backwards compatibility, 178 * so suppress the deprecation warning. We could, I guess, 179 * use getaddrinfo() and construct the array ourselves, but 180 * that's probably not worth the effort, as that wouldn't make 181 * this thread-safe - we can't change the API to require that 182 * our caller free the address array, so we still have to reuse 183 * a local array. 184 */ 185 DIAG_OFF_DEPRECATION 186 if ((hp = gethostbyname(name)) != NULL) { 187 DIAG_ON_DEPRECATION 188 #ifndef h_addr 189 hlist[0] = (bpf_u_int32 *)hp->h_addr; 190 NTOHL(hp->h_addr); 191 return hlist; 192 #else 193 for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) 194 NTOHL(**p); 195 return (bpf_u_int32 **)hp->h_addr_list; 196 #endif 197 } 198 else 199 return 0; 200 } 201 202 struct addrinfo * 203 pcap_nametoaddrinfo(const char *name) 204 { 205 struct addrinfo hints, *res; 206 int error; 207 208 memset(&hints, 0, sizeof(hints)); 209 hints.ai_family = PF_UNSPEC; 210 hints.ai_socktype = SOCK_STREAM; /*not really*/ 211 hints.ai_protocol = IPPROTO_TCP; /*not really*/ 212 error = getaddrinfo(name, NULL, &hints, &res); 213 if (error) 214 return NULL; 215 else 216 return res; 217 } 218 219 /* 220 * Convert net name to internet address. 221 * Return 0 upon failure. 222 * XXX - not guaranteed to be thread-safe! See below for platforms 223 * on which it is thread-safe and on which it isn't. 224 */ 225 #if defined(_WIN32) || defined(__CYGWIN__) 226 bpf_u_int32 227 pcap_nametonetaddr(const char *name _U_) 228 { 229 /* 230 * There's no "getnetbyname()" on Windows. 231 * 232 * XXX - I guess we could use the BSD code to read 233 * C:\Windows\System32\drivers\etc/networks, assuming 234 * that's its home on all the versions of Windows 235 * we use, but that file probably just has the loopback 236 * network on 127/24 on 99 44/100% of Windows machines. 237 * 238 * (Heck, these days it probably just has that on 99 44/100% 239 * of *UN*X* machines.) 240 */ 241 return 0; 242 } 243 #else /* _WIN32 */ 244 bpf_u_int32 245 pcap_nametonetaddr(const char *name) 246 { 247 /* 248 * UN*X. 249 */ 250 struct netent *np; 251 #if defined(HAVE_LINUX_GETNETBYNAME_R) 252 /* 253 * We have Linux's reentrant getnetbyname_r(). 254 */ 255 struct netent result_buf; 256 char buf[1024]; /* arbitrary size */ 257 int h_errnoval; 258 int err; 259 260 /* 261 * Apparently, the man page at 262 * 263 * http://man7.org/linux/man-pages/man3/getnetbyname_r.3.html 264 * 265 * lies when it says 266 * 267 * If the function call successfully obtains a network record, 268 * then *result is set pointing to result_buf; otherwise, *result 269 * is set to NULL. 270 * 271 * and, in fact, at least in some versions of GNU libc, it does 272 * *not* always get set if getnetbyname_r() succeeds. 273 */ 274 np = NULL; 275 err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np, 276 &h_errnoval); 277 if (err != 0) { 278 /* 279 * XXX - dynamically allocate the buffer, and make it 280 * bigger if we get ERANGE back? 281 */ 282 return 0; 283 } 284 #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R) 285 /* 286 * We have Solaris's and IRIX's reentrant getnetbyname_r(). 287 */ 288 struct netent result_buf; 289 char buf[1024]; /* arbitrary size */ 290 291 np = getnetbyname_r(name, &result_buf, buf, (int)sizeof buf); 292 #elif defined(HAVE_AIX_GETNETBYNAME_R) 293 /* 294 * We have AIX's reentrant getnetbyname_r(). 295 */ 296 struct netent result_buf; 297 struct netent_data net_data; 298 299 if (getnetbyname_r(name, &result_buf, &net_data) == -1) 300 np = NULL; 301 else 302 np = &result_buf; 303 #else 304 /* 305 * We don't have any getnetbyname_r(); either we have a 306 * getnetbyname() that uses thread-specific data, in which 307 * case we're thread-safe (sufficiently recent FreeBSD, 308 * sufficiently recent Darwin-based OS, sufficiently recent 309 * HP-UX, sufficiently recent Tru64 UNIX), or we have the 310 * traditional getnetbyname() (everything else, including 311 * current NetBSD and OpenBSD), in which case we're not 312 * thread-safe. 313 */ 314 np = getnetbyname(name); 315 #endif 316 if (np != NULL) 317 return np->n_net; 318 else 319 return 0; 320 } 321 #endif /* _WIN32 */ 322 323 /* 324 * Convert a port name to its port and protocol numbers. 325 * We assume only TCP or UDP. 326 * Return 0 upon failure. 327 */ 328 int 329 pcap_nametoport(const char *name, int *port, int *proto) 330 { 331 struct addrinfo hints, *res, *ai; 332 int error; 333 struct sockaddr_in *in4; 334 #ifdef INET6 335 struct sockaddr_in6 *in6; 336 #endif 337 int tcp_port = -1; 338 int udp_port = -1; 339 340 /* 341 * We check for both TCP and UDP in case there are 342 * ambiguous entries. 343 */ 344 memset(&hints, 0, sizeof(hints)); 345 hints.ai_family = PF_UNSPEC; 346 hints.ai_socktype = SOCK_STREAM; 347 hints.ai_protocol = IPPROTO_TCP; 348 error = getaddrinfo(NULL, name, &hints, &res); 349 if (error != 0) { 350 if (error != EAI_NONAME && 351 error != EAI_SERVICE) { 352 /* 353 * This is a real error, not just "there's 354 * no such service name". 355 * XXX - this doesn't return an error string. 356 */ 357 return 0; 358 } 359 } else { 360 /* 361 * OK, we found it. Did it find anything? 362 */ 363 for (ai = res; ai != NULL; ai = ai->ai_next) { 364 /* 365 * Does it have an address? 366 */ 367 if (ai->ai_addr != NULL) { 368 /* 369 * Yes. Get a port number; we're done. 370 */ 371 if (ai->ai_addr->sa_family == AF_INET) { 372 in4 = (struct sockaddr_in *)ai->ai_addr; 373 tcp_port = ntohs(in4->sin_port); 374 break; 375 } 376 #ifdef INET6 377 if (ai->ai_addr->sa_family == AF_INET6) { 378 in6 = (struct sockaddr_in6 *)ai->ai_addr; 379 tcp_port = ntohs(in6->sin6_port); 380 break; 381 } 382 #endif 383 } 384 } 385 freeaddrinfo(res); 386 } 387 388 memset(&hints, 0, sizeof(hints)); 389 hints.ai_family = PF_UNSPEC; 390 hints.ai_socktype = SOCK_DGRAM; 391 hints.ai_protocol = IPPROTO_UDP; 392 error = getaddrinfo(NULL, name, &hints, &res); 393 if (error != 0) { 394 if (error != EAI_NONAME && 395 error != EAI_SERVICE) { 396 /* 397 * This is a real error, not just "there's 398 * no such service name". 399 * XXX - this doesn't return an error string. 400 */ 401 return 0; 402 } 403 } else { 404 /* 405 * OK, we found it. Did it find anything? 406 */ 407 for (ai = res; ai != NULL; ai = ai->ai_next) { 408 /* 409 * Does it have an address? 410 */ 411 if (ai->ai_addr != NULL) { 412 /* 413 * Yes. Get a port number; we're done. 414 */ 415 if (ai->ai_addr->sa_family == AF_INET) { 416 in4 = (struct sockaddr_in *)ai->ai_addr; 417 udp_port = ntohs(in4->sin_port); 418 break; 419 } 420 #ifdef INET6 421 if (ai->ai_addr->sa_family == AF_INET6) { 422 in6 = (struct sockaddr_in6 *)ai->ai_addr; 423 udp_port = ntohs(in6->sin6_port); 424 break; 425 } 426 #endif 427 } 428 } 429 freeaddrinfo(res); 430 } 431 432 /* 433 * We need to check /etc/services for ambiguous entries. 434 * If we find an ambiguous entry, and it has the 435 * same port number, change the proto to PROTO_UNDEF 436 * so both TCP and UDP will be checked. 437 */ 438 if (tcp_port >= 0) { 439 *port = tcp_port; 440 *proto = IPPROTO_TCP; 441 if (udp_port >= 0) { 442 if (udp_port == tcp_port) 443 *proto = PROTO_UNDEF; 444 #ifdef notdef 445 else 446 /* Can't handle ambiguous names that refer 447 to different port numbers. */ 448 warning("ambiguous port %s in /etc/services", 449 name); 450 #endif 451 } 452 return 1; 453 } 454 if (udp_port >= 0) { 455 *port = udp_port; 456 *proto = IPPROTO_UDP; 457 return 1; 458 } 459 #if defined(ultrix) || defined(__osf__) 460 /* Special hack in case NFS isn't in /etc/services */ 461 if (strcmp(name, "nfs") == 0) { 462 *port = 2049; 463 *proto = PROTO_UNDEF; 464 return 1; 465 } 466 #endif 467 return 0; 468 } 469 470 /* 471 * Convert a string in the form PPP-PPP, where correspond to ports, to 472 * a starting and ending port in a port range. 473 * Return 0 on failure. 474 */ 475 int 476 pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto) 477 { 478 u_int p1, p2; 479 char *off, *cpy; 480 int save_proto; 481 482 if (sscanf(name, "%d-%d", &p1, &p2) != 2) { 483 if ((cpy = strdup(name)) == NULL) 484 return 0; 485 486 if ((off = strchr(cpy, '-')) == NULL) { 487 free(cpy); 488 return 0; 489 } 490 491 *off = '\0'; 492 493 if (pcap_nametoport(cpy, port1, proto) == 0) { 494 free(cpy); 495 return 0; 496 } 497 save_proto = *proto; 498 499 if (pcap_nametoport(off + 1, port2, proto) == 0) { 500 free(cpy); 501 return 0; 502 } 503 free(cpy); 504 505 if (*proto != save_proto) 506 *proto = PROTO_UNDEF; 507 } else { 508 *port1 = p1; 509 *port2 = p2; 510 *proto = PROTO_UNDEF; 511 } 512 513 return 1; 514 } 515 516 /* 517 * XXX - not guaranteed to be thread-safe! See below for platforms 518 * on which it is thread-safe and on which it isn't. 519 */ 520 int 521 pcap_nametoproto(const char *str) 522 { 523 struct protoent *p; 524 #if defined(HAVE_LINUX_GETNETBYNAME_R) 525 /* 526 * We have Linux's reentrant getprotobyname_r(). 527 */ 528 struct protoent result_buf; 529 char buf[1024]; /* arbitrary size */ 530 int err; 531 532 err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p); 533 if (err != 0) { 534 /* 535 * XXX - dynamically allocate the buffer, and make it 536 * bigger if we get ERANGE back? 537 */ 538 return 0; 539 } 540 #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R) 541 /* 542 * We have Solaris's and IRIX's reentrant getprotobyname_r(). 543 */ 544 struct protoent result_buf; 545 char buf[1024]; /* arbitrary size */ 546 547 p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf); 548 #elif defined(HAVE_AIX_GETNETBYNAME_R) 549 /* 550 * We have AIX's reentrant getprotobyname_r(). 551 */ 552 struct protoent result_buf; 553 struct protoent_data proto_data; 554 555 if (getprotobyname_r(str, &result_buf, &proto_data) == -1) 556 p = NULL; 557 else 558 p = &result_buf; 559 #else 560 /* 561 * We don't have any getprotobyname_r(); either we have a 562 * getprotobyname() that uses thread-specific data, in which 563 * case we're thread-safe (sufficiently recent FreeBSD, 564 * sufficiently recent Darwin-based OS, sufficiently recent 565 * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have 566 * the traditional getprotobyname() (everything else, including 567 * current NetBSD and OpenBSD), in which case we're not 568 * thread-safe. 569 */ 570 p = getprotobyname(str); 571 #endif 572 if (p != 0) 573 return p->p_proto; 574 else 575 return PROTO_UNDEF; 576 } 577 578 #include "ethertype.h" 579 580 struct eproto { 581 const char *s; 582 u_short p; 583 }; 584 585 /* 586 * Static data base of ether protocol types. 587 * tcpdump used to import this, and it's declared as an export on 588 * Debian, at least, so make it a public symbol, even though we 589 * don't officially export it by declaring it in a header file. 590 * (Programs *should* do this themselves, as tcpdump now does.) 591 * 592 * We declare it here, right before defining it, to squelch any 593 * warnings we might get from compilers about the lack of a 594 * declaration. 595 */ 596 PCAP_API struct eproto eproto_db[]; 597 PCAP_API_DEF struct eproto eproto_db[] = { 598 { "aarp", ETHERTYPE_AARP }, 599 { "arp", ETHERTYPE_ARP }, 600 { "atalk", ETHERTYPE_ATALK }, 601 { "decnet", ETHERTYPE_DN }, 602 { "ip", ETHERTYPE_IP }, 603 #ifdef INET6 604 { "ip6", ETHERTYPE_IPV6 }, 605 #endif 606 { "lat", ETHERTYPE_LAT }, 607 { "loopback", ETHERTYPE_LOOPBACK }, 608 { "mopdl", ETHERTYPE_MOPDL }, 609 { "moprc", ETHERTYPE_MOPRC }, 610 { "rarp", ETHERTYPE_REVARP }, 611 { "sca", ETHERTYPE_SCA }, 612 { (char *)0, 0 } 613 }; 614 615 int 616 pcap_nametoeproto(const char *s) 617 { 618 struct eproto *p = eproto_db; 619 620 while (p->s != 0) { 621 if (strcmp(p->s, s) == 0) 622 return p->p; 623 p += 1; 624 } 625 return PROTO_UNDEF; 626 } 627 628 #include "llc.h" 629 630 /* Static data base of LLC values. */ 631 static struct eproto llc_db[] = { 632 { "iso", LLCSAP_ISONS }, 633 { "stp", LLCSAP_8021D }, 634 { "ipx", LLCSAP_IPX }, 635 { "netbeui", LLCSAP_NETBEUI }, 636 { (char *)0, 0 } 637 }; 638 639 int 640 pcap_nametollc(const char *s) 641 { 642 struct eproto *p = llc_db; 643 644 while (p->s != 0) { 645 if (strcmp(p->s, s) == 0) 646 return p->p; 647 p += 1; 648 } 649 return PROTO_UNDEF; 650 } 651 652 /* Hex digit to 8-bit unsigned integer. */ 653 static inline u_char 654 xdtoi(u_char c) 655 { 656 if (c >= '0' && c <= '9') 657 return (u_char)(c - '0'); 658 else if (c >= 'a' && c <= 'f') 659 return (u_char)(c - 'a' + 10); 660 else 661 return (u_char)(c - 'A' + 10); 662 } 663 664 int 665 __pcap_atoin(const char *s, bpf_u_int32 *addr) 666 { 667 u_int n; 668 int len; 669 670 *addr = 0; 671 len = 0; 672 for (;;) { 673 n = 0; 674 while (*s && *s != '.') { 675 if (n > 25) { 676 /* The result will be > 255 */ 677 return -1; 678 } 679 n = n * 10 + *s++ - '0'; 680 } 681 if (n > 255) 682 return -1; 683 *addr <<= 8; 684 *addr |= n & 0xff; 685 len += 8; 686 if (*s == '\0') 687 return len; 688 ++s; 689 } 690 /* NOTREACHED */ 691 } 692 693 int 694 __pcap_atodn(const char *s, bpf_u_int32 *addr) 695 { 696 #define AREASHIFT 10 697 #define AREAMASK 0176000 698 #define NODEMASK 01777 699 700 u_int node, area; 701 702 if (sscanf(s, "%d.%d", &area, &node) != 2) 703 return(0); 704 705 *addr = (area << AREASHIFT) & AREAMASK; 706 *addr |= (node & NODEMASK); 707 708 return(32); 709 } 710 711 /* 712 * Convert 's', which can have the one of the forms: 713 * 714 * "xx:xx:xx:xx:xx:xx" 715 * "xx.xx.xx.xx.xx.xx" 716 * "xx-xx-xx-xx-xx-xx" 717 * "xxxx.xxxx.xxxx" 718 * "xxxxxxxxxxxx" 719 * 720 * (or various mixes of ':', '.', and '-') into a new 721 * ethernet address. Assumes 's' is well formed. 722 */ 723 u_char * 724 pcap_ether_aton(const char *s) 725 { 726 register u_char *ep, *e; 727 register u_char d; 728 729 e = ep = (u_char *)malloc(6); 730 if (e == NULL) 731 return (NULL); 732 733 while (*s) { 734 if (*s == ':' || *s == '.' || *s == '-') 735 s += 1; 736 d = xdtoi(*s++); 737 if (PCAP_ISXDIGIT(*s)) { 738 d <<= 4; 739 d |= xdtoi(*s++); 740 } 741 *ep++ = d; 742 } 743 744 return (e); 745 } 746 747 #ifndef HAVE_ETHER_HOSTTON 748 /* 749 * Roll our own. 750 * XXX - not thread-safe, because pcap_next_etherent() isn't thread- 751 * safe! Needs a mutex or a thread-safe pcap_next_etherent(). 752 */ 753 u_char * 754 pcap_ether_hostton(const char *name) 755 { 756 register struct pcap_etherent *ep; 757 register u_char *ap; 758 static FILE *fp = NULL; 759 static int init = 0; 760 761 if (!init) { 762 fp = fopen(PCAP_ETHERS_FILE, "r"); 763 ++init; 764 if (fp == NULL) 765 return (NULL); 766 } else if (fp == NULL) 767 return (NULL); 768 else 769 rewind(fp); 770 771 while ((ep = pcap_next_etherent(fp)) != NULL) { 772 if (strcmp(ep->name, name) == 0) { 773 ap = (u_char *)malloc(6); 774 if (ap != NULL) { 775 memcpy(ap, ep->addr, 6); 776 return (ap); 777 } 778 break; 779 } 780 } 781 return (NULL); 782 } 783 #else 784 /* 785 * Use the OS-supplied routine. 786 * This *should* be thread-safe; the API doesn't have a static buffer. 787 */ 788 u_char * 789 pcap_ether_hostton(const char *name) 790 { 791 register u_char *ap; 792 u_char a[6]; 793 char namebuf[1024]; 794 795 /* 796 * In AIX 7.1 and 7.2: int ether_hostton(char *, struct ether_addr *); 797 */ 798 pcap_strlcpy(namebuf, name, sizeof(namebuf)); 799 ap = NULL; 800 if (ether_hostton(namebuf, (struct ether_addr *)a) == 0) { 801 ap = (u_char *)malloc(6); 802 if (ap != NULL) 803 memcpy((char *)ap, (char *)a, 6); 804 } 805 return (ap); 806 } 807 #endif 808 809 /* 810 * XXX - not guaranteed to be thread-safe! 811 */ 812 int 813 #ifdef DECNETLIB 814 __pcap_nametodnaddr(const char *name, u_short *res) 815 { 816 struct nodeent *getnodebyname(); 817 struct nodeent *nep; 818 819 nep = getnodebyname(name); 820 if (nep == ((struct nodeent *)0)) 821 return(0); 822 823 memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short)); 824 return(1); 825 #else 826 __pcap_nametodnaddr(const char *name _U_, u_short *res _U_) 827 { 828 return(0); 829 #endif 830 } 831