Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Nov 2003 16:37:45 -0800 (PST)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 43019 for review
Message-ID:  <200311250037.hAP0bjqu040783@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=43019

Change 43019 by sam@sam_ebb on 2003/11/24 16:37:31

	replace MT_TAG mbufs by m_tag's for divert sockets; move
	divert-related definitions to a new ip_divert.h file

Affected files ...

.. //depot/projects/netperf/sys/net/if_ethersubr.c#13 edit
.. //depot/projects/netperf/sys/netinet/in_proto.c#7 edit
.. //depot/projects/netperf/sys/netinet/ip_divert.c#18 edit
.. //depot/projects/netperf/sys/netinet/ip_divert.h#1 add
.. //depot/projects/netperf/sys/netinet/ip_fastfwd.c#4 edit
.. //depot/projects/netperf/sys/netinet/ip_fw.h#5 edit
.. //depot/projects/netperf/sys/netinet/ip_fw2.c#19 edit
.. //depot/projects/netperf/sys/netinet/ip_input.c#26 edit
.. //depot/projects/netperf/sys/netinet/ip_output.c#19 edit
.. //depot/projects/netperf/sys/netinet/ip_var.h#14 edit

Differences ...

==== //depot/projects/netperf/sys/net/if_ethersubr.c#13 (text+ko) ====

@@ -393,7 +393,6 @@
 
 	args.m = m;		/* the packet we are looking at		*/
 	args.oif = dst;		/* destination, if any			*/
-	args.divert_rule = 0;	/* we do not support divert yet		*/
 	args.rule = *rule;	/* matching rule to restart		*/
 	args.next_hop = NULL;	/* we do not support forward yet	*/
 	args.eh = &save_eh;	/* MAC header for bridged/MAC packets	*/

==== //depot/projects/netperf/sys/netinet/in_proto.c#7 (text+ko) ====

@@ -57,6 +57,7 @@
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_icmp.h>
+#include <netinet/ip_divert.h>
 #include <netinet/igmp_var.h>
 #ifdef PIM
 #include <netinet/pim_var.h>

==== //depot/projects/netperf/sys/netinet/ip_divert.c#18 (text+ko) ====

@@ -68,6 +68,7 @@
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
 #include <netinet/ip.h>
+#include <netinet/ip_divert.h>
 #include <netinet/ip_var.h>
 
 /*
@@ -150,17 +151,21 @@
  * then pass them along with mbuf chain.
  */
 void
