xref: /netbsd-src/external/bsd/libpcap/dist/nametoaddr.c (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
1 /*	$NetBSD: nametoaddr.c,v 1.7 2024/09/02 15:33:37 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.7 2024/09/02 15:33:37 christos Exp $");
29 
30 #include <config.h>
31 
32 #ifdef DECNETLIB
33 #include <sys/types.h>
34 #include <netdnet/dnetdb.h>
35 #endif
36 
37 #ifdef _WIN32
38   #include <winsock2.h>
39   #include <ws2tcpip.h>
40 
41   #ifdef INET6
42     /*
43      * To quote the MSDN page for getaddrinfo() at
44      *
45      *    https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
46      *
47      * "Support for getaddrinfo on Windows 2000 and older versions
48      * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
49      * later. To execute an application that uses this function on earlier
50      * versions of Windows, then you need to include the Ws2tcpip.h and
51      * Wspiapi.h files. When the Wspiapi.h include file is added, the
52      * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
53      * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
54      * function is implemented in such a way that if the Ws2_32.dll or the
55      * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
56      * Preview for Windows 2000) does not include getaddrinfo, then a
57      * version of getaddrinfo is implemented inline based on code in the
58      * Wspiapi.h header file. This inline code will be used on older Windows
59      * platforms that do not natively support the getaddrinfo function."
60      *
61      * We use getaddrinfo(), so we include Wspiapi.h here.
62      */
63     #include <wspiapi.h>
64   #endif /* INET6 */
65 #else /* _WIN32 */
66   #include <sys/param.h>
67   #include <sys/types.h>
68   #include <sys/socket.h>
69   #include <sys/time.h>
70 
71   #include <netinet/in.h>
72 
73   #ifdef HAVE_ETHER_HOSTTON
74     #if defined(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
75       /*
76        * OK, just include <net/ethernet.h>.
77        */
78       #include <net/ethernet.h>
79     #elif defined(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
80       /*
81        * OK, just include <netinet/ether.h>
82        */
83       #include <netinet/ether.h>
84     #elif defined(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
85       /*
86        * OK, just include <sys/ethernet.h>
87        */
88       #include <sys/ethernet.h>
89     #elif defined(ARPA_INET_H_DECLARES_ETHER_HOSTTON)
90       /*
91        * OK, just include <arpa/inet.h>
92        */
93       #include <arpa/inet.h>
94     #elif defined(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
95       /*
96        * OK, include <netinet/if_ether.h>, after all the other stuff we
97        * need to include or define for its benefit.
98        */
99       #define NEED_NETINET_IF_ETHER_H
100     #else
101       /*
102        * We'll have to declare it ourselves.
103        * If <netinet/if_ether.h> defines struct ether_addr, include
104        * it.  Otherwise, define it ourselves.
105        */
106       #ifdef HAVE_STRUCT_ETHER_ADDR
107         #define NEED_NETINET_IF_ETHER_H
108       #else /* HAVE_STRUCT_ETHER_ADDR */
109 	struct ether_addr {
110 		unsigned char ether_addr_octet[6];
111 	};
112       #endif /* HAVE_STRUCT_ETHER_ADDR */
113     #endif /* what declares ether_hostton() */
114 
115     #ifdef NEED_NETINET_IF_ETHER_H
116       #include <net/if.h>	/* Needed on some platforms */
117       #include <netinet/in.h>	/* Needed on some platforms */
118       #include <netinet/if_ether.h>
119     #endif /* NEED_NETINET_IF_ETHER_H */
120 
121     #ifndef HAVE_DECL_ETHER_HOSTTON
122       /*
123        * No header declares it, so declare it ourselves.
124        */
125       extern int ether_hostton(const char *, struct ether_addr *);
126     #endif /* !defined(HAVE_DECL_ETHER_HOSTTON) */
127   #endif /* HAVE_ETHER_HOSTTON */
128 
129   #include <arpa/inet.h>
130   #include <netdb.h>
131 #endif /* _WIN32 */
132 
133 #include <errno.h>
134 #include <stdlib.h>
135 #include <string.h>
136 #include <stdio.h>
137 
138 #include "pcap-int.h"
139 
140 #include "diag-control.h"
141 
142 #include "gencode.h"
143 #include <pcap/namedb.h>
144 #include "nametoaddr.h"
145 
146 #include "thread-local.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 	char *off, *cpy;
479 	int save_proto;
480 
481 	if ((cpy = strdup(name)) == NULL)
482 		return 0;
483 
484 	if ((off = strchr(cpy, '-')) == NULL) {
485 		free(cpy);
486 		return 0;
487 	}
488 
489 	*off = '\0';
490 
491 	if (pcap_nametoport(cpy, port1, proto) == 0) {
492 		free(cpy);
493 		return 0;
494 	}
495 	save_proto = *proto;
496 
497 	if (pcap_nametoport(off + 1, port2, proto) == 0) {
498 		free(cpy);
499 		return 0;
500 	}
501 	free(cpy);
502 
503 	if (*proto != save_proto)
504 		*proto = PROTO_UNDEF;
505 
506 	return 1;
507 }
508 
509 /*
510  * XXX - not guaranteed to be thread-safe!  See below for platforms
511  * on which it is thread-safe and on which it isn't.
512  */
513 int
514 pcap_nametoproto(const char *str)
515 {
516 	struct protoent *p;
517   #if defined(HAVE_LINUX_GETNETBYNAME_R)
518 	/*
519 	 * We have Linux's reentrant getprotobyname_r().
520 	 */
521 	struct protoent result_buf;
522 	char buf[1024];	/* arbitrary size */
523 	int err;
524 
525 	err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p);
526 	if (err != 0) {
527 		/*
528 		 * XXX - dynamically allocate the buffer, and make it
529 		 * bigger if we get ERANGE back?
530 		 */
531 		return 0;
532 	}
533   #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
534 	/*
535 	 * We have Solaris's and IRIX's reentrant getprotobyname_r().
536 	 */
537 	struct protoent result_buf;
538 	char buf[1024];	/* arbitrary size */
539 
540 	p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf);
541   #elif defined(HAVE_AIX_GETNETBYNAME_R)
542 	/*
543 	 * We have AIX's reentrant getprotobyname_r().
544 	 */
545 	struct protoent result_buf;
546 	struct protoent_data proto_data;
547 
548 	if (getprotobyname_r(str, &result_buf, &proto_data) == -1)
549 		p = NULL;
550 	else
551 		p = &result_buf;
552   #else
553 	/*
554 	 * We don't have any getprotobyname_r(); either we have a
555 	 * getprotobyname() that uses thread-specific data, in which
556 	 * case we're thread-safe (sufficiently recent FreeBSD,
557 	 * sufficiently recent Darwin-based OS, sufficiently recent
558 	 * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have
559 	 * the traditional getprotobyname() (everything else, including
560 	 * current NetBSD and OpenBSD), in which case we're not
561 	 * thread-safe.
562 	 */
563 	p = getprotobyname(str);
564   #endif
565 	if (p != 0)
566 		return p->p_proto;
567 	else
568 		return PROTO_UNDEF;
569 }
570 
571 #include "ethertype.h"
572 
573 struct eproto {
574 	const char *s;
575 	u_short p;
576 };
577 
578 /*
579  * Static data base of ether protocol types.
580  * tcpdump used to import this, and it's declared as an export on
581  * Debian, at least, so make it a public symbol, even though we
582  * don't officially export it by declaring it in a header file.
583  * (Programs *should* do this themselves, as tcpdump now does.)
584  *
585  * We declare it here, right before defining it, to squelch any
586  * warnings we might get from compilers about the lack of a
587  * declaration.
588  */
589 PCAP_API struct eproto eproto_db[];
590 PCAP_API_DEF struct eproto eproto_db[] = {
591 	{ "aarp", ETHERTYPE_AARP },
592 	{ "arp", ETHERTYPE_ARP },
593 	{ "atalk", ETHERTYPE_ATALK },
594 	{ "decnet", ETHERTYPE_DN },
595 	{ "ip", ETHERTYPE_IP },
596 #ifdef INET6
597 	{ "ip6", ETHERTYPE_IPV6 },
598 #endif
599 	{ "lat", ETHERTYPE_LAT },
600 	{ "loopback", ETHERTYPE_LOOPBACK },
601 	{ "mopdl", ETHERTYPE_MOPDL },
602 	{ "moprc", ETHERTYPE_MOPRC },
603 	{ "rarp", ETHERTYPE_REVARP },
604 	{ "sca", ETHERTYPE_SCA },
605 	{ (char *)0, 0 }
606 };
607 
608 int
609 pcap_nametoeproto(const char *s)
610 {
611 	struct eproto *p = eproto_db;
612 
613 	while (p->s != 0) {
614 		if (strcmp(p->s, s) == 0)
615 			return p->p;
616 		p += 1;
617 	}
618 	return PROTO_UNDEF;
619 }
620 
621 #include "llc.h"
622 
623 /* Static data base of LLC values. */
624 static struct eproto llc_db[] = {
625 	{ "iso", LLCSAP_ISONS },
626 	{ "stp", LLCSAP_8021D },
627 	{ "ipx", LLCSAP_IPX },
628 	{ "netbeui", LLCSAP_NETBEUI },
629 	{ (char *)0, 0 }
630 };
631 
632 int
633 pcap_nametollc(const char *s)
634 {
635 	struct eproto *p = llc_db;
636 
637 	while (p->s != 0) {
638 		if (strcmp(p->s, s) == 0)
639 			return p->p;
640 		p += 1;
641 	}
642 	return PROTO_UNDEF;
643 }
644 
645 /* Hex digit to 8-bit unsigned integer. */
646 static inline u_char
647 xdtoi(u_char c)
648 {
649 	if (c >= '0' && c <= '9')
650 		return (u_char)(c - '0');
651 	else if (c >= 'a' && c <= 'f')
652 		return (u_char)(c - 'a' + 10);
653 	else
654 		return (u_char)(c - 'A' + 10);
655 }
656 
657 int
658 __pcap_atoin(const char *s, bpf_u_int32 *addr)
659 {
660 	u_int n;
661 	int len;
662 
663 	*addr = 0;
664 	len = 0;
665 	for (;;) {
666 		n = 0;
667 		while (*s && *s != '.') {
668 			if (n > 25) {
669 				/* The result will be > 255 */
670 				return -1;
671 			}
672 			n = n * 10 + *s++ - '0';
673 		}
674 		if (n > 255)
675 			return -1;
676 		*addr <<= 8;
677 		*addr |= n & 0xff;
678 		len += 8;
679 		if (*s == '\0')
680 			return len;
681 		++s;
682 	}
683 	/* NOTREACHED */
684 }
685 
686 int
687 __pcap_atodn(const char *s, bpf_u_int32 *addr)
688 {
689 #define AREASHIFT 10
690 #define AREAMASK 0176000
691 #define NODEMASK 01777
692 
693 	u_int node, area;
694 
695 	if (sscanf(s, "%d.%d", &area, &node) != 2)
696 		return(0);
697 
698 	*addr = (area << AREASHIFT) & AREAMASK;
699 	*addr |= (node & NODEMASK);
700 
701 	return(32);
702 }
703 
704 /*
705  * Convert 's', which can have the one of the forms:
706  *
707  *	"xx:xx:xx:xx:xx:xx"
708  *	"xx.xx.xx.xx.xx.xx"
709  *	"xx-xx-xx-xx-xx-xx"
710  *	"xxxx.xxxx.xxxx"
711  *	"xxxxxxxxxxxx"
712  *
713  * (or various mixes of ':', '.', and '-') into a new
714  * ethernet address.  Assumes 's' is well formed.
715  */
716 u_char *
717 pcap_ether_aton(const char *s)
718 {
719 	register u_char *ep, *e;
720 	register u_char d;
721 
722 	e = ep = (u_char *)malloc(6);
723 	if (e == NULL)
724 		return (NULL);
725 
726 	while (*s) {
727 		if (*s == ':' || *s == '.' || *s == '-')
728 			s += 1;
729 		d = xdtoi(*s++);
730 		if (PCAP_ISXDIGIT(*s)) {
731 			d <<= 4;
732 			d |= xdtoi(*s++);
733 		}
734 		*ep++ = d;
735 	}
736 
737 	return (e);
738 }
739 
740 #ifndef HAVE_ETHER_HOSTTON
741 /*
742  * Roll our own.
743  *
744  * This should be thread-safe, as we define the static variables
745  * we use to be thread-local, and as pcap_next_etherent() does so
746  * as well.
747  */
748 u_char *
749 pcap_ether_hostton(const char *name)
750 {
751 	register struct pcap_etherent *ep;
752 	register u_char *ap;
753 	static thread_local FILE *fp = NULL;
754 	static thread_local int init = 0;
755 
756 	if (!init) {
757 		fp = fopen(PCAP_ETHERS_FILE, "r");
758 		++init;
759 		if (fp == NULL)
760 			return (NULL);
761 	} else if (fp == NULL)
762 		return (NULL);
763 	else
764 		rewind(fp);
765 
766 	while ((ep = pcap_next_etherent(fp)) != NULL) {
767 		if (strcmp(ep->name, name) == 0) {
768 			ap = (u_char *)malloc(6);
769 			if (ap != NULL) {
770 				memcpy(ap, ep->addr, 6);
771 				return (ap);
772 			}
773 			break;
774 		}
775 	}
776 	return (NULL);
777 }
778 #else
779 /*
780  * Use the OS-supplied routine.
781  * This *should* be thread-safe; the API doesn't have a static buffer.
782  */
783 u_char *
784 pcap_ether_hostton(const char *name)
785 {
786 	register u_char *ap;
787 	u_char a[6];
788 	char namebuf[1024];
789 
790 	/*
791 	 * In AIX 7.1 and 7.2: int ether_hostton(char *, struct ether_addr *);
792 	 */
793 	pcapint_strlcpy(namebuf, name, sizeof(namebuf));
794 	ap = NULL;
795 	if (ether_hostton(namebuf, (struct ether_addr *)a) == 0) {
796 		ap = (u_char *)malloc(6);
797 		if (ap != NULL)
798 			memcpy((char *)ap, (char *)a, 6);
799 	}
800 	return (ap);
801 }
802 #endif
803 
804 /*
805  * XXX - not guaranteed to be thread-safe!
806  */
807 int
808 #ifdef	DECNETLIB
809 __pcap_nametodnaddr(const char *name, u_short *res)
810 {
811 	struct nodeent *getnodebyname();
812 	struct nodeent *nep;
813 
814 	nep = getnodebyname(name);
815 	if (nep == ((struct nodeent *)0))
816 		return(0);
817 
818 	memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short));
819 	return(1);
820 #else
821 __pcap_nametodnaddr(const char *name _U_, u_short *res _U_)
822 {
823 	return(0);
824 #endif
825 }
826