Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 Nov 2004 11:30:31 +0100
From:      Joost Bekkers <joost@jodocus.org>
To:        Andre Oppermann <andre@freebsd.org>
Cc:        freebsd-net@freebsd.org
Subject:   Re: (review request) ipfw and ipsec processing order for outgoingpackets
Message-ID:  <20041129103031.GA19828@bps.jodocus.org>
In-Reply-To: <41AAF696.6ED81FBF@freebsd.org>
References:  <20041129100949.GA19560@bps.jodocus.org> <41AAF696.6ED81FBF@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--9jxsPFA5p3P2qPhR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Nov 29, 2004 at 11:14:46AM +0100, Andre Oppermann wrote:
> > 
> > The attached patch is against 5.3R
> 
> Please post unified diffs.
> 

Ok, here you go.

-- 
greetz Joost
joost@jodocus.org

--9jxsPFA5p3P2qPhR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ipsec_filtergif_2.diff"

--- sys/netinet/dist/ip_output.c	Sat Nov 27 20:56:56 2004
+++ sys/netinet/ip_output.c	Mon Nov 29 10:59:48 2004
@@ -405,6 +405,111 @@
 	}
 
 sendit:
+
+/* Ok, some really weird wizardry going on here. The goal is to pass
+ * packets that are going to be ipsec encapsulated pass through the
+ * firewall first.
+ * 
+ * The PFIL code is split into two pieces:
+ *  1) the main part, which calls the pfil hooks and cleans up after them
+ *  2) a part that handles forwarding (if option IPFIREWALL_FORWARD is in the config)
+ *
+ * Because part 2 is not always include the #defines are done in two steps.
+ *
+ * There are five possible scenarios for this piece of code:
+ *
+ * 1) no ipsec at all			   ->	             pfil
+ * 2) Kame IPSEC without IPSEC_FILTERGIF   ->	      ipsec, pfil
+ * 3) Kame IPSEC with IPSEC_FILTERGIF      ->	pfil, ipsec, pfil
+ * 4) FAST_IPSEC without IPSEC_FILTERGIF   ->	      ipsec, pfil
+ * 5) FAST_IPSEC with IPSEC_FILTERGIF      ->	pfil, ipsec
+ *
+ * The first pfil location is therefor only used if IPSEC_FILTERGIF is defined.
+ * The second location is used if IPSEC_FILTERGIF is not defined of FAST_IPSEC
+ * is not defined.
+ *
+ * The difference in the kame and fast scenarios is caused by fast reinserting
+ * the encapsulated package and 'goto done' where kame will change the current
+ * package to be the encapsulated one. This also causes the strange location of
+ * the first PFIL(); In case of Kame ipsec the code should only be executed if
+ * the packet is actually going to be ipsec-ed. We don't want one packet going
+ * through the firewall twice.
+ */
+
+#define PFIL_RUN_HOOKS(PASSOUT)							\
+	/* Jump over all PFIL processing if hooks are not active. */		\
+	if (inet_pfil_hook.ph_busy_count == -1)					\
+		goto PASSOUT;							\
+										\
+	/* Run through list of hooks for output packets. */			\
+	odst.s_addr = ip->ip_dst.s_addr;					\
+	error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, inp);	\
+	if (error != 0 || m == NULL)						\
+		goto done;							\
+										\
+	ip = mtod(m, struct ip *);						\
+										\
+	/* See if destination IP address was changed by packet filter. */	\
+	if (odst.s_addr != ip->ip_dst.s_addr) {					\
+		m->m_flags |= M_SKIP_FIREWALL;					\
+		if (in_localip(ip->ip_dst)) {					\
+			m->m_flags |= M_FASTFWD_OURS;				\
+			if (m->m_pkthdr.rcvif == NULL)				\
+				m->m_pkthdr.rcvif = loif;			\
+			if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {		\
+				m->m_pkthdr.csum_flags |=			\
+				    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;		\
+				m->m_pkthdr.csum_data = 0xffff;			\
+			}							\
+			m->m_pkthdr.csum_flags |=				\
+			    CSUM_IP_CHECKED | CSUM_IP_VALID;			\
+										\
+			error = netisr_queue(NETISR_IP, m);			\
+			goto done;						\
+		} else								\
+			goto again;						\
+	}
+
+#define PFIL_FORWARD								\
+	/* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */	\
+	if (m->m_flags & M_FASTFWD_OURS) {					\
+		if (m->m_pkthdr.rcvif == NULL)					\
+			m->m_pkthdr.rcvif = loif;				\
+		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {			\
+			m->m_pkthdr.csum_flags |=				\
+			    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;			\
+			m->m_pkthdr.csum_data = 0xffff;				\
+		}								\
+		m->m_pkthdr.csum_flags |=					\
+			    CSUM_IP_CHECKED | CSUM_IP_VALID;			\
+										\
+		error = netisr_queue(NETISR_IP, m);				\
+		goto done;							\
+	}									\
+	/* Or forward to some other address? */					\
+	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);			\
+	if (fwd_tag) {								\
+		if (!in_localip(ip->ip_src) && !in_localaddr(ip->ip_dst)) {	\
+			dst = (struct sockaddr_in *)&ro->ro_dst;		\
+			bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));	\
+			m->m_flags |= M_SKIP_FIREWALL;				\
+			m_tag_delete(m, fwd_tag);				\
+			goto again;						\
+		} else {							\
+			m_tag_delete(m, fwd_tag);				\
+			/* Continue. */						\
+		}								\
+	}
+
+#ifdef IPFIREWALL_FORWARD
+ #define PFIL(endlabel)	PFIL_RUN_HOOKS(endlabel) \
+			PFIL_FORWARD   \
+			endlabel:
+#else
+ #define PFIL(endlabel)	PFIL_RUN_HOOKS(endlabel) \
+			endlabel:
+#endif
+
 #ifdef IPSEC
 	/* get SP for this packet */
 	if (inp == NULL)
