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