Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Nov 2017 07:42:56 +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-11@freebsd.org
Subject:   svn commit: r326388 - stable/11/sys/netpfil/ipfw
Message-ID:  <201711300742.vAU7gujR067843@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Thu Nov 30 07:42:56 2017
New Revision: 326388
URL: https://svnweb.freebsd.org/changeset/base/326388

Log:
  MFC r326086:
    Add ipfw_add_protected_rule() function that creates rule with 65535
    number in the reserved set 31. Use this function to create default rule.
  
  MFC r326115:
    Rework rule ranges matching. Use comparison rule id with UINT32_MAX to
    match all rules with the same rule number.
  
  MFC r326116:
    Move ipfw_send_pkt() from ip_fw_dynamic.c into ip_fw2.c.
    It is not specific for dynamic states function and called also from
    generic code.
  
  MFC r326117:
    Check that address family of state matches address family of packet.
    If it is not matched avoid comparing other state fields.
  
  MFC r326118:
    Modify ipfw's dynamic states KPI.
  
    Hide the locking logic used in the dynamic states implementation from
    generic code. Rename ipfw_install_state() and ipfw_lookup_dyn_rule()
    function to have similar names: ipfw_dyn_install_state() and
    ipfw_dyn_lookup_state(). Move dynamic rule counters updating to the
    ipfw_dyn_lookup_state() function. Now this function return NULL when
    there is no state and pointer to the parent rule when state is found.
    Thus now there is no need to return pointer to dynamic rule, and no need
    to hold bucket lock for this state. Remove ipfw_dyn_unlock() function.
  
    Differential Revision:	https://reviews.freebsd.org/D11657
  
  Obtained from:	Yandex LLC
  Sponsored by:	Yandex LLC

Modified:
  stable/11/sys/netpfil/ipfw/ip_fw2.c
  stable/11/sys/netpfil/ipfw/ip_fw_dynamic.c
  stable/11/sys/netpfil/ipfw/ip_fw_private.h
  stable/11/sys/netpfil/ipfw/ip_fw_sockopt.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netpfil/ipfw/ip_fw2.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/ip_fw2.c	Thu Nov 30 07:24:33 2017	(r326387)
+++ stable/11/sys/netpfil/ipfw/ip_fw2.c	Thu Nov 30 07:42:56 2017	(r326388)
@@ -468,7 +468,156 @@ verify_path(struct in_addr src, struct ifnet *ifp, u_i
 #endif /* __FreeBSD__ */
 }
 
