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