Index: sys/netinet/ip_input.c =================================================================== --- sys/netinet/ip_input.c +++ sys/netinet/ip_input.c @@ -907,13 +907,6 @@ m_freem(m); return; } -#ifdef IPSEC - if (ip_ipsec_fwd(m) != 0) { - IPSTAT_INC(ips_cantforward); - m_freem(m); - return; - } -#endif /* IPSEC */ #ifdef IPSTEALTH if (!V_ipstealth) { #endif Index: sys/netinet/ip_ipsec.h =================================================================== --- sys/netinet/ip_ipsec.h +++ sys/netinet/ip_ipsec.h @@ -33,7 +33,6 @@ #define _NETINET_IP_IPSEC_H_ int ip_ipsec_filtertunnel(struct mbuf *); -int ip_ipsec_fwd(struct mbuf *); int ip_ipsec_input(struct mbuf *, int); int ip_ipsec_mtu(struct mbuf *, int); int ip_ipsec_output(struct mbuf **, struct inpcb *, int *); Index: sys/netinet/ip_ipsec.c =================================================================== --- sys/netinet/ip_ipsec.c +++ sys/netinet/ip_ipsec.c @@ -99,19 +99,6 @@ } /* - * Check if this packet has an active SA and needs to be dropped instead - * of forwarded. - * Called from ip_forward(). - * 1 = drop packet, 0 = forward packet. - */ -int -ip_ipsec_fwd(struct mbuf *m) -{ - - return (ipsec4_in_reject(m, NULL)); -} - -/* * Check if protocol type doesn't have a further header and do IPSEC * decryption or reject right now. Protocols with further headers get * their IPSEC treatment within the protocol specific processing. @@ -180,6 +167,13 @@ * sp == NULL, error != 0 discard packet, report error */ if (sp != NULL) { + /* Only for forwarded packets */ + if (inp == NULL && ipsec_havesp(IPSEC_DIR_INBOUND) && + ipsec4_in_reject(*m, NULL)) { + IPSECSTAT_INC(ips_in_polvio); + goto bad; + } + /* * Do delayed checksums now because we send before * this is done in the normal processing path. Index: sys/netinet/ip_output.c =================================================================== --- sys/netinet/ip_output.c +++ sys/netinet/ip_output.c @@ -451,6 +451,8 @@ #ifdef IPSEC switch(ip_ipsec_output(&m, inp, &error)) { case 1: + if (inp == NULL) + IPSTAT_INC(ips_cantforward); goto bad; case -1: goto done; Index: sys/netinet6/ip6_forward.c =================================================================== --- sys/netinet6/ip6_forward.c +++ sys/netinet6/ip6_forward.c @@ -97,7 +97,7 @@ struct rtentry *rt = NULL; struct route_in6 rin6; int error, type = 0, code = 0; - struct mbuf *mcopy = NULL; + struct mbuf *mcopy; struct ifnet *origifp; /* maybe unnecessary */ u_int32_t inzone, outzone; struct in6_addr src_in6, dst_in6, odst; @@ -134,17 +134,6 @@ m_freem(m); return; } -#ifdef IPSEC - /* - * Check if this packet has an active SA and needs to be dropped - * instead of forwarded. - */ - if (ip6_ipsec_fwd(m) != 0) { - IP6STAT_INC(ip6s_cantforward); - m_freem(m); - return; - } -#endif /* IPSEC */ #ifdef IPSTEALTH if (!V_ip6stealth) { @@ -161,30 +150,18 @@ } #endif - /* - * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU - - * size of IPv6 + ICMPv6 headers) bytes of the packet in case - * we need to generate an ICMP6 message to the src. - * Thanks to M_EXT, in most cases copy will not occur. - * - * It is important to save it before IPsec processing as IPsec - * processing may modify the mbuf. - */ - mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN)); +#ifdef IPSEC + if (!ipsec_havesp(IPSEC_DIR_OUTBOUND)) + goto skip_ipsec; -#ifdef IPSEC /* get a security policy for this packet */ sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, &error); - if (sp == NULL) { + if (sp == NULL && (ipsec_havesp(IPSEC_DIR_INBOUND) && + ipsec6_in_reject(m, NULL)) { IPSEC6STAT_INC(ips_out_inval); IP6STAT_INC(ip6s_cantforward); - if (mcopy) { -#if 0 - /* XXX: what icmp ? */ -#else - m_freem(mcopy); -#endif - } + + /* XXX: what icmp ? */ m_freem(m); return; } @@ -193,22 +170,8 @@ /* check policy */ switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - /* - * This packet is just discarded. - */ - IPSEC6STAT_INC(ips_out_polvio); - IP6STAT_INC(ip6s_cantforward); - KEY_FREESP(&sp); - if (mcopy) { -#if 0 - /* XXX: what icmp ? */ -#else - m_freem(mcopy); -#endif - } - m_freem(m); - return; + /* NOTE: _DISCARD is checked above in ipsec_in_reject */ + /* case IPSEC_POLICY_DISCARD: */ case IPSEC_POLICY_BYPASS: case IPSEC_POLICY_NONE: @@ -222,13 +185,8 @@ printf("ip6_forward: No IPsec request specified.\n"); IP6STAT_INC(ip6s_cantforward); KEY_FREESP(&sp); - if (mcopy) { -#if 0 - /* XXX: what icmp ? */ -#else - m_freem(mcopy); -#endif - } + + /* XXX: what icmp ? */ m_freem(m); return; } @@ -256,9 +214,9 @@ */ for (isr = sp->req; isr; isr = isr->next) { if (isr->saidx.mode == IPSEC_MODE_ANY) - goto doipsectunnel; + break; if (isr->saidx.mode == IPSEC_MODE_TUNNEL) - goto doipsectunnel; + break; } /* @@ -267,7 +225,6 @@ if (!isr) goto skip_ipsec; - doipsectunnel: /* * All the extension headers will become inaccessible * (since they can be encrypted). @@ -312,13 +269,8 @@ break; } IP6STAT_INC(ip6s_cantforward); - if (mcopy) { -#if 0 - /* XXX: what icmp ? */ -#else - m_freem(mcopy); -#endif - } + + /* XXX: what icmp ? */ return; } else { /* @@ -328,11 +280,22 @@ * up after ourselves. */ m = NULL; - goto freecopy; + goto out; } } skip_ipsec: #endif + + /* + * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU - + * size of IPv6 + ICMPv6 headers) bytes of the packet in case + * we need to generate an ICMP6 message to the src. + * Thanks to M_EXT, in most cases copy will not occur. + * + * It is important to save it before IPsec processing as IPsec + * processing may modify the mbuf. + */ + mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN)); again: bzero(&rin6, sizeof(struct route_in6)); dst = (struct sockaddr_in6 *)&rin6.ro_dst; @@ -616,7 +579,7 @@ icmp6_error(mcopy, type, code, 0); goto out; - freecopy: +freecopy: m_freem(mcopy); goto out; bad: Index: sys/netinet6/ip6_ipsec.h =================================================================== --- sys/netinet6/ip6_ipsec.h +++ sys/netinet6/ip6_ipsec.h @@ -33,7 +33,6 @@ #define _NETINET_IP6_IPSEC_H_ int ip6_ipsec_filtertunnel(struct mbuf *); -int ip6_ipsec_fwd(struct mbuf *); int ip6_ipsec_input(struct mbuf *, int); int ip6_ipsec_output(struct mbuf **, struct inpcb *, int *); #if 0 Index: sys/netinet6/ip6_ipsec.c =================================================================== --- sys/netinet6/ip6_ipsec.c +++ sys/netinet6/ip6_ipsec.c @@ -110,19 +110,6 @@ } /* - * Check if this packet has an active SA and needs to be dropped instead - * of forwarded. - * Called from ip6_forward(). - * 1 = drop packet, 0 = forward packet. - */ -int -ip6_ipsec_fwd(struct mbuf *m) -{ - - return (ipsec6_in_reject(m, NULL)); -} - -/* * Check if protocol type doesn't have a further header and do IPSEC * decryption or reject right now. Protocols with further headers get * their IPSEC treatment within the protocol specific processing. Index: sys/netipsec/ipsec.h =================================================================== --- sys/netipsec/ipsec.h +++ sys/netipsec/ipsec.h @@ -314,7 +314,9 @@ caddr_t request, size_t len, struct ucred *cred); extern int ipsec_get_policy(struct inpcb *inpcb, caddr_t request, size_t len, struct mbuf **mp); +extern int ipsec_havesp(u_int); extern int ipsec_delete_pcbpolicy(struct inpcb *); +extern int ipsec_in_reject(struct secpolicy *, struct mbuf *); extern int ipsec4_in_reject(struct mbuf *, struct inpcb *); struct secas; Index: sys/netipsec/ipsec.c =================================================================== --- sys/netipsec/ipsec.c +++ sys/netipsec/ipsec.c @@ -238,7 +238,6 @@ struct ipsecstat, ipsec6stat, "IPsec IPv6 statistics."); #endif /* INET6 */ -static int ipsec_in_reject(struct secpolicy *, struct mbuf *); static int ipsec_setspidx_inpcb(struct mbuf *, struct inpcb *); static int ipsec_setspidx(struct mbuf *, struct secpolicyindex *, int); static void ipsec4_get_ulp(struct mbuf *m, struct secpolicyindex *, int); @@ -813,6 +812,14 @@ free(p, M_IPSEC_INPCB); } +/* Just a wrapper around key_havesp, should inline? */ +int +ipsec_havesp(u_int dir) +{ + + return key_havesp(dir); +} + /* Initialize policy in PCB. */ int ipsec_init_policy(struct socket *so, struct inpcbpolicy **pcb_sp) @@ -1198,7 +1205,7 @@ * 0: valid * 1: invalid */ -static int +int ipsec_in_reject(struct secpolicy *sp, struct mbuf *m) { struct ipsecrequest *isr;