diff options
Diffstat (limited to 'gencode.c')
| -rw-r--r-- | gencode.c | 596 |
1 files changed, 432 insertions, 164 deletions
diff --git a/gencode.c b/gencode.c index 496e02f377e6..31c50a71e3e6 100644 --- a/gencode.c +++ b/gencode.c @@ -19,9 +19,7 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifdef HAVE_CONFIG_H #include <config.h> -#endif #ifdef _WIN32 #include <ws2tcpip.h> @@ -67,7 +65,7 @@ #include "scanner.h" -#if defined(linux) +#if defined(__linux__) #include <linux/types.h> #include <linux/if_packet.h> #include <linux/filter.h> @@ -218,7 +216,7 @@ enum e_offrel { }; /* - * We divy out chunks of memory rather than call malloc each time so + * We divvy out chunks of memory rather than call malloc each time so * we don't have to worry about leaking memory. It's probably * not a big deal if all this memory was wasted but if this ever * goes into a library that would probably not be a good idea. @@ -670,7 +668,7 @@ sdup(compiler_state_t *cstate, const char *s) if (cp == NULL) return (NULL); - pcap_strlcpy(cp, s, n); + pcapint_strlcpy(cp, s, n); return (cp); } @@ -724,22 +722,23 @@ pcap_compile(pcap_t *p, struct bpf_program *program, yyscan_t scanner = NULL; volatile YY_BUFFER_STATE in_buffer = NULL; u_int len; - int rc; + int rc; /* * If this pcap_t hasn't been activated, it doesn't have a * link-layer type, so we can't use it. */ if (!p->activated) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "not-yet-activated pcap_t passed to pcap_compile"); return (PCAP_ERROR); } #ifdef _WIN32 - if (!done) + if (!done) { pcap_wsockinit(); - done = 1; + done = 1; + } #endif #ifdef ENABLE_REMOTE @@ -779,15 +778,18 @@ pcap_compile(pcap_t *p, struct bpf_program *program, cstate.snaplen = pcap_snapshot(p); if (cstate.snaplen == 0) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snaplen of 0 rejects all packets"); rc = PCAP_ERROR; goto quit; } - if (pcap_lex_init(&scanner) != 0) - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + if (pcap_lex_init(&scanner) != 0) { + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "can't initialize scanner"); + rc = PCAP_ERROR; + goto quit; + } in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner); /* @@ -871,7 +873,7 @@ quit: int pcap_compile_nopcap(int snaplen_arg, int linktype_arg, struct bpf_program *program, - const char *buf, int optimize, bpf_u_int32 mask) + const char *buf, int optimize, bpf_u_int32 mask) { pcap_t *p; int ret; @@ -1707,15 +1709,15 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) * For values in the range in which we've assigned new * DLT_ values, only raw "link[N:M]" filtering is supported. */ - if (cstate->linktype >= DLT_MATCHING_MIN && - cstate->linktype <= DLT_MATCHING_MAX) { + if (cstate->linktype >= DLT_HIGH_MATCHING_MIN && + cstate->linktype <= DLT_HIGH_MATCHING_MAX) { cstate->off_linktype.constant_part = OFFSET_NOT_SET; cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = OFFSET_NOT_SET; cstate->off_nl_nosnap = OFFSET_NOT_SET; } else { bpf_set_error(cstate, "unknown data link type %d (min %d, max %d)", - cstate->linktype, DLT_MATCHING_MIN, DLT_MATCHING_MAX); + cstate->linktype, DLT_HIGH_MATCHING_MIN, DLT_HIGH_MATCHING_MAX); return (-1); } break; @@ -1834,7 +1836,7 @@ gen_load_a(compiler_state_t *cstate, enum e_offrel offrel, u_int offset, /* * Load the item at {offset of the link-layer payload} + * {offset, relative to the start of the link-layer - * paylod, of the IPv4 header} + {length of the IPv4 header} + + * payload, of the IPv4 header} + {length of the IPv4 header} + * {specified offset}. * * If the offset of the link-layer payload is variable, @@ -1897,7 +1899,7 @@ gen_loadx_iphdrlen(compiler_state_t *cstate) } else { /* * The offset of the link-layer payload is a constant, - * so no code was generated to load the (non-existent) + * so no code was generated to load the (nonexistent) * variable part of that offset. * * This means we can use the 4*([k]&0xf) addressing @@ -4087,7 +4089,16 @@ gen_hostop6(compiler_state_t *cstate, struct in6_addr *addr, { struct block *b0, *b1; u_int offset; - uint32_t *a, *m; + /* + * Code below needs to access four separate 32-bit parts of the 128-bit + * IPv6 address and mask. In some OSes this is as simple as using the + * s6_addr32 pseudo-member of struct in6_addr, which contains a union of + * 8-, 16- and 32-bit arrays. In other OSes this is not the case, as + * far as libpcap sees it. Hence copy the data before use to avoid + * potential unaligned memory access and the associated compiler + * warnings (whether genuine or not). + */ + bpf_u_int32 a[4], m[4]; switch (dir) { @@ -4141,8 +4152,8 @@ gen_hostop6(compiler_state_t *cstate, struct in6_addr *addr, /*NOTREACHED*/ } /* this order is important */ - a = (uint32_t *)addr; - m = (uint32_t *)mask; + memcpy(a, addr, sizeof(a)); + memcpy(m, mask, sizeof(m)); b1 = gen_mcmp(cstate, OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); b0 = gen_mcmp(cstate, OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); gen_and(b0, b1); @@ -5290,7 +5301,6 @@ gen_gateway(compiler_state_t *cstate, const u_char *eaddr, */ bpf_error(cstate, "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); - break; case DLT_IP_OVER_FC: b0 = gen_ipfchostop(cstate, eaddr, Q_OR); break; @@ -6117,7 +6127,7 @@ gen_protochain(compiler_state_t *cstate, bpf_u_int32 v, int proto) /* * To quote a comment in optimize.c: * - * "These data structures are used in a Cocke and Shwarz style + * "These data structures are used in a Cocke and Schwartz style * value numbering scheme. Since the flowgraph is acyclic, * exit values can be propagated from a node's predecessors * provided it is uniquely defined." @@ -6658,6 +6668,277 @@ gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto, int dir) /*NOTREACHED*/ } +/* + * Convert a non-numeric name to a port number. + */ +static int +nametoport(compiler_state_t *cstate, const char *name, int ipproto) +{ + struct addrinfo hints, *res, *ai; + int error; + struct sockaddr_in *in4; +#ifdef INET6 + struct sockaddr_in6 *in6; +#endif + int port = -1; + + /* + * We check for both TCP and UDP in case there are + * ambiguous entries. + */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = (ipproto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM; + hints.ai_protocol = ipproto; + error = getaddrinfo(NULL, name, &hints, &res); + if (error != 0) { + switch (error) { + + case EAI_NONAME: + case EAI_SERVICE: + /* + * No such port. Just return -1. + */ + break; + +#ifdef EAI_SYSTEM + case EAI_SYSTEM: + /* + * We don't use strerror() because it's not + * guaranteed to be thread-safe on all platforms + * (probably because it might use a non-thread-local + * buffer into which to format an error message + * if the error code isn't one for which it has + * a canned string; three cheers for C string + * handling). + */ + bpf_set_error(cstate, "getaddrinfo(\"%s\" fails with system error: %d", + name, errno); + port = -2; /* a real error */ + break; +#endif + + default: + /* + * This is a real error, not just "there's + * no such service name". + * + * We don't use gai_strerror() because it's not + * guaranteed to be thread-safe on all platforms + * (probably because it might use a non-thread-local + * buffer into which to format an error message + * if the error code isn't one for which it has + * a canned string; three cheers for C string + * handling). + */ + bpf_set_error(cstate, "getaddrinfo(\"%s\") fails with error: %d", + name, error); + port = -2; /* a real error */ + break; + } + } else { + /* + * OK, we found it. Did it find anything? + */ + for (ai = res; ai != NULL; ai = ai->ai_next) { + /* + * Does it have an address? + */ + if (ai->ai_addr != NULL) { + /* + * Yes. Get a port number; we're done. + */ + if (ai->ai_addr->sa_family == AF_INET) { + in4 = (struct sockaddr_in *)ai->ai_addr; + port = ntohs(in4->sin_port); + break; + } +#ifdef INET6 + if (ai->ai_addr->sa_family == AF_INET6) { + in6 = (struct sockaddr_in6 *)ai->ai_addr; + port = ntohs(in6->sin6_port); + break; + } +#endif + } + } + freeaddrinfo(res); + } + return port; +} + +/* + * Convert a string to a port number. + */ +static bpf_u_int32 +stringtoport(compiler_state_t *cstate, const char *string, size_t string_size, + int *proto) +{ + stoulen_ret ret; + char *cpy; + bpf_u_int32 val; + int tcp_port = -1; + int udp_port = -1; + + /* + * See if it's a number. + */ + ret = stoulen(string, string_size, &val, cstate); + switch (ret) { + + case STOULEN_OK: + /* Unknown port type - it's just a number. */ + *proto = PROTO_UNDEF; + break; + + case STOULEN_NOT_OCTAL_NUMBER: + case STOULEN_NOT_HEX_NUMBER: + case STOULEN_NOT_DECIMAL_NUMBER: + /* + * Not a valid number; try looking it up as a port. + */ + cpy = malloc(string_size + 1); /* +1 for terminating '\0' */ + memcpy(cpy, string, string_size); + cpy[string_size] = '\0'; + tcp_port = nametoport(cstate, cpy, IPPROTO_TCP); + if (tcp_port == -2) { + /* + * We got a hard error; the error string has + * already been set. + */ + free(cpy); + longjmp(cstate->top_ctx, 1); + /*NOTREACHED*/ + } + udp_port = nametoport(cstate, cpy, IPPROTO_UDP); + if (udp_port == -2) { + /* + * We got a hard error; the error string has + * already been set. + */ + free(cpy); + longjmp(cstate->top_ctx, 1); + /*NOTREACHED*/ + } + + /* + * We need to check /etc/services for ambiguous entries. + * If we find an ambiguous entry, and it has the + * same port number, change the proto to PROTO_UNDEF + * so both TCP and UDP will be checked. + */ + if (tcp_port >= 0) { + val = (bpf_u_int32)tcp_port; + *proto = IPPROTO_TCP; + if (udp_port >= 0) { + if (udp_port == tcp_port) + *proto = PROTO_UNDEF; +#ifdef notdef + else + /* Can't handle ambiguous names that refer + to different port numbers. */ + warning("ambiguous port %s in /etc/services", + cpy); +#endif + } + free(cpy); + break; + } + if (udp_port >= 0) { + val = (bpf_u_int32)udp_port; + *proto = IPPROTO_UDP; + free(cpy); + break; + } +#if defined(ultrix) || defined(__osf__) + /* Special hack in case NFS isn't in /etc/services */ + if (strcmp(cpy, "nfs") == 0) { + val = 2049; + *proto = PROTO_UNDEF; + free(cpy); + break; + } +#endif + bpf_set_error(cstate, "'%s' is not a valid port", cpy); + free(cpy); + longjmp(cstate->top_ctx, 1); + /*NOTREACHED*/ + + case STOULEN_ERROR: + /* Error already set. */ + longjmp(cstate->top_ctx, 1); + /*NOTREACHED*/ + + default: + /* Should not happen */ + bpf_set_error(cstate, "stoulen returned %d - this should not happen", ret); + longjmp(cstate->top_ctx, 1); + /*NOTREACHED*/ + } + return (val); +} + +/* + * Convert a string in the form PPP-PPP, which correspond to ports, to + * a starting and ending port in a port range. + */ +static void +stringtoportrange(compiler_state_t *cstate, const char *string, + bpf_u_int32 *port1, bpf_u_int32 *port2, int *proto) +{ + char *hyphen_off; + const char *first, *second; + size_t first_size, second_size; + int save_proto; + + if ((hyphen_off = strchr(string, '-')) == NULL) + bpf_error(cstate, "port range '%s' contains no hyphen", string); + + /* + * Make sure there are no other hyphens. + * + * XXX - we support named ports, but there are some port names + * in /etc/services that include hyphens, so this would rule + * that out. + */ + if (strchr(hyphen_off + 1, '-') != NULL) + bpf_error(cstate, "port range '%s' contains more than one hyphen", + string); + + /* + * Get the length of the first port. + */ + first = string; + first_size = hyphen_off - string; + if (first_size == 0) { + /* Range of "-port", which we don't support. */ + bpf_error(cstate, "port range '%s' has no starting port", string); + } + + /* + * Try to convert it to a port. + */ + *port1 = stringtoport(cstate, first, first_size, proto); + save_proto = *proto; + + /* + * Get the length of the second port. + */ + second = hyphen_off + 1; + second_size = strlen(second); + if (second_size == 0) { + /* Range of "port-", which we don't support. */ + bpf_error(cstate, "port range '%s' has no ending port", string); + } + + /* + * Try to convert it to a port. + */ + *port2 = stringtoport(cstate, second, second_size, proto); + if (*proto != save_proto) + *proto = PROTO_UNDEF; +} + struct block * gen_scode(compiler_state_t *cstate, const char *name, struct qual q) { @@ -6675,7 +6956,7 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q) #endif /*INET6*/ struct block *b, *tmp; int port, real_proto; - int port1, port2; + bpf_u_int32 port1, port2; /* * Catch errors reported by us and routines below us, and return NULL @@ -6884,8 +7165,7 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q) if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) bpf_error(cstate, "illegal qualifier of 'portrange'"); - if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0) - bpf_error(cstate, "unknown port in range '%s'", name); + stringtoportrange(cstate, name, &port1, &port2, &real_proto); if (proto == Q_UDP) { if (real_proto == IPPROTO_TCP) bpf_error(cstate, "port in range '%s' is tcp", name); @@ -6913,12 +7193,8 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q) /* override PROTO_UNDEF */ real_proto = IPPROTO_SCTP; } - if (port1 < 0) - bpf_error(cstate, "illegal port number %d < 0", port1); if (port1 > 65535) bpf_error(cstate, "illegal port number %d > 65535", port1); - if (port2 < 0) - bpf_error(cstate, "illegal port number %d < 0", port2); if (port2 > 65535) bpf_error(cstate, "illegal port number %d > 65535", port2); @@ -7151,14 +7427,14 @@ gen_ncode(compiler_state_t *cstate, const char *s, bpf_u_int32 v, struct qual q) #ifdef INET6 struct block * -gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2, - bpf_u_int32 masklen, struct qual q) +gen_mcode6(compiler_state_t *cstate, const char *s, bpf_u_int32 masklen, + struct qual q) { struct addrinfo *res; struct in6_addr *addr; struct in6_addr mask; struct block *b; - uint32_t *a, *m; + bpf_u_int32 a[4], m[4]; /* Same as in gen_hostop6(). */ /* * Catch errors reported by us and routines below us, and return NULL @@ -7167,19 +7443,16 @@ gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2, if (setjmp(cstate->top_ctx)) return (NULL); - if (s2) - bpf_error(cstate, "no mask %s supported", s2); - - res = pcap_nametoaddrinfo(s1); + res = pcap_nametoaddrinfo(s); if (!res) - bpf_error(cstate, "invalid ip6 address %s", s1); + bpf_error(cstate, "invalid ip6 address %s", s); cstate->ai = res; if (res->ai_next) - bpf_error(cstate, "%s resolved to multiple address", s1); + bpf_error(cstate, "%s resolved to multiple address", s); addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; if (masklen > sizeof(mask.s6_addr) * 8) - bpf_error(cstate, "mask length must be <= %u", (unsigned int)(sizeof(mask.s6_addr) * 8)); + bpf_error(cstate, "mask length must be <= %zu", sizeof(mask.s6_addr) * 8); memset(&mask, 0, sizeof(mask)); memset(&mask.s6_addr, 0xff, masklen / 8); if (masklen % 8) { @@ -7187,11 +7460,11 @@ gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2, (0xff << (8 - masklen % 8)) & 0xff; } - a = (uint32_t *)addr; - m = (uint32_t *)&mask; + memcpy(a, addr, sizeof(a)); + memcpy(m, &mask, sizeof(m)); if ((a[0] & ~m[0]) || (a[1] & ~m[1]) || (a[2] & ~m[2]) || (a[3] & ~m[3])) { - bpf_error(cstate, "non-network bits set in \"%s/%d\"", s1, masklen); + bpf_error(cstate, "non-network bits set in \"%s/%d\"", s, masklen); } switch (q.addr) { @@ -7524,58 +7797,54 @@ gen_load_internal(compiler_state_t *cstate, int proto, struct arth *inst, inst->b = b; break; case Q_ICMPV6: - /* - * Do the computation only if the packet contains - * the protocol in question. - */ - b = gen_proto_abbrev_internal(cstate, Q_IPV6); - if (inst->b) { - gen_and(inst->b, b); - } - inst->b = b; - - /* - * Check if we have an icmp6 next header - */ - b = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, 58); - if (inst->b) { - gen_and(inst->b, b); - } - inst->b = b; - - - s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl); - /* - * If "s" is non-null, it has code to arrange that the - * X register contains the variable part of the offset - * of the link-layer payload. Add to it the offset - * computed into the register specified by "index", - * and move that into the X register. Otherwise, just - * load into the X register the offset computed into - * the register specified by "index". - */ - if (s != NULL) { - sappend(s, xfer_to_a(cstate, inst)); - sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X)); - sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX)); - } else { - s = xfer_to_x(cstate, inst); - } + /* + * Do the computation only if the packet contains + * the protocol in question. + */ + b = gen_proto_abbrev_internal(cstate, Q_IPV6); + if (inst->b) + gen_and(inst->b, b); + inst->b = b; + + /* + * Check if we have an icmp6 next header + */ + b = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, 58); + if (inst->b) + gen_and(inst->b, b); + inst->b = b; + + s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl); + /* + * If "s" is non-null, it has code to arrange that the + * X register contains the variable part of the offset + * of the link-layer payload. Add to it the offset + * computed into the register specified by "index", + * and move that into the X register. Otherwise, just + * load into the X register the offset computed into + * the register specified by "index". + */ + if (s != NULL) { + sappend(s, xfer_to_a(cstate, inst)); + sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X)); + sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX)); + } else + s = xfer_to_x(cstate, inst); - /* - * Load the item at the sum of the offset we've put in the - * X register, the offset of the start of the network - * layer header from the beginning of the link-layer - * payload, and the constant part of the offset of the - * start of the link-layer payload. - */ - tmp = new_stmt(cstate, BPF_LD|BPF_IND|size_code); - tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 40; + /* + * Load the item at the sum of the offset we've put in the + * X register, the offset of the start of the network + * layer header from the beginning of the link-layer + * payload, and the constant part of the offset of the + * start of the link-layer payload. + */ + tmp = new_stmt(cstate, BPF_LD|BPF_IND|size_code); + tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 40; - sappend(s, tmp); - sappend(inst->s, s); + sappend(s, tmp); + sappend(inst->s, s); - break; + break; } inst->regno = regno; s = new_stmt(cstate, BPF_ST); @@ -8235,8 +8504,8 @@ gen_ifindex(compiler_state_t *cstate, int ifindex) /* match packets on this interface */ b0 = gen_cmp(cstate, OR_LINKHDR, 4, BPF_W, ifindex); break; - default: -#if defined(linux) + default: +#if defined(__linux__) /* * This is Linux; we require PF_PACKET support. * If this is a *live* capture, we can look at @@ -8247,17 +8516,16 @@ gen_ifindex(compiler_state_t *cstate, int ifindex) /* We have a FILE *, so this is a savefile */ bpf_error(cstate, "ifindex not supported on %s when reading savefiles", pcap_datalink_val_to_description_or_dlt(cstate->linktype)); - b0 = NULL; /*NOTREACHED*/ } /* match ifindex */ b0 = gen_cmp(cstate, OR_LINKHDR, SKF_AD_OFF + SKF_AD_IFINDEX, BPF_W, ifindex); -#else /* defined(linux) */ +#else /* defined(__linux__) */ bpf_error(cstate, "ifindex not supported on %s", pcap_datalink_val_to_description_or_dlt(cstate->linktype)); /*NOTREACHED*/ -#endif /* defined(linux) */ +#endif /* defined(__linux__) */ } return (b0); } @@ -8387,7 +8655,7 @@ gen_inbound(compiler_state_t *cstate, int dir) * with newer capture APIs, allowing it to be saved * in pcapng files. */ -#if defined(linux) +#if defined(__linux__) /* * This is Linux; we require PF_PACKET support. * If this is a *live* capture, we can look at @@ -8407,11 +8675,11 @@ gen_inbound(compiler_state_t *cstate, int dir) /* to filter on inbound traffic, invert the match */ gen_not(b0); } -#else /* defined(linux) */ +#else /* defined(__linux__) */ bpf_error(cstate, "inbound/outbound not supported on %s", pcap_datalink_val_to_description_or_dlt(cstate->linktype)); /*NOTREACHED*/ -#endif /* defined(linux) */ +#endif /* defined(__linux__) */ } return (b0); } @@ -8837,7 +9105,7 @@ gen_vlan_patch_vid_test(compiler_state_t *cstate, struct block *b_vid) /* Jump to the test in b_vid. We need to jump one instruction before * the end of the b_vid block so that we only skip loading the TCI - * from packet data and not the 'and' instruction extractging VID. + * from packet data and not the 'and' instruction extracting VID. */ cnt = 0; for (s2 = b_vid->stmts; s2; s2 = s2->next) @@ -8977,7 +9245,7 @@ gen_vlan(compiler_state_t *cstate, bpf_u_int32 vlan_num, int has_vlan_tag) #endif b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num, has_vlan_tag); - break; + break; case DLT_IEEE802_11: case DLT_PRISM_HEADER: @@ -8992,7 +9260,7 @@ gen_vlan(compiler_state_t *cstate, bpf_u_int32 vlan_num, int has_vlan_tag) /*NOTREACHED*/ } - cstate->vlan_stack_depth++; + cstate->vlan_stack_depth++; return (b0); } @@ -9018,38 +9286,38 @@ gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg, if (setjmp(cstate->top_ctx)) return (NULL); - if (cstate->label_stack_depth > 0) { - /* just match the bottom-of-stack bit clear */ - b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01); - } else { - /* - * We're not in an MPLS stack yet, so check the link-layer - * type against MPLS. - */ - switch (cstate->linktype) { - - case DLT_C_HDLC: /* fall through */ - case DLT_HDLC: - case DLT_EN10MB: - case DLT_NETANALYZER: - case DLT_NETANALYZER_TRANSPARENT: - b0 = gen_linktype(cstate, ETHERTYPE_MPLS); - break; - - case DLT_PPP: - b0 = gen_linktype(cstate, PPP_MPLS_UCAST); - break; - - /* FIXME add other DLT_s ... - * for Frame-Relay/and ATM this may get messy due to SNAP headers - * leave it for now */ - - default: - bpf_error(cstate, "no MPLS support for %s", - pcap_datalink_val_to_description_or_dlt(cstate->linktype)); - /*NOTREACHED*/ - } - } + if (cstate->label_stack_depth > 0) { + /* just match the bottom-of-stack bit clear */ + b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01); + } else { + /* + * We're not in an MPLS stack yet, so check the link-layer + * type against MPLS. + */ + switch (cstate->linktype) { + + case DLT_C_HDLC: /* fall through */ + case DLT_HDLC: + case DLT_EN10MB: + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: + b0 = gen_linktype(cstate, ETHERTYPE_MPLS); + break; + + case DLT_PPP: + b0 = gen_linktype(cstate, PPP_MPLS_UCAST); + break; + + /* FIXME add other DLT_s ... + * for Frame-Relay/and ATM this may get messy due to SNAP headers + * leave it for now */ + + default: + bpf_error(cstate, "no MPLS support for %s", + pcap_datalink_val_to_description_or_dlt(cstate->linktype)); + /*NOTREACHED*/ + } + } /* If a specific MPLS label is requested, check it */ if (has_label_num) { @@ -9064,23 +9332,23 @@ gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg, b0 = b1; } - /* - * Change the offsets to point to the type and data fields within - * the MPLS packet. Just increment the offsets, so that we - * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to - * capture packets with an outer label of 100000 and an inner - * label of 1024. - * - * Increment the MPLS stack depth as well; this indicates that - * we're checking MPLS-encapsulated headers, to make sure higher - * level code generators don't try to match against IP-related - * protocols such as Q_ARP, Q_RARP etc. - * - * XXX - this is a bit of a kludge. See comments in gen_vlan(). - */ - cstate->off_nl_nosnap += 4; - cstate->off_nl += 4; - cstate->label_stack_depth++; + /* + * Change the offsets to point to the type and data fields within + * the MPLS packet. Just increment the offsets, so that we + * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to + * capture packets with an outer label of 100000 and an inner + * label of 1024. + * + * Increment the MPLS stack depth as well; this indicates that + * we're checking MPLS-encapsulated headers, to make sure higher + * level code generators don't try to match against IP-related + * protocols such as Q_ARP, Q_RARP etc. + * + * XXX - this is a bit of a kludge. See comments in gen_vlan(). + */ + cstate->off_nl_nosnap += 4; + cstate->off_nl += 4; + cstate->label_stack_depth++; return (b0); } @@ -9795,8 +10063,8 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field, bpf_error(cstate, "'sio' supported only on SS7"); /* sio coded on 1 byte so max value 255 */ if(jvalue > 255) - bpf_error(cstate, "sio value %u too big; max value = 255", - jvalue); + bpf_error(cstate, "sio value %u too big; max value = 255", + jvalue); b0 = gen_ncmp(cstate, OR_PACKET, newoff_sio, BPF_B, 0xffffffffU, jtype, reverse, jvalue); break; @@ -9805,13 +10073,13 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field, newoff_opc += 3; /* FALLTHROUGH */ - case M_OPC: - if (cstate->off_opc == OFFSET_NOT_SET) + case M_OPC: + if (cstate->off_opc == OFFSET_NOT_SET) bpf_error(cstate, "'opc' supported only on SS7"); /* opc coded on 14 bits so max value 16383 */ if (jvalue > 16383) - bpf_error(cstate, "opc value %u too big; max value = 16383", - jvalue); + bpf_error(cstate, "opc value %u too big; max value = 16383", + jvalue); /* the following instructions are made to convert jvalue * to the form used to write opc in an ss7 message*/ val1 = jvalue & 0x00003c00; @@ -9830,12 +10098,12 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field, /* FALLTHROUGH */ case M_DPC: - if (cstate->off_dpc == OFFSET_NOT_SET) + if (cstate->off_dpc == OFFSET_NOT_SET) bpf_error(cstate, "'dpc' supported only on SS7"); /* dpc coded on 14 bits so max value 16383 */ if (jvalue > 16383) - bpf_error(cstate, "dpc value %u too big; max value = 16383", - jvalue); + bpf_error(cstate, "dpc value %u too big; max value = 16383", + jvalue); /* the following instructions are made to convert jvalue * to the forme used to write dpc in an ss7 message*/ val1 = jvalue & 0x000000ff; @@ -9852,12 +10120,12 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field, /* FALLTHROUGH */ case M_SLS: - if (cstate->off_sls == OFFSET_NOT_SET) + if (cstate->off_sls == OFFSET_NOT_SET) bpf_error(cstate, "'sls' supported only on SS7"); /* sls coded on 4 bits so max value 15 */ if (jvalue > 15) - bpf_error(cstate, "sls value %u too big; max value = 15", - jvalue); + bpf_error(cstate, "sls value %u too big; max value = 15", + jvalue); /* the following instruction is made to convert jvalue * to the forme used to write sls in an ss7 message*/ jvalue = jvalue << 4; |
