Home | History | Annotate | Line # | Download | only in dist
      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