+/*
+ * Generate a TCP packet, containing either a RST or a keepalive.
+ * When flags & TH_RST, we are sending a RST packet, because of a
+ * "reset" action matched the packet.
+ * Otherwise we are sending a keepalive, and flags & TH_
+ * The 'replyto' mbuf is the mbuf being replied to, if any, and is required
+ * so that MAC can label the reply appropriately.
+ */
+struct mbuf *
+ipfw_send_pkt(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t seq,
+    u_int32_t ack, int flags)
+{
+	struct mbuf *m = NULL;		/* stupid compiler */
+	struct ip *h = NULL;		/* stupid compiler */
 #ifdef INET6
+	struct ip6_hdr *h6 = NULL;
+#endif
+	struct tcphdr *th = NULL;
+	int len, dir;
+
+	MGETHDR(m, M_NOWAIT, MT_DATA);
+	if (m == NULL)
+		return (NULL);
+
+	M_SETFIB(m, id->fib);
+#ifdef MAC
+	if (replyto != NULL)
+		mac_netinet_firewall_reply(replyto, m);
+	else
+		mac_netinet_firewall_send(m);
+#else
+	(void)replyto;		/* don't warn about unused arg */
+#endif
+
+	switch (id->addr_type) {
+	case 4:
+		len = sizeof(struct ip) + sizeof(struct tcphdr);
+		break;
+#ifdef INET6
+	case 6:
+		len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
+		break;
+#endif
+	default:
+		/* XXX: log me?!? */
+		FREE_PKT(m);
+		return (NULL);
+	}
+	dir = ((flags & (TH_SYN | TH_RST)) == TH_SYN);
+
+	m->m_data += max_linkhdr;
+	m->m_flags |= M_SKIP_FIREWALL;
+	m->m_pkthdr.len = m->m_len = len;
+	m->m_pkthdr.rcvif = NULL;
+	bzero(m->m_data, len);
+
+	switch (id->addr_type) {
+	case 4:
+		h = mtod(m, struct ip *);
+
+		/* prepare for checksum */
+		h->ip_p = IPPROTO_TCP;
+		h->ip_len = htons(sizeof(struct tcphdr));
+		if (dir) {
+			h->ip_src.s_addr = htonl(id->src_ip);
+			h->ip_dst.s_addr = htonl(id->dst_ip);
+		} else {
+			h->ip_src.s_addr = htonl(id->dst_ip);
+			h->ip_dst.s_addr = htonl(id->src_ip);
+		}
+
+		th = (struct tcphdr *)(h + 1);
+		break;
+#ifdef INET6
+	case 6:
+		h6 = mtod(m, struct ip6_hdr *);
+
+		/* prepare for checksum */
+		h6->ip6_nxt = IPPROTO_TCP;
+		h6->ip6_plen = htons(sizeof(struct tcphdr));
+		if (dir) {
+			h6->ip6_src = id->src_ip6;
+			h6->ip6_dst = id->dst_ip6;
+		} else {
+			h6->ip6_src = id->dst_ip6;
+			h6->ip6_dst = id->src_ip6;
+		}
+
+		th = (struct tcphdr *)(h6 + 1);
+		break;
+#endif
+	}
+
+	if (dir) {
+		th->th_sport = htons(id->src_port);
+		th->th_dport = htons(id->dst_port);
+	} else {
+		th->th_sport = htons(id->dst_port);
+		th->th_dport = htons(id->src_port);
+	}
+	th->th_off = sizeof(struct tcphdr) >> 2;
+
+	if (flags & TH_RST) {
+		if (flags & TH_ACK) {
+			th->th_seq = htonl(ack);
+			th->th_flags = TH_RST;
+		} else {
+			if (flags & TH_SYN)
+				seq++;
+			th->th_ack = htonl(seq);
+			th->th_flags = TH_RST | TH_ACK;
+		}
+	} else {
+		/*
+		 * Keepalive - use caller provided sequence numbers
+		 */
+		th->th_seq = htonl(seq);
+		th->th_ack = htonl(ack);
+		th->th_flags = TH_ACK;
+	}
+
+	switch (id->addr_type) {
+	case 4:
+		th->th_sum = in_cksum(m, len);
+
+		/* finish the ip header */
+		h->ip_v = 4;
+		h->ip_hl = sizeof(*h) >> 2;
+		h->ip_tos = IPTOS_LOWDELAY;
+		h->ip_off = htons(0);
+		h->ip_len = htons(len);
+		h->ip_ttl = V_ip_defttl;
+		h->ip_sum = 0;
+		break;
+#ifdef INET6
+	case 6:
+		th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(*h6),
+		    sizeof(struct tcphdr));
+
+		/* finish the ip6 header */
+		h6->ip6_vfc |= IPV6_VERSION;
+		h6->ip6_hlim = IPV6_DEFHLIM;
+		break;
+#endif
+	}
+
+	return (m);
+}
+
+#ifdef INET6
 /*
  * ipv6 specific rules here...
  */
@@ -973,7 +1122,7 @@ ipfw_chk(struct ip_fw_args *args)
 	 */
 	int dyn_dir = MATCH_UNKNOWN;
 	uint16_t dyn_name = 0;
-	ipfw_dyn_rule *q = NULL;
+	struct ip_fw *q = NULL;
 	struct ip_fw_chain *chain = &V_layer3_chain;
 
 	/*
@@ -2158,7 +2307,7 @@ do {								\
 			 */
 			case O_LIMIT:
 			case O_KEEP_STATE:
