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