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