xref: /freebsd/contrib/libpcap/nametoaddr.c (revision 74bf4e164ba5851606a27d4feff27717452583e5)
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$
25  */
26 
27 #ifndef lint
28 static 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
59 struct mbuf;		/* Squelch compiler warnings on some platforms for */
60 struct 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 
89 static inline int xdtoi(int);
90 
91 /*
92  *  Convert host name to internet address.
93  *  Return 0 upon failure.
94  */
95 bpf_u_int32 **
96 pcap_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
120 struct addrinfo *
121 pcap_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  */
141 bpf_u_int32
142 pcap_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  */
164 int
165 pcap_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 
213 int
214 pcap_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 
227 struct eproto {
228 	char *s;
229 	u_short p;
230 };
231 
232 /* Static data base of ether protocol types. */
233 struct 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 
268 int
269 pcap_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. */
282 static inline int
283 xdtoi(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 
294 int
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 
316 int
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  */
338 u_char *
339 pcap_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 */
362 u_char *
363 pcap_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)
405 extern int ether_hostton(char *, struct ether_addr *);
406 #endif
407 
408 /* Use the os supplied routines */
409 u_char *
410 pcap_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 
425 u_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