diff options
Diffstat (limited to 'sys/netpfil')
-rw-r--r-- | sys/netpfil/ipfw/ip_fw2.c | 42 | ||||
-rw-r--r-- | sys/netpfil/ipfw/ip_fw_sockopt.c | 5 |
2 files changed, 41 insertions, 6 deletions
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c index a4a3830132eb..6796ad81611d 100644 --- a/sys/netpfil/ipfw/ip_fw2.c +++ b/sys/netpfil/ipfw/ip_fw2.c @@ -331,10 +331,10 @@ ipopts_match(struct ip *ip, ipfw_insn *cmd) } static int -tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd) +tcpopts_parse(struct tcphdr *tcp, uint16_t *mss) { - int optlen, bits = 0; u_char *cp = (u_char *)(tcp + 1); + int optlen, bits = 0; int x = (tcp->th_off << 2) - sizeof(struct tcphdr); for (; x > 0; x -= optlen, cp += optlen) { @@ -350,12 +350,13 @@ tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd) } switch (opt) { - default: break; case TCPOPT_MAXSEG: bits |= IP_FW_TCPOPT_MSS; + if (mss != NULL) + *mss = be16dec(cp + 2); break; case TCPOPT_WINDOW: @@ -370,10 +371,16 @@ tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd) case TCPOPT_TIMESTAMP: bits |= IP_FW_TCPOPT_TS; break; - } } - return (flags_match(cmd, bits)); + return (bits); +} + +static int +tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd) +{ + + return (flags_match(cmd, tcpopts_parse(tcp, NULL))); } static int @@ -2316,6 +2323,31 @@ do { \ TCP(ulp)->th_ack); break; + case O_TCPMSS: + if (proto == IPPROTO_TCP && + (args->f_id._flags & TH_SYN) != 0 && + ulp != NULL) { + uint16_t mss, *p; + int i; + + PULLUP_LEN(hlen, ulp, + (TCP(ulp)->th_off << 2)); + if ((tcpopts_parse(TCP(ulp), &mss) & + IP_FW_TCPOPT_MSS) == 0) + break; + if (cmdlen == 1) { + match = (cmd->arg1 == mss); + break; + } + /* Otherwise we have ranges. */ + p = ((ipfw_insn_u16 *)cmd)->ports; + i = cmdlen - 1; + for (; !match && i > 0; i--, p += 2) + match = (mss >= p[0] && + mss <= p[1]); + } + break; + case O_TCPWIN: if (proto == IPPROTO_TCP && offset == 0) { uint16_t x; diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index a83e75447633..297b01ca7d3d 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -1176,7 +1176,9 @@ move_objects(struct ip_fw_chain *ch, ipfw_range_tlv *rt) } } return (c); -}/* +} + +/* * Changes set of given rule rannge @rt * with each other. * @@ -1907,6 +1909,7 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci) case O_IPTTL: case O_IPLEN: case O_TCPDATALEN: + case O_TCPMSS: case O_TCPWIN: case O_TAGGED: if (cmdlen < 1 || cmdlen > 31) |