diff options
author | Denis Ovsienko <denis@ovsienko.info> | 2023-03-12 16:44:28 +0000 |
---|---|---|
committer | Denis Ovsienko <denis@ovsienko.info> | 2023-03-12 16:44:28 +0000 |
commit | 989e1947f418e501bcea4d2cee1a986b455fe173 (patch) | |
tree | d83b9ea1cfc7c0376da304682e15cba5c368e8aa | |
parent | 023844895059279ad51b0b24cc1de5c121d1833e (diff) | |
download | libpcap-989e1947f418e501bcea4d2cee1a986b455fe173.tar.gz |
Clean up DECnet address handling.
In gen_scode() make any id invalid DECnet address. In gen_ncode() make
{N} invalid DECnet address. In __pcap_atodn() replace sscanf() with an
FSM to parse the entire input string and to require a valid nominal
DECnet address syntax. Remove __pcap_nametodnaddr(), which worked on
Ultrix only. Add various comments to explain the context better. In
pcap-filter(3PCAP) clarify the nominal DECnet address syntax and remove
mentions of the host name translation.
Before:
filtertest: decnet name support not included, 'abc' cannot be translated
1 -- no error
100.2000 -- no error
1.2.3 -- no error
1.2.3.4 -- no error
After:
filtertest: invalid DECnet address 'abc'
filtertest: invalid DECnet address '1'
filtertest: invalid DECnet address '100.2000'
filtertest: invalid DECnet address '1.2.3'
filtertest: invalid DECnet address '1.2.3.4'
-rw-r--r-- | CHANGES | 1 | ||||
-rw-r--r-- | gencode.c | 45 | ||||
-rw-r--r-- | nametoaddr.c | 109 | ||||
-rw-r--r-- | nametoaddr.h | 1 | ||||
-rw-r--r-- | pcap-filter.manmisc.in | 11 |
5 files changed, 111 insertions, 56 deletions
@@ -4,6 +4,7 @@ DayOfTheWeek, Month DD, YYYY / The Tcpdump Group Use C99 fixed-width integer types, rather than self-defined fixed-width integer types, in rpcap code. Remove an always-false pointer test from snf_read(). + Clean up DECnet address handling. Link-layer types: Add LINKTYPE_ETW/DLT_ETW. Add LINKTYPE_NETANALYZER_NG/DLT_NETANALYZER_NG (pull request @@ -6775,21 +6775,12 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q) bpf_error(cstate, "only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name"); } else if (proto == Q_DECNET) { - unsigned short dn_addr; - - if (!__pcap_nametodnaddr(name, &dn_addr)) { -#ifdef DECNETLIB - bpf_error(cstate, "unknown decnet host name '%s'\n", name); -#else - bpf_error(cstate, "decnet name support not included, '%s' cannot be translated\n", - name); -#endif - } /* - * I don't think DECNET hosts can be multihomed, so - * there is no need to build up a list of addresses + * A long time ago on Ultrix libpcap supported + * translation of DECnet host names into DECnet + * addresses, but this feature is history now. */ - return (gen_host(cstate, dn_addr, 0, proto, dir, q.addr)); + bpf_error(cstate, "invalid DECnet address '%s'", name); } else { #ifdef INET6 memset(&mask128, 0xff, sizeof(mask128)); @@ -7060,13 +7051,35 @@ gen_ncode(compiler_state_t *cstate, const char *s, bpf_u_int32 v, struct qual q) proto = q.proto; dir = q.dir; - if (s == NULL) + if (s == NULL) { + /* + * v contains a 32-bit unsigned parsed from a string of the + * form {N}, which could be decimal, hexadecimal or octal. + * Although it would be possible to use the value as a raw + * 16-bit DECnet address when the value fits into 16 bits, this + * would be a questionable feature: DECnet address wire + * encoding is little-endian, so this would not work as + * intuitively as the same works for [big-endian] IPv4 + * addresses (0x01020304 means 1.2.3.4). + */ + if (proto == Q_DECNET) + bpf_error(cstate, "invalid DECnet address '%u'", v); vlen = 32; - else if (q.proto == Q_DECNET) { + } else if (proto == Q_DECNET) { + /* + * s points to a string of the form {N}.{N}, {N}.{N}.{N} or + * {N}.{N}.{N}.{N}, of which only the first potentially stands + * for a valid DECnet address. + */ vlen = __pcap_atodn(s, &v); if (vlen == 0) - bpf_error(cstate, "malformed decnet address '%s'", s); + bpf_error(cstate, "invalid DECnet address '%s'", s); } else { + /* + * s points to a string of the form {N}.{N}, {N}.{N}.{N} or + * {N}.{N}.{N}.{N}, all of which potentially stand for a valid + * IPv4 address. + */ vlen = __pcap_atoin(s, &v); if (vlen < 0) bpf_error(cstate, "invalid IPv4 address '%s'", s); diff --git a/nametoaddr.c b/nametoaddr.c index 7a04a61d..a746cb6d 100644 --- a/nametoaddr.c +++ b/nametoaddr.c @@ -26,11 +26,6 @@ #include <config.h> #endif -#ifdef DECNETLIB -#include <sys/types.h> -#include <netdnet/dnetdb.h> -#endif - #ifdef _WIN32 #include <winsock2.h> #include <ws2tcpip.h> @@ -685,6 +680,13 @@ __pcap_atoin(const char *s, bpf_u_int32 *addr) /* NOTREACHED */ } +/* + * If 's' is not a string that is a well-formed DECnet address (aa.nnnn), + * return zero. Otherwise parse the address into the low 16 bits of 'addr' + * and return a non-zero. The binary DECnet address consists of a 6-bit area + * number and a 10-bit node number; neither area 0 nor node 0 are valid for + * normal addressing purposes, but either can appear on the wire. + */ int __pcap_atodn(const char *s, bpf_u_int32 *addr) { @@ -692,14 +694,76 @@ __pcap_atodn(const char *s, bpf_u_int32 *addr) #define AREAMASK 0176000 #define NODEMASK 01777 - u_int node, area; - - if (sscanf(s, "%d.%d", &area, &node) != 2) - return(0); + /* Initialize to squelch a compiler warning only. */ + u_int node = 0, area = 0; + /* + * +--+ +--+ + * | | | | + * v | v | + * --> START --> AREA --> DOT --> NODE --> + * | | | | + * | v v | + * +--------> INVALID <------+ + */ + enum { + START, + AREA, + DOT, + NODE, + INVALID + } fsm_state = START; - *addr = (area << AREASHIFT) & AREAMASK; - *addr |= (node & NODEMASK); + while (*s) { + switch (fsm_state) { + case START: + if (PCAP_ISDIGIT(*s)) { + area = *s - '0'; + fsm_state = AREA; + break; + } + fsm_state = INVALID; + break; + case AREA: + if (*s == '.') { + fsm_state = DOT; + break; + } + if (PCAP_ISDIGIT(*s)) { + area = area * 10 + *s - '0'; + if (area <= AREAMASK >> AREASHIFT) + break; + } + fsm_state = INVALID; + break; + case DOT: + if (PCAP_ISDIGIT(*s)) { + node = *s - '0'; + fsm_state = NODE; + break; + } + fsm_state = INVALID; + break; + case NODE: + if (PCAP_ISDIGIT(*s)) { + node = node * 10 + *s - '0'; + if (node <= NODEMASK) + break; + } + fsm_state = INVALID; + break; + case INVALID: + return 0; + } /* switch */ + s++; + } /* while */ + /* + * This condition is false if the string comes from the lexer, but + * let's not depend on that. + */ + if (fsm_state != NODE) + return 0; + *addr = area << AREASHIFT | node; return(32); } @@ -800,26 +864,3 @@ pcap_ether_hostton(const char *name) return (ap); } #endif - -/* - * XXX - not guaranteed to be thread-safe! - */ -int -#ifdef DECNETLIB -__pcap_nametodnaddr(const char *name, u_short *res) -{ - struct nodeent *getnodebyname(); - struct nodeent *nep; - - nep = getnodebyname(name); - if (nep == ((struct nodeent *)0)) - return(0); - - memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short)); - return(1); -#else -__pcap_nametodnaddr(const char *name _U_, u_short *res _U_) -{ - return(0); -#endif -} diff --git a/nametoaddr.h b/nametoaddr.h index fd6b7e10..8cf718ac 100644 --- a/nametoaddr.h +++ b/nametoaddr.h @@ -41,7 +41,6 @@ extern "C" { */ int __pcap_atodn(const char *, bpf_u_int32 *); int __pcap_atoin(const char *, bpf_u_int32 *); -int __pcap_nametodnaddr(const char *, u_short *); #ifdef __cplusplus } diff --git a/pcap-filter.manmisc.in b/pcap-filter.manmisc.in index 75512cd3..c477251f 100644 --- a/pcap-filter.manmisc.in +++ b/pcap-filter.manmisc.in @@ -18,7 +18,7 @@ .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" -.TH PCAP-FILTER @MAN_MISC_INFO@ "20 February 2023" +.TH PCAP-FILTER @MAN_MISC_INFO@ "12 March 2023" .SH NAME pcap-filter \- packet filter syntax .br @@ -476,10 +476,11 @@ currently know how to parse these protocols. .IP "\fBdecnet src \fIdecnetaddr\fR" True if the DECnet source address is .IR decnetaddr , -which may be an address of the form ``10.123'', or a DECnet host -name. -[DECnet host name support is only available on ULTRIX systems -that are configured to run DECnet.] +which is an address of the form +.B AREANUMBER.NODENUMBER +(for example, "10.123"), where the area number can be between 0 and 63 +and the node number can be between 0 and 1023 and both numbers always use +decimal base. .IP "\fBdecnet dst \fIdecnetaddr\fR" True if the DECnet destination address is .IR decnetaddr . |