@@ -447,6 +552,13 @@
 	default:
 		printf("ip_output: Invalid policy found. %d\n", sp->policy);
 	}
+#endif
+
+#ifdef IPSEC_FILTERGIF
+  PFIL(passout1)
+#endif
+
+#ifdef IPSEC
     {
 	struct ipsec_output_state state;
 	bzero(&state, sizeof(state));
@@ -654,72 +766,14 @@
 spd_done:
 #endif /* FAST_IPSEC */
 
-	/* Jump over all PFIL processing if hooks are not active. */
-	if (inet_pfil_hook.ph_busy_count == -1)
-		goto passout;
-
-	/* Run through list of hooks for output packets. */
-	odst.s_addr = ip->ip_dst.s_addr;
-	error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, inp);
-	if (error != 0 || m == NULL)
-		goto done;
-
-	ip = mtod(m, struct ip *);
-
-	/* See if destination IP address was changed by packet filter. */
-	if (odst.s_addr != ip->ip_dst.s_addr) {
-		m->m_flags |= M_SKIP_FIREWALL;
-		if (in_localip(ip->ip_dst)) {
-			m->m_flags |= M_FASTFWD_OURS;
-			if (m->m_pkthdr.rcvif == NULL)
-				m->m_pkthdr.rcvif = loif;
-			if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
-				m->m_pkthdr.csum_flags |=
-				    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
-				m->m_pkthdr.csum_data = 0xffff;
-			}
-			m->m_pkthdr.csum_flags |=
-			    CSUM_IP_CHECKED | CSUM_IP_VALID;
-
-			error = netisr_queue(NETISR_IP, m);
-			goto done;
-		} else
-			goto again;
-	}
-
-#ifdef IPFIREWALL_FORWARD
-	/* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
-	if (m->m_flags & M_FASTFWD_OURS) {
-		if (m->m_pkthdr.rcvif == NULL)
-			m->m_pkthdr.rcvif = loif;
-		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
-			m->m_pkthdr.csum_flags |=
-			    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
-			m->m_pkthdr.csum_data = 0xffff;
-		}
-		m->m_pkthdr.csum_flags |=
-			    CSUM_IP_CHECKED | CSUM_IP_VALID;
-
-		error = netisr_queue(NETISR_IP, m);
-		goto done;
-	}
-	/* Or forward to some other address? */
-	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
-	if (fwd_tag) {
-		if (!in_localip(ip->ip_src) && !in_localaddr(ip->ip_dst)) {
-			dst = (struct sockaddr_in *)&ro->ro_dst;
-			bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));
-			m->m_flags |= M_SKIP_FIREWALL;
-			m_tag_delete(m, fwd_tag);
-			goto again;
-		} else {
-			m_tag_delete(m, fwd_tag);
-			/* Continue. */
-		}
-	}
+#if !defined FAST_IPSEC || !defined IPSEC_FILTERGIF
+  PFIL(passout2)
 #endif
+#undef PFIL  
+#undef PFIL_RUN_HOOKS
+#undef PFIL_FORWARD
+
 
-passout:
 	/* 127/8 must not appear on wire - RFC1122. */
 	if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
 	    (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {

--9jxsPFA5p3P2qPhR--



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