18cf6c252SPaul Traina /* 2dfd1ee14SBill Fenner * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 38cf6c252SPaul Traina * The Regents of the University of California. All rights reserved. 48cf6c252SPaul Traina * 58cf6c252SPaul Traina * Redistribution and use in source and binary forms, with or without 68cf6c252SPaul Traina * modification, are permitted provided that: (1) source code distributions 78cf6c252SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 88cf6c252SPaul Traina * distributions including binary code include the above copyright notice and 98cf6c252SPaul Traina * this paragraph in its entirety in the documentation or other materials 108cf6c252SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 118cf6c252SPaul Traina * features or use of this software display the following acknowledgement: 128cf6c252SPaul Traina * ``This product includes software developed by the University of California, 138cf6c252SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 148cf6c252SPaul Traina * the University nor the names of its contributors may be used to endorse 158cf6c252SPaul Traina * or promote products derived from this software without specific prior 168cf6c252SPaul Traina * written permission. 178cf6c252SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 188cf6c252SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 198cf6c252SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 208cf6c252SPaul Traina * 218cf6c252SPaul Traina * Name to id translation routines used by the scanner. 228cf6c252SPaul Traina * These functions are not time critical. 23fae05455SBill Fenner * 24fae05455SBill Fenner * $FreeBSD$ 258cf6c252SPaul Traina */ 268cf6c252SPaul Traina 278cf6c252SPaul Traina #ifndef lint 284c6f72b0SBill Fenner static const char rcsid[] = 29fae05455SBill Fenner "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.51 1999/11/25 08:25:35 itojun Exp $ (LBL)"; 308cf6c252SPaul Traina #endif 318cf6c252SPaul Traina 328cf6c252SPaul Traina #include <sys/param.h> 338cf6c252SPaul Traina #include <sys/types.h> /* concession to AIX */ 348cf6c252SPaul Traina #include <sys/socket.h> 35628d2ac1SGarrett Wollman #include <sys/time.h> 368cf6c252SPaul Traina 378cf6c252SPaul Traina #if __STDC__ 388cf6c252SPaul Traina struct mbuf; 398cf6c252SPaul Traina struct rtentry; 408cf6c252SPaul Traina #endif 418cf6c252SPaul Traina 428cf6c252SPaul Traina #include <net/if.h> 43ee3e7633SGarrett Wollman #include <net/ethernet.h> 448cf6c252SPaul Traina #include <netinet/in.h> 458cf6c252SPaul Traina #include <arpa/inet.h> 46fae05455SBill Fenner #ifdef INET6 47fae05455SBill Fenner #include <netdb.h> 48fae05455SBill Fenner #include <sys/socket.h> 49fae05455SBill Fenner #endif /*INET6*/ 508cf6c252SPaul Traina 518cf6c252SPaul Traina #include <ctype.h> 528cf6c252SPaul Traina #include <errno.h> 538cf6c252SPaul Traina #include <stdlib.h> 548cf6c252SPaul Traina #include <memory.h> 558cf6c252SPaul Traina #include <netdb.h> 568cf6c252SPaul Traina #include <stdio.h> 578cf6c252SPaul Traina 588cf6c252SPaul Traina #include "pcap-int.h" 598cf6c252SPaul Traina 608cf6c252SPaul Traina #include "gencode.h" 618cf6c252SPaul Traina #include <pcap-namedb.h> 628cf6c252SPaul Traina 638cf6c252SPaul Traina #include "gnuc.h" 648cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H 658cf6c252SPaul Traina #include "os-proto.h" 668cf6c252SPaul Traina #endif 678cf6c252SPaul Traina 688cf6c252SPaul Traina #ifndef NTOHL 698cf6c252SPaul Traina #define NTOHL(x) (x) = ntohl(x) 708cf6c252SPaul Traina #define NTOHS(x) (x) = ntohs(x) 718cf6c252SPaul Traina #endif 728cf6c252SPaul Traina 738cf6c252SPaul Traina static inline int xdtoi(int); 748cf6c252SPaul Traina 758cf6c252SPaul Traina /* 768cf6c252SPaul Traina * Convert host name to internet address. 778cf6c252SPaul Traina * Return 0 upon failure. 788cf6c252SPaul Traina */ 79fae05455SBill Fenner #ifndef INET6 808cf6c252SPaul Traina bpf_u_int32 ** 818cf6c252SPaul Traina pcap_nametoaddr(const char *name) 828cf6c252SPaul Traina { 838cf6c252SPaul Traina #ifndef h_addr 848cf6c252SPaul Traina static bpf_u_int32 *hlist[2]; 858cf6c252SPaul Traina #endif 868cf6c252SPaul Traina bpf_u_int32 **p; 878cf6c252SPaul Traina struct hostent *hp; 888cf6c252SPaul Traina 898cf6c252SPaul Traina if ((hp = gethostbyname(name)) != NULL) { 908cf6c252SPaul Traina #ifndef h_addr 918cf6c252SPaul Traina hlist[0] = (bpf_u_int32 *)hp->h_addr; 928cf6c252SPaul Traina NTOHL(hp->h_addr); 938cf6c252SPaul Traina return hlist; 948cf6c252SPaul Traina #else 958cf6c252SPaul Traina for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) 968cf6c252SPaul Traina NTOHL(**p); 978cf6c252SPaul Traina return (bpf_u_int32 **)hp->h_addr_list; 988cf6c252SPaul Traina #endif 998cf6c252SPaul Traina } 1008cf6c252SPaul Traina else 1018cf6c252SPaul Traina return 0; 1028cf6c252SPaul Traina } 103fae05455SBill Fenner #else 104fae05455SBill Fenner struct addrinfo * 105fae05455SBill Fenner pcap_nametoaddr(const char *name) 106fae05455SBill Fenner { 107fae05455SBill Fenner struct addrinfo hints, *res; 108fae05455SBill Fenner int error; 109fae05455SBill Fenner 110fae05455SBill Fenner memset(&hints, 0, sizeof(hints)); 111fae05455SBill Fenner hints.ai_family = PF_UNSPEC; 112fae05455SBill Fenner hints.ai_socktype = SOCK_STREAM; /*not really*/ 113fae05455SBill Fenner error = getaddrinfo(name, NULL, &hints, &res); 114fae05455SBill Fenner if (error) 115fae05455SBill Fenner return NULL; 116fae05455SBill Fenner else 117fae05455SBill Fenner return res; 118fae05455SBill Fenner } 119fae05455SBill Fenner #endif /*INET6*/ 1208cf6c252SPaul Traina 1218cf6c252SPaul Traina /* 1228cf6c252SPaul Traina * Convert net name to internet address. 1238cf6c252SPaul Traina * Return 0 upon failure. 1248cf6c252SPaul Traina */ 1258cf6c252SPaul Traina bpf_u_int32 1268cf6c252SPaul Traina pcap_nametonetaddr(const char *name) 1278cf6c252SPaul Traina { 1288cf6c252SPaul Traina struct netent *np; 1298cf6c252SPaul Traina 1308cf6c252SPaul Traina if ((np = getnetbyname(name)) != NULL) 1318cf6c252SPaul Traina return np->n_net; 1328cf6c252SPaul Traina else 1338cf6c252SPaul Traina return 0; 1348cf6c252SPaul Traina } 1358cf6c252SPaul Traina 1368cf6c252SPaul Traina /* 1378cf6c252SPaul Traina * Convert a port name to its port and protocol numbers. 1388cf6c252SPaul Traina * We assume only TCP or UDP. 1398cf6c252SPaul Traina * Return 0 upon failure. 1408cf6c252SPaul Traina */ 1418cf6c252SPaul Traina int 1428cf6c252SPaul Traina pcap_nametoport(const char *name, int *port, int *proto) 1438cf6c252SPaul Traina { 1448cf6c252SPaul Traina struct servent *sp; 1458cf6c252SPaul Traina char *other; 1468cf6c252SPaul Traina 1478cf6c252SPaul Traina sp = getservbyname(name, (char *)0); 1488cf6c252SPaul Traina if (sp != NULL) { 1498cf6c252SPaul Traina NTOHS(sp->s_port); 1508cf6c252SPaul Traina *port = sp->s_port; 1518cf6c252SPaul Traina *proto = pcap_nametoproto(sp->s_proto); 1528cf6c252SPaul Traina /* 1538cf6c252SPaul Traina * We need to check /etc/services for ambiguous entries. 1548cf6c252SPaul Traina * If we find the ambiguous entry, and it has the 1558cf6c252SPaul Traina * same port number, change the proto to PROTO_UNDEF 1568cf6c252SPaul Traina * so both TCP and UDP will be checked. 1578cf6c252SPaul Traina */ 1588cf6c252SPaul Traina if (*proto == IPPROTO_TCP) 1598cf6c252SPaul Traina other = "udp"; 1608cf6c252SPaul Traina else 1618cf6c252SPaul Traina other = "tcp"; 1628cf6c252SPaul Traina 1638cf6c252SPaul Traina sp = getservbyname(name, other); 1648cf6c252SPaul Traina if (sp != 0) { 1658cf6c252SPaul Traina NTOHS(sp->s_port); 1668cf6c252SPaul Traina #ifdef notdef 1678cf6c252SPaul Traina if (*port != sp->s_port) 1688cf6c252SPaul Traina /* Can't handle ambiguous names that refer 1698cf6c252SPaul Traina to different port numbers. */ 1708cf6c252SPaul Traina warning("ambiguous port %s in /etc/services", 1718cf6c252SPaul Traina name); 1728cf6c252SPaul Traina #endif 1738cf6c252SPaul Traina *proto = PROTO_UNDEF; 1748cf6c252SPaul Traina } 1758cf6c252SPaul Traina return 1; 1768cf6c252SPaul Traina } 1778cf6c252SPaul Traina #if defined(ultrix) || defined(__osf__) 1788cf6c252SPaul Traina /* Special hack in case NFS isn't in /etc/services */ 1798cf6c252SPaul Traina if (strcmp(name, "nfs") == 0) { 1808cf6c252SPaul Traina *port = 2049; 1818cf6c252SPaul Traina *proto = PROTO_UNDEF; 1828cf6c252SPaul Traina return 1; 1838cf6c252SPaul Traina } 1848cf6c252SPaul Traina #endif 1858cf6c252SPaul Traina return 0; 1868cf6c252SPaul Traina } 1878cf6c252SPaul Traina 1888cf6c252SPaul Traina int 1898cf6c252SPaul Traina pcap_nametoproto(const char *str) 1908cf6c252SPaul Traina { 1918cf6c252SPaul Traina struct protoent *p; 1928cf6c252SPaul Traina 1938cf6c252SPaul Traina p = getprotobyname(str); 1948cf6c252SPaul Traina if (p != 0) 1958cf6c252SPaul Traina return p->p_proto; 1968cf6c252SPaul Traina else 1978cf6c252SPaul Traina return PROTO_UNDEF; 1988cf6c252SPaul Traina } 1998cf6c252SPaul Traina 2008cf6c252SPaul Traina #include "ethertype.h" 2018cf6c252SPaul Traina 2028cf6c252SPaul Traina struct eproto { 2038cf6c252SPaul Traina char *s; 2048cf6c252SPaul Traina u_short p; 2058cf6c252SPaul Traina }; 2068cf6c252SPaul Traina 2078cf6c252SPaul Traina /* Static data base of ether protocol types. */ 2088cf6c252SPaul Traina struct eproto eproto_db[] = { 209fae05455SBill Fenner #if 0 210fae05455SBill Fenner /* The FreeBSD elf linker generates a request to copy this array 211fae05455SBill Fenner * (including its size) when you link with -lpcap. In order to 212fae05455SBill Fenner * not bump the major version number of this libpcap.so, we need 213fae05455SBill Fenner * to ensure that the array stays the same size. Since PUP is 214fae05455SBill Fenner * likely never seen in real life any more, it's the first to 215fae05455SBill Fenner * be sacrificed (in favor of ip6). 216fae05455SBill Fenner */ 2178cf6c252SPaul Traina { "pup", ETHERTYPE_PUP }, 218fae05455SBill Fenner #endif 2198cf6c252SPaul Traina { "xns", ETHERTYPE_NS }, 2208cf6c252SPaul Traina { "ip", ETHERTYPE_IP }, 221fae05455SBill Fenner #ifdef INET6 222fae05455SBill Fenner { "ip6", ETHERTYPE_IPV6 }, 223fae05455SBill Fenner #endif 2248cf6c252SPaul Traina { "arp", ETHERTYPE_ARP }, 2258cf6c252SPaul Traina { "rarp", ETHERTYPE_REVARP }, 2268cf6c252SPaul Traina { "sprite", ETHERTYPE_SPRITE }, 2278cf6c252SPaul Traina { "mopdl", ETHERTYPE_MOPDL }, 2288cf6c252SPaul Traina { "moprc", ETHERTYPE_MOPRC }, 2298cf6c252SPaul Traina { "decnet", ETHERTYPE_DN }, 2308cf6c252SPaul Traina { "lat", ETHERTYPE_LAT }, 2318cf6c252SPaul Traina { "sca", ETHERTYPE_SCA }, 2328cf6c252SPaul Traina { "lanbridge", ETHERTYPE_LANBRIDGE }, 2338cf6c252SPaul Traina { "vexp", ETHERTYPE_VEXP }, 2348cf6c252SPaul Traina { "vprod", ETHERTYPE_VPROD }, 2358cf6c252SPaul Traina { "atalk", ETHERTYPE_ATALK }, 2368cf6c252SPaul Traina { "atalkarp", ETHERTYPE_AARP }, 2378cf6c252SPaul Traina { "loopback", ETHERTYPE_LOOPBACK }, 2388cf6c252SPaul Traina { "decdts", ETHERTYPE_DECDTS }, 2398cf6c252SPaul Traina { "decdns", ETHERTYPE_DECDNS }, 2408cf6c252SPaul Traina { (char *)0, 0 } 2418cf6c252SPaul Traina }; 2428cf6c252SPaul Traina 2438cf6c252SPaul Traina int 2448cf6c252SPaul Traina pcap_nametoeproto(const char *s) 2458cf6c252SPaul Traina { 2468cf6c252SPaul Traina struct eproto *p = eproto_db; 2478cf6c252SPaul Traina 2488cf6c252SPaul Traina while (p->s != 0) { 2498cf6c252SPaul Traina if (strcmp(p->s, s) == 0) 2508cf6c252SPaul Traina return p->p; 2518cf6c252SPaul Traina p += 1; 2528cf6c252SPaul Traina } 2538cf6c252SPaul Traina return PROTO_UNDEF; 2548cf6c252SPaul Traina } 2558cf6c252SPaul Traina 2568cf6c252SPaul Traina /* Hex digit to integer. */ 2578cf6c252SPaul Traina static inline int 2588cf6c252SPaul Traina xdtoi(c) 2598cf6c252SPaul Traina register int c; 2608cf6c252SPaul Traina { 2618cf6c252SPaul Traina if (isdigit(c)) 2628cf6c252SPaul Traina return c - '0'; 2638cf6c252SPaul Traina else if (islower(c)) 2648cf6c252SPaul Traina return c - 'a' + 10; 2658cf6c252SPaul Traina else 2668cf6c252SPaul Traina return c - 'A' + 10; 2678cf6c252SPaul Traina } 2688cf6c252SPaul Traina 2698cf6c252SPaul Traina int 2708cf6c252SPaul Traina __pcap_atoin(const char *s, bpf_u_int32 *addr) 2718cf6c252SPaul Traina { 2728cf6c252SPaul Traina u_int n; 2738cf6c252SPaul Traina int len; 2748cf6c252SPaul Traina 2758cf6c252SPaul Traina *addr = 0; 2768cf6c252SPaul Traina len = 0; 2778cf6c252SPaul Traina while (1) { 2788cf6c252SPaul Traina n = 0; 2798cf6c252SPaul Traina while (*s && *s != '.') 2808cf6c252SPaul Traina n = n * 10 + *s++ - '0'; 2818cf6c252SPaul Traina *addr <<= 8; 2828cf6c252SPaul Traina *addr |= n & 0xff; 2838cf6c252SPaul Traina len += 8; 2848cf6c252SPaul Traina if (*s == '\0') 2858cf6c252SPaul Traina return len; 2868cf6c252SPaul Traina ++s; 2878cf6c252SPaul Traina } 2888cf6c252SPaul Traina /* NOTREACHED */ 2898cf6c252SPaul Traina } 2908cf6c252SPaul Traina 2918cf6c252SPaul Traina int 2928cf6c252SPaul Traina __pcap_atodn(const char *s, bpf_u_int32 *addr) 2938cf6c252SPaul Traina { 2948cf6c252SPaul Traina #define AREASHIFT 10 2958cf6c252SPaul Traina #define AREAMASK 0176000 2968cf6c252SPaul Traina #define NODEMASK 01777 2978cf6c252SPaul Traina 2988cf6c252SPaul Traina u_int node, area; 2998cf6c252SPaul Traina 3008cf6c252SPaul Traina if (sscanf((char *)s, "%d.%d", &area, &node) != 2) 3018cf6c252SPaul Traina bpf_error("malformed decnet address '%s'", s); 3028cf6c252SPaul Traina 3038cf6c252SPaul Traina *addr = (area << AREASHIFT) & AREAMASK; 3048cf6c252SPaul Traina *addr |= (node & NODEMASK); 3058cf6c252SPaul Traina 3068cf6c252SPaul Traina return(32); 3078cf6c252SPaul Traina } 3088cf6c252SPaul Traina 3098cf6c252SPaul Traina /* 3108cf6c252SPaul Traina * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new 3118cf6c252SPaul Traina * ethernet address. Assumes 's' is well formed. 3128cf6c252SPaul Traina */ 3138cf6c252SPaul Traina u_char * 3148cf6c252SPaul Traina pcap_ether_aton(const char *s) 3158cf6c252SPaul Traina { 3168cf6c252SPaul Traina register u_char *ep, *e; 3178cf6c252SPaul Traina register u_int d; 3188cf6c252SPaul Traina 3198cf6c252SPaul Traina e = ep = (u_char *)malloc(6); 3208cf6c252SPaul Traina 3218cf6c252SPaul Traina while (*s) { 3228cf6c252SPaul Traina if (*s == ':') 3238cf6c252SPaul Traina s += 1; 3248cf6c252SPaul Traina d = xdtoi(*s++); 3258cf6c252SPaul Traina if (isxdigit(*s)) { 3268cf6c252SPaul Traina d <<= 4; 3278cf6c252SPaul Traina d |= xdtoi(*s++); 3288cf6c252SPaul Traina } 3298cf6c252SPaul Traina *ep++ = d; 3308cf6c252SPaul Traina } 3318cf6c252SPaul Traina 3328cf6c252SPaul Traina return (e); 3338cf6c252SPaul Traina } 3348cf6c252SPaul Traina 3358cf6c252SPaul Traina #ifndef HAVE_ETHER_HOSTTON 3368cf6c252SPaul Traina /* Roll our own */ 3378cf6c252SPaul Traina u_char * 3388cf6c252SPaul Traina pcap_ether_hostton(const char *name) 3398cf6c252SPaul Traina { 3408cf6c252SPaul Traina register struct pcap_etherent *ep; 3418cf6c252SPaul Traina register u_char *ap; 3428cf6c252SPaul Traina static FILE *fp = NULL; 3438cf6c252SPaul Traina static init = 0; 3448cf6c252SPaul Traina 3458cf6c252SPaul Traina if (!init) { 3468cf6c252SPaul Traina fp = fopen(PCAP_ETHERS_FILE, "r"); 3478cf6c252SPaul Traina ++init; 3488cf6c252SPaul Traina if (fp == NULL) 3498cf6c252SPaul Traina return (NULL); 3508cf6c252SPaul Traina } else if (fp == NULL) 3518cf6c252SPaul Traina return (NULL); 3528cf6c252SPaul Traina else 3538cf6c252SPaul Traina rewind(fp); 3548cf6c252SPaul Traina 3558cf6c252SPaul Traina while ((ep = pcap_next_etherent(fp)) != NULL) { 3568cf6c252SPaul Traina if (strcmp(ep->name, name) == 0) { 3578cf6c252SPaul Traina ap = (u_char *)malloc(6); 3588cf6c252SPaul Traina if (ap != NULL) { 3598cf6c252SPaul Traina memcpy(ap, ep->addr, 6); 3608cf6c252SPaul Traina return (ap); 3618cf6c252SPaul Traina } 3628cf6c252SPaul Traina break; 3638cf6c252SPaul Traina } 3648cf6c252SPaul Traina } 3658cf6c252SPaul Traina return (NULL); 3668cf6c252SPaul Traina } 3678cf6c252SPaul Traina #else 3688cf6c252SPaul Traina 369fae05455SBill Fenner #if !defined(sgi) && !defined(__NetBSD__) 3708cf6c252SPaul Traina extern int ether_hostton(char *, struct ether_addr *); 3718cf6c252SPaul Traina #endif 3728cf6c252SPaul Traina 3738cf6c252SPaul Traina /* Use the os supplied routines */ 3748cf6c252SPaul Traina u_char * 3758cf6c252SPaul Traina pcap_ether_hostton(const char *name) 3768cf6c252SPaul Traina { 3778cf6c252SPaul Traina register u_char *ap; 3788cf6c252SPaul Traina u_char a[6]; 3798cf6c252SPaul Traina 3808cf6c252SPaul Traina ap = NULL; 3818cf6c252SPaul Traina if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) { 3828cf6c252SPaul Traina ap = (u_char *)malloc(6); 3838cf6c252SPaul Traina if (ap != NULL) 384dfd1ee14SBill Fenner memcpy((char *)ap, (char *)a, 6); 3858cf6c252SPaul Traina } 3868cf6c252SPaul Traina return (ap); 3878cf6c252SPaul Traina } 3888cf6c252SPaul Traina #endif 3898cf6c252SPaul Traina 3908cf6c252SPaul Traina u_short 3918cf6c252SPaul Traina __pcap_nametodnaddr(const char *name) 3928cf6c252SPaul Traina { 3938cf6c252SPaul Traina #ifdef DECNETLIB 3948cf6c252SPaul Traina struct nodeent *getnodebyname(); 3958cf6c252SPaul Traina struct nodeent *nep; 3968cf6c252SPaul Traina unsigned short res; 3978cf6c252SPaul Traina 3988cf6c252SPaul Traina nep = getnodebyname(name); 3998cf6c252SPaul Traina if (nep == ((struct nodeent *)0)) 4008cf6c252SPaul Traina bpf_error("unknown decnet host name '%s'\n", name); 4018cf6c252SPaul Traina 4028cf6c252SPaul Traina memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short)); 4038cf6c252SPaul Traina return(res); 4048cf6c252SPaul Traina #else 4058cf6c252SPaul Traina bpf_error("decnet name support not included, '%s' cannot be translated\n", 4068cf6c252SPaul Traina name); 4078cf6c252SPaul Traina #endif 4088cf6c252SPaul Traina } 409