nametoaddr.c revision 127667
1/*
2 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * Name to id translation routines used by the scanner.
22 * These functions are not time critical.
23 *
24 * $FreeBSD: head/contrib/libpcap/nametoaddr.c 127667 2004-03-31 09:15:09Z bms $
25 */
26
27#ifndef lint
28static const char rcsid[] _U_ =
29    "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.68.2.3 2003/11/19 18:13:48 guy Exp $ (LBL)";
30#endif
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#ifdef WIN32
37#include <pcap-stdinc.h>
38
39#else /* WIN32 */
40
41#include <sys/param.h>
42#include <sys/types.h>				/* concession to AIX */
43#include <sys/socket.h>
44#include <sys/time.h>
45
46#include <netinet/in.h>
47#endif /* WIN32 */
48
49/*
50 * XXX - why was this included even on UNIX?
51 */
52#ifdef __MINGW32__
53#include "IP6_misc.h"
54#endif
55
56#ifndef WIN32
57#ifdef HAVE_ETHER_HOSTTON
58#ifdef HAVE_NETINET_IF_ETHER_H
59struct mbuf;		/* Squelch compiler warnings on some platforms for */
60struct rtentry;		/* declarations in <net/if.h> */
61#include <net/if.h>	/* for "struct ifnet" in "struct arpcom" on Solaris */
62#include <netinet/if_ether.h>
63#endif /* HAVE_NETINET_IF_ETHER_H */
64#endif /* HAVE_ETHER_HOSTTON */
65#include <arpa/inet.h>
66#include <netdb.h>
67#endif /* WIN32 */
68
69#include <ctype.h>
70#include <errno.h>
71#include <stdlib.h>
72#include <memory.h>
73#include <stdio.h>
74
75#include "pcap-int.h"
76
77#include "gencode.h"
78#include <pcap-namedb.h>
79
80#ifdef HAVE_OS_PROTO_H
81#include "os-proto.h"
82#endif
83
84#ifndef NTOHL
85#define NTOHL(x) (x) = ntohl(x)
86#define NTOHS(x) (x) = ntohs(x)
87#endif
88
89static inline int xdtoi(int);
90
91/*
92 *  Convert host name to internet address.
93 *  Return 0 upon failure.
94 */
95bpf_u_int32 **
96pcap_nametoaddr(const char *name)
97{
98#ifndef h_addr
99	static bpf_u_int32 *hlist[2];
100#endif
101	bpf_u_int32 **p;
102	struct hostent *hp;
103
104	if ((hp = gethostbyname(name)) != NULL) {
105#ifndef h_addr
106		hlist[0] = (bpf_u_int32 *)hp->h_addr;
107		NTOHL(hp->h_addr);
108		return hlist;
109#else
110		for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
111			NTOHL(**p);
112		return (bpf_u_int32 **)hp->h_addr_list;
113#endif
114	}
115	else
116		return 0;
117}
118
119#ifdef INET6
120struct addrinfo *
121pcap_nametoaddrinfo(const char *name)
122{
123	struct addrinfo hints, *res;
124	int error;
125
126	memset(&hints, 0, sizeof(hints));
127	hints.ai_family = PF_UNSPEC;
128	hints.ai_socktype = SOCK_STREAM;	/*not really*/
129	error = getaddrinfo(name, NULL, &hints, &res);
130	if (error)
131		return NULL;
132	else
133		return res;
134}
135#endif /*INET6*/
136
137/*
138 *  Convert net name to internet address.
139 *  Return 0 upon failure.
140 */
141bpf_u_int32
142pcap_nametonetaddr(const char *name)
143{
144#ifndef WIN32
145	struct netent *np;
146
147	if ((np = getnetbyname(name)) != NULL)
148		return np->n_net;
149	else
150		return 0;
151#else
152	/*
153	 * There's no "getnetbyname()" on Windows.
154	 */
155	return 0;
156#endif
157}
158
159/*
160 * Convert a port name to its port and protocol numbers.
161 * We assume only TCP or UDP.
162 * Return 0 upon failure.
163 */
164int
165pcap_nametoport(const char *name, int *port, int *proto)
166{
167	struct servent *sp;
168	int tcp_port = -1;
169	int udp_port = -1;
170
171	/*
172	 * We need to check /etc/services for ambiguous entries.
173	 * If we find the ambiguous entry, and it has the
174	 * same port number, change the proto to PROTO_UNDEF
175	 * so both TCP and UDP will be checked.
176	 */
177	sp = getservbyname(name, "tcp");
178	if (sp != NULL) tcp_port = ntohs(sp->s_port);
179	sp = getservbyname(name, "udp");
180	if (sp != NULL) udp_port = ntohs(sp->s_port);
181	if (tcp_port >= 0) {
182		*port = tcp_port;
183		*proto = IPPROTO_TCP;
184		if (udp_port >= 0) {
185			if (udp_port == tcp_port)
186				*proto = PROTO_UNDEF;
187#ifdef notdef
188			else
189				/* Can't handle ambiguous names that refer
190				   to different port numbers. */
191				warning("ambiguous port %s in /etc/services",
192					name);
193#endif
194		}
195		return 1;
196	}
197	if (udp_port >= 0) {
198		*port = udp_port;
199		*proto = IPPROTO_UDP;
200		return 1;
201	}
202#if defined(ultrix) || defined(__osf__)
203	/* Special hack in case NFS isn't in /etc/services */
204	if (strcmp(name, "nfs") == 0) {
205		*port = 2049;
206		*proto = PROTO_UNDEF;
207		return 1;
208	}
209#endif
210	return 0;
211}
212
213int
214pcap_nametoproto(const char *str)
215{
216	struct protoent *p;
217
218	p = getprotobyname(str);
219	if (p != 0)
220		return p->p_proto;
221	else
222		return PROTO_UNDEF;
223}
224
225#include "ethertype.h"
226
227struct eproto {
228	char *s;
229	u_short p;
230};
231
232/* Static data base of ether protocol types. */
233struct eproto eproto_db[] = {
234#if 0
235	/* The FreeBSD elf linker generates a request to copy this array
236	 * (including its size) when you link with -lpcap.  In order to
237	 * not bump the major version number of this libpcap.so, we need
238	 * to ensure that the array stays the same size.  Since PUP is
239	 * likely never seen in real life any more, it's the first to
240	 * be sacrificed (in favor of ip6).
241	 */
242	{ "pup", ETHERTYPE_PUP },
243#endif
244	{ "xns", ETHERTYPE_NS },
245	{ "ip", ETHERTYPE_IP },
246#ifdef INET6
247	{ "ip6", ETHERTYPE_IPV6 },
248#endif
249	{ "arp", ETHERTYPE_ARP },
250	{ "rarp", ETHERTYPE_REVARP },
251	{ "sprite", ETHERTYPE_SPRITE },
252	{ "mopdl", ETHERTYPE_MOPDL },
253	{ "moprc", ETHERTYPE_MOPRC },
254	{ "decnet", ETHERTYPE_DN },
255	{ "lat", ETHERTYPE_LAT },
256	{ "sca", ETHERTYPE_SCA },
257	{ "lanbridge", ETHERTYPE_LANBRIDGE },
258	{ "vexp", ETHERTYPE_VEXP },
259	{ "vprod", ETHERTYPE_VPROD },
260	{ "atalk", ETHERTYPE_ATALK },
261	{ "atalkarp", ETHERTYPE_AARP },
262	{ "loopback", ETHERTYPE_LOOPBACK },
263	{ "decdts", ETHERTYPE_DECDTS },
264	{ "decdns", ETHERTYPE_DECDNS },
265	{ (char *)0, 0 }
266};
267
268int
269pcap_nametoeproto(const char *s)
270{
271	struct eproto *p = eproto_db;
272
273	while (p->s != 0) {
274		if (strcmp(p->s, s) == 0)
275			return p->p;
276		p += 1;
277	}
278	return PROTO_UNDEF;
279}
280
281/* Hex digit to integer. */
282static inline int
283xdtoi(c)
284	register int c;
285{
286	if (isdigit(c))
287		return c - '0';
288	else if (islower(c))
289		return c - 'a' + 10;
290	else
291		return c - 'A' + 10;
292}
293
294int
295__pcap_atoin(const char *s, bpf_u_int32 *addr)
296{
297	u_int n;
298	int len;
299
300	*addr = 0;
301	len = 0;
302	while (1) {
303		n = 0;
304		while (*s && *s != '.')
305			n = n * 10 + *s++ - '0';
306		*addr <<= 8;
307		*addr |= n & 0xff;
308		len += 8;
309		if (*s == '\0')
310			return len;
311		++s;
312	}
313	/* NOTREACHED */
314}
315
316int
317__pcap_atodn(const char *s, bpf_u_int32 *addr)
318{
319#define AREASHIFT 10
320#define AREAMASK 0176000
321#define NODEMASK 01777
322
323	u_int node, area;
324
325	if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
326		bpf_error("malformed decnet address '%s'", s);
327
328	*addr = (area << AREASHIFT) & AREAMASK;
329	*addr |= (node & NODEMASK);
330
331	return(32);
332}
333
334/*
335 * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
336 * ethernet address.  Assumes 's' is well formed.
337 */
338u_char *
339pcap_ether_aton(const char *s)
340{
341	register u_char *ep, *e;
342	register u_int d;
343
344	e = ep = (u_char *)malloc(6);
345
346	while (*s) {
347		if (*s == ':')
348			s += 1;
349		d = xdtoi(*s++);
350		if (isxdigit((unsigned char)*s)) {
351			d <<= 4;
352			d |= xdtoi(*s++);
353		}
354		*ep++ = d;
355	}
356
357	return (e);
358}
359
360#ifndef HAVE_ETHER_HOSTTON
361/* Roll our own */
362u_char *
363pcap_ether_hostton(const char *name)
364{
365	register struct pcap_etherent *ep;
366	register u_char *ap;
367	static FILE *fp = NULL;
368	static int init = 0;
369
370	if (!init) {
371		fp = fopen(PCAP_ETHERS_FILE, "r");
372		++init;
373		if (fp == NULL)
374			return (NULL);
375	} else if (fp == NULL)
376		return (NULL);
377	else
378		rewind(fp);
379
380	while ((ep = pcap_next_etherent(fp)) != NULL) {
381		if (strcmp(ep->name, name) == 0) {
382			ap = (u_char *)malloc(6);
383			if (ap != NULL) {
384				memcpy(ap, ep->addr, 6);
385				return (ap);
386			}
387			break;
388		}
389	}
390	return (NULL);
391}
392#else
393
394/*
395 * XXX - perhaps this should, instead, be declared in "lbl/os-XXX.h" files,
396 * for those OS versions that don't declare it, rather than being declared
397 * here?  That way, for example, we could declare it on FreeBSD 2.x (which
398 * doesn't declare it), but not on FreeBSD 3.x (which declares it like
399 * this) or FreeBSD 4.x (which declares it with its first argument as
400 * "const char *", so no matter how we declare it here, it'll fail to
401 * compile on one of 3.x or 4.x).
402 */
403#if !defined(sgi) && !defined(__NetBSD__) && !defined(__FreeBSD__) && \
404       !defined(_UNICOSMP)
405extern int ether_hostton(char *, struct ether_addr *);
406#endif
407
408/* Use the os supplied routines */
409u_char *
410pcap_ether_hostton(const char *name)
411{
412	register u_char *ap;
413	u_char a[6];
414
415	ap = NULL;
416	if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) {
417		ap = (u_char *)malloc(6);
418		if (ap != NULL)
419			memcpy((char *)ap, (char *)a, 6);
420	}
421	return (ap);
422}
423#endif
424
425u_short
426__pcap_nametodnaddr(const char *name)
427{
428#ifdef	DECNETLIB
429	struct nodeent *getnodebyname();
430	struct nodeent *nep;
431	unsigned short res;
432
433	nep = getnodebyname(name);
434	if (nep == ((struct nodeent *)0))
435		bpf_error("unknown decnet host name '%s'\n", name);
436
437	memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
438	return(res);
439#else
440	bpf_error("decnet name support not included, '%s' cannot be translated\n",
441		name);
442	return(0);
443#endif
444}
445