-divert_packet(struct mbuf *m, int incoming, int port, int rule)
+divert_packet(struct mbuf *m, int incoming)
 {
 	struct ip *ip;
 	struct inpcb *inp;
 	struct socket *sa;
 	u_int16_t nport;
 	struct sockaddr_in divsrc;
+	struct m_tag *mtag;
 
-	/* Sanity check */
-	KASSERT(port != 0, ("%s: port=0", __func__));
-
+	mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
+	if (mtag == NULL) {
+		printf("%s: no divert tag\n", __func__);
+		m_freem(m);
+		return;
+	}
 	/* Assure header */
 	if (m->m_len < sizeof(struct ip) &&
 	    (m = m_pullup(m, sizeof(struct ip))) == 0)
@@ -174,7 +179,7 @@
 	bzero(&divsrc, sizeof(divsrc));
 	divsrc.sin_len = sizeof(divsrc);
 	divsrc.sin_family = AF_INET;
-	divsrc.sin_port = rule;		/* record matching rule */
+	divsrc.sin_port = divert_cookie(mtag);	/* record matching rule */
 	if (incoming) {
 		struct ifaddr *ifa;
 
@@ -234,7 +239,7 @@
 	mtx_lock(&Giant);
 	/* Put packet on socket queue, if any */
 	sa = NULL;
-	nport = htons((u_int16_t)port);
+	nport = htons((u_int16_t)divert_info(mtag));
 	INP_INFO_RLOCK(&divcbinfo);
 	LIST_FOREACH(inp, &divcb, inp_list) {
 		INP_LOCK(inp);
@@ -273,19 +278,8 @@
 	struct sockaddr_in *sin, struct mbuf *control)
 {
 	int error = 0;
-	struct m_hdr divert_tag;
 
-	/*
-	 * Prepare the tag for divert info. Note that a packet
-	 * with a 0 tag in mh_data is effectively untagged,
-	 * so we could optimize that case.
-	 */
-	divert_tag.mh_type = MT_TAG;
-	divert_tag.mh_flags = PACKET_TAG_DIVERT;
-	divert_tag.mh_next = m;
-	divert_tag.mh_data = 0;		/* the matching rule # */
-	divert_tag.mh_nextpkt = NULL;
-	m->m_pkthdr.rcvif = NULL;	/* XXX is it necessary ? */
+	KASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null"));
 
 #ifdef MAC
 	mac_create_mbuf_from_socket(so, m);
@@ -296,9 +290,21 @@
 
 	/* Loopback avoidance and state recovery */
 	if (sin) {
+		struct m_tag *mtag;
+		struct divert_tag *dt;
 		int i;
 
-		divert_tag.mh_data = (caddr_t)(uintptr_t)sin->sin_port;
+		mtag = m_tag_get(PACKET_TAG_DIVERT,
+				sizeof(struct divert_tag), M_NOWAIT);
+		if (mtag == NULL) {
+			error = ENOBUFS;
+			goto cantsend;
+		}
+		dt = (struct divert_tag *)(mtag+1);
+		dt->info = 0;
+		dt->cookie = sin->sin_port;
+		m_tag_prepend(m, mtag);
+
 		/*
 		 * Find receive interface with the given name, stuffed
 		 * (if it exists) in the sin_zero[] field.
@@ -335,7 +341,7 @@
 			/* Send packet to output processing */
 			ipstat.ips_rawout++;			/* XXX */
 
-			error = ip_output((struct mbuf *)&divert_tag,
+			error = ip_output(m,
 				    inp->inp_options, NULL,
 				    (so->so_options & SO_DONTROUTE) |
 				    IP_ALLOWBROADCAST | IP_RAWOUTPUT,
@@ -362,7 +368,7 @@
 			m->m_pkthdr.rcvif = ifa->ifa_ifp;
 		}
 		/* Send packet to input processing */
-		ip_input((struct mbuf *)&divert_tag);
+		ip_input(m);
 	}
 
 	return error;
@@ -372,6 +378,27 @@
 	return error;
 }
 
+/*
+ * Return a copy of the specified packet, but without
+ * the divert tag.  This is used when packets are ``tee'd''
+ * and we want the cloned copy to not have divert processing.
+ */
+struct mbuf *
+divert_clone(struct mbuf *m)
+{
+	struct mbuf *clone;
+	struct m_tag *mtag;
+
+	clone = m_dup(m, M_DONTWAIT);
+	if (clone != NULL) {
+		/* strip divert tag from copy */
+		mtag = m_tag_find(clone, PACKET_TAG_DIVERT, NULL);
+		if (mtag != NULL)
+			m_tag_delete(clone, mtag);
+	}
+	return clone;
+}
+
 static int
 div_attach(struct socket *so, int proto, struct thread *td)
 {

==== //depot/projects/netperf/sys/netinet/ip_fastfwd.c#4 (text+ko) ====

@@ -110,6 +110,7 @@
 #include <machine/in_cksum.h>
 
 #include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
 #include <netinet/ip_dummynet.h>
 
 static int ipfastforward_active = 0;
@@ -373,25 +374,13 @@
 			/*
 			 * See if this is a fragment
 			 */
-			if (ip->ip_off & (IP_MF | IP_OFFMASK)) {
-				MGETHDR(tag, M_DONTWAIT, MT_TAG);
-				if (tag == NULL)
-					goto drop;
-				tag->m_flags = PACKET_TAG_DIVERT;
-				tag->m_data = (caddr_t)(intptr_t)args.divert_rule;
-				tag->m_next = m;
-				/* XXX: really bloody hack, see ip_input */
-				tag->m_nextpkt = (struct mbuf *)1;
-				m = tag;
-				tag = NULL;
-
+			if (ip->ip_off & (IP_MF | IP_OFFMASK))
 				goto droptoours;
-			}
 			/*
 			 * Tee packet
 			 */
 			if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
-				teem = m_dup(m, M_DONTWAIT);
+				teem = divert_clone(m);
 			else
 				teem = m;
 			if (teem == NULL)
@@ -413,7 +402,7 @@
 			/*
 			 * Deliver packet to divert input routine
 			 */
-			divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule);
+			divert_packet(teem, 0);
 			/*
 			 * If this was not tee, we are done
 			 */
@@ -560,27 +549,13 @@
 			/*
 			 * See if this is a fragment
 			 */
-			if (ip->ip_off & (IP_MF | IP_OFFMASK)) {
-				MGETHDR(tag, M_DONTWAIT, MT_TAG);
-				if (tag == NULL) {
-					RTFREE(ro.ro_rt);
-					goto drop;
-				}
-				tag->m_flags = PACKET_TAG_DIVERT;
-				tag->m_data = (caddr_t)(intptr_t)args.divert_rule;
-				tag->m_next = m;
-				/* XXX: really bloody hack, see ip_input */
-				tag->m_nextpkt = (struct mbuf *)1;
-				m = tag;
-				tag = NULL;
-
+			if (ip->ip_off & (IP_MF | IP_OFFMASK))
 				goto droptoours;
-			}
 			/*
 			 * Tee packet
 			 */
 			if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
-				teem = m_dup(m, M_DONTWAIT);
+				teem = divert_clone(m);
 			else
 				teem = m;
 			if (teem == NULL)
@@ -602,7 +577,7 @@
 			/*
 			 * Deliver packet to divert input routine
 			 */
-			divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule);
+			divert_packet(teem, 0);
 			/*
 			 * If this was not tee, we are done
 			 */

==== //depot/projects/netperf/sys/netinet/ip_fw.h#5 (text+ko) ====

@@ -400,7 +400,6 @@
 	int flags;			/* for dummynet			*/
 
 	struct ipfw_flow_id f_id;	/* grabbed from IP header	*/
-	u_int16_t	divert_rule;	/* divert cookie		*/
 	u_int32_t	retval;
 };
 

==== //depot/projects/netperf/sys/netinet/ip_fw2.c#19 (text+ko) ====

@@ -65,6 +65,7 @@
 #include <netinet/ip_var.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
 #include <netinet/ip_dummynet.h>
 #include <netinet/tcp.h>
 #include <netinet/tcp_timer.h>
@@ -1462,6 +1463,7 @@
 	int dyn_dir = MATCH_UNKNOWN;
 	ipfw_dyn_rule *q = NULL;
 	struct ip_fw_chain *chain = &layer3_chain;
+	struct m_tag *mtag;
 
 	if (m->m_flags & M_SKIP_FIREWALL)
 		return 0;	/* accept */
@@ -1550,6 +1552,7 @@
 
 after_ip_checks:
 	IPFW_LOCK(chain);		/* XXX expensive? can we run lock free? */
+	mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
 	if (args->rule) {
 		/*
 		 * Packet has already been tagged. Look for the next rule
@@ -1572,7 +1575,7 @@
 		 * Find the starting rule. It can be either the first
 		 * one, or the one after divert_rule if asked so.
 		 */
-		int skipto = args->divert_rule;
+		int skipto = mtag ? divert_cookie(mtag) : 0;
 
 		f = chain->rules;
 		if (args->eh == NULL && skipto != 0) {
@@ -1588,7 +1591,9 @@
 			}
 		}
 	}
