Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Jul 2019 10:01:09 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r349572 - in stable/12: sbin/ipfw sys/netinet sys/netpfil/ipfw
Message-ID:  <201907011001.x61A19mf050108@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Mon Jul  1 10:01:08 2019
New Revision: 349572
URL: https://svnweb.freebsd.org/changeset/base/349572

Log:
  MFC r349267:
    Add "tcpmss" opcode to match the TCP MSS value.
  
    With this opcode it is possible to match TCP packets with specified
    MSS option, whose value corresponds to configured in opcode value.
    It is allowed to specify single value, range of values, or array of
    specific values or ranges. E.g.
  
     # ipfw add deny log tcp from any to any tcpmss 0-500

Modified:
  stable/12/sbin/ipfw/ipfw.8
  stable/12/sbin/ipfw/ipfw2.c
  stable/12/sbin/ipfw/ipfw2.h
  stable/12/sys/netinet/ip_fw.h
  stable/12/sys/netpfil/ipfw/ip_fw2.c
  stable/12/sys/netpfil/ipfw/ip_fw_sockopt.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sbin/ipfw/ipfw.8
==============================================================================
--- stable/12/sbin/ipfw/ipfw.8	Mon Jul  1 06:22:41 2019	(r349571)
+++ stable/12/sbin/ipfw/ipfw.8	Mon Jul  1 10:01:08 2019	(r349572)
@@ -1,7 +1,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 24, 2019
+.Dd June 21, 2019
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -1989,6 +1989,12 @@ a non-zero offset.
 See the
 .Cm frag
 option for details on matching fragmented packets.
+.It Cm tcpmss Ar tcpmss-list
+Matches TCP packets whose MSS (maximum segment size) value is set to
+.Ar tcpmss-list ,
+which is either a single value or a list of values or ranges
+specified in the same way as
+.Ar ports .
 .It Cm tcpseq Ar seq
 TCP packets only.
 Match if the TCP header sequence number field is set to

