]> The Tcpdump Group git mirrors - libpcap/blob - nametoaddr.c
Lose the unused NTOHS macro.
[libpcap] / nametoaddr.c
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 #include <config.h>
26
27 #ifdef _WIN32
28 #include <winsock2.h>
29 #include <ws2tcpip.h>
30 #else /* _WIN32 */
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/time.h>
35
36 #include <netinet/in.h>
37
38 #if defined(__linux__) && defined(HAVE_ETHER_HOSTTON)
39 #include <features.h>
40 #if ! defined(__GLIBC__) && ! defined(__UCLIBC__)
41 /*
42 * In musl libc (which does not identify itself) ether_hostton() is
43 * present and does not work.
44 */
45 #undef HAVE_ETHER_HOSTTON
46 #endif
47 #endif // defined(__linux__) && defined(HAVE_ETHER_HOSTTON)
48
49 #ifdef HAVE_ETHER_HOSTTON
50 #if defined(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
51 /*
52 * OK, just include <net/ethernet.h>.
53 */
54 #include <net/ethernet.h>
55 #elif defined(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
56 /*
57 * OK, just include <netinet/ether.h>
58 */
59 #include <netinet/ether.h>
60 #elif defined(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
61 /*
62 * OK, just include <sys/ethernet.h>
63 */
64 #include <sys/ethernet.h>
65 #elif defined(ARPA_INET_H_DECLARES_ETHER_HOSTTON)
66 /*
67 * OK, just include <arpa/inet.h>
68 */
69 #include <arpa/inet.h>
70 #elif defined(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
71 /*
72 * OK, include <netinet/if_ether.h>, after all the other stuff we
73 * need to include or define for its benefit.
74 */
75 #define NEED_NETINET_IF_ETHER_H
76 #else
77 /*
78 * We'll have to declare it ourselves.
79 * If <netinet/if_ether.h> defines struct ether_addr, include
80 * it. Otherwise, define it ourselves.
81 */
82 #ifdef HAVE_STRUCT_ETHER_ADDR
83 #define NEED_NETINET_IF_ETHER_H
84 #else /* HAVE_STRUCT_ETHER_ADDR */
85 struct ether_addr {
86 unsigned char ether_addr_octet[6];
87 };
88 #endif /* HAVE_STRUCT_ETHER_ADDR */
89 #endif /* what declares ether_hostton() */
90
91 #ifdef NEED_NETINET_IF_ETHER_H
92 #include <net/if.h> /* Needed on some platforms */
93 #include <netinet/in.h> /* Needed on some platforms */
94 #include <netinet/if_ether.h>
95 #endif /* NEED_NETINET_IF_ETHER_H */
96
97 #ifndef HAVE_DECL_ETHER_HOSTTON
98 /*
99 * No header declares it, so declare it ourselves.
100 */
101 extern int ether_hostton(const char *, struct ether_addr *);
102 #endif /* !defined(HAVE_DECL_ETHER_HOSTTON) */
103 #endif /* HAVE_ETHER_HOSTTON */
104
105 #include <arpa/inet.h>
106 #include <netdb.h>
107 #endif /* _WIN32 */
108
109 #include <errno.h>
110 #include <stdlib.h>
111 #include <string.h>
112 #include <stdio.h>
113
114 #include "pcap-int.h"
115
116 #include "diag-control.h"
117
118 #include "gencode.h"
119 #include <pcap/namedb.h>
120 #include "nametoaddr.h"
121
122 #include "thread-local.h"
123
124 #ifdef HAVE_OS_PROTO_H
125 #include "os-proto.h"
126 #endif
127
128 #ifndef NTOHL
129 #define NTOHL(x) (x) = ntohl(x)
130 #endif
131
132 /*
133 * Convert host name to internet address.
134 * Return 0 upon failure.
135 * XXX - not thread-safe; don't use it inside libpcap.
136 */
137 bpf_u_int32 **
138 pcap_nametoaddr(const char *name)
139 {
140 #ifndef h_addr
141 static bpf_u_int32 *hlist[2];
142 #endif
143 bpf_u_int32 **p;
144 struct hostent *hp;
145
146 /*
147 * gethostbyname() is deprecated on Windows, perhaps because
148 * it's not thread-safe, or because it doesn't support IPv6,
149 * or both.
150 *
151 * We deprecate pcap_nametoaddr() on all platforms because
152 * it's not thread-safe; we supply it for backwards compatibility,
153 * so suppress the deprecation warning. We could, I guess,
154 * use getaddrinfo() and construct the array ourselves, but
155 * that's probably not worth the effort, as that wouldn't make
156 * this thread-safe - we can't change the API to require that
157 * our caller free the address array, so we still have to reuse
158 * a local array.
159 */
160 DIAG_OFF_DEPRECATION
161 if ((hp = gethostbyname(name)) != NULL) {
162 DIAG_ON_DEPRECATION
163 #ifndef h_addr
164 hlist[0] = (bpf_u_int32 *)hp->h_addr;
165 NTOHL(hp->h_addr);
166 return hlist;
167 #else
168 for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
169 NTOHL(**p);
170 return (bpf_u_int32 **)hp->h_addr_list;
171 #endif
172 }
173 else
174 return 0;
175 }
176
177 struct addrinfo *
178 pcap_nametoaddrinfo(const char *name)
179 {
180 struct addrinfo hints, *res;
181 int error;
182
183 memset(&hints, 0, sizeof(hints));
184 hints.ai_family = PF_UNSPEC;
185 hints.ai_socktype = SOCK_STREAM; /*not really*/
186 hints.ai_protocol = IPPROTO_TCP; /*not really*/
187 error = getaddrinfo(name, NULL, &hints, &res);
188 if (error)
189 return NULL;
190 else
191 return res;
192 }
193
194 /*
195 * Convert net name to internet address.
196 * Return 0 upon failure.
197 * XXX - not guaranteed to be thread-safe! See below for platforms
198 * on which it is thread-safe and on which it isn't.
199 */
200 #if defined(_WIN32) || defined(__CYGWIN__)
201 bpf_u_int32
202 pcap_nametonetaddr(const char *name _U_)
203 {
204 /*
205 * There's no "getnetbyname()" on Windows.
206 *
207 * XXX - I guess we could use the BSD code to read
208 * C:\Windows\System32\drivers\etc/networks, assuming
209 * that's its home on all the versions of Windows
210 * we use, but that file probably just has the loopback
211 * network on 127/24 on 99 44/100% of Windows machines.
212 *
213 * (Heck, these days it probably just has that on 99 44/100%
214 * of *UN*X* machines.)
215 */
216 return 0;
217 }
218 #else /* _WIN32 */
219 bpf_u_int32
220 pcap_nametonetaddr(const char *name)
221 {
222 /*
223 * UN*X.
224 */
225 struct netent *np;
226 #if defined(HAVE_LINUX_GETNETBYNAME_R)
227 /*
228 * We have Linux's reentrant getnetbyname_r().
229 */
230 struct netent result_buf;
231 char buf[1024]; /* arbitrary size */
232 int h_errnoval;
233 int err;
234
235 /*
236 * Apparently, the man page at
237 *
238 * http://man7.org/linux/man-pages/man3/getnetbyname_r.3.html
239 *
240 * lies when it says
241 *
242 * If the function call successfully obtains a network record,
243 * then *result is set pointing to result_buf; otherwise, *result
244 * is set to NULL.
245 *
246 * and, in fact, at least in some versions of GNU libc, it does
247 * *not* always get set if getnetbyname_r() succeeds.
248 */
249 np = NULL;
250 err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
251 &h_errnoval);
252 if (err != 0) {
253 /*
254 * XXX - dynamically allocate the buffer, and make it
255 * bigger if we get ERANGE back?
256 */
257 return 0;
258 }
259 #elif defined(HAVE_SOLARIS_GETNETBYNAME_R)
260 /*
261 * We have Solaris's reentrant getnetbyname_r().
262 */
263 struct netent result_buf;
264 char buf[1024]; /* arbitrary size */
265
266 np = getnetbyname_r(name, &result_buf, buf, (int)sizeof buf);
267 #elif defined(HAVE_AIX_GETNETBYNAME_R)
268 /*
269 * We have AIX's reentrant getnetbyname_r().
270 */
271 struct netent result_buf;
272 struct netent_data net_data;
273
274 if (getnetbyname_r(name, &result_buf, &net_data) == -1)
275 np = NULL;
276 else
277 np = &result_buf;
278 #else
279 /*
280 * We don't have any getnetbyname_r(); either we have a
281 * getnetbyname() that uses thread-specific data, in which
282 * case we're thread-safe (sufficiently recent FreeBSD,
283 * sufficiently recent Darwin-based OS, sufficiently recent
284 * HP-UX, or we have the
285 * traditional getnetbyname() (everything else, including
286 * current NetBSD and OpenBSD), in which case we're not
287 * thread-safe.
288 */
289 np = getnetbyname(name);
290 #endif
291 if (np != NULL)
292 return np->n_net;
293 else
294 return 0;
295 }
296 #endif /* _WIN32 */
297
298 /*
299 * Convert a port name to its port and protocol numbers.
300 * We assume only TCP or UDP.
301 * Return 0 upon failure.
302 */
303 int
304 pcap_nametoport(const char *name, int *port, int *proto)
305 {
306 struct addrinfo hints, *res, *ai;
307 int error;
308 struct sockaddr_in *in4;
309 struct sockaddr_in6 *in6;
310 int tcp_port = -1;
311 int udp_port = -1;
312
313 /*
314 * We check for both TCP and UDP in case there are
315 * ambiguous entries.
316 */
317 memset(&hints, 0, sizeof(hints));
318 hints.ai_family = PF_UNSPEC;
319 hints.ai_socktype = SOCK_STREAM;
320 hints.ai_protocol = IPPROTO_TCP;
321 error = getaddrinfo(NULL, name, &hints, &res);
322 if (error != 0) {
323 if (error != EAI_NONAME &&
324 error != EAI_SERVICE) {
325 /*
326 * This is a real error, not just "there's
327 * no such service name".
328 * XXX - this doesn't return an error string.
329 */
330 return 0;
331 }
332 } else {
333 /*
334 * OK, we found it. Did it find anything?
335 */
336 for (ai = res; ai != NULL; ai = ai->ai_next) {
337 /*
338 * Does it have an address?
339 */
340 if (ai->ai_addr != NULL) {
341 /*
342 * Yes. Get a port number; we're done.
343 */
344 if (ai->ai_addr->sa_family == AF_INET) {
345 in4 = (struct sockaddr_in *)ai->ai_addr;
346 tcp_port = ntohs(in4->sin_port);
347 break;
348 }
349 if (ai->ai_addr->sa_family == AF_INET6) {
350 in6 = (struct sockaddr_in6 *)ai->ai_addr;
351 tcp_port = ntohs(in6->sin6_port);
352 break;
353 }
354 }
355 }
356 freeaddrinfo(res);
357 }
358
359 memset(&hints, 0, sizeof(hints));
360 hints.ai_family = PF_UNSPEC;
361 hints.ai_socktype = SOCK_DGRAM;
362 hints.ai_protocol = IPPROTO_UDP;
363 error = getaddrinfo(NULL, name, &hints, &res);
364 if (error != 0) {
365 if (error != EAI_NONAME &&
366 error != EAI_SERVICE) {
367 /*
368 * This is a real error, not just "there's
369 * no such service name".
370 * XXX - this doesn't return an error string.
371 */
372 return 0;
373 }
374 } else {
375 /*
376 * OK, we found it. Did it find anything?
377 */
378 for (ai = res; ai != NULL; ai = ai->ai_next) {
379 /*
380 * Does it have an address?
381 */
382 if (ai->ai_addr != NULL) {
383 /*
384 * Yes. Get a port number; we're done.
385 */
386 if (ai->ai_addr->sa_family == AF_INET) {
387 in4 = (struct sockaddr_in *)ai->ai_addr;
388 udp_port = ntohs(in4->sin_port);
389 break;
390 }
391 if (ai->ai_addr->sa_family == AF_INET6) {
392 in6 = (struct sockaddr_in6 *)ai->ai_addr;
393 udp_port = ntohs(in6->sin6_port);
394 break;
395 }
396 }
397 }
398 freeaddrinfo(res);
399 }
400
401 /*
402 * We need to check /etc/services for ambiguous entries.
403 * If we find an ambiguous entry, and it has the
404 * same port number, change the proto to PROTO_UNDEF
405 * so both TCP and UDP will be checked.
406 */
407 if (tcp_port >= 0) {
408 *port = tcp_port;
409 *proto = IPPROTO_TCP;
410 if (udp_port >= 0) {
411 if (udp_port == tcp_port)
412 *proto = PROTO_UNDEF;
413 #ifdef notdef
414 else
415 /* Can't handle ambiguous names that refer
416 to different port numbers. */
417 warning("ambiguous port %s in /etc/services",
418 name);
419 #endif
420 }
421 return 1;
422 }
423 if (udp_port >= 0) {
424 *port = udp_port;
425 *proto = IPPROTO_UDP;
426 return 1;
427 }
428 return 0;
429 }
430
431 /*
432 * Convert a string in the form PPP-PPP, where correspond to ports, to
433 * a starting and ending port in a port range.
434 * Return 0 on failure.
435 */
436 int
437 pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
438 {
439 char *off, *cpy;
440 int save_proto;
441
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
467 return 1;
468 }
469
470 /*
471 * XXX - not guaranteed to be thread-safe! See below for platforms
472 * on which it is thread-safe and on which it isn't.
473 */
474 int
475 pcap_nametoproto(const char *str)
476 {
477 struct protoent *p;
478 #if defined(HAVE_LINUX_GETPROTOBYNAME_R)
479 /*
480 * We have Linux's reentrant getprotobyname_r().
481 */
482 struct protoent result_buf;
483 char buf[1024]; // "...1024 bytes should be sufficient for most applications."
484 int err;
485
486 err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p);
487 /*
488 * As far as GNU libc implementation goes, an "error" means the
489 * protocol database could not be searched, which could mean err ==
490 * ERANGE if the buffer is too small or ENOENT if the protocols(5)
491 * file does not exist (the man page does not document the latter
492 * eventuality). If the database has been searched normally and the
493 * requested protocol name was not found, it is not an "error" and
494 * err == 0.
495 *
496 * This notwithstanding, p == NULL iff a record was not found for any
497 * reason (whether an "error" or not), which is the same semantics as
498 * in every other HAVE_xxxxx branch of this block. The final check
499 * after the block will catch that if necessary.
500 */
501 if (err != 0) {
502 /*
503 * XXX - dynamically allocate the buffer, and make it
504 * bigger if we get ERANGE back?
505 */
506 return PROTO_UNDEF;
507 }
508 #elif defined(HAVE_SOLARIS_GETPROTOBYNAME_R)
509 /*
510 * We have Solaris's reentrant getprotobyname_r().
511 */
512 struct protoent result_buf;
513 char buf[1024]; // "...must be at least 1024 bytes."
514
515 p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf);
516 #elif defined(HAVE_AIX_GETPROTOBYNAME_R)
517 /*
518 * We have AIX's reentrant getprotobyname_r().
519 */
520 struct protoent result_buf;
521 // "The structure must be zero-filled before it is used..." (OpenBSD).
522 struct protoent_data proto_data = {0};
523
524 if (getprotobyname_r(str, &result_buf, &proto_data) == -1)
525 p = NULL;
526 else
527 p = &result_buf;
528 #else
529 /*
530 * We don't have any getprotobyname_r(); either we have a
531 * getprotobyname() that uses thread-specific data, in which
532 * case we're thread-safe (sufficiently recent FreeBSD,
533 * sufficiently recent Darwin-based OS, sufficiently recent
534 * HP-UX, Windows), or we have
535 * the traditional getprotobyname() (everything else, including
536 * current NetBSD and OpenBSD), in which case we're not
537 * thread-safe.
538 */
539 p = getprotobyname(str);
540 #endif
541 if (p != 0)
542 return p->p_proto;
543 else
544 return PROTO_UNDEF;
545 }
546
547 #include "ethertype.h"
548
549 struct eproto {
550 const char *s;
551 u_short p;
552 };
553
554 /*
555 * Static data base of ether protocol types.
556 * tcpdump used to import this, and it's declared as an export on
557 * Debian, at least, so make it a public symbol, even though we
558 * don't officially export it by declaring it in a header file.
559 * (Programs *should* do this themselves, as tcpdump now does.)
560 *
561 * We declare it here, right before defining it, to squelch any
562 * warnings we might get from compilers about the lack of a
563 * declaration.
564 */
565 PCAP_API struct eproto eproto_db[];
566 PCAP_API_DEF struct eproto eproto_db[] = {
567 { "aarp", ETHERTYPE_AARP },
568 { "arp", ETHERTYPE_ARP },
569 { "atalk", ETHERTYPE_ATALK },
570 { "decnet", ETHERTYPE_DN },
571 { "ip", ETHERTYPE_IP },
572 { "ip6", ETHERTYPE_IPV6 },
573 { "lat", ETHERTYPE_LAT },
574 { "loopback", ETHERTYPE_LOOPBACK },
575 { "mopdl", ETHERTYPE_MOPDL },
576 { "moprc", ETHERTYPE_MOPRC },
577 { "rarp", ETHERTYPE_REVARP },
578 { "sca", ETHERTYPE_SCA },
579 { (char *)0, 0 }
580 };
581
582 int
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
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 u_char
621 pcapint_xdtoi(const u_char c)
622 {
623 if (c >= '0' && c <= '9')
624 return (u_char)(c - '0');
625 else if (c >= 'a' && c <= 'f')
626 return (u_char)(c - 'a' + 10);
627 else
628 return (u_char)(c - 'A' + 10);
629 }
630
631 int
632 pcapint_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 if (n > 25) {
643 /* The result will be > 255 */
644 return -1;
645 }
646 n = n * 10 + *s++ - '0';
647 }
648 if (n > 255)
649 return -1;
650 *addr <<= 8;
651 *addr |= n & 0xff;
652 len += 8;
653 if (*s == '\0')
654 return len;
655 ++s;
656 }
657 /* NOTREACHED */
658 }
659
660 /*
661 * If 's' is not a string that is a well-formed DECnet address (aa.nnnn),
662 * return zero. Otherwise parse the address into the low 16 bits of 'addr'
663 * and return a non-zero. The binary DECnet address consists of a 6-bit area
664 * number and a 10-bit node number; neither area 0 nor node 0 are valid for
665 * normal addressing purposes, but either can appear on the wire.
666 */
667 int
668 pcapint_atodn(const char *s, bpf_u_int32 *addr)
669 {
670 #define AREASHIFT 10
671 #define AREAMASK 0176000
672 #define NODEMASK 01777
673
674 /* Initialize to squelch a compiler warning only. */
675 u_int node = 0, area = 0;
676 /*
677 * +--+ +--+
678 * | | | |
679 * v | v |
680 * --> START --> AREA --> DOT --> NODE -->
681 * | | | |
682 * | v v |
683 * +--------> INVALID <------+
684 */
685 enum {
686 START,
687 AREA,
688 DOT,
689 NODE,
690 INVALID
691 } fsm_state = START;
692
693 while (*s) {
694 switch (fsm_state) {
695 case START:
696 if (PCAP_ISDIGIT(*s)) {
697 area = *s - '0';
698 fsm_state = AREA;
699 break;
700 }
701 fsm_state = INVALID;
702 break;
703 case AREA:
704 if (*s == '.') {
705 fsm_state = DOT;
706 break;
707 }
708 if (PCAP_ISDIGIT(*s)) {
709 area = area * 10 + *s - '0';
710 if (area <= AREAMASK >> AREASHIFT)
711 break;
712 }
713 fsm_state = INVALID;
714 break;
715 case DOT:
716 if (PCAP_ISDIGIT(*s)) {
717 node = *s - '0';
718 fsm_state = NODE;
719 break;
720 }
721 fsm_state = INVALID;
722 break;
723 case NODE:
724 if (PCAP_ISDIGIT(*s)) {
725 node = node * 10 + *s - '0';
726 if (node <= NODEMASK)
727 break;
728 }
729 fsm_state = INVALID;
730 break;
731 case INVALID:
732 return 0;
733 } /* switch */
734 s++;
735 } /* while */
736 /*
737 * This condition is false if the string comes from the lexer, but
738 * let's not depend on that.
739 */
740 if (fsm_state != NODE)
741 return 0;
742
743 *addr = area << AREASHIFT | node;
744 return(32);
745 }
746
747 /*
748 * libpcap ARCnet address format is "^\$[0-9a-fA-F]{1,2}$" in regexp syntax.
749 * Iff the given string is a well-formed ARCnet address, parse the string,
750 * store the 8-bit unsigned value into the provided integer and return 1.
751 * Otherwise return 0.
752 *
753 * --> START -- $ --> DOLLAR -- [0-9a-fA-F] --> HEX1 -- \0 -->-+
754 * | | | |
755 * [.] [.] [0-9a-fA-F] |
756 * | | | |
757 * v v v v
758 * (invalid) <--------+-<---------------[.]-- HEX2 -- \0 -->-+--> (valid)
759 */
760 int
761 pcapint_atoan(const char *s, uint8_t *addr)
762 {
763 enum {
764 START,
765 DOLLAR,
766 HEX1,
767 HEX2,
768 } fsm_state = START;
769 uint8_t tmp = 0;
770
771 while (*s) {
772 switch (fsm_state) {
773 case START:
774 if (*s != '$')
775 goto invalid;
776 fsm_state = DOLLAR;
777 break;
778 case DOLLAR:
779 if (! PCAP_ISXDIGIT(*s))
780 goto invalid;
781 tmp = pcapint_xdtoi(*s);
782 fsm_state = HEX1;
783 break;
784 case HEX1:
785 if (! PCAP_ISXDIGIT(*s))
786 goto invalid;
787 tmp <<= 4;
788 tmp |= pcapint_xdtoi(*s);
789 fsm_state = HEX2;
790 break;
791 case HEX2:
792 goto invalid;
793 } // switch
794 s++;
795 } // while
796 if (fsm_state == HEX1 || fsm_state == HEX2) {
797 *addr = tmp;
798 return 1;
799 }
800
801 invalid:
802 return 0;
803 }
804
805 /*
806 * Convert 's', which can have the one of the forms:
807 *
808 * "xx:xx:xx:xx:xx:xx"
809 * "xx.xx.xx.xx.xx.xx"
810 * "xx-xx-xx-xx-xx-xx"
811 * "xxxx.xxxx.xxxx"
812 * "xxxxxxxxxxxx"
813 *
814 * (or various mixes of ':', '.', and '-') into a new
815 * ethernet address. Assumes 's' is well formed.
816 */
817 u_char *
818 pcap_ether_aton(const char *s)
819 {
820 register u_char *ep, *e;
821 register u_char d;
822
823 e = ep = (u_char *)malloc(6);
824 if (e == NULL)
825 return (NULL);
826
827 while (*s) {
828 if (*s == ':' || *s == '.' || *s == '-')
829 s += 1;
830 d = pcapint_xdtoi(*s++);
831 if (PCAP_ISXDIGIT(*s)) {
832 d <<= 4;
833 d |= pcapint_xdtoi(*s++);
834 }
835 *ep++ = d;
836 }
837
838 return (e);
839 }
840
841 #ifndef HAVE_ETHER_HOSTTON
842 /*
843 * Roll our own.
844 *
845 * This should be thread-safe, as we define the static variables
846 * we use to be thread-local, and as pcap_next_etherent() does so
847 * as well.
848 */
849 u_char *
850 pcap_ether_hostton(const char *name)
851 {
852 register struct pcap_etherent *ep;
853 register u_char *ap;
854 static thread_local FILE *fp = NULL;
855 static thread_local int init = 0;
856
857 if (!init) {
858 fp = fopen(PCAP_ETHERS_FILE, "r");
859 ++init;
860 if (fp == NULL)
861 return (NULL);
862 } else if (fp == NULL)
863 return (NULL);
864 else
865 rewind(fp);
866
867 while ((ep = pcap_next_etherent(fp)) != NULL) {
868 if (strcmp(ep->name, name) == 0) {
869 ap = (u_char *)malloc(6);
870 if (ap != NULL) {
871 memcpy(ap, ep->addr, 6);
872 return (ap);
873 }
874 break;
875 }
876 }
877 return (NULL);
878 }
879 #else
880 /*
881 * Use the OS-supplied routine.
882 * This *should* be thread-safe; the API doesn't have a static buffer.
883 */
884 u_char *
885 pcap_ether_hostton(const char *name)
886 {
887 register u_char *ap;
888 u_char a[6];
889 char namebuf[1024];
890
891 /*
892 * In AIX 7.1 and 7.2: int ether_hostton(char *, struct ether_addr *);
893 */
894 pcapint_strlcpy(namebuf, name, sizeof(namebuf));
895 ap = NULL;
896 if (ether_hostton(namebuf, (struct ether_addr *)a) == 0) {
897 ap = (u_char *)malloc(6);
898 if (ap != NULL)
899 memcpy((char *)ap, (char *)a, 6);
900 }
901 return (ap);
902 }
903 #endif