From owner-freebsd-net@FreeBSD.ORG Mon Nov 29 10:30:58 2004 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id BBC1916A4CE for ; Mon, 29 Nov 2004 10:30:58 +0000 (GMT) Received: from amsfep16-int.chello.nl (amsfep16-int.chello.nl [213.46.243.26]) by mx1.FreeBSD.org (Postfix) with ESMTP id DC74C43D41 for ; Mon, 29 Nov 2004 10:30:57 +0000 (GMT) (envelope-from joost@jodocus.org) Received: from bps.jodocus.org ([80.57.157.16]) by amsfep19-int.chello.nl ESMTP <20041129103032.QFCD23658.amsfep19-int.chello.nl@bps.jodocus.org>; Mon, 29 Nov 2004 11:30:32 +0100 Received: from jodocus.org (localhost [127.0.0.1]) by bps.jodocus.org (8.13.1/8.13.1) with ESMTP id iATAUVwl019901; Mon, 29 Nov 2004 11:30:31 +0100 (CET) (envelope-from joost@jodocus.org) Received: (from joost@localhost) by jodocus.org (8.13.1/8.13.1/Submit) id iATAUVdN019900; Mon, 29 Nov 2004 11:30:31 +0100 (CET) (envelope-from joost) Date: Mon, 29 Nov 2004 11:30:31 +0100 From: Joost Bekkers To: Andre Oppermann Message-ID: <20041129103031.GA19828@bps.jodocus.org> Mail-Followup-To: Joost Bekkers , Andre Oppermann , freebsd-net@freebsd.org References: <20041129100949.GA19560@bps.jodocus.org> <41AAF696.6ED81FBF@freebsd.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="9jxsPFA5p3P2qPhR" Content-Disposition: inline In-Reply-To: <41AAF696.6ED81FBF@freebsd.org> User-Agent: Mutt/1.4.2.1i cc: freebsd-net@freebsd.org Subject: Re: (review request) ipfw and ipsec processing order for outgoingpackets X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 29 Nov 2004 10:30:58 -0000 --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--