Modified: stable/12/sbin/ipfw/ipfw2.c
==============================================================================
--- stable/12/sbin/ipfw/ipfw2.c	Mon Jul  1 06:22:41 2019	(r349571)
+++ stable/12/sbin/ipfw/ipfw2.c	Mon Jul  1 10:01:08 2019	(r349572)
@@ -338,6 +338,7 @@ static struct _s_x rule_options[] = {
 	{ "tcpdatalen",		TOK_TCPDATALEN },
 	{ "tcpflags",		TOK_TCPFLAGS },
 	{ "tcpflgs",		TOK_TCPFLAGS },
+	{ "tcpmss",		TOK_TCPMSS },
 	{ "tcpoptions",		TOK_TCPOPTS },
 	{ "tcpopts",		TOK_TCPOPTS },
 	{ "tcpseq",		TOK_TCPSEQ },
@@ -881,6 +882,7 @@ static struct _s_x _port_name[] = {
 	{"ipttl",	O_IPTTL},
 	{"mac-type",	O_MAC_TYPE},
 	{"tcpdatalen",	O_TCPDATALEN},
+	{"tcpmss",	O_TCPMSS},
 	{"tcpwin",	O_TCPWIN},
 	{"tagged",	O_TAGGED},
 	{NULL,		0}
@@ -1588,6 +1590,7 @@ print_instruction(struct buf_pr *bp, const struct form
 	case O_IPTTL:
 	case O_IPLEN:
 	case O_TCPDATALEN:
+	case O_TCPMSS:
 	case O_TCPWIN:
 		if (F_LEN(cmd) == 1) {
 			switch (cmd->opcode) {
@@ -1603,6 +1606,9 @@ print_instruction(struct buf_pr *bp, const struct form
 			case O_TCPDATALEN:
 				s = "tcpdatalen";
 				break;
+			case O_TCPMSS:
+				s = "tcpmss";
+				break;
 			case O_TCPWIN:
 				s = "tcpwin";
 				break;
@@ -4709,14 +4715,18 @@ read_options:
 			av++;
 			break;
 
+		case TOK_TCPMSS:
 		case TOK_TCPWIN:
-			NEED1("tcpwin requires length");
+			NEED1("tcpmss/tcpwin requires size");
 			if (strpbrk(*av, "-,")) {
-			    if (!add_ports(cmd, *av, 0, O_TCPWIN, cblen))
-				errx(EX_DATAERR, "invalid tcpwin len %s", *av);
+				if (add_ports(cmd, *av, 0,
+				    i == TOK_TCPWIN ? O_TCPWIN : O_TCPMSS,
+				    cblen) == NULL)
+					errx(EX_DATAERR, "invalid %s size %s",
+					    s, *av);
 			} else
-			    fill_cmd(cmd, O_TCPWIN, 0,
-				    strtoul(*av, NULL, 0));
+				fill_cmd(cmd, i == TOK_TCPWIN ? O_TCPWIN :
+				    O_TCPMSS, 0, strtoul(*av, NULL, 0));
 			av++;
 			break;
 

Modified: stable/12/sbin/ipfw/ipfw2.h
==============================================================================
--- stable/12/sbin/ipfw/ipfw2.h	Mon Jul  1 06:22:41 2019	(r349571)
+++ stable/12/sbin/ipfw/ipfw2.h	Mon Jul  1 10:01:08 2019	(r349572)
@@ -151,6 +151,7 @@ enum tokens {
 	TOK_TCPOPTS,
 	TOK_TCPSEQ,
 	TOK_TCPACK,
+	TOK_TCPMSS,
 	TOK_TCPWIN,
 	TOK_ICMPTYPES,
 	TOK_MAC,

Modified: stable/12/sys/netinet/ip_fw.h
==============================================================================
--- stable/12/sys/netinet/ip_fw.h	Mon Jul  1 06:22:41 2019	(r349571)
+++ stable/12/sys/netinet/ip_fw.h	Mon Jul  1 10:01:08 2019	(r349572)
@@ -293,6 +293,7 @@ enum ipfw_opcodes {		/* arguments (4 byte each)	*/
 	O_EXTERNAL_DATA,	/* variable length data */
 
 	O_SKIP_ACTION,		/* none				*/
+	O_TCPMSS,		/* arg1=MSS value */
 
 	O_LAST_OPCODE		/* not an opcode!		*/
 };

Modified: stable/12/sys/netpfil/ipfw/ip_fw2.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/ip_fw2.c	Mon Jul  1 06:22:41 2019	(r349571)
+++ stable/12/sys/netpfil/ipfw/ip_fw2.c	Mon Jul  1 10:01:08 2019	(r349572)
@@ -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,13 +371,19 @@ 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
 iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, struct ip_fw_chain *chain,
     uint32_t *tablearg)
 {
@@ -2273,6 +2280,31 @@ do {								\
 				match = (proto == IPPROTO_TCP && offset == 0 &&
 				    ((ipfw_insn_u32 *)cmd)->d[0] ==
 					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:

Modified: stable/12/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/ip_fw_sockopt.c	Mon Jul  1 06:22:41 2019	(r349571)
+++ stable/12/sys/netpfil/ipfw/ip_fw_sockopt.c	Mon Jul  1 10:01:08 2019	(r349572)
@@ -1177,7 +1177,9 @@ move_objects(struct ip_fw_chain *ch, ipfw_range_tlv *r
 		}
 	}
 	return (c);
-}/*
+}
+
+/*
  * Changes set of given rule rannge @rt
  * with each other.
  *
@@ -1908,6 +1910,7 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, stru
 		case O_IPTTL:
 		case O_IPLEN:
 		case O_TCPDATALEN:
+		case O_TCPMSS:
 		case O_TCPWIN:
 		case O_TAGGED:
 			if (cmdlen < 1 || cmdlen > 31)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201907011001.x61A19mf050108>