117683Spst/* 239294Sfenner * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 317683Spst * The Regents of the University of California. All rights reserved. 417683Spst * 517683Spst * Redistribution and use in source and binary forms, with or without 617683Spst * modification, are permitted provided that: (1) source code distributions 717683Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817683Spst * distributions including binary code include the above copyright notice and 917683Spst * this paragraph in its entirety in the documentation or other materials 1017683Spst * provided with the distribution, and (3) all advertising materials mentioning 1117683Spst * features or use of this software display the following acknowledgement: 1217683Spst * ``This product includes software developed by the University of California, 1317683Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417683Spst * the University nor the names of its contributors may be used to endorse 1517683Spst * or promote products derived from this software without specific prior 1617683Spst * written permission. 1717683Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817683Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917683Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017683Spst * 2117683Spst * Name to id translation routines used by the scanner. 2217683Spst * These functions are not time critical. 2356891Sfenner * 2456891Sfenner * $FreeBSD$ 2517683Spst */ 2617683Spst 2717683Spst#ifndef lint 28127667Sbmsstatic const char rcsid[] _U_ = 29214518Srpaulo "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.83 2008-02-06 10:21:30 guy Exp $ (LBL)"; 3017683Spst#endif 3117683Spst 3275110Sfenner#ifdef HAVE_CONFIG_H 3375110Sfenner#include "config.h" 3475110Sfenner#endif 3575110Sfenner 36214518Srpaulo#ifdef DECNETLIB 37214518Srpaulo#include <sys/types.h> 38214518Srpaulo#include <netdnet/dnetdb.h> 39214518Srpaulo#endif 40214518Srpaulo 41127667Sbms#ifdef WIN32 42127667Sbms#include <pcap-stdinc.h> 43127667Sbms 44127667Sbms#else /* WIN32 */ 45127667Sbms 4617683Spst#include <sys/param.h> 4717683Spst#include <sys/types.h> /* concession to AIX */ 4817683Spst#include <sys/socket.h> 4920287Swollman#include <sys/time.h> 5017683Spst 5117683Spst#include <netinet/in.h> 52127667Sbms#endif /* WIN32 */ 53127667Sbms 54127667Sbms#ifndef WIN32 55127667Sbms#ifdef HAVE_ETHER_HOSTTON 56146771Ssam/* 57146771Ssam * XXX - do we need any of this if <netinet/if_ether.h> doesn't declare 58146771Ssam * ether_hostton()? 59146771Ssam */ 6075110Sfenner#ifdef HAVE_NETINET_IF_ETHER_H 61127667Sbmsstruct mbuf; /* Squelch compiler warnings on some platforms for */ 62127667Sbmsstruct rtentry; /* declarations in <net/if.h> */ 63127667Sbms#include <net/if.h> /* for "struct ifnet" in "struct arpcom" on Solaris */ 6475110Sfenner#include <netinet/if_ether.h> 65127667Sbms#endif /* HAVE_NETINET_IF_ETHER_H */ 66146771Ssam#ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON 67146771Ssam#include <netinet/ether.h> 68146771Ssam#endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */ 69127667Sbms#endif /* HAVE_ETHER_HOSTTON */ 7017683Spst#include <arpa/inet.h> 7156891Sfenner#include <netdb.h> 72127667Sbms#endif /* WIN32 */ 7317683Spst 7417683Spst#include <ctype.h> 7517683Spst#include <errno.h> 7617683Spst#include <stdlib.h> 77147897Ssam#include <string.h> 7817683Spst#include <stdio.h> 7917683Spst 8017683Spst#include "pcap-int.h" 8117683Spst 8217683Spst#include "gencode.h" 83190225Srpaulo#include <pcap/namedb.h> 8417683Spst 8517683Spst#ifdef HAVE_OS_PROTO_H 8617683Spst#include "os-proto.h" 8717683Spst#endif 8817683Spst 8917683Spst#ifndef NTOHL 9017683Spst#define NTOHL(x) (x) = ntohl(x) 9117683Spst#define NTOHS(x) (x) = ntohs(x) 9217683Spst#endif 9317683Spst 9417683Spststatic inline int xdtoi(int); 9517683Spst 9617683Spst/* 9717683Spst * Convert host name to internet address. 9817683Spst * Return 0 upon failure. 9917683Spst */ 10017683Spstbpf_u_int32 ** 10117683Spstpcap_nametoaddr(const char *name) 10217683Spst{ 10317683Spst#ifndef h_addr 10417683Spst static bpf_u_int32 *hlist[2]; 10517683Spst#endif 10617683Spst bpf_u_int32 **p; 10717683Spst struct hostent *hp; 10817683Spst 10917683Spst if ((hp = gethostbyname(name)) != NULL) { 11017683Spst#ifndef h_addr 11117683Spst hlist[0] = (bpf_u_int32 *)hp->h_addr; 11217683Spst NTOHL(hp->h_addr); 11317683Spst return hlist; 11417683Spst#else 11517683Spst for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) 11617683Spst NTOHL(**p); 11717683Spst return (bpf_u_int32 **)hp->h_addr_list; 11817683Spst#endif 11917683Spst } 12017683Spst else 12117683Spst return 0; 12217683Spst} 12375110Sfenner 12475110Sfenner#ifdef INET6 12556891Sfennerstruct addrinfo * 12675110Sfennerpcap_nametoaddrinfo(const char *name) 12756891Sfenner{ 12856891Sfenner struct addrinfo hints, *res; 12956891Sfenner int error; 13017683Spst 13156891Sfenner memset(&hints, 0, sizeof(hints)); 13256891Sfenner hints.ai_family = PF_UNSPEC; 13356891Sfenner hints.ai_socktype = SOCK_STREAM; /*not really*/ 134146771Ssam hints.ai_protocol = IPPROTO_TCP; /*not really*/ 13556891Sfenner error = getaddrinfo(name, NULL, &hints, &res); 13656891Sfenner if (error) 13756891Sfenner return NULL; 13856891Sfenner else 13956891Sfenner return res; 14056891Sfenner} 14156891Sfenner#endif /*INET6*/ 14256891Sfenner 14317683Spst/* 14417683Spst * Convert net name to internet address. 14517683Spst * Return 0 upon failure. 14617683Spst */ 14717683Spstbpf_u_int32 14817683Spstpcap_nametonetaddr(const char *name) 14917683Spst{ 150127667Sbms#ifndef WIN32 15117683Spst struct netent *np; 15217683Spst 15317683Spst if ((np = getnetbyname(name)) != NULL) 15417683Spst return np->n_net; 15517683Spst else 15617683Spst return 0; 157127667Sbms#else 158127667Sbms /* 159127667Sbms * There's no "getnetbyname()" on Windows. 160127667Sbms */ 161127667Sbms return 0; 162127667Sbms#endif 16317683Spst} 16417683Spst 16517683Spst/* 16617683Spst * Convert a port name to its port and protocol numbers. 16717683Spst * We assume only TCP or UDP. 16817683Spst * Return 0 upon failure. 16917683Spst */ 17017683Spstint 17117683Spstpcap_nametoport(const char *name, int *port, int *proto) 17217683Spst{ 17317683Spst struct servent *sp; 174127667Sbms int tcp_port = -1; 175127667Sbms int udp_port = -1; 17617683Spst 177127667Sbms /* 178127667Sbms * We need to check /etc/services for ambiguous entries. 179127667Sbms * If we find the ambiguous entry, and it has the 180127667Sbms * same port number, change the proto to PROTO_UNDEF 181127667Sbms * so both TCP and UDP will be checked. 182127667Sbms */ 183127667Sbms sp = getservbyname(name, "tcp"); 184127667Sbms if (sp != NULL) tcp_port = ntohs(sp->s_port); 185127667Sbms sp = getservbyname(name, "udp"); 186127667Sbms if (sp != NULL) udp_port = ntohs(sp->s_port); 187127667Sbms if (tcp_port >= 0) { 188127667Sbms *port = tcp_port; 189127667Sbms *proto = IPPROTO_TCP; 190127667Sbms if (udp_port >= 0) { 191127667Sbms if (udp_port == tcp_port) 192127667Sbms *proto = PROTO_UNDEF; 19317683Spst#ifdef notdef 194127667Sbms else 19517683Spst /* Can't handle ambiguous names that refer 19617683Spst to different port numbers. */ 19717683Spst warning("ambiguous port %s in /etc/services", 19817683Spst name); 19917683Spst#endif 20017683Spst } 20117683Spst return 1; 20217683Spst } 203127667Sbms if (udp_port >= 0) { 204127667Sbms *port = udp_port; 205127667Sbms *proto = IPPROTO_UDP; 206127667Sbms return 1; 207127667Sbms } 20817683Spst#if defined(ultrix) || defined(__osf__) 20917683Spst /* Special hack in case NFS isn't in /etc/services */ 21017683Spst if (strcmp(name, "nfs") == 0) { 21117683Spst *port = 2049; 21217683Spst *proto = PROTO_UNDEF; 21317683Spst return 1; 21417683Spst } 21517683Spst#endif 21617683Spst return 0; 21717683Spst} 21817683Spst 219147897Ssam/* 220147897Ssam * Convert a string in the form PPP-PPP, where correspond to ports, to 221147897Ssam * a starting and ending port in a port range. 222147897Ssam * Return 0 on failure. 223147897Ssam */ 22417683Spstint 225147897Ssampcap_nametoportrange(const char *name, int *port1, int *port2, int *proto) 226147897Ssam{ 227147897Ssam u_int p1, p2; 228147897Ssam char *off, *cpy; 229147897Ssam int save_proto; 230147897Ssam 231147897Ssam if (sscanf(name, "%d-%d", &p1, &p2) != 2) { 232147897Ssam if ((cpy = strdup(name)) == NULL) 233147897Ssam return 0; 234147897Ssam 235147897Ssam if ((off = strchr(cpy, '-')) == NULL) { 236147897Ssam free(cpy); 237147897Ssam return 0; 238147897Ssam } 239147897Ssam 240147897Ssam *off = '\0'; 241147897Ssam 242147897Ssam if (pcap_nametoport(cpy, port1, proto) == 0) { 243147897Ssam free(cpy); 244147897Ssam return 0; 245147897Ssam } 246147897Ssam save_proto = *proto; 247147897Ssam 248147897Ssam if (pcap_nametoport(off + 1, port2, proto) == 0) { 249147897Ssam free(cpy); 250147897Ssam return 0; 251147897Ssam } 252251129Sdelphij free(cpy); 253147897Ssam 254147897Ssam if (*proto != save_proto) 255147897Ssam *proto = PROTO_UNDEF; 256147897Ssam } else { 257147897Ssam *port1 = p1; 258147897Ssam *port2 = p2; 259147897Ssam *proto = PROTO_UNDEF; 260147897Ssam } 261147897Ssam 262147897Ssam return 1; 263147897Ssam} 264147897Ssam 265147897Ssamint 26617683Spstpcap_nametoproto(const char *str) 26717683Spst{ 26817683Spst struct protoent *p; 26917683Spst 27017683Spst p = getprotobyname(str); 27117683Spst if (p != 0) 27217683Spst return p->p_proto; 27317683Spst else 27417683Spst return PROTO_UNDEF; 27517683Spst} 27617683Spst 27717683Spst#include "ethertype.h" 27817683Spst 27917683Spststruct eproto { 280172680Smlaier const char *s; 28117683Spst u_short p; 28217683Spst}; 28317683Spst 28417683Spst/* Static data base of ether protocol types. */ 28517683Spststruct eproto eproto_db[] = { 28656891Sfenner#if 0 28756891Sfenner /* The FreeBSD elf linker generates a request to copy this array 28856891Sfenner * (including its size) when you link with -lpcap. In order to 28956891Sfenner * not bump the major version number of this libpcap.so, we need 29056891Sfenner * to ensure that the array stays the same size. Since PUP is 29156891Sfenner * likely never seen in real life any more, it's the first to 29256891Sfenner * be sacrificed (in favor of ip6). 29356891Sfenner */ 29417683Spst { "pup", ETHERTYPE_PUP }, 29556891Sfenner#endif 29617683Spst { "xns", ETHERTYPE_NS }, 29717683Spst { "ip", ETHERTYPE_IP }, 29856891Sfenner#ifdef INET6 29956891Sfenner { "ip6", ETHERTYPE_IPV6 }, 30056891Sfenner#endif 30117683Spst { "arp", ETHERTYPE_ARP }, 30217683Spst { "rarp", ETHERTYPE_REVARP }, 30317683Spst { "sprite", ETHERTYPE_SPRITE }, 30417683Spst { "mopdl", ETHERTYPE_MOPDL }, 30517683Spst { "moprc", ETHERTYPE_MOPRC }, 30617683Spst { "decnet", ETHERTYPE_DN }, 30717683Spst { "lat", ETHERTYPE_LAT }, 30817683Spst { "sca", ETHERTYPE_SCA }, 30917683Spst { "lanbridge", ETHERTYPE_LANBRIDGE }, 31017683Spst { "vexp", ETHERTYPE_VEXP }, 31117683Spst { "vprod", ETHERTYPE_VPROD }, 31217683Spst { "atalk", ETHERTYPE_ATALK }, 31317683Spst { "atalkarp", ETHERTYPE_AARP }, 31417683Spst { "loopback", ETHERTYPE_LOOPBACK }, 31517683Spst { "decdts", ETHERTYPE_DECDTS }, 31617683Spst { "decdns", ETHERTYPE_DECDNS }, 31717683Spst { (char *)0, 0 } 31817683Spst}; 31917683Spst 32017683Spstint 32117683Spstpcap_nametoeproto(const char *s) 32217683Spst{ 32317683Spst struct eproto *p = eproto_db; 32417683Spst 32517683Spst while (p->s != 0) { 32617683Spst if (strcmp(p->s, s) == 0) 32717683Spst return p->p; 32817683Spst p += 1; 32917683Spst } 33017683Spst return PROTO_UNDEF; 33117683Spst} 33217683Spst 333146771Ssam#include "llc.h" 334146771Ssam 335146771Ssam/* Static data base of LLC values. */ 336146771Ssamstatic struct eproto llc_db[] = { 337146771Ssam { "iso", LLCSAP_ISONS }, 338146771Ssam { "stp", LLCSAP_8021D }, 339146771Ssam { "ipx", LLCSAP_IPX }, 340146771Ssam { "netbeui", LLCSAP_NETBEUI }, 341146771Ssam { (char *)0, 0 } 342146771Ssam}; 343146771Ssam 344146771Ssamint 345146771Ssampcap_nametollc(const char *s) 346146771Ssam{ 347146771Ssam struct eproto *p = llc_db; 348146771Ssam 349146771Ssam while (p->s != 0) { 350146771Ssam if (strcmp(p->s, s) == 0) 351146771Ssam return p->p; 352146771Ssam p += 1; 353146771Ssam } 354146771Ssam return PROTO_UNDEF; 355146771Ssam} 356146771Ssam 35717683Spst/* Hex digit to integer. */ 35817683Spststatic inline int 35917683Spstxdtoi(c) 36017683Spst register int c; 36117683Spst{ 36217683Spst if (isdigit(c)) 36317683Spst return c - '0'; 36417683Spst else if (islower(c)) 36517683Spst return c - 'a' + 10; 36617683Spst else 36717683Spst return c - 'A' + 10; 36817683Spst} 36917683Spst 37017683Spstint 37117683Spst__pcap_atoin(const char *s, bpf_u_int32 *addr) 37217683Spst{ 37317683Spst u_int n; 37417683Spst int len; 37517683Spst 37617683Spst *addr = 0; 37717683Spst len = 0; 37817683Spst while (1) { 37917683Spst n = 0; 38017683Spst while (*s && *s != '.') 38117683Spst n = n * 10 + *s++ - '0'; 38217683Spst *addr <<= 8; 38317683Spst *addr |= n & 0xff; 38417683Spst len += 8; 38517683Spst if (*s == '\0') 38617683Spst return len; 38717683Spst ++s; 38817683Spst } 38917683Spst /* NOTREACHED */ 39017683Spst} 39117683Spst 39217683Spstint 39317683Spst__pcap_atodn(const char *s, bpf_u_int32 *addr) 39417683Spst{ 39517683Spst#define AREASHIFT 10 39617683Spst#define AREAMASK 0176000 39717683Spst#define NODEMASK 01777 39817683Spst 39917683Spst u_int node, area; 40017683Spst 401172680Smlaier if (sscanf(s, "%d.%d", &area, &node) != 2) 40217683Spst bpf_error("malformed decnet address '%s'", s); 40317683Spst 40417683Spst *addr = (area << AREASHIFT) & AREAMASK; 40517683Spst *addr |= (node & NODEMASK); 40617683Spst 40717683Spst return(32); 40817683Spst} 40917683Spst 41017683Spst/* 411190225Srpaulo * Convert 's', which can have the one of the forms: 412190225Srpaulo * 413190225Srpaulo * "xx:xx:xx:xx:xx:xx" 414190225Srpaulo * "xx.xx.xx.xx.xx.xx" 415190225Srpaulo * "xx-xx-xx-xx-xx-xx" 416190225Srpaulo * "xxxx.xxxx.xxxx" 417190225Srpaulo * "xxxxxxxxxxxx" 418190225Srpaulo * 419190225Srpaulo * (or various mixes of ':', '.', and '-') into a new 42017683Spst * ethernet address. Assumes 's' is well formed. 42117683Spst */ 42217683Spstu_char * 42317683Spstpcap_ether_aton(const char *s) 42417683Spst{ 42517683Spst register u_char *ep, *e; 42617683Spst register u_int d; 42717683Spst 42817683Spst e = ep = (u_char *)malloc(6); 42917683Spst 43017683Spst while (*s) { 431190225Srpaulo if (*s == ':' || *s == '.' || *s == '-') 43217683Spst s += 1; 43317683Spst d = xdtoi(*s++); 43498533Sfenner if (isxdigit((unsigned char)*s)) { 43517683Spst d <<= 4; 43617683Spst d |= xdtoi(*s++); 43717683Spst } 43817683Spst *ep++ = d; 43917683Spst } 44017683Spst 44117683Spst return (e); 44217683Spst} 44317683Spst 44417683Spst#ifndef HAVE_ETHER_HOSTTON 44517683Spst/* Roll our own */ 44617683Spstu_char * 44717683Spstpcap_ether_hostton(const char *name) 44817683Spst{ 44917683Spst register struct pcap_etherent *ep; 45017683Spst register u_char *ap; 45117683Spst static FILE *fp = NULL; 45275110Sfenner static int init = 0; 45317683Spst 45417683Spst if (!init) { 45517683Spst fp = fopen(PCAP_ETHERS_FILE, "r"); 45617683Spst ++init; 45717683Spst if (fp == NULL) 45817683Spst return (NULL); 45917683Spst } else if (fp == NULL) 46017683Spst return (NULL); 46117683Spst else 46217683Spst rewind(fp); 463127667Sbms 46417683Spst while ((ep = pcap_next_etherent(fp)) != NULL) { 46517683Spst if (strcmp(ep->name, name) == 0) { 46617683Spst ap = (u_char *)malloc(6); 46717683Spst if (ap != NULL) { 46817683Spst memcpy(ap, ep->addr, 6); 46917683Spst return (ap); 47017683Spst } 47117683Spst break; 47217683Spst } 47317683Spst } 47417683Spst return (NULL); 47517683Spst} 47617683Spst#else 47717683Spst 478146771Ssam#if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON 479147897Ssam#ifndef HAVE_STRUCT_ETHER_ADDR 480147897Ssamstruct ether_addr { 481147897Ssam unsigned char ether_addr_octet[6]; 482147897Ssam}; 483147897Ssam#endif 484146771Ssamextern int ether_hostton(const char *, struct ether_addr *); 48517683Spst#endif 48617683Spst 48717683Spst/* Use the os supplied routines */ 48817683Spstu_char * 48917683Spstpcap_ether_hostton(const char *name) 49017683Spst{ 49117683Spst register u_char *ap; 49217683Spst u_char a[6]; 49317683Spst 49417683Spst ap = NULL; 495172680Smlaier if (ether_hostton(name, (struct ether_addr *)a) == 0) { 49617683Spst ap = (u_char *)malloc(6); 49717683Spst if (ap != NULL) 49839294Sfenner memcpy((char *)ap, (char *)a, 6); 49917683Spst } 50017683Spst return (ap); 50117683Spst} 50217683Spst#endif 50317683Spst 50417683Spstu_short 50517683Spst__pcap_nametodnaddr(const char *name) 50617683Spst{ 50717683Spst#ifdef DECNETLIB 50817683Spst struct nodeent *getnodebyname(); 50917683Spst struct nodeent *nep; 51017683Spst unsigned short res; 51117683Spst 51217683Spst nep = getnodebyname(name); 51317683Spst if (nep == ((struct nodeent *)0)) 51417683Spst bpf_error("unknown decnet host name '%s'\n", name); 51517683Spst 51617683Spst memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short)); 51717683Spst return(res); 51817683Spst#else 51917683Spst bpf_error("decnet name support not included, '%s' cannot be translated\n", 52017683Spst name); 52198533Sfenner return(0); 52217683Spst#endif 52317683Spst} 524