18cf6c252SPaul Traina /* 28cf6c252SPaul Traina * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 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. 238cf6c252SPaul Traina */ 248cf6c252SPaul Traina 258cf6c252SPaul Traina #ifndef lint 268cf6c252SPaul Traina static char rcsid[] = 278cf6c252SPaul Traina "@(#) $Header: nametoaddr.c,v 1.43 96/07/17 00:11:41 leres Exp $ (LBL)"; 288cf6c252SPaul Traina #endif 298cf6c252SPaul Traina 308cf6c252SPaul Traina #include <sys/param.h> 318cf6c252SPaul Traina #include <sys/types.h> /* concession to AIX */ 328cf6c252SPaul Traina #include <sys/socket.h> 33628d2ac1SGarrett Wollman #include <sys/time.h> 348cf6c252SPaul Traina 358cf6c252SPaul Traina #if __STDC__ 368cf6c252SPaul Traina struct mbuf; 378cf6c252SPaul Traina struct rtentry; 388cf6c252SPaul Traina #endif 398cf6c252SPaul Traina 408cf6c252SPaul Traina #include <net/if.h> 41ee3e7633SGarrett Wollman #include <net/ethernet.h> 428cf6c252SPaul Traina #include <netinet/in.h> 438cf6c252SPaul Traina #include <arpa/inet.h> 448cf6c252SPaul Traina 458cf6c252SPaul Traina #include <ctype.h> 468cf6c252SPaul Traina #include <errno.h> 478cf6c252SPaul Traina #include <stdlib.h> 488cf6c252SPaul Traina #include <memory.h> 498cf6c252SPaul Traina #include <netdb.h> 508cf6c252SPaul Traina #include <stdio.h> 518cf6c252SPaul Traina 528cf6c252SPaul Traina #include "pcap-int.h" 538cf6c252SPaul Traina 548cf6c252SPaul Traina #include "gencode.h" 558cf6c252SPaul Traina #include <pcap-namedb.h> 568cf6c252SPaul Traina 578cf6c252SPaul Traina #include "gnuc.h" 588cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H 598cf6c252SPaul Traina #include "os-proto.h" 608cf6c252SPaul Traina #endif 618cf6c252SPaul Traina 628cf6c252SPaul Traina #ifndef NTOHL 638cf6c252SPaul Traina #define NTOHL(x) (x) = ntohl(x) 648cf6c252SPaul Traina #define NTOHS(x) (x) = ntohs(x) 658cf6c252SPaul Traina #endif 668cf6c252SPaul Traina 678cf6c252SPaul Traina static inline int xdtoi(int); 688cf6c252SPaul Traina 698cf6c252SPaul Traina /* 708cf6c252SPaul Traina * Convert host name to internet address. 718cf6c252SPaul Traina * Return 0 upon failure. 728cf6c252SPaul Traina */ 738cf6c252SPaul Traina bpf_u_int32 ** 748cf6c252SPaul Traina pcap_nametoaddr(const char *name) 758cf6c252SPaul Traina { 768cf6c252SPaul Traina #ifndef h_addr 778cf6c252SPaul Traina static bpf_u_int32 *hlist[2]; 788cf6c252SPaul Traina #endif 798cf6c252SPaul Traina bpf_u_int32 **p; 808cf6c252SPaul Traina struct hostent *hp; 818cf6c252SPaul Traina 828cf6c252SPaul Traina if ((hp = gethostbyname(name)) != NULL) { 838cf6c252SPaul Traina #ifndef h_addr 848cf6c252SPaul Traina hlist[0] = (bpf_u_int32 *)hp->h_addr; 858cf6c252SPaul Traina NTOHL(hp->h_addr); 868cf6c252SPaul Traina return hlist; 878cf6c252SPaul Traina #else 888cf6c252SPaul Traina for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) 898cf6c252SPaul Traina NTOHL(**p); 908cf6c252SPaul Traina return (bpf_u_int32 **)hp->h_addr_list; 918cf6c252SPaul Traina #endif 928cf6c252SPaul Traina } 938cf6c252SPaul Traina else 948cf6c252SPaul Traina return 0; 958cf6c252SPaul Traina } 968cf6c252SPaul Traina 978cf6c252SPaul Traina /* 988cf6c252SPaul Traina * Convert net name to internet address. 998cf6c252SPaul Traina * Return 0 upon failure. 1008cf6c252SPaul Traina */ 1018cf6c252SPaul Traina bpf_u_int32 1028cf6c252SPaul Traina pcap_nametonetaddr(const char *name) 1038cf6c252SPaul Traina { 1048cf6c252SPaul Traina struct netent *np; 1058cf6c252SPaul Traina 1068cf6c252SPaul Traina if ((np = getnetbyname(name)) != NULL) 1078cf6c252SPaul Traina return np->n_net; 1088cf6c252SPaul Traina else 1098cf6c252SPaul Traina return 0; 1108cf6c252SPaul Traina } 1118cf6c252SPaul Traina 1128cf6c252SPaul Traina /* 1138cf6c252SPaul Traina * Convert a port name to its port and protocol numbers. 1148cf6c252SPaul Traina * We assume only TCP or UDP. 1158cf6c252SPaul Traina * Return 0 upon failure. 1168cf6c252SPaul Traina */ 1178cf6c252SPaul Traina int 1188cf6c252SPaul Traina pcap_nametoport(const char *name, int *port, int *proto) 1198cf6c252SPaul Traina { 1208cf6c252SPaul Traina struct servent *sp; 1218cf6c252SPaul Traina char *other; 1228cf6c252SPaul Traina 1238cf6c252SPaul Traina sp = getservbyname(name, (char *)0); 1248cf6c252SPaul Traina if (sp != NULL) { 1258cf6c252SPaul Traina NTOHS(sp->s_port); 1268cf6c252SPaul Traina *port = sp->s_port; 1278cf6c252SPaul Traina *proto = pcap_nametoproto(sp->s_proto); 1288cf6c252SPaul Traina /* 1298cf6c252SPaul Traina * We need to check /etc/services for ambiguous entries. 1308cf6c252SPaul Traina * If we find the ambiguous entry, and it has the 1318cf6c252SPaul Traina * same port number, change the proto to PROTO_UNDEF 1328cf6c252SPaul Traina * so both TCP and UDP will be checked. 1338cf6c252SPaul Traina */ 1348cf6c252SPaul Traina if (*proto == IPPROTO_TCP) 1358cf6c252SPaul Traina other = "udp"; 1368cf6c252SPaul Traina else 1378cf6c252SPaul Traina other = "tcp"; 1388cf6c252SPaul Traina 1398cf6c252SPaul Traina sp = getservbyname(name, other); 1408cf6c252SPaul Traina if (sp != 0) { 1418cf6c252SPaul Traina NTOHS(sp->s_port); 1428cf6c252SPaul Traina #ifdef notdef 1438cf6c252SPaul Traina if (*port != sp->s_port) 1448cf6c252SPaul Traina /* Can't handle ambiguous names that refer 1458cf6c252SPaul Traina to different port numbers. */ 1468cf6c252SPaul Traina warning("ambiguous port %s in /etc/services", 1478cf6c252SPaul Traina name); 1488cf6c252SPaul Traina #endif 1498cf6c252SPaul Traina *proto = PROTO_UNDEF; 1508cf6c252SPaul Traina } 1518cf6c252SPaul Traina return 1; 1528cf6c252SPaul Traina } 1538cf6c252SPaul Traina #if defined(ultrix) || defined(__osf__) 1548cf6c252SPaul Traina /* Special hack in case NFS isn't in /etc/services */ 1558cf6c252SPaul Traina if (strcmp(name, "nfs") == 0) { 1568cf6c252SPaul Traina *port = 2049; 1578cf6c252SPaul Traina *proto = PROTO_UNDEF; 1588cf6c252SPaul Traina return 1; 1598cf6c252SPaul Traina } 1608cf6c252SPaul Traina #endif 1618cf6c252SPaul Traina return 0; 1628cf6c252SPaul Traina } 1638cf6c252SPaul Traina 1648cf6c252SPaul Traina int 1658cf6c252SPaul Traina pcap_nametoproto(const char *str) 1668cf6c252SPaul Traina { 1678cf6c252SPaul Traina struct protoent *p; 1688cf6c252SPaul Traina 1698cf6c252SPaul Traina p = getprotobyname(str); 1708cf6c252SPaul Traina if (p != 0) 1718cf6c252SPaul Traina return p->p_proto; 1728cf6c252SPaul Traina else 1738cf6c252SPaul Traina return PROTO_UNDEF; 1748cf6c252SPaul Traina } 1758cf6c252SPaul Traina 1768cf6c252SPaul Traina #include "ethertype.h" 1778cf6c252SPaul Traina 1788cf6c252SPaul Traina struct eproto { 1798cf6c252SPaul Traina char *s; 1808cf6c252SPaul Traina u_short p; 1818cf6c252SPaul Traina }; 1828cf6c252SPaul Traina 1838cf6c252SPaul Traina /* Static data base of ether protocol types. */ 1848cf6c252SPaul Traina struct eproto eproto_db[] = { 1858cf6c252SPaul Traina { "pup", ETHERTYPE_PUP }, 1868cf6c252SPaul Traina { "xns", ETHERTYPE_NS }, 1878cf6c252SPaul Traina { "ip", ETHERTYPE_IP }, 1888cf6c252SPaul Traina { "arp", ETHERTYPE_ARP }, 1898cf6c252SPaul Traina { "rarp", ETHERTYPE_REVARP }, 1908cf6c252SPaul Traina { "sprite", ETHERTYPE_SPRITE }, 1918cf6c252SPaul Traina { "mopdl", ETHERTYPE_MOPDL }, 1928cf6c252SPaul Traina { "moprc", ETHERTYPE_MOPRC }, 1938cf6c252SPaul Traina { "atalk", ETHERTYPE_ATALK }, 1948cf6c252SPaul Traina { "decnet", ETHERTYPE_DN }, 1958cf6c252SPaul Traina { "lat", ETHERTYPE_LAT }, 1968cf6c252SPaul Traina { "sca", ETHERTYPE_SCA }, 1978cf6c252SPaul Traina { "lanbridge", ETHERTYPE_LANBRIDGE }, 1988cf6c252SPaul Traina { "vexp", ETHERTYPE_VEXP }, 1998cf6c252SPaul Traina { "vprod", ETHERTYPE_VPROD }, 2008cf6c252SPaul Traina { "atalk", ETHERTYPE_ATALK }, 2018cf6c252SPaul Traina { "atalkarp", ETHERTYPE_AARP }, 2028cf6c252SPaul Traina { "loopback", ETHERTYPE_LOOPBACK }, 2038cf6c252SPaul Traina { "decdts", ETHERTYPE_DECDTS }, 2048cf6c252SPaul Traina { "decdns", ETHERTYPE_DECDNS }, 2058cf6c252SPaul Traina { (char *)0, 0 } 2068cf6c252SPaul Traina }; 2078cf6c252SPaul Traina 2088cf6c252SPaul Traina int 2098cf6c252SPaul Traina pcap_nametoeproto(const char *s) 2108cf6c252SPaul Traina { 2118cf6c252SPaul Traina struct eproto *p = eproto_db; 2128cf6c252SPaul Traina 2138cf6c252SPaul Traina while (p->s != 0) { 2148cf6c252SPaul Traina if (strcmp(p->s, s) == 0) 2158cf6c252SPaul Traina return p->p; 2168cf6c252SPaul Traina p += 1; 2178cf6c252SPaul Traina } 2188cf6c252SPaul Traina return PROTO_UNDEF; 2198cf6c252SPaul Traina } 2208cf6c252SPaul Traina 2218cf6c252SPaul Traina /* Hex digit to integer. */ 2228cf6c252SPaul Traina static inline int 2238cf6c252SPaul Traina xdtoi(c) 2248cf6c252SPaul Traina register int c; 2258cf6c252SPaul Traina { 2268cf6c252SPaul Traina if (isdigit(c)) 2278cf6c252SPaul Traina return c - '0'; 2288cf6c252SPaul Traina else if (islower(c)) 2298cf6c252SPaul Traina return c - 'a' + 10; 2308cf6c252SPaul Traina else 2318cf6c252SPaul Traina return c - 'A' + 10; 2328cf6c252SPaul Traina } 2338cf6c252SPaul Traina 2348cf6c252SPaul Traina int 2358cf6c252SPaul Traina __pcap_atoin(const char *s, bpf_u_int32 *addr) 2368cf6c252SPaul Traina { 2378cf6c252SPaul Traina u_int n; 2388cf6c252SPaul Traina int len; 2398cf6c252SPaul Traina 2408cf6c252SPaul Traina *addr = 0; 2418cf6c252SPaul Traina len = 0; 2428cf6c252SPaul Traina while (1) { 2438cf6c252SPaul Traina n = 0; 2448cf6c252SPaul Traina while (*s && *s != '.') 2458cf6c252SPaul Traina n = n * 10 + *s++ - '0'; 2468cf6c252SPaul Traina *addr <<= 8; 2478cf6c252SPaul Traina *addr |= n & 0xff; 2488cf6c252SPaul Traina len += 8; 2498cf6c252SPaul Traina if (*s == '\0') 2508cf6c252SPaul Traina return len; 2518cf6c252SPaul Traina ++s; 2528cf6c252SPaul Traina } 2538cf6c252SPaul Traina /* NOTREACHED */ 2548cf6c252SPaul Traina } 2558cf6c252SPaul Traina 2568cf6c252SPaul Traina int 2578cf6c252SPaul Traina __pcap_atodn(const char *s, bpf_u_int32 *addr) 2588cf6c252SPaul Traina { 2598cf6c252SPaul Traina #define AREASHIFT 10 2608cf6c252SPaul Traina #define AREAMASK 0176000 2618cf6c252SPaul Traina #define NODEMASK 01777 2628cf6c252SPaul Traina 2638cf6c252SPaul Traina u_int node, area; 2648cf6c252SPaul Traina 2658cf6c252SPaul Traina if (sscanf((char *)s, "%d.%d", &area, &node) != 2) 2668cf6c252SPaul Traina bpf_error("malformed decnet address '%s'", s); 2678cf6c252SPaul Traina 2688cf6c252SPaul Traina *addr = (area << AREASHIFT) & AREAMASK; 2698cf6c252SPaul Traina *addr |= (node & NODEMASK); 2708cf6c252SPaul Traina 2718cf6c252SPaul Traina return(32); 2728cf6c252SPaul Traina } 2738cf6c252SPaul Traina 2748cf6c252SPaul Traina /* 2758cf6c252SPaul Traina * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new 2768cf6c252SPaul Traina * ethernet address. Assumes 's' is well formed. 2778cf6c252SPaul Traina */ 2788cf6c252SPaul Traina u_char * 2798cf6c252SPaul Traina pcap_ether_aton(const char *s) 2808cf6c252SPaul Traina { 2818cf6c252SPaul Traina register u_char *ep, *e; 2828cf6c252SPaul Traina register u_int d; 2838cf6c252SPaul Traina 2848cf6c252SPaul Traina e = ep = (u_char *)malloc(6); 2858cf6c252SPaul Traina 2868cf6c252SPaul Traina while (*s) { 2878cf6c252SPaul Traina if (*s == ':') 2888cf6c252SPaul Traina s += 1; 2898cf6c252SPaul Traina d = xdtoi(*s++); 2908cf6c252SPaul Traina if (isxdigit(*s)) { 2918cf6c252SPaul Traina d <<= 4; 2928cf6c252SPaul Traina d |= xdtoi(*s++); 2938cf6c252SPaul Traina } 2948cf6c252SPaul Traina *ep++ = d; 2958cf6c252SPaul Traina } 2968cf6c252SPaul Traina 2978cf6c252SPaul Traina return (e); 2988cf6c252SPaul Traina } 2998cf6c252SPaul Traina 3008cf6c252SPaul Traina #ifndef HAVE_ETHER_HOSTTON 3018cf6c252SPaul Traina /* Roll our own */ 3028cf6c252SPaul Traina u_char * 3038cf6c252SPaul Traina pcap_ether_hostton(const char *name) 3048cf6c252SPaul Traina { 3058cf6c252SPaul Traina register struct pcap_etherent *ep; 3068cf6c252SPaul Traina register u_char *ap; 3078cf6c252SPaul Traina static FILE *fp = NULL; 3088cf6c252SPaul Traina static init = 0; 3098cf6c252SPaul Traina 3108cf6c252SPaul Traina if (!init) { 3118cf6c252SPaul Traina fp = fopen(PCAP_ETHERS_FILE, "r"); 3128cf6c252SPaul Traina ++init; 3138cf6c252SPaul Traina if (fp == NULL) 3148cf6c252SPaul Traina return (NULL); 3158cf6c252SPaul Traina } else if (fp == NULL) 3168cf6c252SPaul Traina return (NULL); 3178cf6c252SPaul Traina else 3188cf6c252SPaul Traina rewind(fp); 3198cf6c252SPaul Traina 3208cf6c252SPaul Traina while ((ep = pcap_next_etherent(fp)) != NULL) { 3218cf6c252SPaul Traina if (strcmp(ep->name, name) == 0) { 3228cf6c252SPaul Traina ap = (u_char *)malloc(6); 3238cf6c252SPaul Traina if (ap != NULL) { 3248cf6c252SPaul Traina memcpy(ap, ep->addr, 6); 3258cf6c252SPaul Traina return (ap); 3268cf6c252SPaul Traina } 3278cf6c252SPaul Traina break; 3288cf6c252SPaul Traina } 3298cf6c252SPaul Traina } 3308cf6c252SPaul Traina return (NULL); 3318cf6c252SPaul Traina } 3328cf6c252SPaul Traina #else 3338cf6c252SPaul Traina 3348cf6c252SPaul Traina #ifndef sgi 3358cf6c252SPaul Traina extern int ether_hostton(char *, struct ether_addr *); 3368cf6c252SPaul Traina #endif 3378cf6c252SPaul Traina 3388cf6c252SPaul Traina /* Use the os supplied routines */ 3398cf6c252SPaul Traina u_char * 3408cf6c252SPaul Traina pcap_ether_hostton(const char *name) 3418cf6c252SPaul Traina { 3428cf6c252SPaul Traina register u_char *ap; 3438cf6c252SPaul Traina u_char a[6]; 3448cf6c252SPaul Traina 3458cf6c252SPaul Traina ap = NULL; 3468cf6c252SPaul Traina if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) { 3478cf6c252SPaul Traina ap = (u_char *)malloc(6); 3488cf6c252SPaul Traina if (ap != NULL) 3498cf6c252SPaul Traina memcpy(ap, a, 6); 3508cf6c252SPaul Traina } 3518cf6c252SPaul Traina return (ap); 3528cf6c252SPaul Traina } 3538cf6c252SPaul Traina #endif 3548cf6c252SPaul Traina 3558cf6c252SPaul Traina u_short 3568cf6c252SPaul Traina __pcap_nametodnaddr(const char *name) 3578cf6c252SPaul Traina { 3588cf6c252SPaul Traina #ifdef DECNETLIB 3598cf6c252SPaul Traina struct nodeent *getnodebyname(); 3608cf6c252SPaul Traina struct nodeent *nep; 3618cf6c252SPaul Traina unsigned short res; 3628cf6c252SPaul Traina 3638cf6c252SPaul Traina nep = getnodebyname(name); 3648cf6c252SPaul Traina if (nep == ((struct nodeent *)0)) 3658cf6c252SPaul Traina bpf_error("unknown decnet host name '%s'\n", name); 3668cf6c252SPaul Traina 3678cf6c252SPaul Traina memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short)); 3688cf6c252SPaul Traina return(res); 3698cf6c252SPaul Traina #else 3708cf6c252SPaul Traina bpf_error("decnet name support not included, '%s' cannot be translated\n", 3718cf6c252SPaul Traina name); 3728cf6c252SPaul Traina #endif 3738cf6c252SPaul Traina } 374