nametoaddr.c revision 63532
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 63532 2000-07-19 16:03:34Z archie $
25 */
26
27#ifndef lint
28static const char rcsid[] =
29    "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.51 1999/11/25 08:25:35 itojun Exp $ (LBL)";
30#endif
31
32#include <sys/param.h>
33#include <sys/types.h>				/* concession to AIX */
34#include <sys/socket.h>
35#include <sys/time.h>
36
37#if __STDC__
38struct mbuf;
39struct rtentry;
40#endif
41
42#include <net/if.h>
43#include <net/ethernet.h>
44#include <netinet/in.h>
45#include <arpa/inet.h>
46#ifdef INET6
47#include <netdb.h>
48#include <sys/socket.h>
49#endif /*INET6*/
50
51#include <ctype.h>
52#include <errno.h>
53#include <stdlib.h>
54#include <memory.h>
55#include <netdb.h>
56#include <stdio.h>
57
58#include "pcap-int.h"
59
60#include "gencode.h"
61#include <pcap-namedb.h>
62
63#include "gnuc.h"
64#ifdef HAVE_OS_PROTO_H
65#include "os-proto.h"
66#endif
67
68#ifndef NTOHL
69#define NTOHL(x) (x) = ntohl(x)
70#define NTOHS(x) (x) = ntohs(x)
71#endif
72
73static inline int xdtoi(int);
74
75/*
76 *  Convert host name to internet address.
77 *  Return 0 upon failure.
78 */
79#ifndef INET6
80bpf_u_int32 **
81pcap_nametoaddr(const char *name)
82{
83#ifndef h_addr
84	static bpf_u_int32 *hlist[2];
85#endif
86	bpf_u_int32 **p;
87	struct hostent *hp;
88
89	if ((hp = gethostbyname(name)) != NULL) {
90#ifndef h_addr
91		hlist[0] = (bpf_u_int32 *)hp->h_addr;
92		NTOHL(hp->h_addr);
93		return hlist;
94#else
95		for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
96			NTOHL(**p);
97		return (bpf_u_int32 **)hp->h_addr_list;
98#endif
99	}
100	else
101		return 0;
102}
103#else
104struct addrinfo *
105pcap_nametoaddr(const char *name)
106{
107	struct addrinfo hints, *res;
108	int error;
109
110	memset(&hints, 0, sizeof(hints));
111	hints.ai_family = PF_UNSPEC;
112	hints.ai_socktype = SOCK_STREAM;	/*not really*/
113	error = getaddrinfo(name, NULL, &hints, &res);
114	if (error)
115		return NULL;
116	else
117		return res;
118}
119#endif /*INET6*/
120
121/*
122 *  Convert net name to internet address.
123 *  Return 0 upon failure.
124 */
125bpf_u_int32
126pcap_nametonetaddr(const char *name)
127{
128	struct netent *np;
129
130	if ((np = getnetbyname(name)) != NULL)
131		return np->n_net;
132	else
133		return 0;
134}
135
136/*
137 * Convert a port name to its port and protocol numbers.
138 * We assume only TCP or UDP.
139 * Return 0 upon failure.
140 */
141int
142pcap_nametoport(const char *name, int *port, int *proto)
143{
144	struct servent *sp;
145	char *other;
146
147	sp = getservbyname(name, (char *)0);
148	if (sp != NULL) {
149		NTOHS(sp->s_port);
150		*port = sp->s_port;
151		*proto = pcap_nametoproto(sp->s_proto);
152		/*
153		 * We need to check /etc/services for ambiguous entries.
154		 * If we find the ambiguous entry, and it has the
155		 * same port number, change the proto to PROTO_UNDEF
156		 * so both TCP and UDP will be checked.
157		 */
158		if (*proto == IPPROTO_TCP)
159			other = "udp";
160		else
161			other = "tcp";
162
163		sp = getservbyname(name, other);
164		if (sp != 0) {
165			NTOHS(sp->s_port);
166#ifdef notdef
167			if (*port != sp->s_port)
168				/* Can't handle ambiguous names that refer
169				   to different port numbers. */
170				warning("ambiguous port %s in /etc/services",
171					name);
172#endif
173			*proto = PROTO_UNDEF;
174		}
175		return 1;
176	}
177#if defined(ultrix) || defined(__osf__)
178	/* Special hack in case NFS isn't in /etc/services */
179	if (strcmp(name, "nfs") == 0) {
180		*port = 2049;
181		*proto = PROTO_UNDEF;
182		return 1;
183	}
184#endif
185	return 0;
186}
187
188int
189pcap_nametoproto(const char *str)
190{
191	struct protoent *p;
192
193	p = getprotobyname(str);
194	if (p != 0)
195		return p->p_proto;
196	else
197		return PROTO_UNDEF;
198}
199
200#include "ethertype.h"
201
202struct eproto {
203	char *s;
204	u_short p;
205};
206
207/* Static data base of ether protocol types. */
208struct eproto eproto_db[] = {
209#if 0
210	/* The FreeBSD elf linker generates a request to copy this array
211	 * (including its size) when you link with -lpcap.  In order to
212	 * not bump the major version number of this libpcap.so, we need
213	 * to ensure that the array stays the same size.  Since PUP is
214	 * likely never seen in real life any more, it's the first to
215	 * be sacrificed (in favor of ip6).
216	 */
217	{ "pup", ETHERTYPE_PUP },
218#endif
219	{ "xns", ETHERTYPE_NS },
220	{ "ip", ETHERTYPE_IP },
221#ifdef INET6
222	{ "ip6", ETHERTYPE_IPV6 },
223#endif
224	{ "arp", ETHERTYPE_ARP },
225	{ "rarp", ETHERTYPE_REVARP },
226	{ "sprite", ETHERTYPE_SPRITE },
227	{ "mopdl", ETHERTYPE_MOPDL },
228	{ "moprc", ETHERTYPE_MOPRC },
229	{ "decnet", ETHERTYPE_DN },
230	{ "lat", ETHERTYPE_LAT },
231	{ "sca", ETHERTYPE_SCA },
232	{ "lanbridge", ETHERTYPE_LANBRIDGE },
233	{ "vexp", ETHERTYPE_VEXP },
234	{ "vprod", ETHERTYPE_VPROD },
235	{ "atalk", ETHERTYPE_ATALK },
236	{ "atalkarp", ETHERTYPE_AARP },
237	{ "loopback", ETHERTYPE_LOOPBACK },
238	{ "decdts", ETHERTYPE_DECDTS },
239	{ "decdns", ETHERTYPE_DECDNS },
240	{ (char *)0, 0 }
241};
242
243int
244pcap_nametoeproto(const char *s)
245{
246	struct eproto *p = eproto_db;
247
248	while (p->s != 0) {
249		if (strcmp(p->s, s) == 0)
250			return p->p;
251		p += 1;
252	}
253	return PROTO_UNDEF;
254}
255
256/* Hex digit to integer. */
257static inline int
258xdtoi(c)
259	register int c;
260{
261	if (isdigit(c))
262		return c - '0';
263	else if (islower(c))
264		return c - 'a' + 10;
265	else
266		return c - 'A' + 10;
267}
268
269int
270__pcap_atoin(const char *s, bpf_u_int32 *addr)
271{
272	u_int n;
273	int len;
274
275	*addr = 0;
276	len = 0;
277	while (1) {
278		n = 0;
279		while (*s && *s != '.')
280			n = n * 10 + *s++ - '0';
281		*addr <<= 8;
282		*addr |= n & 0xff;
283		len += 8;
284		if (*s == '\0')
285			return len;
286		++s;
287	}
288	/* NOTREACHED */
289}
290
291int
292__pcap_atodn(const char *s, bpf_u_int32 *addr)
293{
294#define AREASHIFT 10
295#define AREAMASK 0176000
296#define NODEMASK 01777
297
298	u_int node, area;
299
300	if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
301		bpf_error("malformed decnet address '%s'", s);
302
303	*addr = (area << AREASHIFT) & AREAMASK;
304	*addr |= (node & NODEMASK);
305
306	return(32);
307}
308
309/*
310 * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
311 * ethernet address.  Assumes 's' is well formed.
312 */
313u_char *
314pcap_ether_aton(const char *s)
315{
316	register u_char *ep, *e;
317	register u_int d;
318
319	e = ep = (u_char *)malloc(6);
320
321	while (*s) {
322		if (*s == ':')
323			s += 1;
324		d = xdtoi(*s++);
325		if (isxdigit(*s)) {
326			d <<= 4;
327			d |= xdtoi(*s++);
328		}
329		*ep++ = d;
330	}
331
332	return (e);
333}
334
335#ifndef HAVE_ETHER_HOSTTON
336/* Roll our own */
337u_char *
338pcap_ether_hostton(const char *name)
339{
340	register struct pcap_etherent *ep;
341	register u_char *ap;
342	static FILE *fp = NULL;
343	static init = 0;
344
345	if (!init) {
346		fp = fopen(PCAP_ETHERS_FILE, "r");
347		++init;
348		if (fp == NULL)
349			return (NULL);
350	} else if (fp == NULL)
351		return (NULL);
352	else
353		rewind(fp);
354
355	while ((ep = pcap_next_etherent(fp)) != NULL) {
356		if (strcmp(ep->name, name) == 0) {
357			ap = (u_char *)malloc(6);
358			if (ap != NULL) {
359				memcpy(ap, ep->addr, 6);
360				return (ap);
361			}
362			break;
363		}
364	}
365	return (NULL);
366}
367#else
368
369#if !defined(sgi) && !defined(__NetBSD__) && !defined(__FreeBSD__)
370extern int ether_hostton(char *, struct ether_addr *);
371#endif
372
373/* Use the os supplied routines */
374u_char *
375pcap_ether_hostton(const char *name)
376{
377	register u_char *ap;
378	u_char a[6];
379
380	ap = NULL;
381	if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) {
382		ap = (u_char *)malloc(6);
383		if (ap != NULL)
384			memcpy((char *)ap, (char *)a, 6);
385	}
386	return (ap);
387}
388#endif
389
390u_short
391__pcap_nametodnaddr(const char *name)
392{
393#ifdef	DECNETLIB
394	struct nodeent *getnodebyname();
395	struct nodeent *nep;
396	unsigned short res;
397
398	nep = getnodebyname(name);
399	if (nep == ((struct nodeent *)0))
400		bpf_error("unknown decnet host name '%s'\n", name);
401
402	memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
403	return(res);
404#else
405	bpf_error("decnet name support not included, '%s' cannot be translated\n",
406		name);
407#endif
408}
409