-				if (ipfw_install_state(chain, f,
+				if (ipfw_dyn_install_state(chain, f,
 				    (ipfw_insn_limit *)cmd, args, tablearg)) {
 					/* error or limit violation */
 					retval = IP_FW_DENY;
@@ -2198,28 +2347,25 @@ do {								\
 				if ((dyn_dir == MATCH_UNKNOWN ||
 				    (dyn_name != 0 &&
 				    dyn_name != cmd->arg1)) &&
-				    (q = ipfw_lookup_dyn_rule(&args->f_id,
-				     &dyn_dir, proto == IPPROTO_TCP ?
-				     TCP(ulp): NULL,
+				    (q = ipfw_dyn_lookup_state(&args->f_id,
+				     ulp, pktlen, &dyn_dir,
 				     (dyn_name = cmd->arg1))) != NULL) {
 					/*
-					 * Found dynamic entry, update stats
-					 * and jump to the 'action' part of
-					 * the parent rule by setting
-					 * f, cmd, l and clearing cmdlen.
+					 * Found dynamic entry, jump to the
+					 * 'action' part of the parent rule
+					 * by setting f, cmd, l and clearing
+					 * cmdlen.
 					 */
-					IPFW_INC_DYN_COUNTER(q, pktlen);
+					f = q;
 					/* XXX we would like to have f_pos
 					 * readily accessible in the dynamic
 				         * rule, instead of having to
 					 * lookup q->rule.
 					 */
-					f = q->rule;
 					f_pos = ipfw_find_rule(chain,
-						f->rulenum, f->id);
+					    f->rulenum, f->id);
 					cmd = ACTION_PTR(f);
 					l = f->cmd_len - f->act_ofs;
-					ipfw_dyn_unlock(q);
 					cmdlen = 0;
 					match = 1;
 					break;
@@ -2431,8 +2577,7 @@ do {								\
 			case O_FORWARD_IP:
 				if (args->eh)	/* not valid on layer2 pkts */
 					break;
-				if (q == NULL || q->rule != f ||
-				    dyn_dir == MATCH_FORWARD) {
+				if (q != f || dyn_dir == MATCH_FORWARD) {
 				    struct sockaddr_in *sa;
 
 				    sa = &(((ipfw_insn_sa *)cmd)->sa);
@@ -2492,8 +2637,7 @@ do {								\
 			case O_FORWARD_IP6:
 				if (args->eh)	/* not valid on layer2 pkts */
 					break;
-				if (q == NULL || q->rule != f ||
-				    dyn_dir == MATCH_FORWARD) {
+				if (q != f || dyn_dir == MATCH_FORWARD) {
 					struct sockaddr_in6 *sin6;
 
 					sin6 = &(((ipfw_insn_sa6 *)cmd)->sa);
@@ -2842,11 +2986,6 @@ vnet_ipfw_init(const void *unused)
 	ipfw_init_srv(chain);
 
 	ipfw_init_counters();
-	/* insert the default rule and create the initial map */
-	chain->n_rules = 1;
-	chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO);
-	rule = ipfw_alloc_rule(chain, sizeof(struct ip_fw));
-
 	/* Set initial number of tables */
 	V_fw_tables_max = default_fw_tables;
 	error = ipfw_init_tables(chain, first);
@@ -2857,19 +2996,16 @@ vnet_ipfw_init(const void *unused)
 		return (ENOSPC);
 	}
 
+	IPFW_LOCK_INIT(chain);
+
 	/* fill and insert the default rule */
-	rule->act_ofs = 0;
-	rule->rulenum = IPFW_DEFAULT_RULE;
+	rule = ipfw_alloc_rule(chain, sizeof(struct ip_fw));
 	rule->cmd_len = 1;
-	rule->set = RESVD_SET;
 	rule->cmd[0].len = 1;
 	rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
-	chain->default_rule = chain->map[0] = rule;
-	chain->id = rule->id = 1;
-	/* Pre-calculate rules length for legacy dump format */
-	chain->static_len = sizeof(struct ip_fw_rule0);
+	chain->default_rule = rule;
+	ipfw_add_protected_rule(chain, rule, 0);
 
-	IPFW_LOCK_INIT(chain);
 	ipfw_dyn_init(chain);
 	ipfw_eaction_init(chain, first);
 #ifdef LINEAR_SKIPTO

Modified: stable/11/sys/netpfil/ipfw/ip_fw_dynamic.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/ip_fw_dynamic.c	Thu Nov 30 07:24:33 2017	(r326387)
+++ stable/11/sys/netpfil/ipfw/ip_fw_dynamic.c	Thu Nov 30 07:42:56 2017	(r326388)
@@ -251,7 +251,7 @@ SYSEND
 
 #ifdef INET6
 static __inline int
-hash_packet6(struct ipfw_flow_id *id)
+hash_packet6(const struct ipfw_flow_id *id)
 {
 	u_int32_t i;
 	i = (id->dst_ip6.__u6_addr.__u6_addr32[2]) ^
@@ -268,7 +268,7 @@ hash_packet6(struct ipfw_flow_id *id)
  * and we want to find both in the same bucket.
  */
 static __inline int
-hash_packet(struct ipfw_flow_id *id, int buckets)
+hash_packet(const struct ipfw_flow_id *id, int buckets)
 {
 	u_int32_t i;
 
@@ -476,8 +476,8 @@ static struct opcode_obj_rewrite dyn_opcodes[] = {
  * Print customizable flow id description via log(9) facility.
  */
 static void
-print_dyn_rule_flags(struct ipfw_flow_id *id, int dyn_type, int log_flags,
-    char *prefix, char *postfix)
+print_dyn_rule_flags(const struct ipfw_flow_id *id, int dyn_type,
+    int log_flags, char *prefix, char *postfix)
 {
 	struct in_addr da;
 #ifdef INET6
@@ -511,12 +511,14 @@ print_dyn_rule_flags(struct ipfw_flow_id *id, int dyn_
 
 static void
 dyn_update_proto_state(ipfw_dyn_rule *q, const struct ipfw_flow_id *id,
-    const struct tcphdr *tcp, int dir)
+    const void *ulp, int dir)
 {
+	const struct tcphdr *tcp;
 	uint32_t ack;
 	u_char flags;
 
 	if (id->proto == IPPROTO_TCP) {
+		tcp = (const struct tcphdr *)ulp;
 		flags = id->_flags & (TH_FIN | TH_SYN | TH_RST);
 #define BOTH_SYN	(TH_SYN | (TH_SYN << 8))
 #define BOTH_FIN	(TH_FIN | (TH_FIN << 8))
@@ -592,8 +594,8 @@ dyn_update_proto_state(ipfw_dyn_rule *q, const struct 
  * Lookup a dynamic rule, locked version.
  */
 static ipfw_dyn_rule *
-lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int i, int *match_direction,
-    struct tcphdr *tcp, uint16_t kidx)
+lookup_dyn_rule_locked(const struct ipfw_flow_id *pkt, const void *ulp,
+    int i, int *match_direction, uint16_t kidx)
 {
 	/*
 	 * Stateful ipfw extensions.
@@ -609,6 +611,9 @@ lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int i
 		if (q->dyn_type == O_LIMIT_PARENT)
 			continue;
 
+		if (pkt->addr_type != q->id.addr_type)
+			continue;
+
 		if (pkt->proto != q->id.proto)
 			continue;
 
@@ -657,41 +662,35 @@ lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int i
 	}
 
 	/* update state according to flags */
-	dyn_update_proto_state(q, pkt, tcp, dir);
+	dyn_update_proto_state(q, pkt, ulp, dir);
 done:
 	if (match_direction != NULL)
 		*match_direction = dir;
 	return (q);
 }
 
-ipfw_dyn_rule *
-ipfw_lookup_dyn_rule(struct ipfw_flow_id *pkt, int *match_direction,
-    struct tcphdr *tcp, uint16_t kidx)
+struct ip_fw *
+ipfw_dyn_lookup_state(const struct ipfw_flow_id *pkt, const void *ulp,
+    int pktlen, int *match_direction, uint16_t kidx)
 {
+	struct ip_fw *rule;
 	ipfw_dyn_rule *q;
 	int i;
 
 	i = hash_packet(pkt, V_curr_dyn_buckets);
 
 	IPFW_BUCK_LOCK(i);
-	q = lookup_dyn_rule_locked(pkt, i, match_direction, tcp, kidx);
+	q = lookup_dyn_rule_locked(pkt, ulp, i, match_direction, kidx);
 	if (q == NULL)
-		IPFW_BUCK_UNLOCK(i);
-	/* NB: return table locked when q is not NULL */
-	return q;
+		rule = NULL;
+	else {
+		rule = q->rule;
+		IPFW_INC_DYN_COUNTER(q, pktlen);
+	}
+	IPFW_BUCK_UNLOCK(i);
+	return (rule);
 }
 
-/*
- * Unlock bucket mtx
- * @p - pointer to dynamic rule
- */
-void
-ipfw_dyn_unlock(ipfw_dyn_rule *q)
-{
-
-	IPFW_BUCK_UNLOCK(q->bucket);
-}
-
 static int
 resize_dynamic_table(struct ip_fw_chain *chain, int nbuckets)
 {
@@ -784,7 +783,7 @@ resize_dynamic_table(struct ip_fw_chain *chain, int nb
  * - "parent" rules for the above (O_LIMIT_PARENT).
  */
 static ipfw_dyn_rule *
-add_dyn_rule(struct ipfw_flow_id *id, int i, uint8_t dyn_type,
+add_dyn_rule(const struct ipfw_flow_id *id, int i, uint8_t dyn_type,
     struct ip_fw *rule, uint16_t kidx)
 {
 	ipfw_dyn_rule *r;
@@ -834,8 +833,8 @@ add_dyn_rule(struct ipfw_flow_id *id, int i, uint8_t d
  * If the lookup fails, then install one.
  */
 static ipfw_dyn_rule *
-lookup_dyn_parent(struct ipfw_flow_id *pkt, int *pindex, struct ip_fw *rule,
-    uint16_t kidx)
+lookup_dyn_parent(const struct ipfw_flow_id *pkt, int *pindex,
+    struct ip_fw *rule, uint16_t kidx)
 {
 	ipfw_dyn_rule *q;
 	int i, is_v6;
@@ -879,7 +878,7 @@ lookup_dyn_parent(struct ipfw_flow_id *pkt, int *pinde
  * session limitations are enforced.
  */
 int
-ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
+ipfw_dyn_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
     ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg)
 {
 	ipfw_dyn_rule *q;
@@ -892,7 +891,7 @@ ipfw_install_state(struct ip_fw_chain *chain, struct i
 
 	IPFW_BUCK_LOCK(i);
 
-	q = lookup_dyn_rule_locked(&args->f_id, i, NULL, NULL, cmd->o.arg1);
+	q = lookup_dyn_rule_locked(&args->f_id, NULL, i, NULL, cmd->o.arg1);
 	if (q != NULL) {	/* should never occur */
 		DEB(
 		if (last_log != time_uptime) {
@@ -1018,155 +1017,6 @@ ipfw_install_state(struct ip_fw_chain *chain, struct i
 	dyn_update_proto_state(q, &args->f_id, NULL, MATCH_FORWARD);
 	IPFW_BUCK_UNLOCK(i);
 	return (0);
-}
-
-/*
- * Generate a TCP packet, containing either a RST or a keepalive.
- * When flags & TH_RST, we are sending a RST packet, because of a
- * "reset" action matched the packet.
- * Otherwise we are sending a keepalive, and flags & TH_
- * The 'replyto' mbuf is the mbuf being replied to, if any, and is required
- * so that MAC can label the reply appropriately.
- */
-struct mbuf *
-ipfw_send_pkt(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t seq,
-    u_int32_t ack, int flags)
-{
-	struct mbuf *m = NULL;		/* stupid compiler */
-	int len, dir;
-	struct ip *h = NULL;		/* stupid compiler */
-#ifdef INET6
-	struct ip6_hdr *h6 = NULL;
-#endif
-	struct tcphdr *th = NULL;
-
-	MGETHDR(m, M_NOWAIT, MT_DATA);
-	if (m == NULL)
-		return (NULL);
-
-	M_SETFIB(m, id->fib);
-#ifdef MAC
-	if (replyto != NULL)
-		mac_netinet_firewall_reply(replyto, m);
-	else
-		mac_netinet_firewall_send(m);
-#else
-	(void)replyto;		/* don't warn about unused arg */
-#endif
-
-	switch (id->addr_type) {
-	case 4:
-		len = sizeof(struct ip) + sizeof(struct tcphdr);
-		break;
-#ifdef INET6
-	case 6:
-		len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
-		break;
-#endif
-	default:
-		/* XXX: log me?!? */
-		FREE_PKT(m);
-		return (NULL);
-	}
-	dir = ((flags & (TH_SYN | TH_RST)) == TH_SYN);
-
-	m->m_data += max_linkhdr;
-	m->m_flags |= M_SKIP_FIREWALL;
-	m->m_pkthdr.len = m->m_len = len;
-	m->m_pkthdr.rcvif = NULL;
-	bzero(m->m_data, len);
-
-	switch (id->addr_type) {
-	case 4:
-		h = mtod(m, struct ip *);
-
-		/* prepare for checksum */
-		h->ip_p = IPPROTO_TCP;
-		h->ip_len = htons(sizeof(struct tcphdr));
-		if (dir) {
-			h->ip_src.s_addr = htonl(id->src_ip);
-			h->ip_dst.s_addr = htonl(id->dst_ip);
-		} else {
-			h->ip_src.s_addr = htonl(id->dst_ip);
-			h->ip_dst.s_addr = htonl(id->src_ip);
-		}
-
-		th = (struct tcphdr *)(h + 1);
-		break;
-#ifdef INET6
-	case 6:
-		h6 = mtod(m, struct ip6_hdr *);
-
-		/* prepare for checksum */
-		h6->ip6_nxt = IPPROTO_TCP;
-		h6->ip6_plen = htons(sizeof(struct tcphdr));
-		if (dir) {
-			h6->ip6_src = id->src_ip6;
-			h6->ip6_dst = id->dst_ip6;
-		} else {
-			h6->ip6_src = id->dst_ip6;
-			h6->ip6_dst = id->src_ip6;
-		}
-
-		th = (struct tcphdr *)(h6 + 1);
-		break;
-#endif
-	}
-
-	if (dir) {
-		th->th_sport = htons(id->src_port);
-		th->th_dport = htons(id->dst_port);
-	} else {
-		th->th_sport = htons(id->dst_port);
-		th->th_dport = htons(id->src_port);
-	}
-	th->th_off = sizeof(struct tcphdr) >> 2;
-
-	if (flags & TH_RST) {
-		if (flags & TH_ACK) {
-			th->th_seq = htonl(ack);
-			th->th_flags = TH_RST;
-		} else {
-			if (flags & TH_SYN)
-				seq++;
-			th->th_ack = htonl(seq);
-			th->th_flags = TH_RST | TH_ACK;
-		}
-	} else {
-		/*
-		 * Keepalive - use caller provided sequence numbers
-		 */
-		th->th_seq = htonl(seq);
-		th->th_ack = htonl(ack);
-		th->th_flags = TH_ACK;
-	}
-
-	switch (id->addr_type) {
-	case 4:
-		th->th_sum = in_cksum(m, len);
-
-		/* finish the ip header */
-		h->ip_v = 4;
-		h->ip_hl = sizeof(*h) >> 2;
-		h->ip_tos = IPTOS_LOWDELAY;
-		h->ip_off = htons(0);
-		h->ip_len = htons(len);
-		h->ip_ttl = V_ip_defttl;
-		h->ip_sum = 0;
-		break;
-#ifdef INET6
-	case 6:
-		th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(*h6),
-		    sizeof(struct tcphdr));
-
-		/* finish the ip6 header */
-		h6->ip6_vfc |= IPV6_VERSION;
-		h6->ip6_hlim = IPV6_DEFHLIM;
-		break;
-#endif
-	}
-
-	return (m);
 }
 
 /*

Modified: stable/11/sys/netpfil/ipfw/ip_fw_private.h
==============================================================================
--- stable/11/sys/netpfil/ipfw/ip_fw_private.h	Thu Nov 30 07:24:33 2017	(r326387)
+++ stable/11/sys/netpfil/ipfw/ip_fw_private.h	Thu Nov 30 07:42:56 2017	(r326388)
@@ -183,15 +183,14 @@ struct ip_fw_chain;
 struct sockopt_data;
 int ipfw_is_dyn_rule(struct ip_fw *rule);
 void ipfw_expire_dyn_rules(struct ip_fw_chain *, ipfw_range_tlv *);
-void ipfw_dyn_unlock(ipfw_dyn_rule *q);
 
 struct tcphdr;
 struct mbuf *ipfw_send_pkt(struct mbuf *, struct ipfw_flow_id *,
     u_int32_t, u_int32_t, int);
-int ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
+int ipfw_dyn_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
     ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg);
-ipfw_dyn_rule *ipfw_lookup_dyn_rule(struct ipfw_flow_id *pkt,
-	int *match_direction, struct tcphdr *tcp, uint16_t kidx);
+struct ip_fw *ipfw_dyn_lookup_state(const struct ipfw_flow_id *pkt,
+    const void *ulp, int pktlen, int *match_direction, uint16_t kidx);
 void ipfw_remove_dyn_children(struct ip_fw *rule);
 void ipfw_get_dynamic(struct ip_fw_chain *chain, char **bp, const char *ep);
 int ipfw_dump_states(struct ip_fw_chain *chain, struct sockopt_data *sd);
@@ -625,6 +624,8 @@ void ipfw_destroy_skipto_cache(struct ip_fw_chain *cha
 int ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id);
 int ipfw_ctl3(struct sockopt *sopt);
 int ipfw_chk(struct ip_fw_args *args);
+int ipfw_add_protected_rule(struct ip_fw_chain *chain, struct ip_fw *rule,
+    int locked);
 void ipfw_reap_add(struct ip_fw_chain *chain, struct ip_fw **head,
     struct ip_fw *rule);
 void ipfw_reap_rules(struct ip_fw *head);

Modified: stable/11/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/ip_fw_sockopt.c	Thu Nov 30 07:24:33 2017	(r326387)
+++ stable/11/sys/netpfil/ipfw/ip_fw_sockopt.c	Thu Nov 30 07:42:56 2017	(r326388)
@@ -790,6 +790,30 @@ commit_rules(struct ip_fw_chain *chain, struct rule_ch
 	return (0);
 }
 
+int
+ipfw_add_protected_rule(struct ip_fw_chain *chain, struct ip_fw *rule,
+    int locked)
+{
+	struct ip_fw **map;
+
+	map = get_map(chain, 1, locked);
+	if (map == NULL)
+		return (ENOMEM);
+	if (chain->n_rules > 0)
+		bcopy(chain->map, map,
+		    chain->n_rules * sizeof(struct ip_fw *));
+	map[chain->n_rules] = rule;
+	rule->rulenum = IPFW_DEFAULT_RULE;
+	rule->set = RESVD_SET;
+	rule->id = chain->id + 1;
+	/* We add rule in the end of chain, no need to update skipto cache */
+	map = swap_map(chain, map, chain->n_rules + 1);
+	chain->static_len += RULEUSIZE0(rule);
+	IPFW_UH_WUNLOCK(chain);
+	free(map, M_IPFW);
+	return (0);
+}
+
 /*
  * Adds @rule to the list of rules to reap
  */
@@ -997,10 +1021,9 @@ delete_range(struct ip_fw_chain *chain, ipfw_range_tlv
 	if ((rt->flags & IPFW_RCFLAG_RANGE) != 0) {
 		start = ipfw_find_rule(chain, rt->start_rule, 0);
 
-		end = ipfw_find_rule(chain, rt->end_rule, 0);
-		if (rt->end_rule != IPFW_DEFAULT_RULE)
-			while (chain->map[end]->rulenum == rt->end_rule)
-				end++;
+		if (rt->end_rule >= IPFW_DEFAULT_RULE)
+			rt->end_rule = IPFW_DEFAULT_RULE - 1;
+		end = ipfw_find_rule(chain, rt->end_rule, UINT32_MAX);
 	}
 
 	/* Allocate new map of the same size */
@@ -2377,9 +2400,9 @@ dump_config(struct ip_fw_chain *chain, ip_fw3_opheader
 		if ((rnum = hdr->start_rule) > IPFW_DEFAULT_RULE)
 			rnum = IPFW_DEFAULT_RULE;
 		da.b = ipfw_find_rule(chain, rnum, 0);
-		rnum = hdr->end_rule;
-		rnum = (rnum < IPFW_DEFAULT_RULE) ? rnum+1 : IPFW_DEFAULT_RULE;
-		da.e = ipfw_find_rule(chain, rnum, 0) + 1;
+		rnum = (hdr->end_rule < IPFW_DEFAULT_RULE) ?
+		    hdr->end_rule + 1: IPFW_DEFAULT_RULE;
+		da.e = ipfw_find_rule(chain, rnum, UINT32_MAX) + 1;
 	}
 
 	if (hdr->flags & IPFW_CFG_GET_STATIC) {



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