14edb46e9SPaul Traina /* 24edb46e9SPaul Traina * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 34edb46e9SPaul Traina * The Regents of the University of California. All rights reserved. 44edb46e9SPaul Traina * 54edb46e9SPaul Traina * Redistribution and use in source and binary forms, with or without 64edb46e9SPaul Traina * modification, are permitted provided that: (1) source code distributions 74edb46e9SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 84edb46e9SPaul Traina * distributions including binary code include the above copyright notice and 94edb46e9SPaul Traina * this paragraph in its entirety in the documentation or other materials 104edb46e9SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 114edb46e9SPaul Traina * features or use of this software display the following acknowledgement: 124edb46e9SPaul Traina * ``This product includes software developed by the University of California, 134edb46e9SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 144edb46e9SPaul Traina * the University nor the names of its contributors may be used to endorse 154edb46e9SPaul Traina * or promote products derived from this software without specific prior 164edb46e9SPaul Traina * written permission. 174edb46e9SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 184edb46e9SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 194edb46e9SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 204edb46e9SPaul Traina * 214edb46e9SPaul Traina * Internet, ethernet, port, and protocol string to address 224edb46e9SPaul Traina * and address to string conversion routines 234edb46e9SPaul Traina */ 244edb46e9SPaul Traina #ifndef lint 254edb46e9SPaul Traina static char rcsid[] = 264edb46e9SPaul Traina "@(#) $Header: addrtoname.c,v 1.49 96/07/02 00:19:35 leres Exp $ (LBL)"; 274edb46e9SPaul Traina #endif 284edb46e9SPaul Traina 294edb46e9SPaul Traina #include <sys/types.h> 304edb46e9SPaul Traina #include <sys/socket.h> 314edb46e9SPaul Traina #include <sys/time.h> 324edb46e9SPaul Traina 334edb46e9SPaul Traina #if __STDC__ 344edb46e9SPaul Traina struct mbuf; 354edb46e9SPaul Traina struct rtentry; 364edb46e9SPaul Traina #endif 374edb46e9SPaul Traina #include <net/if.h> 384edb46e9SPaul Traina 394edb46e9SPaul Traina #include <netinet/in.h> 404edb46e9SPaul Traina #include <netinet/if_ether.h> 414edb46e9SPaul Traina 424edb46e9SPaul Traina #include <arpa/inet.h> 434edb46e9SPaul Traina 444edb46e9SPaul Traina #include <ctype.h> 454edb46e9SPaul Traina #include <netdb.h> 464edb46e9SPaul Traina #include <pcap.h> 474edb46e9SPaul Traina #include <pcap-namedb.h> 484edb46e9SPaul Traina #include <signal.h> 494edb46e9SPaul Traina #include <stdio.h> 504edb46e9SPaul Traina #include <string.h> 514edb46e9SPaul Traina #include <stdlib.h> 524edb46e9SPaul Traina #include <unistd.h> 534edb46e9SPaul Traina 544edb46e9SPaul Traina #include "interface.h" 554edb46e9SPaul Traina #include "addrtoname.h" 564edb46e9SPaul Traina #include "llc.h" 574edb46e9SPaul Traina 584edb46e9SPaul Traina /* Forwards */ 594edb46e9SPaul Traina static RETSIGTYPE nohostname(int); 604edb46e9SPaul Traina 614edb46e9SPaul Traina /* 624edb46e9SPaul Traina * hash tables for whatever-to-name translations 634edb46e9SPaul Traina */ 644edb46e9SPaul Traina 654edb46e9SPaul Traina #define HASHNAMESIZE 4096 664edb46e9SPaul Traina 674edb46e9SPaul Traina struct hnamemem { 684edb46e9SPaul Traina u_int32_t addr; 694edb46e9SPaul Traina char *name; 704edb46e9SPaul Traina struct hnamemem *nxt; 714edb46e9SPaul Traina }; 724edb46e9SPaul Traina 734edb46e9SPaul Traina struct hnamemem hnametable[HASHNAMESIZE]; 744edb46e9SPaul Traina struct hnamemem tporttable[HASHNAMESIZE]; 754edb46e9SPaul Traina struct hnamemem uporttable[HASHNAMESIZE]; 764edb46e9SPaul Traina struct hnamemem eprototable[HASHNAMESIZE]; 774edb46e9SPaul Traina struct hnamemem dnaddrtable[HASHNAMESIZE]; 784edb46e9SPaul Traina struct hnamemem llcsaptable[HASHNAMESIZE]; 794edb46e9SPaul Traina 804edb46e9SPaul Traina struct enamemem { 814edb46e9SPaul Traina u_short e_addr0; 824edb46e9SPaul Traina u_short e_addr1; 834edb46e9SPaul Traina u_short e_addr2; 844edb46e9SPaul Traina char *e_name; 854edb46e9SPaul Traina u_char *e_nsap; /* used only for nsaptable[] */ 864edb46e9SPaul Traina struct enamemem *e_nxt; 874edb46e9SPaul Traina }; 884edb46e9SPaul Traina 894edb46e9SPaul Traina struct enamemem enametable[HASHNAMESIZE]; 904edb46e9SPaul Traina struct enamemem nsaptable[HASHNAMESIZE]; 914edb46e9SPaul Traina 924edb46e9SPaul Traina struct protoidmem { 934edb46e9SPaul Traina u_int32_t p_oui; 944edb46e9SPaul Traina u_short p_proto; 954edb46e9SPaul Traina char *p_name; 964edb46e9SPaul Traina struct protoidmem *p_nxt; 974edb46e9SPaul Traina }; 984edb46e9SPaul Traina 994edb46e9SPaul Traina struct protoidmem protoidtable[HASHNAMESIZE]; 1004edb46e9SPaul Traina 1014edb46e9SPaul Traina /* 1024edb46e9SPaul Traina * A faster replacement for inet_ntoa(). 1034edb46e9SPaul Traina */ 1044edb46e9SPaul Traina char * 1054edb46e9SPaul Traina intoa(u_int32_t addr) 1064edb46e9SPaul Traina { 1074edb46e9SPaul Traina register char *cp; 1084edb46e9SPaul Traina register u_int byte; 1094edb46e9SPaul Traina register int n; 1104edb46e9SPaul Traina static char buf[sizeof(".xxx.xxx.xxx.xxx")]; 1114edb46e9SPaul Traina 1124edb46e9SPaul Traina NTOHL(addr); 1134edb46e9SPaul Traina cp = &buf[sizeof buf]; 1144edb46e9SPaul Traina *--cp = '\0'; 1154edb46e9SPaul Traina 1164edb46e9SPaul Traina n = 4; 1174edb46e9SPaul Traina do { 1184edb46e9SPaul Traina byte = addr & 0xff; 1194edb46e9SPaul Traina *--cp = byte % 10 + '0'; 1204edb46e9SPaul Traina byte /= 10; 1214edb46e9SPaul Traina if (byte > 0) { 1224edb46e9SPaul Traina *--cp = byte % 10 + '0'; 1234edb46e9SPaul Traina byte /= 10; 1244edb46e9SPaul Traina if (byte > 0) 1254edb46e9SPaul Traina *--cp = byte + '0'; 1264edb46e9SPaul Traina } 1274edb46e9SPaul Traina *--cp = '.'; 1284edb46e9SPaul Traina addr >>= 8; 1294edb46e9SPaul Traina } while (--n > 0); 1304edb46e9SPaul Traina 1314edb46e9SPaul Traina return cp + 1; 1324edb46e9SPaul Traina } 1334edb46e9SPaul Traina 1344edb46e9SPaul Traina static u_int32_t f_netmask; 1354edb46e9SPaul Traina static u_int32_t f_localnet; 1364edb46e9SPaul Traina static u_int32_t netmask; 1374edb46e9SPaul Traina 1384edb46e9SPaul Traina /* 1394edb46e9SPaul Traina * "getname" is written in this atrocious way to make sure we don't 1404edb46e9SPaul Traina * wait forever while trying to get hostnames from yp. 1414edb46e9SPaul Traina */ 1424edb46e9SPaul Traina #include <setjmp.h> 1434edb46e9SPaul Traina 1444edb46e9SPaul Traina jmp_buf getname_env; 1454edb46e9SPaul Traina 1464edb46e9SPaul Traina static RETSIGTYPE 1474edb46e9SPaul Traina nohostname(int signo) 1484edb46e9SPaul Traina { 1494edb46e9SPaul Traina longjmp(getname_env, 1); 1504edb46e9SPaul Traina } 1514edb46e9SPaul Traina 1524edb46e9SPaul Traina /* 1534edb46e9SPaul Traina * Return a name for the IP address pointed to by ap. This address 1544edb46e9SPaul Traina * is assumed to be in network byte order. 1554edb46e9SPaul Traina */ 1564edb46e9SPaul Traina char * 1574edb46e9SPaul Traina getname(const u_char *ap) 1584edb46e9SPaul Traina { 1594edb46e9SPaul Traina register struct hostent *hp; 1604edb46e9SPaul Traina u_int32_t addr; 1614edb46e9SPaul Traina static struct hnamemem *p; /* static for longjmp() */ 1624edb46e9SPaul Traina 1634edb46e9SPaul Traina #ifndef LBL_ALIGN 1644edb46e9SPaul Traina addr = *(const u_int32_t *)ap; 1654edb46e9SPaul Traina #else 1664edb46e9SPaul Traina /* 1674edb46e9SPaul Traina * Deal with alignment. 1684edb46e9SPaul Traina */ 1694edb46e9SPaul Traina switch ((long)ap & 3) { 1704edb46e9SPaul Traina 1714edb46e9SPaul Traina case 0: 1724edb46e9SPaul Traina addr = *(u_int32_t *)ap; 1734edb46e9SPaul Traina break; 1744edb46e9SPaul Traina 1754edb46e9SPaul Traina case 2: 1764edb46e9SPaul Traina #if BYTE_ORDER == LITTLE_ENDIAN 1774edb46e9SPaul Traina addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) | 1784edb46e9SPaul Traina (u_int32_t)*(u_short *)ap; 1794edb46e9SPaul Traina #else 1804edb46e9SPaul Traina addr = ((u_int32_t)*(u_short *)ap << 16) | 1814edb46e9SPaul Traina (u_int32_t)*(u_short *)(ap + 2); 1824edb46e9SPaul Traina #endif 1834edb46e9SPaul Traina break; 1844edb46e9SPaul Traina 1854edb46e9SPaul Traina default: 1864edb46e9SPaul Traina #if BYTE_ORDER == LITTLE_ENDIAN 1874edb46e9SPaul Traina addr = ((u_int32_t)ap[3] << 24) | 1884edb46e9SPaul Traina ((u_int32_t)ap[2] << 16) | 1894edb46e9SPaul Traina ((u_int32_t)ap[1] << 8) | 1904edb46e9SPaul Traina (u_int32_t)ap[0]; 1914edb46e9SPaul Traina #else 1924edb46e9SPaul Traina addr = ((u_int32_t)ap[0] << 24) | 1934edb46e9SPaul Traina ((u_int32_t)ap[1] << 16) | 1944edb46e9SPaul Traina ((u_int32_t)ap[2] << 8) | 1954edb46e9SPaul Traina (u_int32_t)ap[3]; 1964edb46e9SPaul Traina #endif 1974edb46e9SPaul Traina break; 1984edb46e9SPaul Traina } 1994edb46e9SPaul Traina #endif 2004edb46e9SPaul Traina p = &hnametable[addr & (HASHNAMESIZE-1)]; 2014edb46e9SPaul Traina for (; p->nxt; p = p->nxt) { 2024edb46e9SPaul Traina if (p->addr == addr) 2034edb46e9SPaul Traina return (p->name); 2044edb46e9SPaul Traina } 2054edb46e9SPaul Traina p->addr = addr; 2064edb46e9SPaul Traina p->nxt = newhnamemem(); 2074edb46e9SPaul Traina 2084edb46e9SPaul Traina /* 2094edb46e9SPaul Traina * Only print names when: 2104edb46e9SPaul Traina * (1) -n was not given. 2114edb46e9SPaul Traina * (2) Address is foreign and -f was given. If -f was not 2124edb46e9SPaul Traina * present, f_netmask and f_local are 0 and the second 2134edb46e9SPaul Traina * test will succeed. 2144edb46e9SPaul Traina * (3) The host portion is not 0 (i.e., a network address). 2154edb46e9SPaul Traina * (4) The host portion is not broadcast. 2164edb46e9SPaul Traina */ 2174edb46e9SPaul Traina if (!nflag && (addr & f_netmask) == f_localnet 2184edb46e9SPaul Traina && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) { 2194edb46e9SPaul Traina if (!setjmp(getname_env)) { 2204edb46e9SPaul Traina (void)signal(SIGALRM, nohostname); 2214edb46e9SPaul Traina (void)alarm(20); 2224edb46e9SPaul Traina hp = gethostbyaddr((char *)&addr, 4, AF_INET); 2234edb46e9SPaul Traina (void)alarm(0); 2244edb46e9SPaul Traina if (hp) { 2254edb46e9SPaul Traina char *dotp; 2264edb46e9SPaul Traina 2274edb46e9SPaul Traina p->name = savestr(hp->h_name); 2284edb46e9SPaul Traina if (Nflag) { 2294edb46e9SPaul Traina /* Remove domain qualifications */ 2304edb46e9SPaul Traina dotp = strchr(p->name, '.'); 2314edb46e9SPaul Traina if (dotp) 2324edb46e9SPaul Traina *dotp = '\0'; 2334edb46e9SPaul Traina } 2344edb46e9SPaul Traina return (p->name); 2354edb46e9SPaul Traina } 2364edb46e9SPaul Traina } 2374edb46e9SPaul Traina } 2384edb46e9SPaul Traina p->name = savestr(intoa(addr)); 2394edb46e9SPaul Traina return (p->name); 2404edb46e9SPaul Traina } 2414edb46e9SPaul Traina 2424edb46e9SPaul Traina static char hex[] = "0123456789abcdef"; 2434edb46e9SPaul Traina 2444edb46e9SPaul Traina 2454edb46e9SPaul Traina /* Find the hash node that corresponds the ether address 'ep' */ 2464edb46e9SPaul Traina 2474edb46e9SPaul Traina static inline struct enamemem * 2484edb46e9SPaul Traina lookup_emem(const u_char *ep) 2494edb46e9SPaul Traina { 2504edb46e9SPaul Traina register u_int i, j, k; 2514edb46e9SPaul Traina struct enamemem *tp; 2524edb46e9SPaul Traina 2534edb46e9SPaul Traina k = (ep[0] << 8) | ep[1]; 2544edb46e9SPaul Traina j = (ep[2] << 8) | ep[3]; 2554edb46e9SPaul Traina i = (ep[4] << 8) | ep[5]; 2564edb46e9SPaul Traina 2574edb46e9SPaul Traina tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; 2584edb46e9SPaul Traina while (tp->e_nxt) 2594edb46e9SPaul Traina if (tp->e_addr0 == i && 2604edb46e9SPaul Traina tp->e_addr1 == j && 2614edb46e9SPaul Traina tp->e_addr2 == k) 2624edb46e9SPaul Traina return tp; 2634edb46e9SPaul Traina else 2644edb46e9SPaul Traina tp = tp->e_nxt; 2654edb46e9SPaul Traina tp->e_addr0 = i; 2664edb46e9SPaul Traina tp->e_addr1 = j; 2674edb46e9SPaul Traina tp->e_addr2 = k; 2684edb46e9SPaul Traina tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); 2694edb46e9SPaul Traina if (tp->e_nxt == NULL) 2704edb46e9SPaul Traina error("lookup_emem: calloc"); 2714edb46e9SPaul Traina 2724edb46e9SPaul Traina return tp; 2734edb46e9SPaul Traina } 2744edb46e9SPaul Traina 2754edb46e9SPaul Traina /* Find the hash node that corresponds the NSAP 'nsap' */ 2764edb46e9SPaul Traina 2774edb46e9SPaul Traina static inline struct enamemem * 2784edb46e9SPaul Traina lookup_nsap(register const u_char *nsap) 2794edb46e9SPaul Traina { 2804edb46e9SPaul Traina register u_int i, j, k; 2814edb46e9SPaul Traina int nlen = *nsap; 2824edb46e9SPaul Traina struct enamemem *tp; 2834edb46e9SPaul Traina const u_char *ensap = nsap + nlen - 6; 2844edb46e9SPaul Traina 2854edb46e9SPaul Traina if (nlen > 6) { 2864edb46e9SPaul Traina k = (ensap[0] << 8) | ensap[1]; 2874edb46e9SPaul Traina j = (ensap[2] << 8) | ensap[3]; 2884edb46e9SPaul Traina i = (ensap[4] << 8) | ensap[5]; 2894edb46e9SPaul Traina } 2904edb46e9SPaul Traina else 2914edb46e9SPaul Traina i = j = k = 0; 2924edb46e9SPaul Traina 2934edb46e9SPaul Traina tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)]; 2944edb46e9SPaul Traina while (tp->e_nxt) 2954edb46e9SPaul Traina if (tp->e_addr0 == i && 2964edb46e9SPaul Traina tp->e_addr1 == j && 2974edb46e9SPaul Traina tp->e_addr2 == k && 2984edb46e9SPaul Traina tp->e_nsap[0] == nlen && 2994edb46e9SPaul Traina memcmp((char *)&(nsap[1]), 3004edb46e9SPaul Traina (char *)&(tp->e_nsap[1]), nlen) == 0) 3014edb46e9SPaul Traina return tp; 3024edb46e9SPaul Traina else 3034edb46e9SPaul Traina tp = tp->e_nxt; 3044edb46e9SPaul Traina tp->e_addr0 = i; 3054edb46e9SPaul Traina tp->e_addr1 = j; 3064edb46e9SPaul Traina tp->e_addr2 = k; 3074edb46e9SPaul Traina tp->e_nsap = (u_char *)malloc(nlen + 1); 3084edb46e9SPaul Traina if (tp->e_nsap == NULL) 3094edb46e9SPaul Traina error("lookup_nsap: malloc"); 3104edb46e9SPaul Traina memcpy(tp->e_nsap, nsap, nlen + 1); 3114edb46e9SPaul Traina tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); 3124edb46e9SPaul Traina if (tp->e_nxt == NULL) 3134edb46e9SPaul Traina error("lookup_nsap: calloc"); 3144edb46e9SPaul Traina 3154edb46e9SPaul Traina return tp; 3164edb46e9SPaul Traina } 3174edb46e9SPaul Traina 3184edb46e9SPaul Traina /* Find the hash node that corresponds the protoid 'pi'. */ 3194edb46e9SPaul Traina 3204edb46e9SPaul Traina static inline struct protoidmem * 3214edb46e9SPaul Traina lookup_protoid(const u_char *pi) 3224edb46e9SPaul Traina { 3234edb46e9SPaul Traina register u_int i, j; 3244edb46e9SPaul Traina struct protoidmem *tp; 3254edb46e9SPaul Traina 3264edb46e9SPaul Traina /* 5 octets won't be aligned */ 3274edb46e9SPaul Traina i = (((pi[0] << 8) + pi[1]) << 8) + pi[2]; 3284edb46e9SPaul Traina j = (pi[3] << 8) + pi[4]; 3294edb46e9SPaul Traina /* XXX should be endian-insensitive, but do big-endian testing XXX */ 3304edb46e9SPaul Traina 3314edb46e9SPaul Traina tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)]; 3324edb46e9SPaul Traina while (tp->p_nxt) 3334edb46e9SPaul Traina if (tp->p_oui == i && tp->p_proto == j) 3344edb46e9SPaul Traina return tp; 3354edb46e9SPaul Traina else 3364edb46e9SPaul Traina tp = tp->p_nxt; 3374edb46e9SPaul Traina tp->p_oui = i; 3384edb46e9SPaul Traina tp->p_proto = j; 3394edb46e9SPaul Traina tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp)); 3404edb46e9SPaul Traina if (tp->p_nxt == NULL) 3414edb46e9SPaul Traina error("lookup_protoid: calloc"); 3424edb46e9SPaul Traina 3434edb46e9SPaul Traina return tp; 3444edb46e9SPaul Traina } 3454edb46e9SPaul Traina 3464edb46e9SPaul Traina char * 3474edb46e9SPaul Traina etheraddr_string(register const u_char *ep) 3484edb46e9SPaul Traina { 3494edb46e9SPaul Traina register u_int i, j; 3504edb46e9SPaul Traina register char *cp; 3514edb46e9SPaul Traina register struct enamemem *tp; 3524edb46e9SPaul Traina char buf[sizeof("00:00:00:00:00:00")]; 3534edb46e9SPaul Traina 3544edb46e9SPaul Traina tp = lookup_emem(ep); 3554edb46e9SPaul Traina if (tp->e_name) 3564edb46e9SPaul Traina return (tp->e_name); 3574edb46e9SPaul Traina #ifdef HAVE_ETHER_NTOHOST 3584edb46e9SPaul Traina if (!nflag) { 3594edb46e9SPaul Traina char buf[128]; 3604edb46e9SPaul Traina if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) { 3614edb46e9SPaul Traina tp->e_name = savestr(buf); 3624edb46e9SPaul Traina return (tp->e_name); 3634edb46e9SPaul Traina } 3644edb46e9SPaul Traina } 3654edb46e9SPaul Traina #endif 3664edb46e9SPaul Traina cp = buf; 3674edb46e9SPaul Traina if ((j = *ep >> 4) != 0) 3684edb46e9SPaul Traina *cp++ = hex[j]; 3694edb46e9SPaul Traina *cp++ = hex[*ep++ & 0xf]; 3704edb46e9SPaul Traina for (i = 5; (int)--i >= 0;) { 3714edb46e9SPaul Traina *cp++ = ':'; 3724edb46e9SPaul Traina if ((j = *ep >> 4) != 0) 3734edb46e9SPaul Traina *cp++ = hex[j]; 3744edb46e9SPaul Traina *cp++ = hex[*ep++ & 0xf]; 3754edb46e9SPaul Traina } 3764edb46e9SPaul Traina *cp = '\0'; 3774edb46e9SPaul Traina tp->e_name = savestr(buf); 3784edb46e9SPaul Traina return (tp->e_name); 3794edb46e9SPaul Traina } 3804edb46e9SPaul Traina 3814edb46e9SPaul Traina char * 3824edb46e9SPaul Traina etherproto_string(u_short port) 3834edb46e9SPaul Traina { 3844edb46e9SPaul Traina register char *cp; 3854edb46e9SPaul Traina register struct hnamemem *tp; 3864edb46e9SPaul Traina register u_int32_t i = port; 3874edb46e9SPaul Traina char buf[sizeof("0000")]; 3884edb46e9SPaul Traina 3894edb46e9SPaul Traina for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 3904edb46e9SPaul Traina if (tp->addr == i) 3914edb46e9SPaul Traina return (tp->name); 3924edb46e9SPaul Traina 3934edb46e9SPaul Traina tp->addr = i; 3944edb46e9SPaul Traina tp->nxt = newhnamemem(); 3954edb46e9SPaul Traina 3964edb46e9SPaul Traina cp = buf; 3974edb46e9SPaul Traina NTOHS(port); 3984edb46e9SPaul Traina *cp++ = hex[port >> 12 & 0xf]; 3994edb46e9SPaul Traina *cp++ = hex[port >> 8 & 0xf]; 4004edb46e9SPaul Traina *cp++ = hex[port >> 4 & 0xf]; 4014edb46e9SPaul Traina *cp++ = hex[port & 0xf]; 4024edb46e9SPaul Traina *cp++ = '\0'; 4034edb46e9SPaul Traina tp->name = savestr(buf); 4044edb46e9SPaul Traina return (tp->name); 4054edb46e9SPaul Traina } 4064edb46e9SPaul Traina 4074edb46e9SPaul Traina char * 4084edb46e9SPaul Traina protoid_string(register const u_char *pi) 4094edb46e9SPaul Traina { 4104edb46e9SPaul Traina register u_int i, j; 4114edb46e9SPaul Traina register char *cp; 4124edb46e9SPaul Traina register struct protoidmem *tp; 4134edb46e9SPaul Traina char buf[sizeof("00:00:00:00:00")]; 4144edb46e9SPaul Traina 4154edb46e9SPaul Traina tp = lookup_protoid(pi); 4164edb46e9SPaul Traina if (tp->p_name) 4174edb46e9SPaul Traina return tp->p_name; 4184edb46e9SPaul Traina 4194edb46e9SPaul Traina cp = buf; 4204edb46e9SPaul Traina if ((j = *pi >> 4) != 0) 4214edb46e9SPaul Traina *cp++ = hex[j]; 4224edb46e9SPaul Traina *cp++ = hex[*pi++ & 0xf]; 4234edb46e9SPaul Traina for (i = 4; (int)--i >= 0;) { 4244edb46e9SPaul Traina *cp++ = ':'; 4254edb46e9SPaul Traina if ((j = *pi >> 4) != 0) 4264edb46e9SPaul Traina *cp++ = hex[j]; 4274edb46e9SPaul Traina *cp++ = hex[*pi++ & 0xf]; 4284edb46e9SPaul Traina } 4294edb46e9SPaul Traina *cp = '\0'; 4304edb46e9SPaul Traina tp->p_name = savestr(buf); 4314edb46e9SPaul Traina return (tp->p_name); 4324edb46e9SPaul Traina } 4334edb46e9SPaul Traina 4344edb46e9SPaul Traina char * 4354edb46e9SPaul Traina llcsap_string(u_char sap) 4364edb46e9SPaul Traina { 4374edb46e9SPaul Traina register char *cp; 4384edb46e9SPaul Traina register struct hnamemem *tp; 4394edb46e9SPaul Traina register u_int32_t i = sap; 4404edb46e9SPaul Traina char buf[sizeof("sap 00")]; 4414edb46e9SPaul Traina 4424edb46e9SPaul Traina for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 4434edb46e9SPaul Traina if (tp->addr == i) 4444edb46e9SPaul Traina return (tp->name); 4454edb46e9SPaul Traina 4464edb46e9SPaul Traina tp->addr = i; 4474edb46e9SPaul Traina tp->nxt = newhnamemem(); 4484edb46e9SPaul Traina 4494edb46e9SPaul Traina cp = buf; 4504edb46e9SPaul Traina (void)strcpy(cp, "sap "); 4514edb46e9SPaul Traina cp += strlen(cp); 4524edb46e9SPaul Traina *cp++ = hex[sap >> 4 & 0xf]; 4534edb46e9SPaul Traina *cp++ = hex[sap & 0xf]; 4544edb46e9SPaul Traina *cp++ = '\0'; 4554edb46e9SPaul Traina tp->name = savestr(buf); 4564edb46e9SPaul Traina return (tp->name); 4574edb46e9SPaul Traina } 4584edb46e9SPaul Traina 4594edb46e9SPaul Traina char * 4604edb46e9SPaul Traina isonsap_string(const u_char *nsap) 4614edb46e9SPaul Traina { 4624edb46e9SPaul Traina register u_int i, nlen = nsap[0]; 4634edb46e9SPaul Traina register char *cp; 4644edb46e9SPaul Traina register struct enamemem *tp; 4654edb46e9SPaul Traina 4664edb46e9SPaul Traina tp = lookup_nsap(nsap); 4674edb46e9SPaul Traina if (tp->e_name) 4684edb46e9SPaul Traina return tp->e_name; 4694edb46e9SPaul Traina 4704edb46e9SPaul Traina tp->e_name = cp = (char *)malloc(nlen * 2 + 2); 4714edb46e9SPaul Traina if (cp == NULL) 4724edb46e9SPaul Traina error("isonsap_string: malloc"); 4734edb46e9SPaul Traina 4744edb46e9SPaul Traina nsap++; 4754edb46e9SPaul Traina *cp++ = '/'; 4764edb46e9SPaul Traina for (i = nlen; (int)--i >= 0;) { 4774edb46e9SPaul Traina *cp++ = hex[*nsap >> 4]; 4784edb46e9SPaul Traina *cp++ = hex[*nsap++ & 0xf]; 4794edb46e9SPaul Traina } 4804edb46e9SPaul Traina *cp = '\0'; 4814edb46e9SPaul Traina return (tp->e_name); 4824edb46e9SPaul Traina } 4834edb46e9SPaul Traina 4844edb46e9SPaul Traina char * 4854edb46e9SPaul Traina tcpport_string(u_short port) 4864edb46e9SPaul Traina { 4874edb46e9SPaul Traina register struct hnamemem *tp; 4884edb46e9SPaul Traina register u_int32_t i = port; 4894edb46e9SPaul Traina char buf[sizeof("00000")]; 4904edb46e9SPaul Traina 4914edb46e9SPaul Traina for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 4924edb46e9SPaul Traina if (tp->addr == i) 4934edb46e9SPaul Traina return (tp->name); 4944edb46e9SPaul Traina 4954edb46e9SPaul Traina tp->addr = i; 4964edb46e9SPaul Traina tp->nxt = newhnamemem(); 4974edb46e9SPaul Traina 4984edb46e9SPaul Traina (void)sprintf(buf, "%u", i); 4994edb46e9SPaul Traina tp->name = savestr(buf); 5004edb46e9SPaul Traina return (tp->name); 5014edb46e9SPaul Traina } 5024edb46e9SPaul Traina 5034edb46e9SPaul Traina char * 5044edb46e9SPaul Traina udpport_string(register u_short port) 5054edb46e9SPaul Traina { 5064edb46e9SPaul Traina register struct hnamemem *tp; 5074edb46e9SPaul Traina register u_int32_t i = port; 5084edb46e9SPaul Traina char buf[sizeof("00000")]; 5094edb46e9SPaul Traina 5104edb46e9SPaul Traina for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 5114edb46e9SPaul Traina if (tp->addr == i) 5124edb46e9SPaul Traina return (tp->name); 5134edb46e9SPaul Traina 5144edb46e9SPaul Traina tp->addr = i; 5154edb46e9SPaul Traina tp->nxt = newhnamemem(); 5164edb46e9SPaul Traina 5174edb46e9SPaul Traina (void)sprintf(buf, "%u", i); 5184edb46e9SPaul Traina tp->name = savestr(buf); 5194edb46e9SPaul Traina return (tp->name); 5204edb46e9SPaul Traina } 5214edb46e9SPaul Traina 5224edb46e9SPaul Traina static void 5234edb46e9SPaul Traina init_servarray(void) 5244edb46e9SPaul Traina { 5254edb46e9SPaul Traina struct servent *sv; 5264edb46e9SPaul Traina register struct hnamemem *table; 5274edb46e9SPaul Traina register int i; 5284edb46e9SPaul Traina char buf[sizeof("0000000000")]; 5294edb46e9SPaul Traina 5304edb46e9SPaul Traina while ((sv = getservent()) != NULL) { 5314edb46e9SPaul Traina int port = ntohs(sv->s_port); 5324edb46e9SPaul Traina i = port & (HASHNAMESIZE-1); 5334edb46e9SPaul Traina if (strcmp(sv->s_proto, "tcp") == 0) 5344edb46e9SPaul Traina table = &tporttable[i]; 5354edb46e9SPaul Traina else if (strcmp(sv->s_proto, "udp") == 0) 5364edb46e9SPaul Traina table = &uporttable[i]; 5374edb46e9SPaul Traina else 5384edb46e9SPaul Traina continue; 5394edb46e9SPaul Traina 5404edb46e9SPaul Traina while (table->name) 5414edb46e9SPaul Traina table = table->nxt; 5424edb46e9SPaul Traina if (nflag) { 5434edb46e9SPaul Traina (void)sprintf(buf, "%d", port); 5444edb46e9SPaul Traina table->name = savestr(buf); 5454edb46e9SPaul Traina } else 5464edb46e9SPaul Traina table->name = savestr(sv->s_name); 5474edb46e9SPaul Traina table->addr = port; 5484edb46e9SPaul Traina table->nxt = newhnamemem(); 5494edb46e9SPaul Traina } 5504edb46e9SPaul Traina endservent(); 5514edb46e9SPaul Traina } 5524edb46e9SPaul Traina 5534edb46e9SPaul Traina /*XXX from libbpfc.a */ 5544edb46e9SPaul Traina extern struct eproto { 5554edb46e9SPaul Traina char *s; 5564edb46e9SPaul Traina u_short p; 5574edb46e9SPaul Traina } eproto_db[]; 5584edb46e9SPaul Traina 5594edb46e9SPaul Traina static void 5604edb46e9SPaul Traina init_eprotoarray(void) 5614edb46e9SPaul Traina { 5624edb46e9SPaul Traina register int i; 5634edb46e9SPaul Traina register struct hnamemem *table; 5644edb46e9SPaul Traina 5654edb46e9SPaul Traina for (i = 0; eproto_db[i].s; i++) { 5664edb46e9SPaul Traina int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1); 5674edb46e9SPaul Traina table = &eprototable[j]; 5684edb46e9SPaul Traina while (table->name) 5694edb46e9SPaul Traina table = table->nxt; 5704edb46e9SPaul Traina table->name = eproto_db[i].s; 5714edb46e9SPaul Traina table->addr = ntohs(eproto_db[i].p); 5724edb46e9SPaul Traina table->nxt = newhnamemem(); 5734edb46e9SPaul Traina } 5744edb46e9SPaul Traina } 5754edb46e9SPaul Traina 5764edb46e9SPaul Traina /* 5774edb46e9SPaul Traina * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet 5784edb46e9SPaul Traina * types. 5794edb46e9SPaul Traina */ 5804edb46e9SPaul Traina static void 5814edb46e9SPaul Traina init_protoidarray(void) 5824edb46e9SPaul Traina { 5834edb46e9SPaul Traina register int i; 5844edb46e9SPaul Traina register struct protoidmem *tp; 5854edb46e9SPaul Traina u_char protoid[5]; 5864edb46e9SPaul Traina 5874edb46e9SPaul Traina protoid[0] = 0; 5884edb46e9SPaul Traina protoid[1] = 0; 5894edb46e9SPaul Traina protoid[2] = 0; 5904edb46e9SPaul Traina for (i = 0; eproto_db[i].s; i++) { 5914edb46e9SPaul Traina u_short etype = htons(eproto_db[i].p); 5924edb46e9SPaul Traina 5934edb46e9SPaul Traina memcpy((char *)&protoid[3], (char *)&etype, 2); 5944edb46e9SPaul Traina tp = lookup_protoid(protoid); 5954edb46e9SPaul Traina tp->p_name = savestr(eproto_db[i].s); 5964edb46e9SPaul Traina } 5974edb46e9SPaul Traina } 5984edb46e9SPaul Traina 5994edb46e9SPaul Traina static struct etherlist { 6004edb46e9SPaul Traina u_char addr[6]; 6014edb46e9SPaul Traina char *name; 6024edb46e9SPaul Traina } etherlist[] = { 6034edb46e9SPaul Traina {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, 6044edb46e9SPaul Traina {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } 6054edb46e9SPaul Traina }; 6064edb46e9SPaul Traina 6074edb46e9SPaul Traina /* 6084edb46e9SPaul Traina * Initialize the ethers hash table. We take two different approaches 6094edb46e9SPaul Traina * depending on whether or not the system provides the ethers name 6104edb46e9SPaul Traina * service. If it does, we just wire in a few names at startup, 6114edb46e9SPaul Traina * and etheraddr_string() fills in the table on demand. If it doesn't, 6124edb46e9SPaul Traina * then we suck in the entire /etc/ethers file at startup. The idea 6134edb46e9SPaul Traina * is that parsing the local file will be fast, but spinning through 6144edb46e9SPaul Traina * all the ethers entries via NIS & next_etherent might be very slow. 6154edb46e9SPaul Traina * 6164edb46e9SPaul Traina * XXX pcap_next_etherent doesn't belong in the pcap interface, but 6174edb46e9SPaul Traina * since the pcap module already does name-to-address translation, 6184edb46e9SPaul Traina * it's already does most of the work for the ethernet address-to-name 6194edb46e9SPaul Traina * translation, so we just pcap_next_etherent as a convenience. 6204edb46e9SPaul Traina */ 6214edb46e9SPaul Traina static void 6224edb46e9SPaul Traina init_etherarray(void) 6234edb46e9SPaul Traina { 6244edb46e9SPaul Traina register struct etherlist *el; 6254edb46e9SPaul Traina register struct enamemem *tp; 6264edb46e9SPaul Traina #ifdef HAVE_ETHER_NTOHOST 6274edb46e9SPaul Traina char name[256]; 6284edb46e9SPaul Traina #else 6294edb46e9SPaul Traina register struct pcap_etherent *ep; 6304edb46e9SPaul Traina register FILE *fp; 6314edb46e9SPaul Traina 6324edb46e9SPaul Traina /* Suck in entire ethers file */ 6334edb46e9SPaul Traina fp = fopen(PCAP_ETHERS_FILE, "r"); 6344edb46e9SPaul Traina if (fp != NULL) { 6354edb46e9SPaul Traina while ((ep = pcap_next_etherent(fp)) != NULL) { 6364edb46e9SPaul Traina tp = lookup_emem(ep->addr); 6374edb46e9SPaul Traina tp->e_name = savestr(ep->name); 6384edb46e9SPaul Traina } 6394edb46e9SPaul Traina (void)fclose(fp); 6404edb46e9SPaul Traina } 6414edb46e9SPaul Traina #endif 6424edb46e9SPaul Traina 6434edb46e9SPaul Traina /* Hardwire some ethernet names */ 6444edb46e9SPaul Traina for (el = etherlist; el->name != NULL; ++el) { 6454edb46e9SPaul Traina tp = lookup_emem(el->addr); 6464edb46e9SPaul Traina /* Don't override existing name */ 6474edb46e9SPaul Traina if (tp->e_name != NULL) 6484edb46e9SPaul Traina continue; 6494edb46e9SPaul Traina 6504edb46e9SPaul Traina #ifdef HAVE_ETHER_NTOHOST 6514edb46e9SPaul Traina /* Use yp/nis version of name if available */ 6524edb46e9SPaul Traina if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) { 6534edb46e9SPaul Traina tp->e_name = savestr(name); 6544edb46e9SPaul Traina continue; 6554edb46e9SPaul Traina } 6564edb46e9SPaul Traina #endif 6574edb46e9SPaul Traina tp->e_name = el->name; 6584edb46e9SPaul Traina } 6594edb46e9SPaul Traina } 6604edb46e9SPaul Traina 6614edb46e9SPaul Traina static struct tok llcsap_db[] = { 6624edb46e9SPaul Traina { LLCSAP_NULL, "null" }, 6634edb46e9SPaul Traina { LLCSAP_8021B_I, "802.1b-gsap" }, 6644edb46e9SPaul Traina { LLCSAP_8021B_G, "802.1b-isap" }, 6654edb46e9SPaul Traina { LLCSAP_IP, "ip-sap" }, 6664edb46e9SPaul Traina { LLCSAP_PROWAYNM, "proway-nm" }, 6674edb46e9SPaul Traina { LLCSAP_8021D, "802.1d" }, 6684edb46e9SPaul Traina { LLCSAP_RS511, "eia-rs511" }, 6694edb46e9SPaul Traina { LLCSAP_ISO8208, "x.25/llc2" }, 6704edb46e9SPaul Traina { LLCSAP_PROWAY, "proway" }, 6714edb46e9SPaul Traina { LLCSAP_ISONS, "iso-clns" }, 6724edb46e9SPaul Traina { LLCSAP_GLOBAL, "global" }, 6734edb46e9SPaul Traina { 0, NULL } 6744edb46e9SPaul Traina }; 6754edb46e9SPaul Traina 6764edb46e9SPaul Traina static void 6774edb46e9SPaul Traina init_llcsaparray(void) 6784edb46e9SPaul Traina { 6794edb46e9SPaul Traina register int i; 6804edb46e9SPaul Traina register struct hnamemem *table; 6814edb46e9SPaul Traina 6824edb46e9SPaul Traina for (i = 0; llcsap_db[i].s != NULL; i++) { 6834edb46e9SPaul Traina table = &llcsaptable[llcsap_db[i].v]; 6844edb46e9SPaul Traina while (table->name) 6854edb46e9SPaul Traina table = table->nxt; 6864edb46e9SPaul Traina table->name = llcsap_db[i].s; 6874edb46e9SPaul Traina table->addr = llcsap_db[i].v; 6884edb46e9SPaul Traina table->nxt = newhnamemem(); 6894edb46e9SPaul Traina } 6904edb46e9SPaul Traina } 6914edb46e9SPaul Traina 6924edb46e9SPaul Traina /* 6934edb46e9SPaul Traina * Initialize the address to name translation machinery. We map all 6944edb46e9SPaul Traina * non-local IP addresses to numeric addresses if fflag is true (i.e., 6954edb46e9SPaul Traina * to prevent blocking on the nameserver). localnet is the IP address 6964edb46e9SPaul Traina * of the local network. mask is its subnet mask. 6974edb46e9SPaul Traina */ 6984edb46e9SPaul Traina void 6994edb46e9SPaul Traina init_addrtoname(int fflag, u_int32_t localnet, u_int32_t mask) 7004edb46e9SPaul Traina { 7014edb46e9SPaul Traina netmask = mask; 7024edb46e9SPaul Traina if (fflag) { 7034edb46e9SPaul Traina f_localnet = localnet; 7044edb46e9SPaul Traina f_netmask = mask; 7054edb46e9SPaul Traina } 7064edb46e9SPaul Traina if (nflag) 7074edb46e9SPaul Traina /* 7084edb46e9SPaul Traina * Simplest way to suppress names. 7094edb46e9SPaul Traina */ 7104edb46e9SPaul Traina return; 7114edb46e9SPaul Traina 7124edb46e9SPaul Traina init_etherarray(); 7134edb46e9SPaul Traina init_servarray(); 7144edb46e9SPaul Traina init_eprotoarray(); 7154edb46e9SPaul Traina init_llcsaparray(); 7164edb46e9SPaul Traina init_protoidarray(); 7174edb46e9SPaul Traina } 7184edb46e9SPaul Traina 7194edb46e9SPaul Traina char * 7204edb46e9SPaul Traina dnaddr_string(u_short dnaddr) 7214edb46e9SPaul Traina { 7224edb46e9SPaul Traina register struct hnamemem *tp; 7234edb46e9SPaul Traina 7244edb46e9SPaul Traina for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0; 7254edb46e9SPaul Traina tp = tp->nxt) 7264edb46e9SPaul Traina if (tp->addr == dnaddr) 7274edb46e9SPaul Traina return (tp->name); 7284edb46e9SPaul Traina 7294edb46e9SPaul Traina tp->addr = dnaddr; 7304edb46e9SPaul Traina tp->nxt = newhnamemem(); 7314edb46e9SPaul Traina if (nflag) 7324edb46e9SPaul Traina tp->name = dnnum_string(dnaddr); 7334edb46e9SPaul Traina else 7344edb46e9SPaul Traina tp->name = dnname_string(dnaddr); 7354edb46e9SPaul Traina 7364edb46e9SPaul Traina return(tp->name); 7374edb46e9SPaul Traina } 7384edb46e9SPaul Traina 7394edb46e9SPaul Traina /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */ 7404edb46e9SPaul Traina struct hnamemem * 7414edb46e9SPaul Traina newhnamemem() 7424edb46e9SPaul Traina { 7434edb46e9SPaul Traina register struct hnamemem *p; 7444edb46e9SPaul Traina static struct hnamemem *ptr = NULL; 7454edb46e9SPaul Traina static u_int num = 0; 7464edb46e9SPaul Traina 7474edb46e9SPaul Traina if (num <= 0) { 7484edb46e9SPaul Traina num = 64; 7494edb46e9SPaul Traina ptr = (struct hnamemem *)calloc(num, sizeof (*ptr)); 7504edb46e9SPaul Traina if (ptr == NULL) 7514edb46e9SPaul Traina error("newhnamemem: calloc"); 7524edb46e9SPaul Traina } 7534edb46e9SPaul Traina --num; 7544edb46e9SPaul Traina p = ptr++; 7554edb46e9SPaul Traina return (p); 7564edb46e9SPaul Traina } 757