FWD under bridged enviroment...

Kelly Yancey kbyanc at posi.net
Thu Aug 19 11:47:56 PDT 2004


yOn Tue, 17 Aug 2004, Patrick Tracanelli wrote:

> Kelly, I remember you said once that you had modified the code in a
> different way Luigi had done and posted here (Rizzo's patch for
> revision); I considere patching ip_fw2.c and ip_input.c to get it
> working, where can I find your patches to read it?
>
> I want to see the two ways it was done :}
>

  It isn't pretty as mbuf tags had not been backported to -stable yet when
I originally wrote the attached diffs (circa FreeBSD 4.7).  I also just
noticed that the MGETHDR with M_NOWAIT is bogus as the following code
doesn't check for it failing.  I'll cleanup both of these points when I
port the code to 5.x and post the resulting patch.
  These diffs were just pulled out of my local CVS with other changes in
the network stack, so it is doubtful they will apply cleanly against any
version of FreeBSD (although 4.7p23 should have the highest odds).  Since
you said you just wanted to read the code, though, it shouldn't be a
problem.  If it looks like I missed a file, please let me know,

  Kelly

--
Kelly Yancey  -  kbyanc@{posi.net,FreeBSD.org}  -  kelly at nttmcl.com
-------------- next part --------------
Index: ip_fw2.c
===================================================================
RCS file: /home/cvs/acs/base/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -p -r1.9 -r1.11
--- ip_fw2.c	3 Jan 2003 23:34:19 -0000	1.9
+++ ip_fw2.c	8 Jan 2003 06:14:48 -0000	1.11
@@ -580,17 +580,17 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 	}
 	if (oif || m->m_pkthdr.rcvif)
 		log(LOG_SECURITY | LOG_INFO,
-		    "ipfw: %d %s %s %s via %s%d%s\n",
+		    "ipfw: %d %s %s %s via %s%d%s (layer %d)\n",
 		    f ? f->rulenum : -1,
 		    action, proto, oif ? "out" : "in",
 		    oif ? oif->if_name : m->m_pkthdr.rcvif->if_name,
 		    oif ? oif->if_unit : m->m_pkthdr.rcvif->if_unit,
-		    fragment);
+		    fragment, eh ? 2 : 3);
 	else
 		log(LOG_SECURITY | LOG_INFO,
-		    "ipfw: %d %s %s [no if info]%s\n",
+		    "ipfw: %d %s %s [no if info]%s (layer %d)\n",
 		    f ? f->rulenum : -1,
-		    action, proto, fragment);
+		    action, proto, fragment, eh ? 2 : 3);
 	if (limit_reached)
 		log(LOG_SECURITY | LOG_NOTICE,
 		    "ipfw: limit %d reached on entry %d\n",
@@ -1939,8 +1939,10 @@ check_body:
 				goto done;
 
 			case O_FORWARD_IP:
-				if (args->eh)	/* not valid on layer2 pkts */
-					break;
+				if (args->eh && oif != NULL) {
+					/* ignore outbound layer2 pkts */
+					goto next_rule;
+				}
 				if (!q || dyn_dir == MATCH_FORWARD)
 					args->next_hop =
 					    &((ipfw_insn_sa *)cmd)->sa;
Index: ip_input.c
===================================================================
RCS file: /home/cvs/acs/base/src/sys/netinet/ip_input.c,v
retrieving revision 1.14
retrieving revision 1.16
diff -u -p -r1.14 -r1.16
--- ip_input.c	3 Jan 2003 04:46:53 -0000	1.14
+++ ip_input.c	8 Jan 2003 06:16:06 -0000	1.16
@@ -369,8 +369,18 @@ ip_input(struct mbuf *m)
 		case PACKET_TAG_IPFORWARD:
 			args.next_hop = (struct sockaddr_in *)m->m_hdr.mh_data;
 			break;
+		case PACKET_TAG_IPFORWARD | M_PROTO5: {
+			/* XXX This should be taken out and shot! */
+			struct mbuf *tag = m;
+			m = m->m_next;
+			args.next_hop = (struct sockaddr_in *)tag->m_hdr.mh_data;
+			m_free(tag);
+			KASSERT(m->m_type != MT_TAG, ("XXX kill me"));
+			goto posttags;
+			}
 		}
 	}
+posttags:
 
 	KASSERT(m != NULL && (m->m_flags & M_PKTHDR) != 0,
 	    ("ip_input: no HDR"));
Index: if_ethersubr.c
===================================================================
RCS file: /home/cvs/acs/base/src/sys/net/if_ethersubr.c,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -p -r1.9 -r1.11
--- if_ethersubr.c	3 Jan 2003 04:40:06 -0000	1.9
+++ if_ethersubr.c	8 Jan 2003 06:16:05 -0000	1.11
@@ -501,7 +501,7 @@ ether_ipfw_chk(struct mbuf **m0, struct 
 	args.oif = flags & ETHER_IPFW_OUTPUT ? ifp : NULL;
 	args.divert_rule = divert_rule;
 	args.rule = *rule;	/* matching rule to restart		*/
-	args.next_hop = NULL;	/* we do not support forward yet	*/
+	args.next_hop = NULL;	/* IPFORWARD				*/
 	args.eh = &save_eh;	/* MAC header for bridged/MAC packets	*/
 	i = ip_fw_chk_ptr(&args);
 	*m0 = args.m;
@@ -510,7 +510,7 @@ ether_ipfw_chk(struct mbuf **m0, struct 
 	if ( (i & IP_FW_PORT_DENY_FLAG) || *m0 == NULL) /* drop */
 		return 0;
 
-	if (i == 0) /* a PASS rule.  */
+	if (i == 0 && args.next_hop == NULL) /* a PASS rule.  */
 		return 1;
 
 	if (DUMMYNET_LOADED && (i & IP_FW_PORT_DYNT_FLAG)) {
@@ -589,6 +589,36 @@ ether_ipfw_chk(struct mbuf **m0, struct 
 
 		/* If 'tee', continue with original packet */
 		return (clone != NULL);
+	}
+#endif
+
+#ifdef INET
+	/*
+	 * IPFIREWALL_FORWARD
+	 *
+	 * XXX Only support IP forwarding during in-bound processing.
+	 */
+	if (i == 0 && args.next_hop != NULL && args.oif == NULL) {
+		/*
+		 * Packet must be IP to match an IP forward rule.  Tag it and
+		 * pass it along to ip_input() for processing.
+		 * XXX Relies on nothing in the netisr processing examining
+		 *     the leading mbuf as it's our tag rather than a proper
+		 *     packet header.
+		 * XXX This is pretty expensive (and ugly!).  This can be
+		 *     cleaned up using -current's packet tagging.
+		 */
+		struct mbuf *tag;
+
+		MGETHDR(tag, M_DONTWAIT, MT_TAG);
+		tag->m_hdr.mh_flags = PACKET_TAG_IPFORWARD | M_PROTO5; /* Hack! */
+		tag->m_hdr.mh_data = (caddr_t)args.next_hop;
+		tag->m_hdr.mh_next = *m0;
+
+		schednetisr(NETISR_IP);
+		(void) IF_HANDOFF(&ipintrq, tag, NULL);
+		*m0 = NULL;
+		return 0;
 	}
 #endif
 


More information about the freebsd-ipfw mailing list