addrtoname.c revision 56896
117680Spst/* 239300Sfenner * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017680Spst * 2117680Spst * Internet, ethernet, port, and protocol string to address 2217680Spst * and address to string conversion routines 2356896Sfenner * 2456896Sfenner * $FreeBSD: head/contrib/tcpdump/addrtoname.c 56896 2000-01-30 01:05:24Z fenner $ 2517680Spst */ 2617680Spst#ifndef lint 2726183Sfennerstatic const char rcsid[] = 2856896Sfenner "@(#) $Header: /tcpdump/master/tcpdump/addrtoname.c,v 1.64 1999/11/21 09:36:44 fenner Exp $ (LBL)"; 2917680Spst#endif 3017680Spst 3156896Sfenner#ifdef HAVE_CONFIG_H 3256896Sfenner#include "config.h" 3356896Sfenner#endif 3456896Sfenner 3517680Spst#include <sys/types.h> 3617680Spst#include <sys/socket.h> 3717680Spst#include <sys/time.h> 3817680Spst 3917680Spst#if __STDC__ 4017680Spststruct mbuf; 4117680Spststruct rtentry; 4217680Spst#endif 4317680Spst#include <net/if.h> 4417680Spst 4517680Spst#include <netinet/in.h> 4621262Swollman#include <net/ethernet.h> 4717680Spst 4856896Sfenner#ifdef INET6 4956896Sfenner#include <netinet6/ip6.h> 5056896Sfenner#endif 5156896Sfenner 5217680Spst#include <arpa/inet.h> 5317680Spst 5417680Spst#include <ctype.h> 5517680Spst#include <netdb.h> 5617680Spst#include <pcap.h> 5717680Spst#include <pcap-namedb.h> 5839300Sfenner#ifdef HAVE_MALLOC_H 5939300Sfenner#include <malloc.h> 6039300Sfenner#endif 6139300Sfenner#ifdef HAVE_MEMORY_H 6239300Sfenner#include <memory.h> 6339300Sfenner#endif 6417680Spst#include <signal.h> 6517680Spst#include <stdio.h> 6617680Spst#include <string.h> 6717680Spst#include <stdlib.h> 6817680Spst#include <unistd.h> 6917680Spst 7017680Spst#include "interface.h" 7117680Spst#include "addrtoname.h" 7217680Spst#include "llc.h" 7339300Sfenner#include "savestr.h" 7439300Sfenner#include "setsignal.h" 7517680Spst 7617680Spst/* Forwards */ 7717680Spststatic RETSIGTYPE nohostname(int); 7817680Spst 7917680Spst/* 8017680Spst * hash tables for whatever-to-name translations 8117680Spst */ 8217680Spst 8317680Spst#define HASHNAMESIZE 4096 8417680Spst 8517680Spststruct hnamemem { 8617680Spst u_int32_t addr; 8717680Spst char *name; 8817680Spst struct hnamemem *nxt; 8917680Spst}; 9017680Spst 9117680Spststruct hnamemem hnametable[HASHNAMESIZE]; 9217680Spststruct hnamemem tporttable[HASHNAMESIZE]; 9317680Spststruct hnamemem uporttable[HASHNAMESIZE]; 9417680Spststruct hnamemem eprototable[HASHNAMESIZE]; 9517680Spststruct hnamemem dnaddrtable[HASHNAMESIZE]; 9617680Spststruct hnamemem llcsaptable[HASHNAMESIZE]; 9717680Spst 9856896Sfenner#ifdef INET6 9956896Sfennerstruct h6namemem { 10056896Sfenner struct in6_addr addr; 10156896Sfenner char *name; 10256896Sfenner struct h6namemem *nxt; 10356896Sfenner}; 10456896Sfenner 10556896Sfennerstruct h6namemem h6nametable[HASHNAMESIZE]; 10656896Sfenner#endif /* INET6 */ 10756896Sfenner 10817680Spststruct enamemem { 10917680Spst u_short e_addr0; 11017680Spst u_short e_addr1; 11117680Spst u_short e_addr2; 11217680Spst char *e_name; 11317680Spst u_char *e_nsap; /* used only for nsaptable[] */ 11417680Spst struct enamemem *e_nxt; 11517680Spst}; 11617680Spst 11717680Spststruct enamemem enametable[HASHNAMESIZE]; 11817680Spststruct enamemem nsaptable[HASHNAMESIZE]; 11917680Spst 12017680Spststruct protoidmem { 12117680Spst u_int32_t p_oui; 12217680Spst u_short p_proto; 12317680Spst char *p_name; 12417680Spst struct protoidmem *p_nxt; 12517680Spst}; 12617680Spst 12717680Spststruct protoidmem protoidtable[HASHNAMESIZE]; 12817680Spst 12917680Spst/* 13017680Spst * A faster replacement for inet_ntoa(). 13117680Spst */ 13217680Spstchar * 13317680Spstintoa(u_int32_t addr) 13417680Spst{ 13517680Spst register char *cp; 13617680Spst register u_int byte; 13717680Spst register int n; 13817680Spst static char buf[sizeof(".xxx.xxx.xxx.xxx")]; 13917680Spst 14017680Spst NTOHL(addr); 14117680Spst cp = &buf[sizeof buf]; 14217680Spst *--cp = '\0'; 14317680Spst 14417680Spst n = 4; 14517680Spst do { 14617680Spst byte = addr & 0xff; 14717680Spst *--cp = byte % 10 + '0'; 14817680Spst byte /= 10; 14917680Spst if (byte > 0) { 15017680Spst *--cp = byte % 10 + '0'; 15117680Spst byte /= 10; 15217680Spst if (byte > 0) 15317680Spst *--cp = byte + '0'; 15417680Spst } 15517680Spst *--cp = '.'; 15617680Spst addr >>= 8; 15717680Spst } while (--n > 0); 15817680Spst 15917680Spst return cp + 1; 16017680Spst} 16117680Spst 16217680Spststatic u_int32_t f_netmask; 16317680Spststatic u_int32_t f_localnet; 16417680Spststatic u_int32_t netmask; 16517680Spst 16617680Spst/* 16717680Spst * "getname" is written in this atrocious way to make sure we don't 16817680Spst * wait forever while trying to get hostnames from yp. 16917680Spst */ 17017680Spst#include <setjmp.h> 17117680Spst 17217680Spstjmp_buf getname_env; 17317680Spst 17417680Spststatic RETSIGTYPE 17517680Spstnohostname(int signo) 17617680Spst{ 17717680Spst longjmp(getname_env, 1); 17817680Spst} 17917680Spst 18017680Spst/* 18117680Spst * Return a name for the IP address pointed to by ap. This address 18217680Spst * is assumed to be in network byte order. 18317680Spst */ 18417680Spstchar * 18517680Spstgetname(const u_char *ap) 18617680Spst{ 18717680Spst register struct hostent *hp; 18817680Spst u_int32_t addr; 18917680Spst static struct hnamemem *p; /* static for longjmp() */ 19017680Spst 19117680Spst#ifndef LBL_ALIGN 19217680Spst addr = *(const u_int32_t *)ap; 19317680Spst#else 19456896Sfenner memcpy(&addr, ap, sizeof(addr)); 19517680Spst#endif 19617680Spst p = &hnametable[addr & (HASHNAMESIZE-1)]; 19717680Spst for (; p->nxt; p = p->nxt) { 19817680Spst if (p->addr == addr) 19917680Spst return (p->name); 20017680Spst } 20117680Spst p->addr = addr; 20217680Spst p->nxt = newhnamemem(); 20317680Spst 20417680Spst /* 20517680Spst * Only print names when: 20617680Spst * (1) -n was not given. 20739300Sfenner * (2) Address is foreign and -f was given. (If -f was not 20839300Sfenner * give, f_netmask and f_local are 0 and the test 20939300Sfenner * evaluates to true) 21039300Sfenner * (3) -a was given or the host portion is not all ones 21139300Sfenner * nor all zeros (i.e. not a network or broadcast address) 21217680Spst */ 21339300Sfenner if (!nflag && 21439300Sfenner (addr & f_netmask) == f_localnet && 21539300Sfenner (aflag || 21639300Sfenner !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))) { 21717680Spst if (!setjmp(getname_env)) { 21839300Sfenner (void)setsignal(SIGALRM, nohostname); 21917680Spst (void)alarm(20); 22017680Spst hp = gethostbyaddr((char *)&addr, 4, AF_INET); 22117680Spst (void)alarm(0); 22217680Spst if (hp) { 22317680Spst char *dotp; 22417680Spst 22517680Spst p->name = savestr(hp->h_name); 22617680Spst if (Nflag) { 22717680Spst /* Remove domain qualifications */ 22817680Spst dotp = strchr(p->name, '.'); 22917680Spst if (dotp) 23017680Spst *dotp = '\0'; 23117680Spst } 23217680Spst return (p->name); 23317680Spst } 23417680Spst } 23517680Spst } 23617680Spst p->name = savestr(intoa(addr)); 23717680Spst return (p->name); 23817680Spst} 23917680Spst 24056896Sfenner#ifdef INET6 24156896Sfenner/* 24256896Sfenner * Return a name for the IP6 address pointed to by ap. This address 24356896Sfenner * is assumed to be in network byte order. 24456896Sfenner */ 24556896Sfennerchar * 24656896Sfennergetname6(const u_char *ap) 24756896Sfenner{ 24856896Sfenner register struct hostent *hp; 24956896Sfenner struct in6_addr addr; 25056896Sfenner static struct h6namemem *p; /* static for longjmp() */ 25156896Sfenner register char *cp; 25256896Sfenner char ntop_buf[INET6_ADDRSTRLEN]; 25356896Sfenner 25456896Sfenner memcpy(&addr, ap, sizeof(addr)); 25556896Sfenner p = &h6nametable[*(u_int16_t *)&addr.s6_addr[14] & (HASHNAMESIZE-1)]; 25656896Sfenner for (; p->nxt; p = p->nxt) { 25756896Sfenner if (memcmp(&p->addr, &addr, sizeof(addr)) == 0) 25856896Sfenner return (p->name); 25956896Sfenner } 26056896Sfenner p->addr = addr; 26156896Sfenner p->nxt = newh6namemem(); 26256896Sfenner 26356896Sfenner /* 26456896Sfenner * Only print names when: 26556896Sfenner * (1) -n was not given. 26656896Sfenner * (2) Address is foreign and -f was given. (If -f was not 26756896Sfenner * give, f_netmask and f_local are 0 and the test 26856896Sfenner * evaluates to true) 26956896Sfenner * (3) -a was given or the host portion is not all ones 27056896Sfenner * nor all zeros (i.e. not a network or broadcast address) 27156896Sfenner */ 27256896Sfenner if (!nflag 27356896Sfenner#if 0 27456896Sfenner && 27556896Sfenner (addr & f_netmask) == f_localnet && 27656896Sfenner (aflag || 27756896Sfenner !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff)) 27856896Sfenner#endif 27956896Sfenner ) { 28056896Sfenner if (!setjmp(getname_env)) { 28156896Sfenner (void)setsignal(SIGALRM, nohostname); 28256896Sfenner (void)alarm(20); 28356896Sfenner hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6); 28456896Sfenner (void)alarm(0); 28556896Sfenner if (hp) { 28656896Sfenner char *dotp; 28756896Sfenner 28856896Sfenner p->name = savestr(hp->h_name); 28956896Sfenner if (Nflag) { 29056896Sfenner /* Remove domain qualifications */ 29156896Sfenner dotp = strchr(p->name, '.'); 29256896Sfenner if (dotp) 29356896Sfenner *dotp = '\0'; 29456896Sfenner } 29556896Sfenner return (p->name); 29656896Sfenner } 29756896Sfenner } 29856896Sfenner } 29956896Sfenner cp = (char *)inet_ntop(AF_INET6, &addr, ntop_buf, sizeof(ntop_buf)); 30056896Sfenner p->name = savestr(cp); 30156896Sfenner return (p->name); 30256896Sfenner} 30356896Sfenner#endif /* INET6 */ 30456896Sfenner 30517680Spststatic char hex[] = "0123456789abcdef"; 30617680Spst 30717680Spst 30817680Spst/* Find the hash node that corresponds the ether address 'ep' */ 30917680Spst 31017680Spststatic inline struct enamemem * 31117680Spstlookup_emem(const u_char *ep) 31217680Spst{ 31317680Spst register u_int i, j, k; 31417680Spst struct enamemem *tp; 31517680Spst 31617680Spst k = (ep[0] << 8) | ep[1]; 31717680Spst j = (ep[2] << 8) | ep[3]; 31817680Spst i = (ep[4] << 8) | ep[5]; 31917680Spst 32017680Spst tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; 32117680Spst while (tp->e_nxt) 32217680Spst if (tp->e_addr0 == i && 32317680Spst tp->e_addr1 == j && 32417680Spst tp->e_addr2 == k) 32517680Spst return tp; 32617680Spst else 32717680Spst tp = tp->e_nxt; 32817680Spst tp->e_addr0 = i; 32917680Spst tp->e_addr1 = j; 33017680Spst tp->e_addr2 = k; 33117680Spst tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); 33217680Spst if (tp->e_nxt == NULL) 33317680Spst error("lookup_emem: calloc"); 33417680Spst 33517680Spst return tp; 33617680Spst} 33717680Spst 33817680Spst/* Find the hash node that corresponds the NSAP 'nsap' */ 33917680Spst 34017680Spststatic inline struct enamemem * 34117680Spstlookup_nsap(register const u_char *nsap) 34217680Spst{ 34317680Spst register u_int i, j, k; 34417680Spst int nlen = *nsap; 34517680Spst struct enamemem *tp; 34617680Spst const u_char *ensap = nsap + nlen - 6; 34717680Spst 34817680Spst if (nlen > 6) { 34917680Spst k = (ensap[0] << 8) | ensap[1]; 35017680Spst j = (ensap[2] << 8) | ensap[3]; 35117680Spst i = (ensap[4] << 8) | ensap[5]; 35217680Spst } 35317680Spst else 35417680Spst i = j = k = 0; 35517680Spst 35617680Spst tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)]; 35717680Spst while (tp->e_nxt) 35817680Spst if (tp->e_addr0 == i && 35917680Spst tp->e_addr1 == j && 36017680Spst tp->e_addr2 == k && 36117680Spst tp->e_nsap[0] == nlen && 36217680Spst memcmp((char *)&(nsap[1]), 36317680Spst (char *)&(tp->e_nsap[1]), nlen) == 0) 36417680Spst return tp; 36517680Spst else 36617680Spst tp = tp->e_nxt; 36717680Spst tp->e_addr0 = i; 36817680Spst tp->e_addr1 = j; 36917680Spst tp->e_addr2 = k; 37017680Spst tp->e_nsap = (u_char *)malloc(nlen + 1); 37117680Spst if (tp->e_nsap == NULL) 37217680Spst error("lookup_nsap: malloc"); 37339300Sfenner memcpy((char *)tp->e_nsap, (char *)nsap, nlen + 1); 37417680Spst tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); 37517680Spst if (tp->e_nxt == NULL) 37617680Spst error("lookup_nsap: calloc"); 37717680Spst 37817680Spst return tp; 37917680Spst} 38017680Spst 38117680Spst/* Find the hash node that corresponds the protoid 'pi'. */ 38217680Spst 38317680Spststatic inline struct protoidmem * 38417680Spstlookup_protoid(const u_char *pi) 38517680Spst{ 38617680Spst register u_int i, j; 38717680Spst struct protoidmem *tp; 38817680Spst 38917680Spst /* 5 octets won't be aligned */ 39017680Spst i = (((pi[0] << 8) + pi[1]) << 8) + pi[2]; 39117680Spst j = (pi[3] << 8) + pi[4]; 39217680Spst /* XXX should be endian-insensitive, but do big-endian testing XXX */ 39317680Spst 39417680Spst tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)]; 39517680Spst while (tp->p_nxt) 39617680Spst if (tp->p_oui == i && tp->p_proto == j) 39717680Spst return tp; 39817680Spst else 39917680Spst tp = tp->p_nxt; 40017680Spst tp->p_oui = i; 40117680Spst tp->p_proto = j; 40217680Spst tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp)); 40317680Spst if (tp->p_nxt == NULL) 40417680Spst error("lookup_protoid: calloc"); 40517680Spst 40617680Spst return tp; 40717680Spst} 40817680Spst 40917680Spstchar * 41017680Spstetheraddr_string(register const u_char *ep) 41117680Spst{ 41217680Spst register u_int i, j; 41317680Spst register char *cp; 41417680Spst register struct enamemem *tp; 41517680Spst char buf[sizeof("00:00:00:00:00:00")]; 41617680Spst 41717680Spst tp = lookup_emem(ep); 41817680Spst if (tp->e_name) 41917680Spst return (tp->e_name); 42017680Spst#ifdef HAVE_ETHER_NTOHOST 42117680Spst if (!nflag) { 42217680Spst char buf[128]; 42317680Spst if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) { 42417680Spst tp->e_name = savestr(buf); 42517680Spst return (tp->e_name); 42617680Spst } 42717680Spst } 42817680Spst#endif 42917680Spst cp = buf; 43017680Spst if ((j = *ep >> 4) != 0) 43117680Spst *cp++ = hex[j]; 43217680Spst *cp++ = hex[*ep++ & 0xf]; 43317680Spst for (i = 5; (int)--i >= 0;) { 43417680Spst *cp++ = ':'; 43517680Spst if ((j = *ep >> 4) != 0) 43617680Spst *cp++ = hex[j]; 43717680Spst *cp++ = hex[*ep++ & 0xf]; 43817680Spst } 43917680Spst *cp = '\0'; 44017680Spst tp->e_name = savestr(buf); 44117680Spst return (tp->e_name); 44217680Spst} 44317680Spst 44417680Spstchar * 44517680Spstetherproto_string(u_short port) 44617680Spst{ 44717680Spst register char *cp; 44817680Spst register struct hnamemem *tp; 44917680Spst register u_int32_t i = port; 45017680Spst char buf[sizeof("0000")]; 45117680Spst 45217680Spst for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 45317680Spst if (tp->addr == i) 45417680Spst return (tp->name); 45517680Spst 45617680Spst tp->addr = i; 45717680Spst tp->nxt = newhnamemem(); 45817680Spst 45917680Spst cp = buf; 46017680Spst NTOHS(port); 46117680Spst *cp++ = hex[port >> 12 & 0xf]; 46217680Spst *cp++ = hex[port >> 8 & 0xf]; 46317680Spst *cp++ = hex[port >> 4 & 0xf]; 46417680Spst *cp++ = hex[port & 0xf]; 46517680Spst *cp++ = '\0'; 46617680Spst tp->name = savestr(buf); 46717680Spst return (tp->name); 46817680Spst} 46917680Spst 47017680Spstchar * 47117680Spstprotoid_string(register const u_char *pi) 47217680Spst{ 47317680Spst register u_int i, j; 47417680Spst register char *cp; 47517680Spst register struct protoidmem *tp; 47617680Spst char buf[sizeof("00:00:00:00:00")]; 47717680Spst 47817680Spst tp = lookup_protoid(pi); 47917680Spst if (tp->p_name) 48017680Spst return tp->p_name; 48117680Spst 48217680Spst cp = buf; 48317680Spst if ((j = *pi >> 4) != 0) 48417680Spst *cp++ = hex[j]; 48517680Spst *cp++ = hex[*pi++ & 0xf]; 48617680Spst for (i = 4; (int)--i >= 0;) { 48717680Spst *cp++ = ':'; 48817680Spst if ((j = *pi >> 4) != 0) 48917680Spst *cp++ = hex[j]; 49017680Spst *cp++ = hex[*pi++ & 0xf]; 49117680Spst } 49217680Spst *cp = '\0'; 49317680Spst tp->p_name = savestr(buf); 49417680Spst return (tp->p_name); 49517680Spst} 49617680Spst 49717680Spstchar * 49817680Spstllcsap_string(u_char sap) 49917680Spst{ 50017680Spst register char *cp; 50117680Spst register struct hnamemem *tp; 50217680Spst register u_int32_t i = sap; 50317680Spst char buf[sizeof("sap 00")]; 50417680Spst 50517680Spst for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 50617680Spst if (tp->addr == i) 50717680Spst return (tp->name); 50817680Spst 50917680Spst tp->addr = i; 51017680Spst tp->nxt = newhnamemem(); 51117680Spst 51217680Spst cp = buf; 51317680Spst (void)strcpy(cp, "sap "); 51417680Spst cp += strlen(cp); 51517680Spst *cp++ = hex[sap >> 4 & 0xf]; 51617680Spst *cp++ = hex[sap & 0xf]; 51717680Spst *cp++ = '\0'; 51817680Spst tp->name = savestr(buf); 51917680Spst return (tp->name); 52017680Spst} 52117680Spst 52217680Spstchar * 52317680Spstisonsap_string(const u_char *nsap) 52417680Spst{ 52517680Spst register u_int i, nlen = nsap[0]; 52617680Spst register char *cp; 52717680Spst register struct enamemem *tp; 52817680Spst 52917680Spst tp = lookup_nsap(nsap); 53017680Spst if (tp->e_name) 53117680Spst return tp->e_name; 53217680Spst 53317688Spst tp->e_name = cp = (char *)malloc(nlen * 2 + 2 + (nlen>>1)); 53417680Spst if (cp == NULL) 53517680Spst error("isonsap_string: malloc"); 53617680Spst 53717680Spst nsap++; 53817688Spst for (i = 0; i < nlen; i++) { 53917680Spst *cp++ = hex[*nsap >> 4]; 54017680Spst *cp++ = hex[*nsap++ & 0xf]; 54117688Spst if (((i & 1) == 0) && (i + 1 < nlen)) 54217688Spst *cp++ = '.'; 54317680Spst } 54417680Spst *cp = '\0'; 54517680Spst return (tp->e_name); 54617680Spst} 54717680Spst 54817680Spstchar * 54917680Spsttcpport_string(u_short port) 55017680Spst{ 55117680Spst register struct hnamemem *tp; 55217680Spst register u_int32_t i = port; 55317680Spst char buf[sizeof("00000")]; 55417680Spst 55517680Spst for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 55617680Spst if (tp->addr == i) 55717680Spst return (tp->name); 55817680Spst 55917680Spst tp->addr = i; 56017680Spst tp->nxt = newhnamemem(); 56117680Spst 56217680Spst (void)sprintf(buf, "%u", i); 56317680Spst tp->name = savestr(buf); 56417680Spst return (tp->name); 56517680Spst} 56617680Spst 56717680Spstchar * 56817680Spstudpport_string(register u_short port) 56917680Spst{ 57017680Spst register struct hnamemem *tp; 57117680Spst register u_int32_t i = port; 57217680Spst char buf[sizeof("00000")]; 57317680Spst 57417680Spst for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 57517680Spst if (tp->addr == i) 57617680Spst return (tp->name); 57717680Spst 57817680Spst tp->addr = i; 57917680Spst tp->nxt = newhnamemem(); 58017680Spst 58117680Spst (void)sprintf(buf, "%u", i); 58217680Spst tp->name = savestr(buf); 58317680Spst return (tp->name); 58417680Spst} 58517680Spst 58617680Spststatic void 58717680Spstinit_servarray(void) 58817680Spst{ 58917680Spst struct servent *sv; 59017680Spst register struct hnamemem *table; 59117680Spst register int i; 59217680Spst char buf[sizeof("0000000000")]; 59317680Spst 59417680Spst while ((sv = getservent()) != NULL) { 59517680Spst int port = ntohs(sv->s_port); 59617680Spst i = port & (HASHNAMESIZE-1); 59717680Spst if (strcmp(sv->s_proto, "tcp") == 0) 59817680Spst table = &tporttable[i]; 59917680Spst else if (strcmp(sv->s_proto, "udp") == 0) 60017680Spst table = &uporttable[i]; 60117680Spst else 60217680Spst continue; 60317680Spst 60417680Spst while (table->name) 60517680Spst table = table->nxt; 60617680Spst if (nflag) { 60717680Spst (void)sprintf(buf, "%d", port); 60817680Spst table->name = savestr(buf); 60917680Spst } else 61017680Spst table->name = savestr(sv->s_name); 61117680Spst table->addr = port; 61217680Spst table->nxt = newhnamemem(); 61317680Spst } 61417680Spst endservent(); 61517680Spst} 61617680Spst 61717680Spst/*XXX from libbpfc.a */ 61817680Spstextern struct eproto { 61917680Spst char *s; 62017680Spst u_short p; 62117680Spst} eproto_db[]; 62217680Spst 62317680Spststatic void 62417680Spstinit_eprotoarray(void) 62517680Spst{ 62617680Spst register int i; 62717680Spst register struct hnamemem *table; 62817680Spst 62917680Spst for (i = 0; eproto_db[i].s; i++) { 63017680Spst int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1); 63117680Spst table = &eprototable[j]; 63217680Spst while (table->name) 63317680Spst table = table->nxt; 63417680Spst table->name = eproto_db[i].s; 63517680Spst table->addr = ntohs(eproto_db[i].p); 63617680Spst table->nxt = newhnamemem(); 63717680Spst } 63817680Spst} 63917680Spst 64017680Spst/* 64117680Spst * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet 64217680Spst * types. 64317680Spst */ 64417680Spststatic void 64517680Spstinit_protoidarray(void) 64617680Spst{ 64717680Spst register int i; 64817680Spst register struct protoidmem *tp; 64917680Spst u_char protoid[5]; 65017680Spst 65117680Spst protoid[0] = 0; 65217680Spst protoid[1] = 0; 65317680Spst protoid[2] = 0; 65417680Spst for (i = 0; eproto_db[i].s; i++) { 65517680Spst u_short etype = htons(eproto_db[i].p); 65617680Spst 65717680Spst memcpy((char *)&protoid[3], (char *)&etype, 2); 65817680Spst tp = lookup_protoid(protoid); 65917680Spst tp->p_name = savestr(eproto_db[i].s); 66017680Spst } 66117680Spst} 66217680Spst 66317680Spststatic struct etherlist { 66417680Spst u_char addr[6]; 66517680Spst char *name; 66617680Spst} etherlist[] = { 66717680Spst {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, 66817680Spst {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } 66917680Spst}; 67017680Spst 67117680Spst/* 67217680Spst * Initialize the ethers hash table. We take two different approaches 67317680Spst * depending on whether or not the system provides the ethers name 67417680Spst * service. If it does, we just wire in a few names at startup, 67517680Spst * and etheraddr_string() fills in the table on demand. If it doesn't, 67617680Spst * then we suck in the entire /etc/ethers file at startup. The idea 67717680Spst * is that parsing the local file will be fast, but spinning through 67817680Spst * all the ethers entries via NIS & next_etherent might be very slow. 67917680Spst * 68017680Spst * XXX pcap_next_etherent doesn't belong in the pcap interface, but 68117680Spst * since the pcap module already does name-to-address translation, 68217680Spst * it's already does most of the work for the ethernet address-to-name 68317680Spst * translation, so we just pcap_next_etherent as a convenience. 68417680Spst */ 68517680Spststatic void 68617680Spstinit_etherarray(void) 68717680Spst{ 68817680Spst register struct etherlist *el; 68917680Spst register struct enamemem *tp; 69017680Spst#ifdef HAVE_ETHER_NTOHOST 69117680Spst char name[256]; 69217680Spst#else 69317680Spst register struct pcap_etherent *ep; 69417680Spst register FILE *fp; 69517680Spst 69617680Spst /* Suck in entire ethers file */ 69717680Spst fp = fopen(PCAP_ETHERS_FILE, "r"); 69817680Spst if (fp != NULL) { 69917680Spst while ((ep = pcap_next_etherent(fp)) != NULL) { 70017680Spst tp = lookup_emem(ep->addr); 70117680Spst tp->e_name = savestr(ep->name); 70217680Spst } 70317680Spst (void)fclose(fp); 70417680Spst } 70517680Spst#endif 70617680Spst 70717680Spst /* Hardwire some ethernet names */ 70817680Spst for (el = etherlist; el->name != NULL; ++el) { 70917680Spst tp = lookup_emem(el->addr); 71017680Spst /* Don't override existing name */ 71117680Spst if (tp->e_name != NULL) 71217680Spst continue; 71317680Spst 71417680Spst#ifdef HAVE_ETHER_NTOHOST 71517680Spst /* Use yp/nis version of name if available */ 71617680Spst if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) { 71717680Spst tp->e_name = savestr(name); 71817680Spst continue; 71917680Spst } 72017680Spst#endif 72117680Spst tp->e_name = el->name; 72217680Spst } 72317680Spst} 72417680Spst 72517680Spststatic struct tok llcsap_db[] = { 72617680Spst { LLCSAP_NULL, "null" }, 72717680Spst { LLCSAP_8021B_I, "802.1b-gsap" }, 72817680Spst { LLCSAP_8021B_G, "802.1b-isap" }, 72917680Spst { LLCSAP_IP, "ip-sap" }, 73017680Spst { LLCSAP_PROWAYNM, "proway-nm" }, 73117680Spst { LLCSAP_8021D, "802.1d" }, 73217680Spst { LLCSAP_RS511, "eia-rs511" }, 73317680Spst { LLCSAP_ISO8208, "x.25/llc2" }, 73417680Spst { LLCSAP_PROWAY, "proway" }, 73517680Spst { LLCSAP_ISONS, "iso-clns" }, 73617680Spst { LLCSAP_GLOBAL, "global" }, 73717680Spst { 0, NULL } 73817680Spst}; 73917680Spst 74017680Spststatic void 74117680Spstinit_llcsaparray(void) 74217680Spst{ 74317680Spst register int i; 74417680Spst register struct hnamemem *table; 74517680Spst 74617680Spst for (i = 0; llcsap_db[i].s != NULL; i++) { 74717680Spst table = &llcsaptable[llcsap_db[i].v]; 74817680Spst while (table->name) 74917680Spst table = table->nxt; 75017680Spst table->name = llcsap_db[i].s; 75117680Spst table->addr = llcsap_db[i].v; 75217680Spst table->nxt = newhnamemem(); 75317680Spst } 75417680Spst} 75517680Spst 75617680Spst/* 75717680Spst * Initialize the address to name translation machinery. We map all 75817680Spst * non-local IP addresses to numeric addresses if fflag is true (i.e., 75917680Spst * to prevent blocking on the nameserver). localnet is the IP address 76017680Spst * of the local network. mask is its subnet mask. 76117680Spst */ 76217680Spstvoid 76339300Sfennerinit_addrtoname(u_int32_t localnet, u_int32_t mask) 76417680Spst{ 76517680Spst netmask = mask; 76617680Spst if (fflag) { 76717680Spst f_localnet = localnet; 76817680Spst f_netmask = mask; 76917680Spst } 77017680Spst if (nflag) 77117680Spst /* 77217680Spst * Simplest way to suppress names. 77317680Spst */ 77417680Spst return; 77517680Spst 77617680Spst init_etherarray(); 77717680Spst init_servarray(); 77817680Spst init_eprotoarray(); 77917680Spst init_llcsaparray(); 78017680Spst init_protoidarray(); 78117680Spst} 78217680Spst 78317680Spstchar * 78417680Spstdnaddr_string(u_short dnaddr) 78517680Spst{ 78617680Spst register struct hnamemem *tp; 78717680Spst 78817680Spst for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0; 78917680Spst tp = tp->nxt) 79017680Spst if (tp->addr == dnaddr) 79117680Spst return (tp->name); 79217680Spst 79317680Spst tp->addr = dnaddr; 79417680Spst tp->nxt = newhnamemem(); 79517680Spst if (nflag) 79617680Spst tp->name = dnnum_string(dnaddr); 79717680Spst else 79817680Spst tp->name = dnname_string(dnaddr); 79917680Spst 80017680Spst return(tp->name); 80117680Spst} 80217680Spst 80317680Spst/* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */ 80417680Spststruct hnamemem * 80526183Sfennernewhnamemem(void) 80617680Spst{ 80717680Spst register struct hnamemem *p; 80817680Spst static struct hnamemem *ptr = NULL; 80917680Spst static u_int num = 0; 81017680Spst 81117680Spst if (num <= 0) { 81217680Spst num = 64; 81317680Spst ptr = (struct hnamemem *)calloc(num, sizeof (*ptr)); 81417680Spst if (ptr == NULL) 81517680Spst error("newhnamemem: calloc"); 81617680Spst } 81717680Spst --num; 81817680Spst p = ptr++; 81917680Spst return (p); 82017680Spst} 82156896Sfenner 82256896Sfenner#ifdef INET6 82356896Sfenner/* Return a zero'ed h6namemem struct and cuts down on calloc() overhead */ 82456896Sfennerstruct h6namemem * 82556896Sfennernewh6namemem(void) 82656896Sfenner{ 82756896Sfenner register struct h6namemem *p; 82856896Sfenner static struct h6namemem *ptr = NULL; 82956896Sfenner static u_int num = 0; 83056896Sfenner 83156896Sfenner if (num <= 0) { 83256896Sfenner num = 64; 83356896Sfenner ptr = (struct h6namemem *)calloc(num, sizeof (*ptr)); 83456896Sfenner if (ptr == NULL) 83556896Sfenner error("newh6namemem: calloc"); 83656896Sfenner } 83756896Sfenner --num; 83856896Sfenner p = ptr++; 83956896Sfenner return (p); 84056896Sfenner} 84156896Sfenner#endif /* INET6 */ 842