1 /* 2 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * Internet, ethernet, port, and protocol string to address 22 * and address to string conversion routines 23 */ 24 #ifndef lint 25 static const char rcsid[] = 26 "@(#) $Header: addrtoname.c,v 1.61 97/06/15 13:20:18 leres Exp $ (LBL)"; 27 #endif 28 29 #include <sys/types.h> 30 #include <sys/socket.h> 31 #include <sys/time.h> 32 33 #if __STDC__ 34 struct mbuf; 35 struct rtentry; 36 #endif 37 #include <net/if.h> 38 39 #include <netinet/in.h> 40 #include <net/ethernet.h> 41 42 #include <arpa/inet.h> 43 44 #include <ctype.h> 45 #include <netdb.h> 46 #include <pcap.h> 47 #include <pcap-namedb.h> 48 #ifdef HAVE_MALLOC_H 49 #include <malloc.h> 50 #endif 51 #ifdef HAVE_MEMORY_H 52 #include <memory.h> 53 #endif 54 #include <signal.h> 55 #include <stdio.h> 56 #include <string.h> 57 #include <stdlib.h> 58 #include <unistd.h> 59 60 #include "interface.h" 61 #include "addrtoname.h" 62 #include "llc.h" 63 #include "savestr.h" 64 #include "setsignal.h" 65 66 /* Forwards */ 67 static RETSIGTYPE nohostname(int); 68 69 /* 70 * hash tables for whatever-to-name translations 71 */ 72 73 #define HASHNAMESIZE 4096 74 75 struct hnamemem { 76 u_int32_t addr; 77 char *name; 78 struct hnamemem *nxt; 79 }; 80 81 struct hnamemem hnametable[HASHNAMESIZE]; 82 struct hnamemem tporttable[HASHNAMESIZE]; 83 struct hnamemem uporttable[HASHNAMESIZE]; 84 struct hnamemem eprototable[HASHNAMESIZE]; 85 struct hnamemem dnaddrtable[HASHNAMESIZE]; 86 struct hnamemem llcsaptable[HASHNAMESIZE]; 87 88 struct enamemem { 89 u_short e_addr0; 90 u_short e_addr1; 91 u_short e_addr2; 92 char *e_name; 93 u_char *e_nsap; /* used only for nsaptable[] */ 94 struct enamemem *e_nxt; 95 }; 96 97 struct enamemem enametable[HASHNAMESIZE]; 98 struct enamemem nsaptable[HASHNAMESIZE]; 99 100 struct protoidmem { 101 u_int32_t p_oui; 102 u_short p_proto; 103 char *p_name; 104 struct protoidmem *p_nxt; 105 }; 106 107 struct protoidmem protoidtable[HASHNAMESIZE]; 108 109 /* 110 * A faster replacement for inet_ntoa(). 111 */ 112 char * 113 intoa(u_int32_t addr) 114 { 115 register char *cp; 116 register u_int byte; 117 register int n; 118 static char buf[sizeof(".xxx.xxx.xxx.xxx")]; 119 120 NTOHL(addr); 121 cp = &buf[sizeof buf]; 122 *--cp = '\0'; 123 124 n = 4; 125 do { 126 byte = addr & 0xff; 127 *--cp = byte % 10 + '0'; 128 byte /= 10; 129 if (byte > 0) { 130 *--cp = byte % 10 + '0'; 131 byte /= 10; 132 if (byte > 0) 133 *--cp = byte + '0'; 134 } 135 *--cp = '.'; 136 addr >>= 8; 137 } while (--n > 0); 138 139 return cp + 1; 140 } 141 142 static u_int32_t f_netmask; 143 static u_int32_t f_localnet; 144 static u_int32_t netmask; 145 146 /* 147 * "getname" is written in this atrocious way to make sure we don't 148 * wait forever while trying to get hostnames from yp. 149 */ 150 #include <setjmp.h> 151 152 jmp_buf getname_env; 153 154 static RETSIGTYPE 155 nohostname(int signo) 156 { 157 longjmp(getname_env, 1); 158 } 159 160 /* 161 * Return a name for the IP address pointed to by ap. This address 162 * is assumed to be in network byte order. 163 */ 164 char * 165 getname(const u_char *ap) 166 { 167 register struct hostent *hp; 168 u_int32_t addr; 169 static struct hnamemem *p; /* static for longjmp() */ 170 171 #ifndef LBL_ALIGN 172 addr = *(const u_int32_t *)ap; 173 #else 174 /* 175 * Extract 32 bits in network order, dealing with alignment. 176 */ 177 switch ((long)ap & 3) { 178 179 case 0: 180 addr = *(u_int32_t *)ap; 181 break; 182 183 case 2: 184 #ifdef WORDS_BIGENDIAN 185 addr = ((u_int32_t)*(u_short *)ap << 16) | 186 (u_int32_t)*(u_short *)(ap + 2); 187 #else 188 addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) | 189 (u_int32_t)*(u_short *)ap; 190 #endif 191 break; 192 193 default: 194 #ifdef WORDS_BIGENDIAN 195 addr = ((u_int32_t)ap[0] << 24) | 196 ((u_int32_t)ap[1] << 16) | 197 ((u_int32_t)ap[2] << 8) | 198 (u_int32_t)ap[3]; 199 #else 200 addr = ((u_int32_t)ap[3] << 24) | 201 ((u_int32_t)ap[2] << 16) | 202 ((u_int32_t)ap[1] << 8) | 203 (u_int32_t)ap[0]; 204 #endif 205 break; 206 } 207 #endif 208 p = &hnametable[addr & (HASHNAMESIZE-1)]; 209 for (; p->nxt; p = p->nxt) { 210 if (p->addr == addr) 211 return (p->name); 212 } 213 p->addr = addr; 214 p->nxt = newhnamemem(); 215 216 /* 217 * Only print names when: 218 * (1) -n was not given. 219 * (2) Address is foreign and -f was given. (If -f was not 220 * give, f_netmask and f_local are 0 and the test 221 * evaluates to true) 222 * (3) -a was given or the host portion is not all ones 223 * nor all zeros (i.e. not a network or broadcast address) 224 */ 225 if (!nflag && 226 (addr & f_netmask) == f_localnet && 227 (aflag || 228 !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))) { 229 if (!setjmp(getname_env)) { 230 (void)setsignal(SIGALRM, nohostname); 231 (void)alarm(20); 232 hp = gethostbyaddr((char *)&addr, 4, AF_INET); 233 (void)alarm(0); 234 if (hp) { 235 char *dotp; 236 237 p->name = savestr(hp->h_name); 238 if (Nflag) { 239 /* Remove domain qualifications */ 240 dotp = strchr(p->name, '.'); 241 if (dotp) 242 *dotp = '\0'; 243 } 244 return (p->name); 245 } 246 } 247 } 248 p->name = savestr(intoa(addr)); 249 return (p->name); 250 } 251 252 static char hex[] = "0123456789abcdef"; 253 254 255 /* Find the hash node that corresponds the ether address 'ep' */ 256 257 static inline struct enamemem * 258 lookup_emem(const u_char *ep) 259 { 260 register u_int i, j, k; 261 struct enamemem *tp; 262 263 k = (ep[0] << 8) | ep[1]; 264 j = (ep[2] << 8) | ep[3]; 265 i = (ep[4] << 8) | ep[5]; 266 267 tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; 268 while (tp->e_nxt) 269 if (tp->e_addr0 == i && 270 tp->e_addr1 == j && 271 tp->e_addr2 == k) 272 return tp; 273 else 274 tp = tp->e_nxt; 275 tp->e_addr0 = i; 276 tp->e_addr1 = j; 277 tp->e_addr2 = k; 278 tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); 279 if (tp->e_nxt == NULL) 280 error("lookup_emem: calloc"); 281 282 return tp; 283 } 284 285 /* Find the hash node that corresponds the NSAP 'nsap' */ 286 287 static inline struct enamemem * 288 lookup_nsap(register const u_char *nsap) 289 { 290 register u_int i, j, k; 291 int nlen = *nsap; 292 struct enamemem *tp; 293 const u_char *ensap = nsap + nlen - 6; 294 295 if (nlen > 6) { 296 k = (ensap[0] << 8) | ensap[1]; 297 j = (ensap[2] << 8) | ensap[3]; 298 i = (ensap[4] << 8) | ensap[5]; 299 } 300 else 301 i = j = k = 0; 302 303 tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)]; 304 while (tp->e_nxt) 305 if (tp->e_addr0 == i && 306 tp->e_addr1 == j && 307 tp->e_addr2 == k && 308 tp->e_nsap[0] == nlen && 309 memcmp((char *)&(nsap[1]), 310 (char *)&(tp->e_nsap[1]), nlen) == 0) 311 return tp; 312 else 313 tp = tp->e_nxt; 314 tp->e_addr0 = i; 315 tp->e_addr1 = j; 316 tp->e_addr2 = k; 317 tp->e_nsap = (u_char *)malloc(nlen + 1); 318 if (tp->e_nsap == NULL) 319 error("lookup_nsap: malloc"); 320 memcpy((char *)tp->e_nsap, (char *)nsap, nlen + 1); 321 tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); 322 if (tp->e_nxt == NULL) 323 error("lookup_nsap: calloc"); 324 325 return tp; 326 } 327 328 /* Find the hash node that corresponds the protoid 'pi'. */ 329 330 static inline struct protoidmem * 331 lookup_protoid(const u_char *pi) 332 { 333 register u_int i, j; 334 struct protoidmem *tp; 335 336 /* 5 octets won't be aligned */ 337 i = (((pi[0] << 8) + pi[1]) << 8) + pi[2]; 338 j = (pi[3] << 8) + pi[4]; 339 /* XXX should be endian-insensitive, but do big-endian testing XXX */ 340 341 tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)]; 342 while (tp->p_nxt) 343 if (tp->p_oui == i && tp->p_proto == j) 344 return tp; 345 else 346 tp = tp->p_nxt; 347 tp->p_oui = i; 348 tp->p_proto = j; 349 tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp)); 350 if (tp->p_nxt == NULL) 351 error("lookup_protoid: calloc"); 352 353 return tp; 354 } 355 356 char * 357 etheraddr_string(register const u_char *ep) 358 { 359 register u_int i, j; 360 register char *cp; 361 register struct enamemem *tp; 362 char buf[sizeof("00:00:00:00:00:00")]; 363 364 tp = lookup_emem(ep); 365 if (tp->e_name) 366 return (tp->e_name); 367 #ifdef HAVE_ETHER_NTOHOST 368 if (!nflag) { 369 char buf[128]; 370 if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) { 371 tp->e_name = savestr(buf); 372 return (tp->e_name); 373 } 374 } 375 #endif 376 cp = buf; 377 if ((j = *ep >> 4) != 0) 378 *cp++ = hex[j]; 379 *cp++ = hex[*ep++ & 0xf]; 380 for (i = 5; (int)--i >= 0;) { 381 *cp++ = ':'; 382 if ((j = *ep >> 4) != 0) 383 *cp++ = hex[j]; 384 *cp++ = hex[*ep++ & 0xf]; 385 } 386 *cp = '\0'; 387 tp->e_name = savestr(buf); 388 return (tp->e_name); 389 } 390 391 char * 392 etherproto_string(u_short port) 393 { 394 register char *cp; 395 register struct hnamemem *tp; 396 register u_int32_t i = port; 397 char buf[sizeof("0000")]; 398 399 for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 400 if (tp->addr == i) 401 return (tp->name); 402 403 tp->addr = i; 404 tp->nxt = newhnamemem(); 405 406 cp = buf; 407 NTOHS(port); 408 *cp++ = hex[port >> 12 & 0xf]; 409 *cp++ = hex[port >> 8 & 0xf]; 410 *cp++ = hex[port >> 4 & 0xf]; 411 *cp++ = hex[port & 0xf]; 412 *cp++ = '\0'; 413 tp->name = savestr(buf); 414 return (tp->name); 415 } 416 417 char * 418 protoid_string(register const u_char *pi) 419 { 420 register u_int i, j; 421 register char *cp; 422 register struct protoidmem *tp; 423 char buf[sizeof("00:00:00:00:00")]; 424 425 tp = lookup_protoid(pi); 426 if (tp->p_name) 427 return tp->p_name; 428 429 cp = buf; 430 if ((j = *pi >> 4) != 0) 431 *cp++ = hex[j]; 432 *cp++ = hex[*pi++ & 0xf]; 433 for (i = 4; (int)--i >= 0;) { 434 *cp++ = ':'; 435 if ((j = *pi >> 4) != 0) 436 *cp++ = hex[j]; 437 *cp++ = hex[*pi++ & 0xf]; 438 } 439 *cp = '\0'; 440 tp->p_name = savestr(buf); 441 return (tp->p_name); 442 } 443 444 char * 445 llcsap_string(u_char sap) 446 { 447 register char *cp; 448 register struct hnamemem *tp; 449 register u_int32_t i = sap; 450 char buf[sizeof("sap 00")]; 451 452 for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 453 if (tp->addr == i) 454 return (tp->name); 455 456 tp->addr = i; 457 tp->nxt = newhnamemem(); 458 459 cp = buf; 460 (void)strcpy(cp, "sap "); 461 cp += strlen(cp); 462 *cp++ = hex[sap >> 4 & 0xf]; 463 *cp++ = hex[sap & 0xf]; 464 *cp++ = '\0'; 465 tp->name = savestr(buf); 466 return (tp->name); 467 } 468 469 char * 470 isonsap_string(const u_char *nsap) 471 { 472 register u_int i, nlen = nsap[0]; 473 register char *cp; 474 register struct enamemem *tp; 475 476 tp = lookup_nsap(nsap); 477 if (tp->e_name) 478 return tp->e_name; 479 480 tp->e_name = cp = (char *)malloc(nlen * 2 + 2 + (nlen>>1)); 481 if (cp == NULL) 482 error("isonsap_string: malloc"); 483 484 nsap++; 485 for (i = 0; i < nlen; i++) { 486 *cp++ = hex[*nsap >> 4]; 487 *cp++ = hex[*nsap++ & 0xf]; 488 if (((i & 1) == 0) && (i + 1 < nlen)) 489 *cp++ = '.'; 490 } 491 *cp = '\0'; 492 return (tp->e_name); 493 } 494 495 char * 496 tcpport_string(u_short port) 497 { 498 register struct hnamemem *tp; 499 register u_int32_t i = port; 500 char buf[sizeof("00000")]; 501 502 for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 503 if (tp->addr == i) 504 return (tp->name); 505 506 tp->addr = i; 507 tp->nxt = newhnamemem(); 508 509 (void)sprintf(buf, "%u", i); 510 tp->name = savestr(buf); 511 return (tp->name); 512 } 513 514 char * 515 udpport_string(register u_short port) 516 { 517 register struct hnamemem *tp; 518 register u_int32_t i = port; 519 char buf[sizeof("00000")]; 520 521 for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 522 if (tp->addr == i) 523 return (tp->name); 524 525 tp->addr = i; 526 tp->nxt = newhnamemem(); 527 528 (void)sprintf(buf, "%u", i); 529 tp->name = savestr(buf); 530 return (tp->name); 531 } 532 533 static void 534 init_servarray(void) 535 { 536 struct servent *sv; 537 register struct hnamemem *table; 538 register int i; 539 char buf[sizeof("0000000000")]; 540 541 while ((sv = getservent()) != NULL) { 542 int port = ntohs(sv->s_port); 543 i = port & (HASHNAMESIZE-1); 544 if (strcmp(sv->s_proto, "tcp") == 0) 545 table = &tporttable[i]; 546 else if (strcmp(sv->s_proto, "udp") == 0) 547 table = &uporttable[i]; 548 else 549 continue; 550 551 while (table->name) 552 table = table->nxt; 553 if (nflag) { 554 (void)sprintf(buf, "%d", port); 555 table->name = savestr(buf); 556 } else 557 table->name = savestr(sv->s_name); 558 table->addr = port; 559 table->nxt = newhnamemem(); 560 } 561 endservent(); 562 } 563 564 /*XXX from libbpfc.a */ 565 extern struct eproto { 566 char *s; 567 u_short p; 568 } eproto_db[]; 569 570 static void 571 init_eprotoarray(void) 572 { 573 register int i; 574 register struct hnamemem *table; 575 576 for (i = 0; eproto_db[i].s; i++) { 577 int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1); 578 table = &eprototable[j]; 579 while (table->name) 580 table = table->nxt; 581 table->name = eproto_db[i].s; 582 table->addr = ntohs(eproto_db[i].p); 583 table->nxt = newhnamemem(); 584 } 585 } 586 587 /* 588 * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet 589 * types. 590 */ 591 static void 592 init_protoidarray(void) 593 { 594 register int i; 595 register struct protoidmem *tp; 596 u_char protoid[5]; 597 598 protoid[0] = 0; 599 protoid[1] = 0; 600 protoid[2] = 0; 601 for (i = 0; eproto_db[i].s; i++) { 602 u_short etype = htons(eproto_db[i].p); 603 604 memcpy((char *)&protoid[3], (char *)&etype, 2); 605 tp = lookup_protoid(protoid); 606 tp->p_name = savestr(eproto_db[i].s); 607 } 608 } 609 610 static struct etherlist { 611 u_char addr[6]; 612 char *name; 613 } etherlist[] = { 614 {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, 615 {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } 616 }; 617 618 /* 619 * Initialize the ethers hash table. We take two different approaches 620 * depending on whether or not the system provides the ethers name 621 * service. If it does, we just wire in a few names at startup, 622 * and etheraddr_string() fills in the table on demand. If it doesn't, 623 * then we suck in the entire /etc/ethers file at startup. The idea 624 * is that parsing the local file will be fast, but spinning through 625 * all the ethers entries via NIS & next_etherent might be very slow. 626 * 627 * XXX pcap_next_etherent doesn't belong in the pcap interface, but 628 * since the pcap module already does name-to-address translation, 629 * it's already does most of the work for the ethernet address-to-name 630 * translation, so we just pcap_next_etherent as a convenience. 631 */ 632 static void 633 init_etherarray(void) 634 { 635 register struct etherlist *el; 636 register struct enamemem *tp; 637 #ifdef HAVE_ETHER_NTOHOST 638 char name[256]; 639 #else 640 register struct pcap_etherent *ep; 641 register FILE *fp; 642 643 /* Suck in entire ethers file */ 644 fp = fopen(PCAP_ETHERS_FILE, "r"); 645 if (fp != NULL) { 646 while ((ep = pcap_next_etherent(fp)) != NULL) { 647 tp = lookup_emem(ep->addr); 648 tp->e_name = savestr(ep->name); 649 } 650 (void)fclose(fp); 651 } 652 #endif 653 654 /* Hardwire some ethernet names */ 655 for (el = etherlist; el->name != NULL; ++el) { 656 tp = lookup_emem(el->addr); 657 /* Don't override existing name */ 658 if (tp->e_name != NULL) 659 continue; 660 661 #ifdef HAVE_ETHER_NTOHOST 662 /* Use yp/nis version of name if available */ 663 if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) { 664 tp->e_name = savestr(name); 665 continue; 666 } 667 #endif 668 tp->e_name = el->name; 669 } 670 } 671 672 static struct tok llcsap_db[] = { 673 { LLCSAP_NULL, "null" }, 674 { LLCSAP_8021B_I, "802.1b-gsap" }, 675 { LLCSAP_8021B_G, "802.1b-isap" }, 676 { LLCSAP_IP, "ip-sap" }, 677 { LLCSAP_PROWAYNM, "proway-nm" }, 678 { LLCSAP_8021D, "802.1d" }, 679 { LLCSAP_RS511, "eia-rs511" }, 680 { LLCSAP_ISO8208, "x.25/llc2" }, 681 { LLCSAP_PROWAY, "proway" }, 682 { LLCSAP_ISONS, "iso-clns" }, 683 { LLCSAP_GLOBAL, "global" }, 684 { 0, NULL } 685 }; 686 687 static void 688 init_llcsaparray(void) 689 { 690 register int i; 691 register struct hnamemem *table; 692 693 for (i = 0; llcsap_db[i].s != NULL; i++) { 694 table = &llcsaptable[llcsap_db[i].v]; 695 while (table->name) 696 table = table->nxt; 697 table->name = llcsap_db[i].s; 698 table->addr = llcsap_db[i].v; 699 table->nxt = newhnamemem(); 700 } 701 } 702 703 /* 704 * Initialize the address to name translation machinery. We map all 705 * non-local IP addresses to numeric addresses if fflag is true (i.e., 706 * to prevent blocking on the nameserver). localnet is the IP address 707 * of the local network. mask is its subnet mask. 708 */ 709 void 710 init_addrtoname(u_int32_t localnet, u_int32_t mask) 711 { 712 netmask = mask; 713 if (fflag) { 714 f_localnet = localnet; 715 f_netmask = mask; 716 } 717 if (nflag) 718 /* 719 * Simplest way to suppress names. 720 */ 721 return; 722 723 init_etherarray(); 724 init_servarray(); 725 init_eprotoarray(); 726 init_llcsaparray(); 727 init_protoidarray(); 728 } 729 730 char * 731 dnaddr_string(u_short dnaddr) 732 { 733 register struct hnamemem *tp; 734 735 for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0; 736 tp = tp->nxt) 737 if (tp->addr == dnaddr) 738 return (tp->name); 739 740 tp->addr = dnaddr; 741 tp->nxt = newhnamemem(); 742 if (nflag) 743 tp->name = dnnum_string(dnaddr); 744 else 745 tp->name = dnname_string(dnaddr); 746 747 return(tp->name); 748 } 749 750 /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */ 751 struct hnamemem * 752 newhnamemem(void) 753 { 754 register struct hnamemem *p; 755 static struct hnamemem *ptr = NULL; 756 static u_int num = 0; 757 758 if (num <= 0) { 759 num = 64; 760 ptr = (struct hnamemem *)calloc(num, sizeof (*ptr)); 761 if (ptr == NULL) 762 error("newhnamemem: calloc"); 763 } 764 --num; 765 p = ptr++; 766 return (p); 767 } 768