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