1 /* $NetBSD: nametoaddr.c,v 1.8 2026/03/18 23:43:20 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.8 2026/03/18 23:43:20 christos Exp $"); 29 30 #include <config.h> 31 32 #ifdef DECNETLIB 33 #include <sys/types.h> 34 #include <netdnet/dnetdb.h> 35 #endif 36 37 #ifdef _WIN32 38 #include <winsock2.h> 39 #include <ws2tcpip.h> 40 #else /* _WIN32 */ 41 #include <sys/param.h> 42 #include <sys/types.h> 43 #include <sys/socket.h> 44 #include <sys/time.h> 45 46 #include <netinet/in.h> 47 48 #ifdef HAVE_ETHER_HOSTTON 49 #if defined(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON) 50 /* 51 * OK, just include <net/ethernet.h>. 52 */ 53 #include <net/ethernet.h> 54 #elif defined(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON) 55 /* 56 * OK, just include <netinet/ether.h> 57 */ 58 #include <netinet/ether.h> 59 #elif defined(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON) 60 /* 61 * OK, just include <sys/ethernet.h> 62 */ 63 #include <sys/ethernet.h> 64 #elif defined(ARPA_INET_H_DECLARES_ETHER_HOSTTON) 65 /* 66 * OK, just include <arpa/inet.h> 67 */ 68 #include <arpa/inet.h> 69 #elif defined(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON) 70 /* 71 * OK, include <netinet/if_ether.h>, after all the other stuff we 72 * need to include or define for its benefit. 73 */ 74 #define NEED_NETINET_IF_ETHER_H 75 #else 76 /* 77 * We'll have to declare it ourselves. 78 * If <netinet/if_ether.h> defines struct ether_addr, include 79 * it. Otherwise, define it ourselves. 80 */ 81 #ifdef HAVE_STRUCT_ETHER_ADDR 82 #define NEED_NETINET_IF_ETHER_H 83 #else /* HAVE_STRUCT_ETHER_ADDR */ 84 struct ether_addr { 85 unsigned char ether_addr_octet[6]; 86 }; 87 #endif /* HAVE_STRUCT_ETHER_ADDR */ 88 #endif /* what declares ether_hostton() */ 89 90 #ifdef NEED_NETINET_IF_ETHER_H 91 #include <net/if.h> /* Needed on some platforms */ 92 #include <netinet/in.h> /* Needed on some platforms */ 93 #include <netinet/if_ether.h> 94 #endif /* NEED_NETINET_IF_ETHER_H */ 95 96 #ifndef HAVE_DECL_ETHER_HOSTTON 97 /* 98 * No header declares it, so declare it ourselves. 99 */ 100 extern int ether_hostton(const char *, struct ether_addr *); 101 #endif /* !defined(HAVE_DECL_ETHER_HOSTTON) */ 102 #endif /* HAVE_ETHER_HOSTTON */ 103 104 #include <arpa/inet.h> 105 #include <netdb.h> 106 #endif /* _WIN32 */ 107 108 #include <errno.h> 109 #include <stdlib.h> 110 #include <string.h> 111 #include <stdio.h> 112 113 #include "pcap-int.h" 114 115 #include "diag-control.h" 116 117 #include "gencode.h" 118 #include <pcap/namedb.h> 119 #include "nametoaddr.h" 120 121 #include "thread-local.h" 122 123 #ifdef HAVE_OS_PROTO_H 124 #include "os-proto.h" 125 #endif 126 127 #ifndef NTOHL 128 #define NTOHL(x) (x) = ntohl(x) 129 #define NTOHS(x) (x) = ntohs(x) 130 #endif 131 132 /* 133 * Convert host name to internet address. 134 * Return 0 upon failure. 135 * XXX - not thread-safe; don't use it inside libpcap. 136 */ 137 bpf_u_int32 ** 138 pcap_nametoaddr(const char *name) 139 { 140 #ifndef h_addr 141 static bpf_u_int32 *hlist[2]; 142 #endif 143 bpf_u_int32 **p; 144 struct hostent *hp; 145 146 /* 147 * gethostbyname() is deprecated on Windows, perhaps because 148 * it's not thread-safe, or because it doesn't support IPv6, 149 * or both. 150 * 151 * We deprecate pcap_nametoaddr() on all platforms because 152 * it's not thread-safe; we supply it for backwards compatibility, 153 * so suppress the deprecation warning. We could, I guess, 154 * use getaddrinfo() and construct the array ourselves, but 155 * that's probably not worth the effort, as that wouldn't make 156 * this thread-safe - we can't change the API to require that 157 * our caller free the address array, so we still have to reuse 158 * a local array. 159 */ 160 DIAG_OFF_DEPRECATION 161 if ((hp = gethostbyname(name)) != NULL) { 162 DIAG_ON_DEPRECATION 163 #ifndef h_addr 164 hlist[0] = (bpf_u_int32 *)hp->h_addr; 165 NTOHL(hp->h_addr); 166 return hlist; 167 #else 168 for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) 169 NTOHL(**p); 170 return (bpf_u_int32 **)hp->h_addr_list; 171 #endif 172 } 173 else 174 return 0; 175 } 176 177 struct addrinfo * 178 pcap_nametoaddrinfo(const char *name) 179 { 180 struct addrinfo hints, *res; 181 int error; 182 183 memset(&hints, 0, sizeof(hints)); 184 hints.ai_family = PF_UNSPEC; 185 hints.ai_socktype = SOCK_STREAM; /*not really*/ 186 hints.ai_protocol = IPPROTO_TCP; /*not really*/ 187 error = getaddrinfo(name, NULL, &hints, &res); 188 if (error) 189 return NULL; 190 else 191 return res; 192 } 193 194 /* 195 * Convert net name to internet address. 196 * Return 0 upon failure. 197 * XXX - not guaranteed to be thread-safe! See below for platforms 198 * on which it is thread-safe and on which it isn't. 199 */ 200 #if defined(_WIN32) || defined(__CYGWIN__) 201 bpf_u_int32 202 pcap_nametonetaddr(const char *name _U_) 203 { 204 /* 205 * There's no "getnetbyname()" on Windows. 206 * 207 * XXX - I guess we could use the BSD code to read 208 * C:\Windows\System32\drivers\etc/networks, assuming 209 * that's its home on all the versions of Windows 210 * we use, but that file probably just has the loopback 211 * network on 127/24 on 99 44/100% of Windows machines. 212 * 213 * (Heck, these days it probably just has that on 99 44/100% 214 * of *UN*X* machines.) 215 */ 216 return 0; 217 } 218 #else /* _WIN32 */ 219 bpf_u_int32 220 pcap_nametonetaddr(const char *name) 221 { 222 /* 223 * UN*X. 224 */ 225 struct netent *np; 226 #if defined(HAVE_LINUX_GETNETBYNAME_R) 227 /* 228 * We have Linux's reentrant getnetbyname_r(). 229 */ 230 struct netent result_buf; 231 char buf[1024]; /* arbitrary size */ 232 int h_errnoval; 233 int err; 234 235 /* 236 * Apparently, the man page at 237 * 238 * http://man7.org/linux/man-pages/man3/getnetbyname_r.3.html 239 * 240 * lies when it says 241 * 242 * If the function call successfully obtains a network record, 243 * then *result is set pointing to result_buf; otherwise, *result 244 * is set to NULL. 245 * 246 * and, in fact, at least in some versions of GNU libc, it does 247 * *not* always get set if getnetbyname_r() succeeds. 248 */ 249 np = NULL; 250 err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np, 251 &h_errnoval); 252 if (err != 0) { 253 /* 254 * XXX - dynamically allocate the buffer, and make it 255 * bigger if we get ERANGE back? 256 */ 257 return 0; 258 } 259 #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R) 260 /* 261 * We have Solaris's and IRIX's reentrant getnetbyname_r(). 262 */ 263 struct netent result_buf; 264 char buf[1024]; /* arbitrary size */ 265 266 np = getnetbyname_r(name, &result_buf, buf, (int)sizeof buf); 267 #elif defined(HAVE_AIX_GETNETBYNAME_R) 268 /* 269 * We have AIX's reentrant getnetbyname_r(). 270 */ 271 struct netent result_buf; 272 struct netent_data net_data; 273 274 if (getnetbyname_r(name, &result_buf, &net_data) == -1) 275 np = NULL; 276 else 277 np = &result_buf; 278 #else 279 /* 280 * We don't have any getnetbyname_r(); either we have a 281 * getnetbyname() that uses thread-specific data, in which 282 * case we're thread-safe (sufficiently recent FreeBSD, 283 * sufficiently recent Darwin-based OS, sufficiently recent 284 * HP-UX, sufficiently recent Tru64 UNIX), or we have the 285 * traditional getnetbyname() (everything else, including 286 * current NetBSD and OpenBSD), in which case we're not 287 * thread-safe. 288 */ 289 np = getnetbyname(name); 290 #endif 291 if (np != NULL) 292 return np->n_net; 293 else 294 return 0; 295 } 296 #endif /* _WIN32 */ 297 298 /* 299 * Convert a port name to its port and protocol numbers. 300 * We assume only TCP or UDP. 301 * Return 0 upon failure. 302 */ 303 int 304 pcap_nametoport(const char *name, int *port, int *proto) 305 { 306 struct addrinfo hints, *res, *ai; 307 int error; 308 struct sockaddr_in *in4; 309 #ifdef INET6 310 struct sockaddr_in6 *in6; 311 #endif 312 int tcp_port = -1; 313 int udp_port = -1; 314 315 /* 316 * We check for both TCP and UDP in case there are 317 * ambiguous entries. 318 */ 319 memset(&hints, 0, sizeof(hints)); 320 hints.ai_family = PF_UNSPEC; 321 hints.ai_socktype = SOCK_STREAM; 322 hints.ai_protocol = IPPROTO_TCP; 323 error = getaddrinfo(NULL, name, &hints, &res); 324 if (error != 0) { 325 if (error != EAI_NONAME && 326 error != EAI_SERVICE) { 327 /* 328 * This is a real error, not just "there's 329 * no such service name". 330 * XXX - this doesn't return an error string. 331 */ 332 return 0; 333 } 334 } else { 335 /* 336 * OK, we found it. Did it find anything? 337 */ 338 for (ai = res; ai != NULL; ai = ai->ai_next) { 339 /* 340 * Does it have an address? 341 */ 342 if (ai->ai_addr != NULL) { 343 /* 344 * Yes. Get a port number; we're done. 345 */ 346 if (ai->ai_addr->sa_family == AF_INET) { 347 in4 = (struct sockaddr_in *)ai->ai_addr; 348 tcp_port = ntohs(in4->sin_port); 349 break; 350 } 351 #ifdef INET6 352 if (ai->ai_addr->sa_family == AF_INET6) { 353 in6 = (struct sockaddr_in6 *)ai->ai_addr; 354 tcp_port = ntohs(in6->sin6_port); 355 break; 356 } 357 #endif 358 } 359 } 360 freeaddrinfo(res); 361 } 362 363 memset(&hints, 0, sizeof(hints)); 364 hints.ai_family = PF_UNSPEC; 365 hints.ai_socktype = SOCK_DGRAM; 366 hints.ai_protocol = IPPROTO_UDP; 367 error = getaddrinfo(NULL, name, &hints, &res); 368 if (error != 0) { 369 if (error != EAI_NONAME && 370 error != EAI_SERVICE) { 371 /* 372 * This is a real error, not just "there's 373 * no such service name". 374 * XXX - this doesn't return an error string. 375 */ 376 return 0; 377 } 378 } else { 379 /* 380 * OK, we found it. Did it find anything? 381 */ 382 for (ai = res; ai != NULL; ai = ai->ai_next) { 383 /* 384 * Does it have an address? 385 */ 386 if (ai->ai_addr != NULL) { 387 /* 388 * Yes. Get a port number; we're done. 389 */ 390 if (ai->ai_addr->sa_family == AF_INET) { 391 in4 = (struct sockaddr_in *)ai->ai_addr; 392 udp_port = ntohs(in4->sin_port); 393 break; 394 } 395 #ifdef INET6 396 if (ai->ai_addr->sa_family == AF_INET6) { 397 in6 = (struct sockaddr_in6 *)ai->ai_addr; 398 udp_port = ntohs(in6->sin6_port); 399 break; 400 } 401 #endif 402 } 403 } 404 freeaddrinfo(res); 405 } 406 407 /* 408 * We need to check /etc/services for ambiguous entries. 409 * If we find an ambiguous entry, and it has the 410 * same port number, change the proto to PROTO_UNDEF 411 * so both TCP and UDP will be checked. 412 */ 413 if (tcp_port >= 0) { 414 *port = tcp_port; 415 *proto = IPPROTO_TCP; 416 if (udp_port >= 0) { 417 if (udp_port == tcp_port) 418 *proto = PROTO_UNDEF; 419 #ifdef notdef 420 else 421 /* Can't handle ambiguous names that refer 422 to different port numbers. */ 423 warning("ambiguous port %s in /etc/services", 424 name); 425 #endif 426 } 427 return 1; 428 } 429 if (udp_port >= 0) { 430 *port = udp_port; 431 *proto = IPPROTO_UDP; 432 return 1; 433 } 434 #if defined(ultrix) || defined(__osf__) 435 /* Special hack in case NFS isn't in /etc/services */ 436 if (strcmp(name, "nfs") == 0) { 437 *port = 2049; 438 *proto = PROTO_UNDEF; 439 return 1; 440 } 441 #endif 442 return 0; 443 } 444 445 /* 446 * Convert a string in the form PPP-PPP, where correspond to ports, to 447 * a starting and ending port in a port range. 448 * Return 0 on failure. 449 */ 450 int 451 pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto) 452 { 453 char *off, *cpy; 454 int save_proto; 455 456 if ((cpy = strdup(name)) == NULL) 457 return 0; 458 459 if ((off = strchr(cpy, '-')) == NULL) { 460 free(cpy); 461 return 0; 462 } 463 464 *off = '\0'; 465 466 if (pcap_nametoport(cpy, port1, proto) == 0) { 467 free(cpy); 468 return 0; 469 } 470 save_proto = *proto; 471 472 if (pcap_nametoport(off + 1, port2, proto) == 0) { 473 free(cpy); 474 return 0; 475 } 476 free(cpy); 477 478 if (*proto != save_proto) 479 *proto = PROTO_UNDEF; 480 481 return 1; 482 } 483 484 /* 485 * XXX - not guaranteed to be thread-safe! See below for platforms 486 * on which it is thread-safe and on which it isn't. 487 */ 488 int 489 pcap_nametoproto(const char *str) 490 { 491 struct protoent *p; 492 #if defined(HAVE_LINUX_GETNETBYNAME_R) 493 /* 494 * We have Linux's reentrant getprotobyname_r(). 495 */ 496 struct protoent result_buf; 497 char buf[1024]; /* arbitrary size */ 498 int err; 499 500 err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p); 501 if (err != 0) { 502 /* 503 * XXX - dynamically allocate the buffer, and make it 504 * bigger if we get ERANGE back? 505 */ 506 return 0; 507 } 508 #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R) 509 /* 510 * We have Solaris's and IRIX's reentrant getprotobyname_r(). 511 */ 512 struct protoent result_buf; 513 char buf[1024]; /* arbitrary size */ 514 515 p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf); 516 #elif defined(HAVE_AIX_GETNETBYNAME_R) 517 /* 518 * We have AIX's reentrant getprotobyname_r(). 519 */ 520 struct protoent result_buf; 521 struct protoent_data proto_data; 522 523 if (getprotobyname_r(str, &result_buf, &proto_data) == -1) 524 p = NULL; 525 else 526 p = &result_buf; 527 #else 528 /* 529 * We don't have any getprotobyname_r(); either we have a 530 * getprotobyname() that uses thread-specific data, in which 531 * case we're thread-safe (sufficiently recent FreeBSD, 532 * sufficiently recent Darwin-based OS, sufficiently recent 533 * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have 534 * the traditional getprotobyname() (everything else, including 535 * current NetBSD and OpenBSD), in which case we're not 536 * thread-safe. 537 */ 538 p = getprotobyname(str); 539 #endif 540 if (p != 0) 541 return p->p_proto; 542 else 543 return PROTO_UNDEF; 544 } 545 546 #include "ethertype.h" 547 548 struct eproto { 549 const char *s; 550 u_short p; 551 }; 552 553 /* 554 * Static data base of ether protocol types. 555 * tcpdump used to import this, and it's declared as an export on 556 * Debian, at least, so make it a public symbol, even though we 557 * don't officially export it by declaring it in a header file. 558 * (Programs *should* do this themselves, as tcpdump now does.) 559 * 560 * We declare it here, right before defining it, to squelch any 561 * warnings we might get from compilers about the lack of a 562 * declaration. 563 */ 564 PCAP_API struct eproto eproto_db[]; 565 PCAP_API_DEF struct eproto eproto_db[] = { 566 { "aarp", ETHERTYPE_AARP }, 567 { "arp", ETHERTYPE_ARP }, 568 { "atalk", ETHERTYPE_ATALK }, 569 { "decnet", ETHERTYPE_DN }, 570 { "ip", ETHERTYPE_IP }, 571 #ifdef INET6 572 { "ip6", ETHERTYPE_IPV6 }, 573 #endif 574 { "lat", ETHERTYPE_LAT }, 575 { "loopback", ETHERTYPE_LOOPBACK }, 576 { "mopdl", ETHERTYPE_MOPDL }, 577 { "moprc", ETHERTYPE_MOPRC }, 578 { "rarp", ETHERTYPE_REVARP }, 579 { "sca", ETHERTYPE_SCA }, 580 { (char *)0, 0 } 581 }; 582 583 int 584 pcap_nametoeproto(const char *s) 585 { 586 struct eproto *p = eproto_db; 587 588 while (p->s != 0) { 589 if (strcmp(p->s, s) == 0) 590 return p->p; 591 p += 1; 592 } 593 return PROTO_UNDEF; 594 } 595 596 #include "llc.h" 597 598 /* Static data base of LLC values. */ 599 static struct eproto llc_db[] = { 600 { "iso", LLCSAP_ISONS }, 601 { "stp", LLCSAP_8021D }, 602 { "ipx", LLCSAP_IPX }, 603 { "netbeui", LLCSAP_NETBEUI }, 604 { (char *)0, 0 } 605 }; 606 607 int 608 pcap_nametollc(const char *s) 609 { 610 struct eproto *p = llc_db; 611 612 while (p->s != 0) { 613 if (strcmp(p->s, s) == 0) 614 return p->p; 615 p += 1; 616 } 617 return PROTO_UNDEF; 618 } 619 620 /* Hex digit to 8-bit unsigned integer. */ 621 static inline u_char 622 pcapint_xdtoi(u_char c) 623 { 624 if (c >= '0' && c <= '9') 625 return (u_char)(c - '0'); 626 else if (c >= 'a' && c <= 'f') 627 return (u_char)(c - 'a' + 10); 628 else 629 return (u_char)(c - 'A' + 10); 630 } 631 632 int 633 __pcap_atoin(const char *s, bpf_u_int32 *addr) 634 { 635 u_int n; 636 int len; 637 638 *addr = 0; 639 len = 0; 640 for (;;) { 641 n = 0; 642 while (*s && *s != '.') { 643 if (n > 25) { 644 /* The result will be > 255 */ 645 return -1; 646 } 647 n = n * 10 + *s++ - '0'; 648 } 649 if (n > 255) 650 return -1; 651 *addr <<= 8; 652 *addr |= n & 0xff; 653 len += 8; 654 if (*s == '\0') 655 return len; 656 ++s; 657 } 658 /* NOTREACHED */ 659 } 660 661 int 662 __pcap_atodn(const char *s, bpf_u_int32 *addr) 663 { 664 #define AREASHIFT 10 665 #define AREAMASK 0176000 666 #define NODEMASK 01777 667 668 u_int node, area; 669 670 if (sscanf(s, "%d.%d", &area, &node) != 2) 671 return(0); 672 673 *addr = (area << AREASHIFT) & AREAMASK; 674 *addr |= (node & NODEMASK); 675 676 return(32); 677 } 678 679 /* 680 * libpcap ARCnet address format is "^\$[0-9a-fA-F]{1,2}$" in regexp syntax. 681 * Iff the given string is a well-formed ARCnet address, parse the string, 682 * store the 8-bit unsigned value into the provided integer and return 1. 683 * Otherwise return 0. 684 * 685 * --> START -- $ --> DOLLAR -- [0-9a-fA-F] --> HEX1 -- \0 -->-+ 686 * | | | | 687 * [.] [.] [0-9a-fA-F] | 688 * | | | | 689 * v v v v 690 * (invalid) <--------+-<---------------[.]-- HEX2 -- \0 -->-+--> (valid) 691 */ 692 int 693 pcapint_atoan(const char *s, uint8_t *addr) 694 { 695 enum { 696 START, 697 DOLLAR, 698 HEX1, 699 HEX2, 700 } fsm_state = START; 701 uint8_t tmp = 0; 702 703 while (*s) { 704 switch (fsm_state) { 705 case START: 706 if (*s != '$') 707 goto invalid; 708 fsm_state = DOLLAR; 709 break; 710 case DOLLAR: 711 if (! PCAP_ISXDIGIT(*s)) 712 goto invalid; 713 tmp = pcapint_xdtoi(*s); 714 fsm_state = HEX1; 715 break; 716 case HEX1: 717 if (! PCAP_ISXDIGIT(*s)) 718 goto invalid; 719 tmp <<= 4; 720 tmp |= pcapint_xdtoi(*s); 721 fsm_state = HEX2; 722 break; 723 case HEX2: 724 goto invalid; 725 } // switch 726 s++; 727 } // while 728 if (fsm_state == HEX1 || fsm_state == HEX2) { 729 *addr = tmp; 730 return 1; 731 } 732 733 invalid: 734 return 0; 735 } 736 737 // Man page: "xxxxxxxxxxxx", regexp: "^[0-9a-fA-F]{12}$". 738 static u_char 739 pcapint_atomac48_xxxxxxxxxxxx(const char *s, uint8_t *addr) 740 { 741 if (strlen(s) == 12 && 742 PCAP_ISXDIGIT(s[0]) && 743 PCAP_ISXDIGIT(s[1]) && 744 PCAP_ISXDIGIT(s[2]) && 745 PCAP_ISXDIGIT(s[3]) && 746 PCAP_ISXDIGIT(s[4]) && 747 PCAP_ISXDIGIT(s[5]) && 748 PCAP_ISXDIGIT(s[6]) && 749 PCAP_ISXDIGIT(s[7]) && 750 PCAP_ISXDIGIT(s[8]) && 751 PCAP_ISXDIGIT(s[9]) && 752 PCAP_ISXDIGIT(s[10]) && 753 PCAP_ISXDIGIT(s[11])) { 754 addr[0] = pcapint_xdtoi(s[0]) << 4 | pcapint_xdtoi(s[1]); 755 addr[1] = pcapint_xdtoi(s[2]) << 4 | pcapint_xdtoi(s[3]); 756 addr[2] = pcapint_xdtoi(s[4]) << 4 | pcapint_xdtoi(s[5]); 757 addr[3] = pcapint_xdtoi(s[6]) << 4 | pcapint_xdtoi(s[7]); 758 addr[4] = pcapint_xdtoi(s[8]) << 4 | pcapint_xdtoi(s[9]); 759 addr[5] = pcapint_xdtoi(s[10]) << 4 | pcapint_xdtoi(s[11]); 760 return 1; 761 } 762 return 0; 763 } 764 765 // Man page: "xxxx.xxxx.xxxx", regexp: "^[0-9a-fA-F]{4}(\.[0-9a-fA-F]{4}){2}$". 766 static u_char 767 pcapint_atomac48_xxxx_3_times(const char *s, uint8_t *addr) 768 { 769 const char sep = '.'; 770 if (strlen(s) == 14 && 771 PCAP_ISXDIGIT(s[0]) && 772 PCAP_ISXDIGIT(s[1]) && 773 PCAP_ISXDIGIT(s[2]) && 774 PCAP_ISXDIGIT(s[3]) && 775 s[4] == sep && 776 PCAP_ISXDIGIT(s[5]) && 777 PCAP_ISXDIGIT(s[6]) && 778 PCAP_ISXDIGIT(s[7]) && 779 PCAP_ISXDIGIT(s[8]) && 780 s[9] == sep && 781 PCAP_ISXDIGIT(s[10]) && 782 PCAP_ISXDIGIT(s[11]) && 783 PCAP_ISXDIGIT(s[12]) && 784 PCAP_ISXDIGIT(s[13])) { 785 addr[0] = pcapint_xdtoi(s[0]) << 4 | pcapint_xdtoi(s[1]); 786 addr[1] = pcapint_xdtoi(s[2]) << 4 | pcapint_xdtoi(s[3]); 787 addr[2] = pcapint_xdtoi(s[5]) << 4 | pcapint_xdtoi(s[6]); 788 addr[3] = pcapint_xdtoi(s[7]) << 4 | pcapint_xdtoi(s[8]); 789 addr[4] = pcapint_xdtoi(s[10]) << 4 | pcapint_xdtoi(s[11]); 790 addr[5] = pcapint_xdtoi(s[12]) << 4 | pcapint_xdtoi(s[13]); 791 return 1; 792 } 793 return 0; 794 } 795 796 /* 797 * Man page: "xx:xx:xx:xx:xx:xx", regexp: "^[0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,2}){5}$". 798 * Man page: "xx-xx-xx-xx-xx-xx", regexp: "^[0-9a-fA-F]{1,2}(-[0-9a-fA-F]{1,2}){5}$". 799 * Man page: "xx.xx.xx.xx.xx.xx", regexp: "^[0-9a-fA-F]{1,2}(\.[0-9a-fA-F]{1,2}){5}$". 800 * (Any "xx" above can be "x", which is equivalent to "0x".) 801 * 802 * An equivalent (and parametrisable for EUI-64) FSM could be implemented using 803 * a smaller graph, but that graph would be neither acyclic nor planar nor 804 * trivial to verify. 805 * 806 * | 807 * [.] v 808 * +<---------- START 809 * | | 810 * | | [0-9a-fA-F] 811 * | [.] v 812 * +<--------- BYTE0_X ----------+ 813 * | | | 814 * | | [0-9a-fA-F] | 815 * | [.] v | 816 * +<--------- BYTE0_XX | [:\.-] 817 * | | | 818 * | | [:\.-] | 819 * | [.] v | 820 * +<----- BYTE0_SEP_BYTE1 <-----+ 821 * | | 822 * | | [0-9a-fA-F] 823 * | [.] v 824 * +<--------- BYTE1_X ----------+ 825 * | | | 826 * | | [0-9a-fA-F] | 827 * | [.] v | 828 * +<--------- BYTE1_XX | <sep> 829 * | | | 830 * | | <sep> | 831 * | [.] v | 832 * +<----- BYTE1_SEP_BYTE2 <-----+ 833 * | | 834 * | | [0-9a-fA-F] 835 * | [.] v 836 * +<--------- BYTE2_X ----------+ 837 * | | | 838 * | | [0-9a-fA-F] | 839 * | [.] v | 840 * +<--------- BYTE2_XX | <sep> 841 * | | | 842 * | | <sep> | 843 * | [.] v | 844 * +<----- BYTE2_SEP_BYTE3 <-----+ 845 * | | 846 * | | [0-9a-fA-F] 847 * | [.] v 848 * +<--------- BYTE3_X ----------+ 849 * | | | 850 * | | [0-9a-fA-F] | 851 * | [.] v | 852 * +<--------- BYTE3_XX | <sep> 853 * | | | 854 * | | <sep> | 855 * | [.] v | 856 * +<----- BYTE3_SEP_BYTE4 <-----+ 857 * | | 858 * | | [0-9a-fA-F] 859 * | [.] v 860 * +<--------- BYTE4_X ----------+ 861 * | | | 862 * | | [0-9a-fA-F] | 863 * | [.] v | 864 * +<--------- BYTE4_XX | <sep> 865 * | | | 866 * | | <sep> | 867 * | [.] v | 868 * +<----- BYTE4_SEP_BYTE5 <-----+ 869 * | | 870 * | | [0-9a-fA-F] 871 * | [.] v 872 * +<--------- BYTE5_X ----------+ 873 * | | | 874 * | | [0-9a-fA-F] | 875 * | [.] v | 876 * +<--------- BYTE5_XX | \0 877 * | | | 878 * | | \0 | 879 * | | v 880 * +--> (reject) +---------> (accept) 881 * 882 */ 883 static u_char 884 pcapint_atomac48_x_xx_6_times(const char *s, uint8_t *addr) 885 { 886 enum { 887 START, 888 BYTE0_X, 889 BYTE0_XX, 890 BYTE0_SEP_BYTE1, 891 BYTE1_X, 892 BYTE1_XX, 893 BYTE1_SEP_BYTE2, 894 BYTE2_X, 895 BYTE2_XX, 896 BYTE2_SEP_BYTE3, 897 BYTE3_X, 898 BYTE3_XX, 899 BYTE3_SEP_BYTE4, 900 BYTE4_X, 901 BYTE4_XX, 902 BYTE4_SEP_BYTE5, 903 BYTE5_X, 904 BYTE5_XX, 905 } fsm_state = START; 906 uint8_t buf[6]; 907 const char *seplist = ":.-"; 908 char sep; 909 910 while (*s) { 911 switch (fsm_state) { 912 case START: 913 if (PCAP_ISXDIGIT(*s)) { 914 buf[0] = pcapint_xdtoi(*s); 915 fsm_state = BYTE0_X; 916 break; 917 } 918 goto reject; 919 case BYTE0_X: 920 if (strchr(seplist, *s)) { 921 sep = *s; 922 fsm_state = BYTE0_SEP_BYTE1; 923 break; 924 } 925 if (PCAP_ISXDIGIT(*s)) { 926 buf[0] = buf[0] << 4 | pcapint_xdtoi(*s); 927 fsm_state = BYTE0_XX; 928 break; 929 } 930 goto reject; 931 case BYTE0_XX: 932 if (strchr(seplist, *s)) { 933 sep = *s; 934 fsm_state = BYTE0_SEP_BYTE1; 935 break; 936 } 937 goto reject; 938 case BYTE0_SEP_BYTE1: 939 if (PCAP_ISXDIGIT(*s)) { 940 buf[1] = pcapint_xdtoi(*s); 941 fsm_state = BYTE1_X; 942 break; 943 } 944 goto reject; 945 case BYTE1_X: 946 if (*s == sep) { 947 fsm_state = BYTE1_SEP_BYTE2; 948 break; 949 } 950 if (PCAP_ISXDIGIT(*s)) { 951 buf[1] = buf[1] << 4 | pcapint_xdtoi(*s); 952 fsm_state = BYTE1_XX; 953 break; 954 } 955 goto reject; 956 case BYTE1_XX: 957 if (*s == sep) { 958 fsm_state = BYTE1_SEP_BYTE2; 959 break; 960 } 961 goto reject; 962 case BYTE1_SEP_BYTE2: 963 if (PCAP_ISXDIGIT(*s)) { 964 buf[2] = pcapint_xdtoi(*s); 965 fsm_state = BYTE2_X; 966 break; 967 } 968 goto reject; 969 case BYTE2_X: 970 if (*s == sep) { 971 fsm_state = BYTE2_SEP_BYTE3; 972 break; 973 } 974 if (PCAP_ISXDIGIT(*s)) { 975 buf[2] = buf[2] << 4 | pcapint_xdtoi(*s); 976 fsm_state = BYTE2_XX; 977 break; 978 } 979 goto reject; 980 case BYTE2_XX: 981 if (*s == sep) { 982 fsm_state = BYTE2_SEP_BYTE3; 983 break; 984 } 985 goto reject; 986 case BYTE2_SEP_BYTE3: 987 if (PCAP_ISXDIGIT(*s)) { 988 buf[3] = pcapint_xdtoi(*s); 989 fsm_state = BYTE3_X; 990 break; 991 } 992 goto reject; 993 case BYTE3_X: 994 if (*s == sep) { 995 fsm_state = BYTE3_SEP_BYTE4; 996 break; 997 } 998 if (PCAP_ISXDIGIT(*s)) { 999 buf[3] = buf[3] << 4 | pcapint_xdtoi(*s); 1000 fsm_state = BYTE3_XX; 1001 break; 1002 } 1003 goto reject; 1004 case BYTE3_XX: 1005 if (*s == sep) { 1006 fsm_state = BYTE3_SEP_BYTE4; 1007 break; 1008 } 1009 goto reject; 1010 case BYTE3_SEP_BYTE4: 1011 if (PCAP_ISXDIGIT(*s)) { 1012 buf[4] = pcapint_xdtoi(*s); 1013 fsm_state = BYTE4_X; 1014 break; 1015 } 1016 goto reject; 1017 case BYTE4_X: 1018 if (*s == sep) { 1019 fsm_state = BYTE4_SEP_BYTE5; 1020 break; 1021 } 1022 if (PCAP_ISXDIGIT(*s)) { 1023 buf[4] = buf[4] << 4 | pcapint_xdtoi(*s); 1024 fsm_state = BYTE4_XX; 1025 break; 1026 } 1027 goto reject; 1028 case BYTE4_XX: 1029 if (*s == sep) { 1030 fsm_state = BYTE4_SEP_BYTE5; 1031 break; 1032 } 1033 goto reject; 1034 case BYTE4_SEP_BYTE5: 1035 if (PCAP_ISXDIGIT(*s)) { 1036 buf[5] = pcapint_xdtoi(*s); 1037 fsm_state = BYTE5_X; 1038 break; 1039 } 1040 goto reject; 1041 case BYTE5_X: 1042 if (PCAP_ISXDIGIT(*s)) { 1043 buf[5] = buf[5] << 4 | pcapint_xdtoi(*s); 1044 fsm_state = BYTE5_XX; 1045 break; 1046 } 1047 goto reject; 1048 case BYTE5_XX: 1049 goto reject; 1050 } // switch 1051 s++; 1052 } // while 1053 1054 if (fsm_state == BYTE5_X || fsm_state == BYTE5_XX) { 1055 // accept 1056 memcpy(addr, buf, sizeof(buf)); 1057 return 1; 1058 } 1059 1060 reject: 1061 return 0; 1062 } 1063 1064 // The 'addr' argument must point to an array of at least 6 elements. 1065 static int 1066 pcapint_atomac48(const char *s, uint8_t *addr) 1067 { 1068 return s && ( 1069 pcapint_atomac48_xxxxxxxxxxxx(s, addr) || 1070 pcapint_atomac48_xxxx_3_times(s, addr) || 1071 pcapint_atomac48_x_xx_6_times(s, addr) 1072 ); 1073 } 1074 1075 /* 1076 * If 's' is a MAC-48 address in one of the forms documented in pcap-filter(7) 1077 * for "ether host", return a pointer to an allocated buffer with the binary 1078 * value of the address. Return NULL on any error. 1079 */ 1080 u_char * 1081 pcap_ether_aton(const char *s) 1082 { 1083 uint8_t tmp[6]; 1084 if (! pcapint_atomac48(s, tmp)) 1085 return (NULL); 1086 1087 u_char *e = malloc(6); 1088 if (e == NULL) 1089 return (NULL); 1090 memcpy(e, tmp, sizeof(tmp)); 1091 return (e); 1092 } 1093 1094 #ifndef HAVE_ETHER_HOSTTON 1095 /* 1096 * Roll our own. 1097 * 1098 * This should be thread-safe, as we define the static variables 1099 * we use to be thread-local, and as pcap_next_etherent() does so 1100 * as well. 1101 */ 1102 u_char * 1103 pcap_ether_hostton(const char *name) 1104 { 1105 register struct pcap_etherent *ep; 1106 register u_char *ap; 1107 static thread_local FILE *fp = NULL; 1108 static thread_local int init = 0; 1109 1110 if (!init) { 1111 fp = fopen(PCAP_ETHERS_FILE, "r"); 1112 ++init; 1113 if (fp == NULL) 1114 return (NULL); 1115 } else if (fp == NULL) 1116 return (NULL); 1117 else 1118 rewind(fp); 1119 1120 while ((ep = pcap_next_etherent(fp)) != NULL) { 1121 if (strcmp(ep->name, name) == 0) { 1122 ap = (u_char *)malloc(6); 1123 if (ap != NULL) { 1124 memcpy(ap, ep->addr, 6); 1125 return (ap); 1126 } 1127 break; 1128 } 1129 } 1130 return (NULL); 1131 } 1132 #else 1133 /* 1134 * Use the OS-supplied routine. 1135 * This *should* be thread-safe; the API doesn't have a static buffer. 1136 */ 1137 u_char * 1138 pcap_ether_hostton(const char *name) 1139 { 1140 register u_char *ap; 1141 u_char a[6]; 1142 char namebuf[1024]; 1143 1144 /* 1145 * In AIX 7.1 and 7.2: int ether_hostton(char *, struct ether_addr *); 1146 */ 1147 pcapint_strlcpy(namebuf, name, sizeof(namebuf)); 1148 ap = NULL; 1149 if (ether_hostton(namebuf, (struct ether_addr *)a) == 0) { 1150 ap = (u_char *)malloc(6); 1151 if (ap != NULL) 1152 memcpy((char *)ap, (char *)a, 6); 1153 } 1154 return (ap); 1155 } 1156 #endif 1157 1158 /* 1159 * XXX - not guaranteed to be thread-safe! 1160 */ 1161 int 1162 #ifdef DECNETLIB 1163 __pcap_nametodnaddr(const char *name, u_short *res) 1164 { 1165 struct nodeent *getnodebyname(); 1166 struct nodeent *nep; 1167 1168 nep = getnodebyname(name); 1169 if (nep == ((struct nodeent *)0)) 1170 return(0); 1171 1172 memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short)); 1173 return(1); 1174 #else 1175 __pcap_nametodnaddr(const char *name _U_, u_short *res _U_) 1176 { 1177 return(0); 1178 #endif 1179 } 1180