-	args->divert_rule = 0;	/* reset to avoid confusion later */
+	/* reset divert rule to avoid confusion later */
+	if (mtag)
+		m_tag_delete(m, mtag);
 
 	/*
 	 * Now scan the rules, and parse microinstructions for each rule.
@@ -2023,14 +2028,29 @@
 				goto done;
 
 			case O_DIVERT:
-			case O_TEE:
+			case O_TEE: {
+				struct divert_tag *dt;
+
 				if (args->eh) /* not on layer 2 */
 					break;
-				args->divert_rule = f->rulenum;
-				retval = (cmd->opcode == O_DIVERT) ?
+				mtag = m_tag_get(PACKET_TAG_DIVERT,
+						sizeof(struct divert_tag),
+						M_NOWAIT);
+				if (mtag == NULL) {
+					/* XXX statistic */
+					/* drop packet */
+					IPFW_UNLOCK(chain);
+					return IP_FW_PORT_DENY_FLAG;
+				}
+				dt = (struct divert_tag *)(mtag+1);
+				dt->cookie = f->rulenum;
+				dt->info = (cmd->opcode == O_DIVERT) ?
 				    cmd->arg1 :
 				    cmd->arg1 | IP_FW_PORT_TEE_FLAG;
+				m_tag_prepend(m, mtag);
+				retval = dt->info;
 				goto done;
+			}
 
 			case O_COUNT:
 			case O_SKIPTO:

==== //depot/projects/netperf/sys/netinet/ip_input.c#26 (text+ko) ====

@@ -78,6 +78,7 @@
 #include <sys/socketvar.h>
 
 #include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
 #include <netinet/ip_dummynet.h>
 
 #ifdef IPSEC
@@ -239,8 +240,7 @@
 static void	ip_forward(struct mbuf *m, int srcrt,
 			struct sockaddr_in *next_hop);
 static void	ip_freef(struct ipqhead *, struct ipq *);
