addrtoname.c revision 39300
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 2317680Spst */ 2417680Spst#ifndef lint 2526183Sfennerstatic const char rcsid[] = 2639300Sfenner "@(#) $Header: addrtoname.c,v 1.61 97/06/15 13:20:18 leres Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2917680Spst#include <sys/types.h> 3017680Spst#include <sys/socket.h> 3117680Spst#include <sys/time.h> 3217680Spst 3317680Spst#if __STDC__ 3417680Spststruct mbuf; 3517680Spststruct rtentry; 3617680Spst#endif 3717680Spst#include <net/if.h> 3817680Spst 3917680Spst#include <netinet/in.h> 4021262Swollman#include <net/ethernet.h> 4117680Spst 4217680Spst#include <arpa/inet.h> 4317680Spst 4417680Spst#include <ctype.h> 4517680Spst#include <netdb.h> 4617680Spst#include <pcap.h> 4717680Spst#include <pcap-namedb.h> 4839300Sfenner#ifdef HAVE_MALLOC_H 4939300Sfenner#include <malloc.h> 5039300Sfenner#endif 5139300Sfenner#ifdef HAVE_MEMORY_H 5239300Sfenner#include <memory.h> 5339300Sfenner#endif 5417680Spst#include <signal.h> 5517680Spst#include <stdio.h> 5617680Spst#include <string.h> 5717680Spst#include <stdlib.h> 5817680Spst#include <unistd.h> 5917680Spst 6017680Spst#include "interface.h" 6117680Spst#include "addrtoname.h" 6217680Spst#include "llc.h" 6339300Sfenner#include "savestr.h" 6439300Sfenner#include "setsignal.h" 6517680Spst 6617680Spst/* Forwards */ 6717680Spststatic RETSIGTYPE nohostname(int); 6817680Spst 6917680Spst/* 7017680Spst * hash tables for whatever-to-name translations 7117680Spst */ 7217680Spst 7317680Spst#define HASHNAMESIZE 4096 7417680Spst 7517680Spststruct hnamemem { 7617680Spst u_int32_t addr; 7717680Spst char *name; 7817680Spst struct hnamemem *nxt; 7917680Spst}; 8017680Spst 8117680Spststruct hnamemem hnametable[HASHNAMESIZE]; 8217680Spststruct hnamemem tporttable[HASHNAMESIZE]; 8317680Spststruct hnamemem uporttable[HASHNAMESIZE]; 8417680Spststruct hnamemem eprototable[HASHNAMESIZE]; 8517680Spststruct hnamemem dnaddrtable[HASHNAMESIZE]; 8617680Spststruct hnamemem llcsaptable[HASHNAMESIZE]; 8717680Spst 8817680Spststruct enamemem { 8917680Spst u_short e_addr0; 9017680Spst u_short e_addr1; 9117680Spst u_short e_addr2; 9217680Spst char *e_name; 9317680Spst u_char *e_nsap; /* used only for nsaptable[] */ 9417680Spst struct enamemem *e_nxt; 9517680Spst}; 9617680Spst 9717680Spststruct enamemem enametable[HASHNAMESIZE]; 9817680Spststruct enamemem nsaptable[HASHNAMESIZE]; 9917680Spst 10017680Spststruct protoidmem { 10117680Spst u_int32_t p_oui; 10217680Spst u_short p_proto; 10317680Spst char *p_name; 10417680Spst struct protoidmem *p_nxt; 10517680Spst}; 10617680Spst 10717680Spststruct protoidmem protoidtable[HASHNAMESIZE]; 10817680Spst 10917680Spst/* 11017680Spst * A faster replacement for inet_ntoa(). 11117680Spst */ 11217680Spstchar * 11317680Spstintoa(u_int32_t addr) 11417680Spst{ 11517680Spst register char *cp; 11617680Spst register u_int byte; 11717680Spst register int n; 11817680Spst static char buf[sizeof(".xxx.xxx.xxx.xxx")]; 11917680Spst 12017680Spst NTOHL(addr); 12117680Spst cp = &buf[sizeof buf]; 12217680Spst *--cp = '\0'; 12317680Spst 12417680Spst n = 4; 12517680Spst do { 12617680Spst byte = addr & 0xff; 12717680Spst *--cp = byte % 10 + '0'; 12817680Spst byte /= 10; 12917680Spst if (byte > 0) { 13017680Spst *--cp = byte % 10 + '0'; 13117680Spst byte /= 10; 13217680Spst if (byte > 0) 13317680Spst *--cp = byte + '0'; 13417680Spst } 13517680Spst *--cp = '.'; 13617680Spst addr >>= 8; 13717680Spst } while (--n > 0); 13817680Spst 13917680Spst return cp + 1; 14017680Spst} 14117680Spst 14217680Spststatic u_int32_t f_netmask; 14317680Spststatic u_int32_t f_localnet; 14417680Spststatic u_int32_t netmask; 14517680Spst 14617680Spst/* 14717680Spst * "getname" is written in this atrocious way to make sure we don't 14817680Spst * wait forever while trying to get hostnames from yp. 14917680Spst */ 15017680Spst#include <setjmp.h> 15117680Spst 15217680Spstjmp_buf getname_env; 15317680Spst 15417680Spststatic RETSIGTYPE 15517680Spstnohostname(int signo) 15617680Spst{ 15717680Spst longjmp(getname_env, 1); 15817680Spst} 15917680Spst 16017680Spst/* 16117680Spst * Return a name for the IP address pointed to by ap. This address 16217680Spst * is assumed to be in network byte order. 16317680Spst */ 16417680Spstchar * 16517680Spstgetname(const u_char *ap) 16617680Spst{ 16717680Spst register struct hostent *hp; 16817680Spst u_int32_t addr; 16917680Spst static struct hnamemem *p; /* static for longjmp() */ 17017680Spst 17117680Spst#ifndef LBL_ALIGN 17217680Spst addr = *(const u_int32_t *)ap; 17317680Spst#else 17417680Spst /* 17526183Sfenner * Extract 32 bits in network order, dealing with alignment. 17617680Spst */ 17717680Spst switch ((long)ap & 3) { 17817680Spst 17917680Spst case 0: 18017680Spst addr = *(u_int32_t *)ap; 18117680Spst break; 18217680Spst 18317680Spst case 2: 18426183Sfenner#ifdef WORDS_BIGENDIAN 18526183Sfenner addr = ((u_int32_t)*(u_short *)ap << 16) | 18626183Sfenner (u_int32_t)*(u_short *)(ap + 2); 18726183Sfenner#else 18817680Spst addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) | 18917680Spst (u_int32_t)*(u_short *)ap; 19017680Spst#endif 19117680Spst break; 19217680Spst 19317680Spst default: 19426183Sfenner#ifdef WORDS_BIGENDIAN 19526183Sfenner addr = ((u_int32_t)ap[0] << 24) | 19626183Sfenner ((u_int32_t)ap[1] << 16) | 19726183Sfenner ((u_int32_t)ap[2] << 8) | 19826183Sfenner (u_int32_t)ap[3]; 19926183Sfenner#else 20017680Spst addr = ((u_int32_t)ap[3] << 24) | 20117680Spst ((u_int32_t)ap[2] << 16) | 20217680Spst ((u_int32_t)ap[1] << 8) | 20317680Spst (u_int32_t)ap[0]; 20417680Spst#endif 20517680Spst break; 20617680Spst } 20717680Spst#endif 20817680Spst p = &hnametable[addr & (HASHNAMESIZE-1)]; 20917680Spst for (; p->nxt; p = p->nxt) { 21017680Spst if (p->addr == addr) 21117680Spst return (p->name); 21217680Spst } 21317680Spst p->addr = addr; 21417680Spst p->nxt = newhnamemem(); 21517680Spst 21617680Spst /* 21717680Spst * Only print names when: 21817680Spst * (1) -n was not given. 21939300Sfenner * (2) Address is foreign and -f was given. (If -f was not 22039300Sfenner * give, f_netmask and f_local are 0 and the test 22139300Sfenner * evaluates to true) 22239300Sfenner * (3) -a was given or the host portion is not all ones 22339300Sfenner * nor all zeros (i.e. not a network or broadcast address) 22417680Spst */ 22539300Sfenner if (!nflag && 22639300Sfenner (addr & f_netmask) == f_localnet && 22739300Sfenner (aflag || 22839300Sfenner !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))) { 22917680Spst if (!setjmp(getname_env)) { 23039300Sfenner (void)setsignal(SIGALRM, nohostname); 23117680Spst (void)alarm(20); 23217680Spst hp = gethostbyaddr((char *)&addr, 4, AF_INET); 23317680Spst (void)alarm(0); 23417680Spst if (hp) { 23517680Spst char *dotp; 23617680Spst 23717680Spst p->name = savestr(hp->h_name); 23817680Spst if (Nflag) { 23917680Spst /* Remove domain qualifications */ 24017680Spst dotp = strchr(p->name, '.'); 24117680Spst if (dotp) 24217680Spst *dotp = '\0'; 24317680Spst } 24417680Spst return (p->name); 24517680Spst } 24617680Spst } 24717680Spst } 24817680Spst p->name = savestr(intoa(addr)); 24917680Spst return (p->name); 25017680Spst} 25117680Spst 25217680Spststatic char hex[] = "0123456789abcdef"; 25317680Spst 25417680Spst 25517680Spst/* Find the hash node that corresponds the ether address 'ep' */ 25617680Spst 25717680Spststatic inline struct enamemem * 25817680Spstlookup_emem(const u_char *ep) 25917680Spst{ 26017680Spst register u_int i, j, k; 26117680Spst struct enamemem *tp; 26217680Spst 26317680Spst k = (ep[0] << 8) | ep[1]; 26417680Spst j = (ep[2] << 8) | ep[3]; 26517680Spst i = (ep[4] << 8) | ep[5]; 26617680Spst 26717680Spst tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; 26817680Spst while (tp->e_nxt) 26917680Spst if (tp->e_addr0 == i && 27017680Spst tp->e_addr1 == j && 27117680Spst tp->e_addr2 == k) 27217680Spst return tp; 27317680Spst else 27417680Spst tp = tp->e_nxt; 27517680Spst tp->e_addr0 = i; 27617680Spst tp->e_addr1 = j; 27717680Spst tp->e_addr2 = k; 27817680Spst tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); 27917680Spst if (tp->e_nxt == NULL) 28017680Spst error("lookup_emem: calloc"); 28117680Spst 28217680Spst return tp; 28317680Spst} 28417680Spst 28517680Spst/* Find the hash node that corresponds the NSAP 'nsap' */ 28617680Spst 28717680Spststatic inline struct enamemem * 28817680Spstlookup_nsap(register const u_char *nsap) 28917680Spst{ 29017680Spst register u_int i, j, k; 29117680Spst int nlen = *nsap; 29217680Spst struct enamemem *tp; 29317680Spst const u_char *ensap = nsap + nlen - 6; 29417680Spst 29517680Spst if (nlen > 6) { 29617680Spst k = (ensap[0] << 8) | ensap[1]; 29717680Spst j = (ensap[2] << 8) | ensap[3]; 29817680Spst i = (ensap[4] << 8) | ensap[5]; 29917680Spst } 30017680Spst else 30117680Spst i = j = k = 0; 30217680Spst 30317680Spst tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)]; 30417680Spst while (tp->e_nxt) 30517680Spst if (tp->e_addr0 == i && 30617680Spst tp->e_addr1 == j && 30717680Spst tp->e_addr2 == k && 30817680Spst tp->e_nsap[0] == nlen && 30917680Spst memcmp((char *)&(nsap[1]), 31017680Spst (char *)&(tp->e_nsap[1]), nlen) == 0) 31117680Spst return tp; 31217680Spst else 31317680Spst tp = tp->e_nxt; 31417680Spst tp->e_addr0 = i; 31517680Spst tp->e_addr1 = j; 31617680Spst tp->e_addr2 = k; 31717680Spst tp->e_nsap = (u_char *)malloc(nlen + 1); 31817680Spst if (tp->e_nsap == NULL) 31917680Spst error("lookup_nsap: malloc"); 32039300Sfenner memcpy((char *)tp->e_nsap, (char *)nsap, nlen + 1); 32117680Spst tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); 32217680Spst if (tp->e_nxt == NULL) 32317680Spst error("lookup_nsap: calloc"); 32417680Spst 32517680Spst return tp; 32617680Spst} 32717680Spst 32817680Spst/* Find the hash node that corresponds the protoid 'pi'. */ 32917680Spst 33017680Spststatic inline struct protoidmem * 33117680Spstlookup_protoid(const u_char *pi) 33217680Spst{ 33317680Spst register u_int i, j; 33417680Spst struct protoidmem *tp; 33517680Spst 33617680Spst /* 5 octets won't be aligned */ 33717680Spst i = (((pi[0] << 8) + pi[1]) << 8) + pi[2]; 33817680Spst j = (pi[3] << 8) + pi[4]; 33917680Spst /* XXX should be endian-insensitive, but do big-endian testing XXX */ 34017680Spst 34117680Spst tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)]; 34217680Spst while (tp->p_nxt) 34317680Spst if (tp->p_oui == i && tp->p_proto == j) 34417680Spst return tp; 34517680Spst else 34617680Spst tp = tp->p_nxt; 34717680Spst tp->p_oui = i; 34817680Spst tp->p_proto = j; 34917680Spst tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp)); 35017680Spst if (tp->p_nxt == NULL) 35117680Spst error("lookup_protoid: calloc"); 35217680Spst 35317680Spst return tp; 35417680Spst} 35517680Spst 35617680Spstchar * 35717680Spstetheraddr_string(register const u_char *ep) 35817680Spst{ 35917680Spst register u_int i, j; 36017680Spst register char *cp; 36117680Spst register struct enamemem *tp; 36217680Spst char buf[sizeof("00:00:00:00:00:00")]; 36317680Spst 36417680Spst tp = lookup_emem(ep); 36517680Spst if (tp->e_name) 36617680Spst return (tp->e_name); 36717680Spst#ifdef HAVE_ETHER_NTOHOST 36817680Spst if (!nflag) { 36917680Spst char buf[128]; 37017680Spst if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) { 37117680Spst tp->e_name = savestr(buf); 37217680Spst return (tp->e_name); 37317680Spst } 37417680Spst } 37517680Spst#endif 37617680Spst cp = buf; 37717680Spst if ((j = *ep >> 4) != 0) 37817680Spst *cp++ = hex[j]; 37917680Spst *cp++ = hex[*ep++ & 0xf]; 38017680Spst for (i = 5; (int)--i >= 0;) { 38117680Spst *cp++ = ':'; 38217680Spst if ((j = *ep >> 4) != 0) 38317680Spst *cp++ = hex[j]; 38417680Spst *cp++ = hex[*ep++ & 0xf]; 38517680Spst } 38617680Spst *cp = '\0'; 38717680Spst tp->e_name = savestr(buf); 38817680Spst return (tp->e_name); 38917680Spst} 39017680Spst 39117680Spstchar * 39217680Spstetherproto_string(u_short port) 39317680Spst{ 39417680Spst register char *cp; 39517680Spst register struct hnamemem *tp; 39617680Spst register u_int32_t i = port; 39717680Spst char buf[sizeof("0000")]; 39817680Spst 39917680Spst for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 40017680Spst if (tp->addr == i) 40117680Spst return (tp->name); 40217680Spst 40317680Spst tp->addr = i; 40417680Spst tp->nxt = newhnamemem(); 40517680Spst 40617680Spst cp = buf; 40717680Spst NTOHS(port); 40817680Spst *cp++ = hex[port >> 12 & 0xf]; 40917680Spst *cp++ = hex[port >> 8 & 0xf]; 41017680Spst *cp++ = hex[port >> 4 & 0xf]; 41117680Spst *cp++ = hex[port & 0xf]; 41217680Spst *cp++ = '\0'; 41317680Spst tp->name = savestr(buf); 41417680Spst return (tp->name); 41517680Spst} 41617680Spst 41717680Spstchar * 41817680Spstprotoid_string(register const u_char *pi) 41917680Spst{ 42017680Spst register u_int i, j; 42117680Spst register char *cp; 42217680Spst register struct protoidmem *tp; 42317680Spst char buf[sizeof("00:00:00:00:00")]; 42417680Spst 42517680Spst tp = lookup_protoid(pi); 42617680Spst if (tp->p_name) 42717680Spst return tp->p_name; 42817680Spst 42917680Spst cp = buf; 43017680Spst if ((j = *pi >> 4) != 0) 43117680Spst *cp++ = hex[j]; 43217680Spst *cp++ = hex[*pi++ & 0xf]; 43317680Spst for (i = 4; (int)--i >= 0;) { 43417680Spst *cp++ = ':'; 43517680Spst if ((j = *pi >> 4) != 0) 43617680Spst *cp++ = hex[j]; 43717680Spst *cp++ = hex[*pi++ & 0xf]; 43817680Spst } 43917680Spst *cp = '\0'; 44017680Spst tp->p_name = savestr(buf); 44117680Spst return (tp->p_name); 44217680Spst} 44317680Spst 44417680Spstchar * 44517680Spstllcsap_string(u_char sap) 44617680Spst{ 44717680Spst register char *cp; 44817680Spst register struct hnamemem *tp; 44917680Spst register u_int32_t i = sap; 45017680Spst char buf[sizeof("sap 00")]; 45117680Spst 45217680Spst for (tp = &llcsaptable[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 (void)strcpy(cp, "sap "); 46117680Spst cp += strlen(cp); 46217680Spst *cp++ = hex[sap >> 4 & 0xf]; 46317680Spst *cp++ = hex[sap & 0xf]; 46417680Spst *cp++ = '\0'; 46517680Spst tp->name = savestr(buf); 46617680Spst return (tp->name); 46717680Spst} 46817680Spst 46917680Spstchar * 47017680Spstisonsap_string(const u_char *nsap) 47117680Spst{ 47217680Spst register u_int i, nlen = nsap[0]; 47317680Spst register char *cp; 47417680Spst register struct enamemem *tp; 47517680Spst 47617680Spst tp = lookup_nsap(nsap); 47717680Spst if (tp->e_name) 47817680Spst return tp->e_name; 47917680Spst 48017688Spst tp->e_name = cp = (char *)malloc(nlen * 2 + 2 + (nlen>>1)); 48117680Spst if (cp == NULL) 48217680Spst error("isonsap_string: malloc"); 48317680Spst 48417680Spst nsap++; 48517688Spst for (i = 0; i < nlen; i++) { 48617680Spst *cp++ = hex[*nsap >> 4]; 48717680Spst *cp++ = hex[*nsap++ & 0xf]; 48817688Spst if (((i & 1) == 0) && (i + 1 < nlen)) 48917688Spst *cp++ = '.'; 49017680Spst } 49117680Spst *cp = '\0'; 49217680Spst return (tp->e_name); 49317680Spst} 49417680Spst 49517680Spstchar * 49617680Spsttcpport_string(u_short port) 49717680Spst{ 49817680Spst register struct hnamemem *tp; 49917680Spst register u_int32_t i = port; 50017680Spst char buf[sizeof("00000")]; 50117680Spst 50217680Spst for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 50317680Spst if (tp->addr == i) 50417680Spst return (tp->name); 50517680Spst 50617680Spst tp->addr = i; 50717680Spst tp->nxt = newhnamemem(); 50817680Spst 50917680Spst (void)sprintf(buf, "%u", i); 51017680Spst tp->name = savestr(buf); 51117680Spst return (tp->name); 51217680Spst} 51317680Spst 51417680Spstchar * 51517680Spstudpport_string(register u_short port) 51617680Spst{ 51717680Spst register struct hnamemem *tp; 51817680Spst register u_int32_t i = port; 51917680Spst char buf[sizeof("00000")]; 52017680Spst 52117680Spst for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 52217680Spst if (tp->addr == i) 52317680Spst return (tp->name); 52417680Spst 52517680Spst tp->addr = i; 52617680Spst tp->nxt = newhnamemem(); 52717680Spst 52817680Spst (void)sprintf(buf, "%u", i); 52917680Spst tp->name = savestr(buf); 53017680Spst return (tp->name); 53117680Spst} 53217680Spst 53317680Spststatic void 53417680Spstinit_servarray(void) 53517680Spst{ 53617680Spst struct servent *sv; 53717680Spst register struct hnamemem *table; 53817680Spst register int i; 53917680Spst char buf[sizeof("0000000000")]; 54017680Spst 54117680Spst while ((sv = getservent()) != NULL) { 54217680Spst int port = ntohs(sv->s_port); 54317680Spst i = port & (HASHNAMESIZE-1); 54417680Spst if (strcmp(sv->s_proto, "tcp") == 0) 54517680Spst table = &tporttable[i]; 54617680Spst else if (strcmp(sv->s_proto, "udp") == 0) 54717680Spst table = &uporttable[i]; 54817680Spst else 54917680Spst continue; 55017680Spst 55117680Spst while (table->name) 55217680Spst table = table->nxt; 55317680Spst if (nflag) { 55417680Spst (void)sprintf(buf, "%d", port); 55517680Spst table->name = savestr(buf); 55617680Spst } else 55717680Spst table->name = savestr(sv->s_name); 55817680Spst table->addr = port; 55917680Spst table->nxt = newhnamemem(); 56017680Spst } 56117680Spst endservent(); 56217680Spst} 56317680Spst 56417680Spst/*XXX from libbpfc.a */ 56517680Spstextern struct eproto { 56617680Spst char *s; 56717680Spst u_short p; 56817680Spst} eproto_db[]; 56917680Spst 57017680Spststatic void 57117680Spstinit_eprotoarray(void) 57217680Spst{ 57317680Spst register int i; 57417680Spst register struct hnamemem *table; 57517680Spst 57617680Spst for (i = 0; eproto_db[i].s; i++) { 57717680Spst int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1); 57817680Spst table = &eprototable[j]; 57917680Spst while (table->name) 58017680Spst table = table->nxt; 58117680Spst table->name = eproto_db[i].s; 58217680Spst table->addr = ntohs(eproto_db[i].p); 58317680Spst table->nxt = newhnamemem(); 58417680Spst } 58517680Spst} 58617680Spst 58717680Spst/* 58817680Spst * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet 58917680Spst * types. 59017680Spst */ 59117680Spststatic void 59217680Spstinit_protoidarray(void) 59317680Spst{ 59417680Spst register int i; 59517680Spst register struct protoidmem *tp; 59617680Spst u_char protoid[5]; 59717680Spst 59817680Spst protoid[0] = 0; 59917680Spst protoid[1] = 0; 60017680Spst protoid[2] = 0; 60117680Spst for (i = 0; eproto_db[i].s; i++) { 60217680Spst u_short etype = htons(eproto_db[i].p); 60317680Spst 60417680Spst memcpy((char *)&protoid[3], (char *)&etype, 2); 60517680Spst tp = lookup_protoid(protoid); 60617680Spst tp->p_name = savestr(eproto_db[i].s); 60717680Spst } 60817680Spst} 60917680Spst 61017680Spststatic struct etherlist { 61117680Spst u_char addr[6]; 61217680Spst char *name; 61317680Spst} etherlist[] = { 61417680Spst {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, 61517680Spst {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } 61617680Spst}; 61717680Spst 61817680Spst/* 61917680Spst * Initialize the ethers hash table. We take two different approaches 62017680Spst * depending on whether or not the system provides the ethers name 62117680Spst * service. If it does, we just wire in a few names at startup, 62217680Spst * and etheraddr_string() fills in the table on demand. If it doesn't, 62317680Spst * then we suck in the entire /etc/ethers file at startup. The idea 62417680Spst * is that parsing the local file will be fast, but spinning through 62517680Spst * all the ethers entries via NIS & next_etherent might be very slow. 62617680Spst * 62717680Spst * XXX pcap_next_etherent doesn't belong in the pcap interface, but 62817680Spst * since the pcap module already does name-to-address translation, 62917680Spst * it's already does most of the work for the ethernet address-to-name 63017680Spst * translation, so we just pcap_next_etherent as a convenience. 63117680Spst */ 63217680Spststatic void 63317680Spstinit_etherarray(void) 63417680Spst{ 63517680Spst register struct etherlist *el; 63617680Spst register struct enamemem *tp; 63717680Spst#ifdef HAVE_ETHER_NTOHOST 63817680Spst char name[256]; 63917680Spst#else 64017680Spst register struct pcap_etherent *ep; 64117680Spst register FILE *fp; 64217680Spst 64317680Spst /* Suck in entire ethers file */ 64417680Spst fp = fopen(PCAP_ETHERS_FILE, "r"); 64517680Spst if (fp != NULL) { 64617680Spst while ((ep = pcap_next_etherent(fp)) != NULL) { 64717680Spst tp = lookup_emem(ep->addr); 64817680Spst tp->e_name = savestr(ep->name); 64917680Spst } 65017680Spst (void)fclose(fp); 65117680Spst } 65217680Spst#endif 65317680Spst 65417680Spst /* Hardwire some ethernet names */ 65517680Spst for (el = etherlist; el->name != NULL; ++el) { 65617680Spst tp = lookup_emem(el->addr); 65717680Spst /* Don't override existing name */ 65817680Spst if (tp->e_name != NULL) 65917680Spst continue; 66017680Spst 66117680Spst#ifdef HAVE_ETHER_NTOHOST 66217680Spst /* Use yp/nis version of name if available */ 66317680Spst if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) { 66417680Spst tp->e_name = savestr(name); 66517680Spst continue; 66617680Spst } 66717680Spst#endif 66817680Spst tp->e_name = el->name; 66917680Spst } 67017680Spst} 67117680Spst 67217680Spststatic struct tok llcsap_db[] = { 67317680Spst { LLCSAP_NULL, "null" }, 67417680Spst { LLCSAP_8021B_I, "802.1b-gsap" }, 67517680Spst { LLCSAP_8021B_G, "802.1b-isap" }, 67617680Spst { LLCSAP_IP, "ip-sap" }, 67717680Spst { LLCSAP_PROWAYNM, "proway-nm" }, 67817680Spst { LLCSAP_8021D, "802.1d" }, 67917680Spst { LLCSAP_RS511, "eia-rs511" }, 68017680Spst { LLCSAP_ISO8208, "x.25/llc2" }, 68117680Spst { LLCSAP_PROWAY, "proway" }, 68217680Spst { LLCSAP_ISONS, "iso-clns" }, 68317680Spst { LLCSAP_GLOBAL, "global" }, 68417680Spst { 0, NULL } 68517680Spst}; 68617680Spst 68717680Spststatic void 68817680Spstinit_llcsaparray(void) 68917680Spst{ 69017680Spst register int i; 69117680Spst register struct hnamemem *table; 69217680Spst 69317680Spst for (i = 0; llcsap_db[i].s != NULL; i++) { 69417680Spst table = &llcsaptable[llcsap_db[i].v]; 69517680Spst while (table->name) 69617680Spst table = table->nxt; 69717680Spst table->name = llcsap_db[i].s; 69817680Spst table->addr = llcsap_db[i].v; 69917680Spst table->nxt = newhnamemem(); 70017680Spst } 70117680Spst} 70217680Spst 70317680Spst/* 70417680Spst * Initialize the address to name translation machinery. We map all 70517680Spst * non-local IP addresses to numeric addresses if fflag is true (i.e., 70617680Spst * to prevent blocking on the nameserver). localnet is the IP address 70717680Spst * of the local network. mask is its subnet mask. 70817680Spst */ 70917680Spstvoid 71039300Sfennerinit_addrtoname(u_int32_t localnet, u_int32_t mask) 71117680Spst{ 71217680Spst netmask = mask; 71317680Spst if (fflag) { 71417680Spst f_localnet = localnet; 71517680Spst f_netmask = mask; 71617680Spst } 71717680Spst if (nflag) 71817680Spst /* 71917680Spst * Simplest way to suppress names. 72017680Spst */ 72117680Spst return; 72217680Spst 72317680Spst init_etherarray(); 72417680Spst init_servarray(); 72517680Spst init_eprotoarray(); 72617680Spst init_llcsaparray(); 72717680Spst init_protoidarray(); 72817680Spst} 72917680Spst 73017680Spstchar * 73117680Spstdnaddr_string(u_short dnaddr) 73217680Spst{ 73317680Spst register struct hnamemem *tp; 73417680Spst 73517680Spst for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0; 73617680Spst tp = tp->nxt) 73717680Spst if (tp->addr == dnaddr) 73817680Spst return (tp->name); 73917680Spst 74017680Spst tp->addr = dnaddr; 74117680Spst tp->nxt = newhnamemem(); 74217680Spst if (nflag) 74317680Spst tp->name = dnnum_string(dnaddr); 74417680Spst else 74517680Spst tp->name = dnname_string(dnaddr); 74617680Spst 74717680Spst return(tp->name); 74817680Spst} 74917680Spst 75017680Spst/* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */ 75117680Spststruct hnamemem * 75226183Sfennernewhnamemem(void) 75317680Spst{ 75417680Spst register struct hnamemem *p; 75517680Spst static struct hnamemem *ptr = NULL; 75617680Spst static u_int num = 0; 75717680Spst 75817680Spst if (num <= 0) { 75917680Spst num = 64; 76017680Spst ptr = (struct hnamemem *)calloc(num, sizeof (*ptr)); 76117680Spst if (ptr == NULL) 76217680Spst error("newhnamemem: calloc"); 76317680Spst } 76417680Spst --num; 76517680Spst p = ptr++; 76617680Spst return (p); 76717680Spst} 768