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 */
156 bpf_u_int32 **
pcap_nametoaddr(const char * name)157 pcap_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
180 struct addrinfo *
pcap_nametoaddrinfo(const char * name)181 pcap_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 */
203 bpf_u_int32
pcap_nametonetaddr(const char * name)204 pcap_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 err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
235 &h_errnoval);
236 if (err != 0) {
237 /*
238 * XXX - dynamically allocate the buffer, and make it
239 * bigger if we get ERANGE back?
240 */
241 return 0;
242 }
243 #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
244 /*
245 * We have Solaris's and IRIX's reentrant getnetbyname_r().
246 */
247 struct netent result_buf;
248 char buf[1024]; /* arbitrary size */
249
250 np = getnetbyname_r(name, &result_buf, buf, (int)sizeof buf);
251 #elif defined(HAVE_AIX_GETNETBYNAME_R)
252 /*
253 * We have AIX's reentrant getnetbyname_r().
254 */
255 struct netent result_buf;
256 struct netent_data net_data;
257
258 if (getnetbyname_r(name, &result_buf, &net_data) == -1)
259 np = NULL;
260 else
261 np = &result_buf;
262 #else
263 /*
264 * We don't have any getnetbyname_r(); either we have a
265 * getnetbyname() that uses thread-specific data, in which
266 * case we're thread-safe (sufficiently recent FreeBSD,
267 * sufficiently recent Darwin-based OS, sufficiently recent
268 * HP-UX, sufficiently recent Tru64 UNIX), or we have the
269 * traditional getnetbyname() (everything else, including
270 * current NetBSD and OpenBSD), in which case we're not
271 * thread-safe.
272 */
273 np = getnetbyname(name);
274 #endif
275 if (np != NULL)
276 return np->n_net;
277 else
278 return 0;
279 #endif /* _WIN32 */
280 }
281
282 /*
283 * Convert a port name to its port and protocol numbers.
284 * We assume only TCP or UDP.
285 * Return 0 upon failure.
286 */
287 int
pcap_nametoport(const char * name,int * port,int * proto)288 pcap_nametoport(const char *name, int *port, int *proto)
289 {
290 struct addrinfo hints, *res, *ai;
291 int error;
292 struct sockaddr_in *in4;
293 #ifdef INET6
294 struct sockaddr_in6 *in6;
295 #endif
296 int tcp_port = -1;
297 int udp_port = -1;
298
299 /*
300 * We check for both TCP and UDP in case there are
301 * ambiguous entries.
302 */
303 memset(&hints, 0, sizeof(hints));
304 hints.ai_family = PF_UNSPEC;
305 hints.ai_socktype = SOCK_STREAM;
306 hints.ai_protocol = IPPROTO_TCP;
307 error = getaddrinfo(NULL, name, &hints, &res);
308 if (error != 0) {
309 if (error != EAI_NONAME &&
310 error != EAI_SERVICE) {
311 /*
312 * This is a real error, not just "there's
313 * no such service name".
314 * XXX - this doesn't return an error string.
315 */
316 return 0;
317 }
318 } else {
319 /*
320 * OK, we found it. Did it find anything?
321 */
322 for (ai = res; ai != NULL; ai = ai->ai_next) {
323 /*
324 * Does it have an address?
325 */
326 if (ai->ai_addr != NULL) {
327 /*
328 * Yes. Get a port number; we're done.
329 */
330 if (ai->ai_addr->sa_family == AF_INET) {
331 in4 = (struct sockaddr_in *)ai->ai_addr;
332 tcp_port = ntohs(in4->sin_port);
333 break;
334 }
335 #ifdef INET6
336 if (ai->ai_addr->sa_family == AF_INET6) {
337 in6 = (struct sockaddr_in6 *)ai->ai_addr;
338 tcp_port = ntohs(in6->sin6_port);
339 break;
340 }
341 #endif
342 }
343 }
344 freeaddrinfo(res);
345 }
346
347 memset(&hints, 0, sizeof(hints));
348 hints.ai_family = PF_UNSPEC;
349 hints.ai_socktype = SOCK_DGRAM;
350 hints.ai_protocol = IPPROTO_UDP;
351 error = getaddrinfo(NULL, name, &hints, &res);
352 if (error != 0) {
353 if (error != EAI_NONAME &&
354 error != EAI_SERVICE) {
355 /*
356 * This is a real error, not just "there's
357 * no such service name".
358 * XXX - this doesn't return an error string.
359 */
360 return 0;
361 }
362 } else {
363 /*
364 * OK, we found it. Did it find anything?
365 */
366 for (ai = res; ai != NULL; ai = ai->ai_next) {
367 /*
368 * Does it have an address?
369 */
370 if (ai->ai_addr != NULL) {
371 /*
372 * Yes. Get a port number; we're done.
373 */
374 if (ai->ai_addr->sa_family == AF_INET) {
375 in4 = (struct sockaddr_in *)ai->ai_addr;
376 udp_port = ntohs(in4->sin_port);
377 break;
378 }
379 #ifdef INET6
380 if (ai->ai_addr->sa_family == AF_INET6) {
381 in6 = (struct sockaddr_in6 *)ai->ai_addr;
382 udp_port = ntohs(in6->sin6_port);
383 break;
384 }
385 #endif
386 }
387 }
388 freeaddrinfo(res);
389 }
390
391 /*
392 * We need to check /etc/services for ambiguous entries.
393 * If we find an ambiguous entry, and it has the
394 * same port number, change the proto to PROTO_UNDEF
395 * so both TCP and UDP will be checked.
396 */
397 if (tcp_port >= 0) {
398 *port = tcp_port;
399 *proto = IPPROTO_TCP;
400 if (udp_port >= 0) {
401 if (udp_port == tcp_port)
402 *proto = PROTO_UNDEF;
403 #ifdef notdef
404 else
405 /* Can't handle ambiguous names that refer
406 to different port numbers. */
407 warning("ambiguous port %s in /etc/services",
408 name);
409 #endif
410 }
411 return 1;
412 }
413 if (udp_port >= 0) {
414 *port = udp_port;
415 *proto = IPPROTO_UDP;
416 return 1;
417 }
418 #if defined(ultrix) || defined(__osf__)
419 /* Special hack in case NFS isn't in /etc/services */
420 if (strcmp(name, "nfs") == 0) {
421 *port = 2049;
422 *proto = PROTO_UNDEF;
423 return 1;
424 }
425 #endif
426 return 0;
427 }
428
429 /*
430 * Convert a string in the form PPP-PPP, where correspond to ports, to
431 * a starting and ending port in a port range.
432 * Return 0 on failure.
433 */
434 int
pcap_nametoportrange(const char * name,int * port1,int * port2,int * proto)435 pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
436 {
437 u_int p1, p2;
438 char *off, *cpy;
439 int save_proto;
440
441 if (sscanf(name, "%d-%d", &p1, &p2) != 2) {
442 if ((cpy = strdup(name)) == NULL)
443 return 0;
444
445 if ((off = strchr(cpy, '-')) == NULL) {
446 free(cpy);
447 return 0;
448 }
449
450 *off = '\0';
451
452 if (pcap_nametoport(cpy, port1, proto) == 0) {
453 free(cpy);
454 return 0;
455 }
456 save_proto = *proto;
457
458 if (pcap_nametoport(off + 1, port2, proto) == 0) {
459 free(cpy);
460 return 0;
461 }
462 free(cpy);
463
464 if (*proto != save_proto)
465 *proto = PROTO_UNDEF;
466 } else {
467 *port1 = p1;
468 *port2 = p2;
469 *proto = PROTO_UNDEF;
470 }
471
472 return 1;
473 }
474
475 /*
476 * XXX - not guaranteed to be thread-safe! See below for platforms
477 * on which it is thread-safe and on which it isn't.
478 */
479 int
pcap_nametoproto(const char * str)480 pcap_nametoproto(const char *str)
481 {
482 struct protoent *p;
483 #if defined(HAVE_LINUX_GETNETBYNAME_R)
484 /*
485 * We have Linux's reentrant getprotobyname_r().
486 */
487 struct protoent result_buf;
488 char buf[1024]; /* arbitrary size */
489 int err;
490
491 err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p);
492 if (err != 0) {
493 /*
494 * XXX - dynamically allocate the buffer, and make it
495 * bigger if we get ERANGE back?
496 */
497 return 0;
498 }
499 #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
500 /*
501 * We have Solaris's and IRIX's reentrant getprotobyname_r().
502 */
503 struct protoent result_buf;
504 char buf[1024]; /* arbitrary size */
505
506 p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf);
507 #elif defined(HAVE_AIX_GETNETBYNAME_R)
508 /*
509 * We have AIX's reentrant getprotobyname_r().
510 */
511 struct protoent result_buf;
512 struct protoent_data proto_data;
513
514 if (getprotobyname_r(str, &result_buf, &proto_data) == -1)
515 p = NULL;
516 else
517 p = &result_buf;
518 #else
519 /*
520 * We don't have any getprotobyname_r(); either we have a
521 * getprotobyname() that uses thread-specific data, in which
522 * case we're thread-safe (sufficiently recent FreeBSD,
523 * sufficiently recent Darwin-based OS, sufficiently recent
524 * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have
525 * the traditional getprotobyname() (everything else, including
526 * current NetBSD and OpenBSD), in which case we're not
527 * thread-safe.
528 */
529 p = getprotobyname(str);
530 #endif
531 if (p != 0)
532 return p->p_proto;
533 else
534 return PROTO_UNDEF;
535 }
536
537 #include "ethertype.h"
538
539 struct eproto {
540 const char *s;
541 u_short p;
542 };
543
544 /*
545 * Static data base of ether protocol types.
546 * tcpdump used to import this, and it's declared as an export on
547 * Debian, at least, so make it a public symbol, even though we
548 * don't officially export it by declaring it in a header file.
549 * (Programs *should* do this themselves, as tcpdump now does.)
550 *
551 * We declare it here, right before defining it, to squelch any
552 * warnings we might get from compilers about the lack of a
553 * declaration.
554 */
555 PCAP_API struct eproto eproto_db[];
556 PCAP_API_DEF struct eproto eproto_db[] = {
557 { "pup", ETHERTYPE_PUP },
558 { "xns", ETHERTYPE_NS },
559 { "ip", ETHERTYPE_IP },
560 #ifdef INET6
561 { "ip6", ETHERTYPE_IPV6 },
562 #endif
563 { "arp", ETHERTYPE_ARP },
564 { "rarp", ETHERTYPE_REVARP },
565 { "sprite", ETHERTYPE_SPRITE },
566 { "mopdl", ETHERTYPE_MOPDL },
567 { "moprc", ETHERTYPE_MOPRC },
568 { "decnet", ETHERTYPE_DN },
569 { "lat", ETHERTYPE_LAT },
570 { "sca", ETHERTYPE_SCA },
571 { "lanbridge", ETHERTYPE_LANBRIDGE },
572 { "vexp", ETHERTYPE_VEXP },
573 { "vprod", ETHERTYPE_VPROD },
574 { "atalk", ETHERTYPE_ATALK },
575 { "atalkarp", ETHERTYPE_AARP },
576 { "loopback", ETHERTYPE_LOOPBACK },
577 { "decdts", ETHERTYPE_DECDTS },
578 { "decdns", ETHERTYPE_DECDNS },
579 { (char *)0, 0 }
580 };
581
582 int
pcap_nametoeproto(const char * s)583 pcap_nametoeproto(const char *s)
584 {
585 struct eproto *p = eproto_db;
586
587 while (p->s != 0) {
588 if (strcmp(p->s, s) == 0)
589 return p->p;
590 p += 1;
591 }
592 return PROTO_UNDEF;
593 }
594
595 #include "llc.h"
596
597 /* Static data base of LLC values. */
598 static struct eproto llc_db[] = {
599 { "iso", LLCSAP_ISONS },
600 { "stp", LLCSAP_8021D },
601 { "ipx", LLCSAP_IPX },
602 { "netbeui", LLCSAP_NETBEUI },
603 { (char *)0, 0 }
604 };
605
606 int
pcap_nametollc(const char * s)607 pcap_nametollc(const char *s)
608 {
609 struct eproto *p = llc_db;
610
611 while (p->s != 0) {
612 if (strcmp(p->s, s) == 0)
613 return p->p;
614 p += 1;
615 }
616 return PROTO_UNDEF;
617 }
618
619 /* Hex digit to 8-bit unsigned integer. */
620 static inline u_char
xdtoi(u_char c)621 xdtoi(u_char c)
622 {
623 if (isdigit(c))
624 return (u_char)(c - '0');
625 else if (islower(c))
626 return (u_char)(c - 'a' + 10);
627 else
628 return (u_char)(c - 'A' + 10);
629 }
630
631 int
__pcap_atoin(const char * s,bpf_u_int32 * addr)632 __pcap_atoin(const char *s, bpf_u_int32 *addr)
633 {
634 u_int n;
635 int len;
636
637 *addr = 0;
638 len = 0;
639 for (;;) {
640 n = 0;
641 while (*s && *s != '.')
642 n = n * 10 + *s++ - '0';
643 *addr <<= 8;
644 *addr |= n & 0xff;
645 len += 8;
646 if (*s == '\0')
647 return len;
648 ++s;
649 }
650 /* NOTREACHED */
651 }
652
653 int
__pcap_atodn(const char * s,bpf_u_int32 * addr)654 __pcap_atodn(const char *s, bpf_u_int32 *addr)
655 {
656 #define AREASHIFT 10
657 #define AREAMASK 0176000
658 #define NODEMASK 01777
659
660 u_int node, area;
661
662 if (sscanf(s, "%d.%d", &area, &node) != 2)
663 return(0);
664
665 *addr = (area << AREASHIFT) & AREAMASK;
666 *addr |= (node & NODEMASK);
667
668 return(32);
669 }
670
671 /*
672 * Convert 's', which can have the one of the forms:
673 *
674 * "xx:xx:xx:xx:xx:xx"
675 * "xx.xx.xx.xx.xx.xx"
676 * "xx-xx-xx-xx-xx-xx"
677 * "xxxx.xxxx.xxxx"
678 * "xxxxxxxxxxxx"
679 *
680 * (or various mixes of ':', '.', and '-') into a new
681 * ethernet address. Assumes 's' is well formed.
682 */
683 u_char *
pcap_ether_aton(const char * s)684 pcap_ether_aton(const char *s)
685 {
686 register u_char *ep, *e;
687 register u_char d;
688
689 e = ep = (u_char *)malloc(6);
690 if (e == NULL)
691 return (NULL);
692
693 while (*s) {
694 if (*s == ':' || *s == '.' || *s == '-')
695 s += 1;
696 d = xdtoi(*s++);
697 if (isxdigit((unsigned char)*s)) {
698 d <<= 4;
699 d |= xdtoi(*s++);
700 }
701 *ep++ = d;
702 }
703
704 return (e);
705 }
706
707 #ifndef HAVE_ETHER_HOSTTON
708 /*
709 * Roll our own.
710 * XXX - not thread-safe, because pcap_next_etherent() isn't thread-
711 * safe! Needs a mutex or a thread-safe pcap_next_etherent().
712 */
713 u_char *
pcap_ether_hostton(const char * name)714 pcap_ether_hostton(const char *name)
715 {
716 register struct pcap_etherent *ep;
717 register u_char *ap;
718 static FILE *fp = NULL;
719 static int init = 0;
720
721 if (!init) {
722 fp = fopen(PCAP_ETHERS_FILE, "r");
723 ++init;
724 if (fp == NULL)
725 return (NULL);
726 } else if (fp == NULL)
727 return (NULL);
728 else
729 rewind(fp);
730
731 while ((ep = pcap_next_etherent(fp)) != NULL) {
732 if (strcmp(ep->name, name) == 0) {
733 ap = (u_char *)malloc(6);
734 if (ap != NULL) {
735 memcpy(ap, ep->addr, 6);
736 return (ap);
737 }
738 break;
739 }
740 }
741 return (NULL);
742 }
743 #else
744 /*
745 * Use the OS-supplied routine.
746 * This *should* be thread-safe; the API doesn't have a static buffer.
747 */
748 u_char *
pcap_ether_hostton(const char * name)749 pcap_ether_hostton(const char *name)
750 {
751 register u_char *ap;
752 u_char a[6];
753
754 ap = NULL;
755 if (ether_hostton(name, (struct ether_addr *)a) == 0) {
756 ap = (u_char *)malloc(6);
757 if (ap != NULL)
758 memcpy((char *)ap, (char *)a, 6);
759 }
760 return (ap);
761 }
762 #endif
763
764 /*
765 * XXX - not guaranteed to be thread-safe!
766 */
767 int
768 #ifdef DECNETLIB
__pcap_nametodnaddr(const char * name,u_short * res)769 __pcap_nametodnaddr(const char *name, u_short *res)
770 {
771 struct nodeent *getnodebyname();
772 struct nodeent *nep;
773
774 nep = getnodebyname(name);
775 if (nep == ((struct nodeent *)0))
776 return(0);
777
778 memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short));
779 return(1);
780 #else
781 __pcap_nametodnaddr(const char *name _U_, u_short *res _U_)
782 {
783 return(0);
784 #endif
785 }
786