-static struct	mbuf *ip_reass(struct mbuf *, struct ipqhead *,
-		struct ipq *, u_int32_t *, u_int16_t *);
+static struct	mbuf *ip_reass(struct mbuf *, struct ipqhead *, struct ipq *);
 
 /*
  * IP initialization: fill in IP protocol switch table.
@@ -303,7 +303,9 @@
 	int    ours = 0;
 	u_short sum;
 	struct in_addr pkt_dst;
-	u_int32_t divert_info = 0;		/* packet divert/tee info */
+#ifdef IPDIVERT
+	u_int32_t divert_info;			/* packet divert/tee info */
+#endif
 	struct ip_fw_args args;
 	int dchg = 0;				/* dest changed after fw */
 #ifdef PFIL_HOOKS
@@ -318,7 +320,6 @@
 
 	args.eh = NULL;
 	args.oif = NULL;
-	args.divert_rule = 0;			/* divert cookie */
 	args.next_hop = NULL;
 
 	/*
@@ -339,10 +340,6 @@
 			    m->_m_tag_id);
 			break;
 
-		case PACKET_TAG_DIVERT:
-			args.divert_rule = (intptr_t)m->m_hdr.mh_data & 0xffff;
-			break;
-
 		case PACKET_TAG_IPFORWARD:
 			args.next_hop = (struct sockaddr_in *)m->m_hdr.mh_data;
 			break;
@@ -527,7 +524,6 @@
 #ifdef IPDIVERT
 		if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) {
 			/* Divert or tee packet */
-			divert_info = i;
 			goto ours;
 		}
 #endif
@@ -835,13 +831,11 @@
 
 		/*
 		 * Attempt reassembly; if it succeeds, proceed.
-		 * ip_reass() will return a different mbuf, and update
-		 * the divert info in divert_info and args.divert_rule.
+		 * ip_reass() will return a different mbuf.
 		 */
 		ipstat.ips_fragments++;
 		m->m_pkthdr.header = ip;
-		m = ip_reass(m,
-		    &ipq[sum], fp, &divert_info, &args.divert_rule);
+		m = ip_reass(m, &ipq[sum], fp);
 		IPQ_UNLOCK();
 		if (m == 0)
 			return;
@@ -851,7 +845,7 @@
 		hlen = ip->ip_hl << 2;
 #ifdef IPDIVERT
 		/* Restore original checksum before diverting packet */
