nametoaddr.c revision 75110
198937Sdes/*
298937Sdes * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
3126274Sdes *	The Regents of the University of California.  All rights reserved.
498937Sdes *
598937Sdes * Redistribution and use in source and binary forms, with or without
6149749Sdes * modification, are permitted provided that: (1) source code distributions
798937Sdes * retain the above copyright notice and this paragraph in its entirety, (2)
898937Sdes * distributions including binary code include the above copyright notice and
9124208Sdes * this paragraph in its entirety in the documentation or other materials
1098937Sdes * provided with the distribution, and (3) all advertising materials mentioning
1198937Sdes * features or use of this software display the following acknowledgement:
1298937Sdes * ``This product includes software developed by the University of California,
1398937Sdes * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1498937Sdes * the University nor the names of its contributors may be used to endorse
1598937Sdes * or promote products derived from this software without specific prior
1698937Sdes * written permission.
1798937Sdes * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1898937Sdes * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1998937Sdes * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2098937Sdes *
2198937Sdes * Name to id translation routines used by the scanner.
2298937Sdes * These functions are not time critical.
2398937Sdes *
2498937Sdes * $FreeBSD: head/contrib/libpcap/nametoaddr.c 75110 2001-04-03 04:32:48Z fenner $
2598937Sdes */
2698937Sdes
27124208Sdes#ifndef lint
28162852Sdesstatic const char rcsid[] =
2998937Sdes    "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.57.2.1 2001/01/17 18:21:56 guy Exp $ (LBL)";
3098937Sdes#endif
3198937Sdes
3298937Sdes#ifdef HAVE_CONFIG_H
3398937Sdes#include "config.h"
3498937Sdes#endif
3598937Sdes
36137015Sdes#include <sys/param.h>
37149749Sdes#include <sys/types.h>				/* concession to AIX */
3898937Sdes#include <sys/socket.h>
3998937Sdes#include <sys/time.h>
4098937Sdes
4198937Sdesstruct mbuf;
4298937Sdesstruct rtentry;
4398937Sdes#include <net/if.h>
4498937Sdes#include <netinet/in.h>
4598937Sdes#ifdef HAVE_NETINET_IF_ETHER_H
4698937Sdes#include <netinet/if_ether.h>
4798937Sdes#endif
4898937Sdes#include <arpa/inet.h>
4998937Sdes#ifdef INET6
50137015Sdes#include <netdb.h>
5198937Sdes#include <sys/socket.h>
5298937Sdes#endif /*INET6*/
5398937Sdes
5498937Sdes#include <ctype.h>
5598937Sdes#include <errno.h>
56124208Sdes#include <stdlib.h>
5798937Sdes#include <memory.h>
5898937Sdes#include <netdb.h>
5998937Sdes#include <stdio.h>
6098937Sdes
6198937Sdes#include "pcap-int.h"
6298937Sdes
6398937Sdes#include "gencode.h"
6498937Sdes#include <pcap-namedb.h>
6598937Sdes
6698937Sdes#ifdef HAVE_OS_PROTO_H
6798937Sdes#include "os-proto.h"
68137015Sdes#endif
6998937Sdes
7098937Sdes#ifndef NTOHL
7198937Sdes#define NTOHL(x) (x) = ntohl(x)
7298937Sdes#define NTOHS(x) (x) = ntohs(x)
7398937Sdes#endif
7498937Sdes
7598937Sdesstatic inline int xdtoi(int);
7698937Sdes
7798937Sdes/*
78124208Sdes *  Convert host name to internet address.
7998937Sdes *  Return 0 upon failure.
8098937Sdes */
8198937Sdesbpf_u_int32 **
8298937Sdespcap_nametoaddr(const char *name)
8398937Sdes{
84137015Sdes#ifndef h_addr
85124208Sdes	static bpf_u_int32 *hlist[2];
8698937Sdes#endif
8798937Sdes	bpf_u_int32 **p;
88106121Sdes	struct hostent *hp;
8998937Sdes
9098937Sdes	if ((hp = gethostbyname(name)) != NULL) {
9198937Sdes#ifndef h_addr
9298937Sdes		hlist[0] = (bpf_u_int32 *)hp->h_addr;
9398937Sdes		NTOHL(hp->h_addr);
9498937Sdes		return hlist;
9598937Sdes#else
9698937Sdes		for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
97126274Sdes			NTOHL(**p);
9898937Sdes		return (bpf_u_int32 **)hp->h_addr_list;
9998937Sdes#endif
10098937Sdes	}
10198937Sdes	else
10298937Sdes		return 0;
10398937Sdes}
104162852Sdes
10598937Sdes#ifdef INET6
106struct addrinfo *
107pcap_nametoaddrinfo(const char *name)
108{
109	struct addrinfo hints, *res;
110	int error;
111
112	memset(&hints, 0, sizeof(hints));
113	hints.ai_family = PF_UNSPEC;
114	hints.ai_socktype = SOCK_STREAM;	/*not really*/
115	error = getaddrinfo(name, NULL, &hints, &res);
116	if (error)
117		return NULL;
118	else
119		return res;
120}
121#endif /*INET6*/
122
123/*
124 *  Convert net name to internet address.
125 *  Return 0 upon failure.
126 */
127bpf_u_int32
128pcap_nametonetaddr(const char *name)
129{
130	struct netent *np;
131
132	if ((np = getnetbyname(name)) != NULL)
133		return np->n_net;
134	else
135		return 0;
136}
137
138/*
139 * Convert a port name to its port and protocol numbers.
140 * We assume only TCP or UDP.
141 * Return 0 upon failure.
142 */
143int
144pcap_nametoport(const char *name, int *port, int *proto)
145{
146	struct servent *sp;
147	char *other;
148
149	sp = getservbyname(name, (char *)0);
150	if (sp != NULL) {
151		NTOHS(sp->s_port);
152		*port = sp->s_port;
153		*proto = pcap_nametoproto(sp->s_proto);
154		/*
155		 * We need to check /etc/services for ambiguous entries.
156		 * If we find the ambiguous entry, and it has the
157		 * same port number, change the proto to PROTO_UNDEF
158		 * so both TCP and UDP will be checked.
159		 */
160		if (*proto == IPPROTO_TCP)
161			other = "udp";
162		else
163			other = "tcp";
164
165		sp = getservbyname(name, other);
166		if (sp != 0) {
167			NTOHS(sp->s_port);
168#ifdef notdef
169			if (*port != sp->s_port)
170				/* Can't handle ambiguous names that refer
171				   to different port numbers. */
172				warning("ambiguous port %s in /etc/services",
173					name);
174#endif
175			*proto = PROTO_UNDEF;
176		}
177		return 1;
178	}
179#if defined(ultrix) || defined(__osf__)
180	/* Special hack in case NFS isn't in /etc/services */
181	if (strcmp(name, "nfs") == 0) {
182		*port = 2049;
183		*proto = PROTO_UNDEF;
184		return 1;
185	}
186#endif
187	return 0;
188}
189
190int
191pcap_nametoproto(const char *str)
192{
193	struct protoent *p;
194
195	p = getprotobyname(str);
196	if (p != 0)
197		return p->p_proto;
198	else
199		return PROTO_UNDEF;
200}
201
202#include "ethertype.h"
203
204struct eproto {
205	char *s;
206	u_short p;
207};
208
209/* Static data base of ether protocol types. */
210struct eproto eproto_db[] = {
211#if 0
212	/* The FreeBSD elf linker generates a request to copy this array
213	 * (including its size) when you link with -lpcap.  In order to
214	 * not bump the major version number of this libpcap.so, we need
215	 * to ensure that the array stays the same size.  Since PUP is
216	 * likely never seen in real life any more, it's the first to
217	 * be sacrificed (in favor of ip6).
218	 */
219	{ "pup", ETHERTYPE_PUP },
220#endif
221	{ "xns", ETHERTYPE_NS },
222	{ "ip", ETHERTYPE_IP },
223#ifdef INET6
224	{ "ip6", ETHERTYPE_IPV6 },
225#endif
226	{ "arp", ETHERTYPE_ARP },
227	{ "rarp", ETHERTYPE_REVARP },
228	{ "sprite", ETHERTYPE_SPRITE },
229	{ "mopdl", ETHERTYPE_MOPDL },
230	{ "moprc", ETHERTYPE_MOPRC },
231	{ "decnet", ETHERTYPE_DN },
232	{ "lat", ETHERTYPE_LAT },
233	{ "sca", ETHERTYPE_SCA },
234	{ "lanbridge", ETHERTYPE_LANBRIDGE },
235	{ "vexp", ETHERTYPE_VEXP },
236	{ "vprod", ETHERTYPE_VPROD },
237	{ "atalk", ETHERTYPE_ATALK },
238	{ "atalkarp", ETHERTYPE_AARP },
239	{ "loopback", ETHERTYPE_LOOPBACK },
240	{ "decdts", ETHERTYPE_DECDTS },
241	{ "decdns", ETHERTYPE_DECDNS },
242	{ (char *)0, 0 }
243};
244
245int
246pcap_nametoeproto(const char *s)
247{
248	struct eproto *p = eproto_db;
249
250	while (p->s != 0) {
251		if (strcmp(p->s, s) == 0)
252			return p->p;
253		p += 1;
254	}
255	return PROTO_UNDEF;
256}
257
258/* Hex digit to integer. */
259static inline int
260xdtoi(c)
261	register int c;
262{
263	if (isdigit(c))
264		return c - '0';
265	else if (islower(c))
266		return c - 'a' + 10;
267	else
268		return c - 'A' + 10;
269}
270
271int
272__pcap_atoin(const char *s, bpf_u_int32 *addr)
273{
274	u_int n;
275	int len;
276
277	*addr = 0;
278	len = 0;
279	while (1) {
280		n = 0;
281		while (*s && *s != '.')
282			n = n * 10 + *s++ - '0';
283		*addr <<= 8;
284		*addr |= n & 0xff;
285		len += 8;
286		if (*s == '\0')
287			return len;
288		++s;
289	}
290	/* NOTREACHED */
291}
292
293int
294__pcap_atodn(const char *s, bpf_u_int32 *addr)
295{
296#define AREASHIFT 10
297#define AREAMASK 0176000
298#define NODEMASK 01777
299
300	u_int node, area;
301
302	if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
303		bpf_error("malformed decnet address '%s'", s);
304
305	*addr = (area << AREASHIFT) & AREAMASK;
306	*addr |= (node & NODEMASK);
307
308	return(32);
309}
310
311/*
312 * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
313 * ethernet address.  Assumes 's' is well formed.
314 */
315u_char *
316pcap_ether_aton(const char *s)
317{
318	register u_char *ep, *e;
319	register u_int d;
320
321	e = ep = (u_char *)malloc(6);
322
323	while (*s) {
324		if (*s == ':')
325			s += 1;
326		d = xdtoi(*s++);
327		if (isxdigit(*s)) {
328			d <<= 4;
329			d |= xdtoi(*s++);
330		}
331		*ep++ = d;
332	}
333
334	return (e);
335}
336
337#ifndef HAVE_ETHER_HOSTTON
338/* Roll our own */
339u_char *
340pcap_ether_hostton(const char *name)
341{
342	register struct pcap_etherent *ep;
343	register u_char *ap;
344	static FILE *fp = NULL;
345	static int init = 0;
346
347	if (!init) {
348		fp = fopen(PCAP_ETHERS_FILE, "r");
349		++init;
350		if (fp == NULL)
351			return (NULL);
352	} else if (fp == NULL)
353		return (NULL);
354	else
355		rewind(fp);
356
357	while ((ep = pcap_next_etherent(fp)) != NULL) {
358		if (strcmp(ep->name, name) == 0) {
359			ap = (u_char *)malloc(6);
360			if (ap != NULL) {
361				memcpy(ap, ep->addr, 6);
362				return (ap);
363			}
364			break;
365		}
366	}
367	return (NULL);
368}
369#else
370
371/*
372 * XXX - perhaps this should, instead, be declared in "lbl/os-XXX.h" files,
373 * for those OS versions that don't declare it, rather than being declared
374 * here?  That way, for example, we could declare it on FreeBSD 2.x (which
375 * doesn't declare it), but not on FreeBSD 3.x (which declares it like
376 * this) or FreeBSD 4.x (which declares it with its first argument as
377 * "const char *", so no matter how we declare it here, it'll fail to
378 * compile on one of 3.x or 4.x).
379 */
380#if !defined(sgi) && !defined(__NetBSD__) && !defined(__FreeBSD__)
381extern int ether_hostton(char *, struct ether_addr *);
382#endif
383
384/* Use the os supplied routines */
385u_char *
386pcap_ether_hostton(const char *name)
387{
388	register u_char *ap;
389	u_char a[6];
390
391	ap = NULL;
392	if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) {
393		ap = (u_char *)malloc(6);
394		if (ap != NULL)
395			memcpy((char *)ap, (char *)a, 6);
396	}
397	return (ap);
398}
399#endif
400
401u_short
402__pcap_nametodnaddr(const char *name)
403{
404#ifdef	DECNETLIB
405	struct nodeent *getnodebyname();
406	struct nodeent *nep;
407	unsigned short res;
408
409	nep = getnodebyname(name);
410	if (nep == ((struct nodeent *)0))
411		bpf_error("unknown decnet host name '%s'\n", name);
412
413	memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
414	return(res);
415#else
416	bpf_error("decnet name support not included, '%s' cannot be translated\n",
417		name);
418#endif
419}
420