xref: /netbsd-src/external/bsd/libpcap/dist/nametoaddr.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /*	$NetBSD: nametoaddr.c,v 1.6 2023/08/17 15:18:12 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  *
23  * Name to id translation routines used by the scanner.
24  * These functions are not time critical.
25  */
26 
27 #include <sys/cdefs.h>
28 __RCSID("$NetBSD: nametoaddr.c,v 1.6 2023/08/17 15:18:12 christos Exp $");
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #ifdef DECNETLIB
35 #include <sys/types.h>
36 #include <netdnet/dnetdb.h>
37 #endif
38 
39 #ifdef _WIN32
40   #include <winsock2.h>
41   #include <ws2tcpip.h>
42 
43   #ifdef INET6
44     /*
45      * To quote the MSDN page for getaddrinfo() at
46      *
47      *    https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
48      *
49      * "Support for getaddrinfo on Windows 2000 and older versions
50      * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
51      * later. To execute an application that uses this function on earlier
52      * versions of Windows, then you need to include the Ws2tcpip.h and
53      * Wspiapi.h files. When the Wspiapi.h include file is added, the
54      * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
55      * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
56      * function is implemented in such a way that if the Ws2_32.dll or the
57      * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
58      * Preview for Windows 2000) does not include getaddrinfo, then a
59      * version of getaddrinfo is implemented inline based on code in the
60      * Wspiapi.h header file. This inline code will be used on older Windows
61      * platforms that do not natively support the getaddrinfo function."
62      *
63      * We use getaddrinfo(), so we include Wspiapi.h here.
64      */
65     #include <wspiapi.h>
66   #endif /* INET6 */
67 #else /* _WIN32 */
68   #include <sys/param.h>
69   #include <sys/types.h>
70   #include <sys/socket.h>
71   #include <sys/time.h>
72 
73   #include <netinet/in.h>
74 
75   #ifdef HAVE_ETHER_HOSTTON
76     #if defined(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
77       /*
78        * OK, just include <net/ethernet.h>.
79        */
80       #include <net/ethernet.h>
81     #elif defined(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
82       /*
83        * OK, just include <netinet/ether.h>
84        */
85       #include <netinet/ether.h>
86     #elif defined(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
87       /*
88        * OK, just include <sys/ethernet.h>
89        */
90       #include <sys/ethernet.h>
91     #elif defined(ARPA_INET_H_DECLARES_ETHER_HOSTTON)
92       /*
93        * OK, just include <arpa/inet.h>
94        */
95       #include <arpa/inet.h>
96     #elif defined(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
97       /*
98        * OK, include <netinet/if_ether.h>, after all the other stuff we
99        * need to include or define for its benefit.
100        */
101       #define NEED_NETINET_IF_ETHER_H
102     #else
103       /*
104        * We'll have to declare it ourselves.
105        * If <netinet/if_ether.h> defines struct ether_addr, include
106        * it.  Otherwise, define it ourselves.
107        */
108       #ifdef HAVE_STRUCT_ETHER_ADDR
109         #define NEED_NETINET_IF_ETHER_H
110       #else /* HAVE_STRUCT_ETHER_ADDR */
111 	struct ether_addr {
112 		unsigned char ether_addr_octet[6];
113 	};
114       #endif /* HAVE_STRUCT_ETHER_ADDR */
115     #endif /* what declares ether_hostton() */
116 
117     #ifdef NEED_NETINET_IF_ETHER_H
118       #include <net/if.h>	/* Needed on some platforms */
119       #include <netinet/in.h>	/* Needed on some platforms */
120       #include <netinet/if_ether.h>
121     #endif /* NEED_NETINET_IF_ETHER_H */
122 
123     #ifndef HAVE_DECL_ETHER_HOSTTON
124       /*
125        * No header declares it, so declare it ourselves.
126        */
127       extern int ether_hostton(const char *, struct ether_addr *);
128     #endif /* !defined(HAVE_DECL_ETHER_HOSTTON) */
129   #endif /* HAVE_ETHER_HOSTTON */
130 
131   #include <arpa/inet.h>
132   #include <netdb.h>
133 #endif /* _WIN32 */
134 
135 #include <errno.h>
136 #include <stdlib.h>
137 #include <string.h>
138 #include <stdio.h>
139 
140 #include "pcap-int.h"
141 
142 #include "diag-control.h"
143 
144 #include "gencode.h"
145 #include <pcap/namedb.h>
146 #include "nametoaddr.h"
147 
148 #ifdef HAVE_OS_PROTO_H
149 #include "os-proto.h"
150 #endif
151 
152 #ifndef NTOHL
153 #define NTOHL(x) (x) = ntohl(x)
154 #define NTOHS(x) (x) = ntohs(x)
155 #endif
156 
157 /*
158  *  Convert host name to internet address.
159  *  Return 0 upon failure.
160  *  XXX - not thread-safe; don't use it inside libpcap.
161  */
162 bpf_u_int32 **
163 pcap_nametoaddr(const char *name)
164 {
165 #ifndef h_addr
166 	static bpf_u_int32 *hlist[2];
167 #endif
168 	bpf_u_int32 **p;
169 	struct hostent *hp;
170 
171 	/*
172 	 * gethostbyname() is deprecated on Windows, perhaps because
173 	 * it's not thread-safe, or because it doesn't support IPv6,
174 	 * or both.
175 	 *
176 	 * We deprecate pcap_nametoaddr() on all platforms because
177 	 * it's not thread-safe; we supply it for backwards compatibility,
178 	 * so suppress the deprecation warning.  We could, I guess,
179 	 * use getaddrinfo() and construct the array ourselves, but
180 	 * that's probably not worth the effort, as that wouldn't make
181 	 * this thread-safe - we can't change the API to require that
182 	 * our caller free the address array, so we still have to reuse
183 	 * a local array.
184 	 */
185 DIAG_OFF_DEPRECATION
186 	if ((hp = gethostbyname(name)) != NULL) {
187 DIAG_ON_DEPRECATION
188 #ifndef h_addr
189 		hlist[0] = (bpf_u_int32 *)hp->h_addr;
190 		NTOHL(hp->h_addr);
191 		return hlist;
192 #else
193 		for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
194 			NTOHL(**p);
195 		return (bpf_u_int32 **)hp->h_addr_list;
196 #endif
197 	}
198 	else
199 		return 0;
200 }
201 
202 struct addrinfo *
203 pcap_nametoaddrinfo(const char *name)
204 {
205 	struct addrinfo hints, *res;
206 	int error;
207 
208 	memset(&hints, 0, sizeof(hints));
209 	hints.ai_family = PF_UNSPEC;
210 	hints.ai_socktype = SOCK_STREAM;	/*not really*/
211 	hints.ai_protocol = IPPROTO_TCP;	/*not really*/
212 	error = getaddrinfo(name, NULL, &hints, &res);
213 	if (error)
214 		return NULL;
215 	else
216 		return res;
217 }
218 
219 /*
220  *  Convert net name to internet address.
221  *  Return 0 upon failure.
222  *  XXX - not guaranteed to be thread-safe!  See below for platforms
223  *  on which it is thread-safe and on which it isn't.
224  */
225 #if defined(_WIN32) || defined(__CYGWIN__)
226 bpf_u_int32
227 pcap_nametonetaddr(const char *name _U_)
228 {
229 	/*
230 	 * There's no "getnetbyname()" on Windows.
231 	 *
232 	 * XXX - I guess we could use the BSD code to read
233 	 * C:\Windows\System32\drivers\etc/networks, assuming
234 	 * that's its home on all the versions of Windows
235 	 * we use, but that file probably just has the loopback
236 	 * network on 127/24 on 99 44/100% of Windows machines.
237 	 *
238 	 * (Heck, these days it probably just has that on 99 44/100%
239 	 * of *UN*X* machines.)
240 	 */
241 	return 0;
242 }
243 #else /* _WIN32 */
244 bpf_u_int32
245 pcap_nametonetaddr(const char *name)
246 {
247 	/*
248 	 * UN*X.
249 	 */
250 	struct netent *np;
251   #if defined(HAVE_LINUX_GETNETBYNAME_R)
252 	/*
253 	 * We have Linux's reentrant getnetbyname_r().
254 	 */
255 	struct netent result_buf;
256 	char buf[1024];	/* arbitrary size */
257 	int h_errnoval;
258 	int err;
259 
260 	/*
261 	 * Apparently, the man page at
262 	 *
263 	 *    http://man7.org/linux/man-pages/man3/getnetbyname_r.3.html
264 	 *
265 	 * lies when it says
266 	 *
267 	 *    If the function call successfully obtains a network record,
268 	 *    then *result is set pointing to result_buf; otherwise, *result
269 	 *    is set to NULL.
270 	 *
271 	 * and, in fact, at least in some versions of GNU libc, it does
272 	 * *not* always get set if getnetbyname_r() succeeds.
273 	 */
274 	np = NULL;
275 	err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
276 	    &h_errnoval);
277 	if (err != 0) {
278 		/*
279 		 * XXX - dynamically allocate the buffer, and make it
280 		 * bigger if we get ERANGE back?
281 		 */
282 		return 0;
283 	}
284   #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
285 	/*
286 	 * We have Solaris's and IRIX's reentrant getnetbyname_r().
287 	 */
288 	struct netent result_buf;
289 	char buf[1024];	/* arbitrary size */
290 
291 	np = getnetbyname_r(name, &result_buf, buf, (int)sizeof buf);
292   #elif defined(HAVE_AIX_GETNETBYNAME_R)
293 	/*
294 	 * We have AIX's reentrant getnetbyname_r().
295 	 */
296 	struct netent result_buf;
297 	struct netent_data net_data;
298 
299 	if (getnetbyname_r(name, &result_buf, &net_data) == -1)
300 		np = NULL;
301 	else
302 		np = &result_buf;
303   #else
304 	/*
305 	 * We don't have any getnetbyname_r(); either we have a
306 	 * getnetbyname() that uses thread-specific data, in which
307 	 * case we're thread-safe (sufficiently recent FreeBSD,
308 	 * sufficiently recent Darwin-based OS, sufficiently recent
309 	 * HP-UX, sufficiently recent Tru64 UNIX), or we have the
310 	 * traditional getnetbyname() (everything else, including
311 	 * current NetBSD and OpenBSD), in which case we're not
312 	 * thread-safe.
313 	 */
314 	np = getnetbyname(name);
315   #endif
316 	if (np != NULL)
317 		return np->n_net;
318 	else
319 		return 0;
320 }
321 #endif /* _WIN32 */
322 
323 /*
324  * Convert a port name to its port and protocol numbers.
325  * We assume only TCP or UDP.
326  * Return 0 upon failure.
327  */
328 int
329 pcap_nametoport(const char *name, int *port, int *proto)
330 {
331 	struct addrinfo hints, *res, *ai;
332 	int error;
333 	struct sockaddr_in *in4;
334 #ifdef INET6
335 	struct sockaddr_in6 *in6;
336 #endif
337 	int tcp_port = -1;
338 	int udp_port = -1;
339 
340 	/*
341 	 * We check for both TCP and UDP in case there are
342 	 * ambiguous entries.
343 	 */
344 	memset(&hints, 0, sizeof(hints));
345 	hints.ai_family = PF_UNSPEC;
346 	hints.ai_socktype = SOCK_STREAM;
347 	hints.ai_protocol = IPPROTO_TCP;
348 	error = getaddrinfo(NULL, name, &hints, &res);
349 	if (error != 0) {
350 		if (error != EAI_NONAME &&
351 		    error != EAI_SERVICE) {
352 			/*
353 			 * This is a real error, not just "there's
354 			 * no such service name".
355 			 * XXX - this doesn't return an error string.
356 			 */
357 			return 0;
358 		}
359 	} else {
360 		/*
361 		 * OK, we found it.  Did it find anything?
362 		 */
363 		for (ai = res; ai != NULL; ai = ai->ai_next) {
364 			/*
365 			 * Does it have an address?
366 			 */
367 			if (ai->ai_addr != NULL) {
368 				/*
369 				 * Yes.  Get a port number; we're done.
370 				 */
371 				if (ai->ai_addr->sa_family == AF_INET) {
372 					in4 = (struct sockaddr_in *)ai->ai_addr;
373 					tcp_port = ntohs(in4->sin_port);
374 					break;
375 				}
376 #ifdef INET6
377 				if (ai->ai_addr->sa_family == AF_INET6) {
378 					in6 = (struct sockaddr_in6 *)ai->ai_addr;
379 					tcp_port = ntohs(in6->sin6_port);
380 					break;
381 				}
382 #endif
383 			}
384 		}
385 		freeaddrinfo(res);
386 	}
387 
388 	memset(&hints, 0, sizeof(hints));
389 	hints.ai_family = PF_UNSPEC;
390 	hints.ai_socktype = SOCK_DGRAM;
391 	hints.ai_protocol = IPPROTO_UDP;
392 	error = getaddrinfo(NULL, name, &hints, &res);
393 	if (error != 0) {
394 		if (error != EAI_NONAME &&
395 		    error != EAI_SERVICE) {
396 			/*
397 			 * This is a real error, not just "there's
398 			 * no such service name".
399 			 * XXX - this doesn't return an error string.
400 			 */
401 			return 0;
402 		}
403 	} else {
404 		/*
405 		 * OK, we found it.  Did it find anything?
406 		 */
407 		for (ai = res; ai != NULL; ai = ai->ai_next) {
408 			/*
409 			 * Does it have an address?
410 			 */
411 			if (ai->ai_addr != NULL) {
412 				/*
413 				 * Yes.  Get a port number; we're done.
414 				 */
415 				if (ai->ai_addr->sa_family == AF_INET) {
416 					in4 = (struct sockaddr_in *)ai->ai_addr;
417 					udp_port = ntohs(in4->sin_port);
418 					break;
419 				}
420 #ifdef INET6
421 				if (ai->ai_addr->sa_family == AF_INET6) {
422 					in6 = (struct sockaddr_in6 *)ai->ai_addr;
423 					udp_port = ntohs(in6->sin6_port);
424 					break;
425 				}
426 #endif
427 			}
428 		}
429 		freeaddrinfo(res);
430 	}
431 
432 	/*
433 	 * We need to check /etc/services for ambiguous entries.
434 	 * If we find an ambiguous entry, and it has the
435 	 * same port number, change the proto to PROTO_UNDEF
436 	 * so both TCP and UDP will be checked.
437 	 */
438 	if (tcp_port >= 0) {
439 		*port = tcp_port;
440 		*proto = IPPROTO_TCP;
441 		if (udp_port >= 0) {
442 			if (udp_port == tcp_port)
443 				*proto = PROTO_UNDEF;
444 #ifdef notdef
445 			else
446 				/* Can't handle ambiguous names that refer
447 				   to different port numbers. */
448 				warning("ambiguous port %s in /etc/services",
449 					name);
450 #endif
451 		}
452 		return 1;
453 	}
454 	if (udp_port >= 0) {
455 		*port = udp_port;
456 		*proto = IPPROTO_UDP;
457 		return 1;
458 	}
459 #if defined(ultrix) || defined(__osf__)
460 	/* Special hack in case NFS isn't in /etc/services */
461 	if (strcmp(name, "nfs") == 0) {
462 		*port = 2049;
463 		*proto = PROTO_UNDEF;
464 		return 1;
465 	}
466 #endif
467 	return 0;
468 }
469 
470 /*
471  * Convert a string in the form PPP-PPP, where correspond to ports, to
472  * a starting and ending port in a port range.
473  * Return 0 on failure.
474  */
475 int
476 pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
477 {
478 	u_int p1, p2;
479 	char *off, *cpy;
480 	int save_proto;
481 
482 	if (sscanf(name, "%d-%d", &p1, &p2) != 2) {
483 		if ((cpy = strdup(name)) == NULL)
484 			return 0;
485 
486 		if ((off = strchr(cpy, '-')) == NULL) {
487 			free(cpy);
488 			return 0;
489 		}
490 
491 		*off = '\0';
492 
493 		if (pcap_nametoport(cpy, port1, proto) == 0) {
494 			free(cpy);
495 			return 0;
496 		}
497 		save_proto = *proto;
498 
499 		if (pcap_nametoport(off + 1, port2, proto) == 0) {
500 			free(cpy);
501 			return 0;
502 		}
503 		free(cpy);
504 
505 		if (*proto != save_proto)
506 			*proto = PROTO_UNDEF;
507 	} else {
508 		*port1 = p1;
509 		*port2 = p2;
510 		*proto = PROTO_UNDEF;
511 	}
512 
513 	return 1;
514 }
515 
516 /*
517  * XXX - not guaranteed to be thread-safe!  See below for platforms
518  * on which it is thread-safe and on which it isn't.
519  */
520 int
521 pcap_nametoproto(const char *str)
522 {
523 	struct protoent *p;
524   #if defined(HAVE_LINUX_GETNETBYNAME_R)
525 	/*
526 	 * We have Linux's reentrant getprotobyname_r().
527 	 */
528 	struct protoent result_buf;
529 	char buf[1024];	/* arbitrary size */
530 	int err;
531 
532 	err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p);
533 	if (err != 0) {
534 		/*
535 		 * XXX - dynamically allocate the buffer, and make it
536 		 * bigger if we get ERANGE back?
537 		 */
538 		return 0;
539 	}
540   #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
541 	/*
542 	 * We have Solaris's and IRIX's reentrant getprotobyname_r().
543 	 */
544 	struct protoent result_buf;
545 	char buf[1024];	/* arbitrary size */
546 
547 	p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf);
548   #elif defined(HAVE_AIX_GETNETBYNAME_R)
549 	/*
550 	 * We have AIX's reentrant getprotobyname_r().
551 	 */
552 	struct protoent result_buf;
553 	struct protoent_data proto_data;
554 
555 	if (getprotobyname_r(str, &result_buf, &proto_data) == -1)
556 		p = NULL;
557 	else
558 		p = &result_buf;
559   #else
560 	/*
561 	 * We don't have any getprotobyname_r(); either we have a
562 	 * getprotobyname() that uses thread-specific data, in which
563 	 * case we're thread-safe (sufficiently recent FreeBSD,
564 	 * sufficiently recent Darwin-based OS, sufficiently recent
565 	 * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have
566 	 * the traditional getprotobyname() (everything else, including
567 	 * current NetBSD and OpenBSD), in which case we're not
568 	 * thread-safe.
569 	 */
570 	p = getprotobyname(str);
571   #endif
572 	if (p != 0)
573 		return p->p_proto;
574 	else
575 		return PROTO_UNDEF;
576 }
577 
578 #include "ethertype.h"
579 
580 struct eproto {
581 	const char *s;
582 	u_short p;
583 };
584 
585 /*
586  * Static data base of ether protocol types.
587  * tcpdump used to import this, and it's declared as an export on
588  * Debian, at least, so make it a public symbol, even though we
589  * don't officially export it by declaring it in a header file.
590  * (Programs *should* do this themselves, as tcpdump now does.)
591  *
592  * We declare it here, right before defining it, to squelch any
593  * warnings we might get from compilers about the lack of a
594  * declaration.
595  */
596 PCAP_API struct eproto eproto_db[];
597 PCAP_API_DEF struct eproto eproto_db[] = {
598 	{ "aarp", ETHERTYPE_AARP },
599 	{ "arp", ETHERTYPE_ARP },
600 	{ "atalk", ETHERTYPE_ATALK },
601 	{ "decnet", ETHERTYPE_DN },
602 	{ "ip", ETHERTYPE_IP },
603 #ifdef INET6
604 	{ "ip6", ETHERTYPE_IPV6 },
605 #endif
606 	{ "lat", ETHERTYPE_LAT },
607 	{ "loopback", ETHERTYPE_LOOPBACK },
608 	{ "mopdl", ETHERTYPE_MOPDL },
609 	{ "moprc", ETHERTYPE_MOPRC },
610 	{ "rarp", ETHERTYPE_REVARP },
611 	{ "sca", ETHERTYPE_SCA },
612 	{ (char *)0, 0 }
613 };
614 
615 int
616 pcap_nametoeproto(const char *s)
617 {
618 	struct eproto *p = eproto_db;
619 
620 	while (p->s != 0) {
621 		if (strcmp(p->s, s) == 0)
622 			return p->p;
623 		p += 1;
624 	}
625 	return PROTO_UNDEF;
626 }
627 
628 #include "llc.h"
629 
630 /* Static data base of LLC values. */
631 static struct eproto llc_db[] = {
632 	{ "iso", LLCSAP_ISONS },
633 	{ "stp", LLCSAP_8021D },
634 	{ "ipx", LLCSAP_IPX },
635 	{ "netbeui", LLCSAP_NETBEUI },
636 	{ (char *)0, 0 }
637 };
638 
639 int
640 pcap_nametollc(const char *s)
641 {
642 	struct eproto *p = llc_db;
643 
644 	while (p->s != 0) {
645 		if (strcmp(p->s, s) == 0)
646 			return p->p;
647 		p += 1;
648 	}
649 	return PROTO_UNDEF;
650 }
651 
652 /* Hex digit to 8-bit unsigned integer. */
653 static inline u_char
654 xdtoi(u_char c)
655 {
656 	if (c >= '0' && c <= '9')
657 		return (u_char)(c - '0');
658 	else if (c >= 'a' && c <= 'f')
659 		return (u_char)(c - 'a' + 10);
660 	else
661 		return (u_char)(c - 'A' + 10);
662 }
663 
664 int
665 __pcap_atoin(const char *s, bpf_u_int32 *addr)
666 {
667 	u_int n;
668 	int len;
669 
670 	*addr = 0;
671 	len = 0;
672 	for (;;) {
673 		n = 0;
674 		while (*s && *s != '.') {
675 			if (n > 25) {
676 				/* The result will be > 255 */
677 				return -1;
678 			}
679 			n = n * 10 + *s++ - '0';
680 		}
681 		if (n > 255)
682 			return -1;
683 		*addr <<= 8;
684 		*addr |= n & 0xff;
685 		len += 8;
686 		if (*s == '\0')
687 			return len;
688 		++s;
689 	}
690 	/* NOTREACHED */
691 }
692 
693 int
694 __pcap_atodn(const char *s, bpf_u_int32 *addr)
695 {
696 #define AREASHIFT 10
697 #define AREAMASK 0176000
698 #define NODEMASK 01777
699 
700 	u_int node, area;
701 
702 	if (sscanf(s, "%d.%d", &area, &node) != 2)
703 		return(0);
704 
705 	*addr = (area << AREASHIFT) & AREAMASK;
706 	*addr |= (node & NODEMASK);
707 
708 	return(32);
709 }
710 
711 /*
712  * Convert 's', which can have the one of the forms:
713  *
714  *	"xx:xx:xx:xx:xx:xx"
715  *	"xx.xx.xx.xx.xx.xx"
716  *	"xx-xx-xx-xx-xx-xx"
717  *	"xxxx.xxxx.xxxx"
718  *	"xxxxxxxxxxxx"
719  *
720  * (or various mixes of ':', '.', and '-') into a new
721  * ethernet address.  Assumes 's' is well formed.
722  */
723 u_char *
724 pcap_ether_aton(const char *s)
725 {
726 	register u_char *ep, *e;
727 	register u_char d;
728 
729 	e = ep = (u_char *)malloc(6);
730 	if (e == NULL)
731 		return (NULL);
732 
733 	while (*s) {
734 		if (*s == ':' || *s == '.' || *s == '-')
735 			s += 1;
736 		d = xdtoi(*s++);
737 		if (PCAP_ISXDIGIT(*s)) {
738 			d <<= 4;
739 			d |= xdtoi(*s++);
740 		}
741 		*ep++ = d;
742 	}
743 
744 	return (e);
745 }
746 
747 #ifndef HAVE_ETHER_HOSTTON
748 /*
749  * Roll our own.
750  * XXX - not thread-safe, because pcap_next_etherent() isn't thread-
751  * safe!  Needs a mutex or a thread-safe pcap_next_etherent().
752  */
753 u_char *
754 pcap_ether_hostton(const char *name)
755 {
756 	register struct pcap_etherent *ep;
757 	register u_char *ap;
758 	static FILE *fp = NULL;
759 	static int init = 0;
760 
761 	if (!init) {
762 		fp = fopen(PCAP_ETHERS_FILE, "r");
763 		++init;
764 		if (fp == NULL)
765 			return (NULL);
766 	} else if (fp == NULL)
767 		return (NULL);
768 	else
769 		rewind(fp);
770 
771 	while ((ep = pcap_next_etherent(fp)) != NULL) {
772 		if (strcmp(ep->name, name) == 0) {
773 			ap = (u_char *)malloc(6);
774 			if (ap != NULL) {
775 				memcpy(ap, ep->addr, 6);
776 				return (ap);
777 			}
778 			break;
779 		}
780 	}
781 	return (NULL);
782 }
783 #else
784 /*
785  * Use the OS-supplied routine.
786  * This *should* be thread-safe; the API doesn't have a static buffer.
787  */
788 u_char *
789 pcap_ether_hostton(const char *name)
790 {
791 	register u_char *ap;
792 	u_char a[6];
793 	char namebuf[1024];
794 
795 	/*
796 	 * In AIX 7.1 and 7.2: int ether_hostton(char *, struct ether_addr *);
797 	 */
798 	pcap_strlcpy(namebuf, name, sizeof(namebuf));
799 	ap = NULL;
800 	if (ether_hostton(namebuf, (struct ether_addr *)a) == 0) {
801 		ap = (u_char *)malloc(6);
802 		if (ap != NULL)
803 			memcpy((char *)ap, (char *)a, 6);
804 	}
805 	return (ap);
806 }
807 #endif
808 
809 /*
810  * XXX - not guaranteed to be thread-safe!
811  */
812 int
813 #ifdef	DECNETLIB
814 __pcap_nametodnaddr(const char *name, u_short *res)
815 {
816 	struct nodeent *getnodebyname();
817 	struct nodeent *nep;
818 
819 	nep = getnodebyname(name);
820 	if (nep == ((struct nodeent *)0))
821 		return(0);
822 
823 	memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short));
824 	return(1);
825 #else
826 __pcap_nametodnaddr(const char *name _U_, u_short *res _U_)
827 {
828 	return(0);
829 #endif
830 }
831