-		if (divert_info != 0) {
+		if (divert_find_info(m) != 0) {
 			ip->ip_len += hlen;
 			ip->ip_len = htons(ip->ip_len);
 			ip->ip_off = htons(ip->ip_off);
@@ -872,12 +866,15 @@
 	/*
 	 * Divert or tee packet to the divert protocol if required.
 	 */
+	divert_info = divert_find_info(m);
 	if (divert_info != 0) {
-		struct mbuf *clone = NULL;
+		struct mbuf *clone;
 
 		/* Clone packet if we're doing a 'tee' */
 		if ((divert_info & IP_FW_PORT_TEE_FLAG) != 0)
-			clone = m_dup(m, M_DONTWAIT);
+			clone = divert_clone(m);
+		else
+			clone = NULL;
 
 		/* Restore packet header fields to original values */
 		ip->ip_len += hlen;
@@ -885,7 +882,7 @@
 		ip->ip_off = htons(ip->ip_off);
 
 		/* Deliver packet to divert input routine */
-		divert_packet(m, 1, divert_info & 0xffff, args.divert_rule);
+		divert_packet(m, 1);
 		ipstat.ips_delivered++;
 
 		/* If 'tee', continue with original packet */
@@ -896,12 +893,11 @@
 		ip->ip_len += hlen;
 		/*
 		 * Jump backwards to complete processing of the
-		 * packet. But first clear divert_info to avoid
-		 * entering this block again.
-		 * We do not need to clear args.divert_rule
-		 * or args.next_hop as they will not be used.
+		 * packet.  We do not need to clear args.next_hop
+		 * as that will not be used again and the cloned packet
+		 * doesn't contain a divert packet tag so we won't
+		 * re-entry this block.
 		 */
-		divert_info = 0;
 		goto pass;
 	}
 #endif
@@ -995,8 +991,7 @@
  */
 
 static struct mbuf *
-ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
-	u_int32_t *divinfo, u_int16_t *divert_rule)
+ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp)
 {
 	struct ip *ip = mtod(m, struct ip *);
 	register struct mbuf *p, *q, *nq;
@@ -1038,10 +1033,6 @@
 		fp->ipq_dst = ip->ip_dst;
 		fp->ipq_frags = m;
 		m->m_nextpkt = NULL;
-#ifdef IPDIVERT
-		fp->ipq_div_info = 0;
-		fp->ipq_div_cookie = 0;
-#endif
 		goto inserted;
 	} else {
 		fp->ipq_nfrags++;
@@ -1125,16 +1116,15 @@
 inserted:
 
 #ifdef IPDIVERT
-	/*
-	 * Transfer firewall instructions to the fragment structure.
-	 * Only trust info in the fragment at offset 0.
-	 */
-	if (ip->ip_off == 0) {
-		fp->ipq_div_info = *divinfo;
-		fp->ipq_div_cookie = *divert_rule;
+	if (ip->ip_off != 0) {
+		/*
+		 * Strip any divert information; only the info
+		 * on the first fragment is used/kept.
+		 */
+		struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
+		if (mtag)
+			m_tag_delete(m, mtag);
 	}
-	*divinfo = 0;
-	*divert_rule = 0;
 #endif
 
 	/*
@@ -1200,15 +1190,7 @@
 	mac_destroy_ipq(fp);
 #endif
 
-#ifdef IPDIVERT
 	/*
-	 * Extract firewall instructions from the fragment structure.
-	 */
-	*divinfo = fp->ipq_div_info;
-	*divert_rule = fp->ipq_div_cookie;
-#endif
-
-	/*
 	 * Create header for new ip packet by
 	 * modifying header of first packet;
 	 * dequeue and discard fragment reassembly header.
@@ -1228,10 +1210,6 @@
 	return (m);
 
 dropfrag:
-#ifdef IPDIVERT
-	*divinfo = 0;
-	*divert_rule = 0;
-#endif
 	ipstat.ips_fragdropped++;
 	if (fp != NULL)
 		fp->ipq_nfrags--;

==== //depot/projects/netperf/sys/netinet/ip_output.c#19 (text+ko) ====

@@ -90,6 +90,7 @@
 #endif /*FAST_IPSEC*/
 
 #include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
 #include <netinet/ip_dummynet.h>
 
 #define print_ip(x, a, y)	 printf("%s %d.%d.%d.%d%s",\
@@ -160,7 +161,6 @@
 	args.eh = NULL;
 	args.rule = NULL;
 	args.next_hop = NULL;
-	args.divert_rule = 0;			/* divert cookie */
 
 	/* Grab info from MT_TAG mbufs prepended to the chain. */
 	for (; m0 && m0->m_type == MT_TAG; m0 = m0->m_next) {
@@ -170,10 +170,6 @@
 			    m0->_m_tag_id);
 			break;
 
-		case PACKET_TAG_DIVERT:
-			args.divert_rule = (intptr_t)m0->m_data & 0xffff;
-			break;
-
 		case PACKET_TAG_IPFORWARD:
 			args.next_hop = (struct sockaddr_in *)m0->m_data;
 			break;
@@ -819,11 +815,13 @@
 		}
 #ifdef IPDIVERT
 		if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
-			struct mbuf *clone = NULL;
+			struct mbuf *clone;
 
 			/* Clone packet if we're doing a 'tee' */
 			if ((off & IP_FW_PORT_TEE_FLAG) != 0)
-				clone = m_dup(m, M_DONTWAIT);
+				clone = divert_clone(m);
+			else
+				clone = NULL;
 
 			/*
 			 * XXX
@@ -840,7 +838,7 @@
 			ip->ip_off = htons(ip->ip_off);
 
 			/* Deliver packet to divert input routine */
-			divert_packet(m, 0, off & 0xffff, args.divert_rule);
+			divert_packet(m, 0);
 
 			/* If 'tee', continue with original packet */
 			if (clone != NULL) {

==== //depot/projects/netperf/sys/netinet/ip_var.h#14 (text+ko) ====

@@ -65,8 +65,6 @@
 	struct mbuf *ipq_frags;		/* to ip headers of fragments */
 	struct	in_addr ipq_src,ipq_dst;
 	u_char	ipq_nfrags;		/* # frags in this packet */
-	u_int32_t ipq_div_info;		/* ipfw divert port & flags */
-	u_int16_t ipq_div_cookie;	/* ipfw divert cookie */
 	struct label *ipq_label;		/* MAC label */
 };
 #endif /* _KERNEL */
@@ -198,14 +196,6 @@
 extern void	(*rsvp_input_p)(struct mbuf *m, int off);
 
 
-#ifdef IPDIVERT
-void	div_init(void);
-void	div_input(struct mbuf *, int);
-void	div_ctlinput(int, struct sockaddr *, void *);
-void	divert_packet(struct mbuf *m, int incoming, int port, int rule);
-extern struct pr_usrreqs div_usrreqs;
-#endif
-
 #ifdef PFIL_HOOKS
 extern	struct pfil_head inet_pfil_hook;
 #endif



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