diff options
author | kp <kp@FreeBSD.org> | 2015-06-18 20:57:21 +0000 |
---|---|---|
committer | kp <kp@FreeBSD.org> | 2015-06-18 20:57:21 +0000 |
commit | 1af840c38ec20bb93f4838a45f3df0e34d6c5660 (patch) | |
tree | ff7b70e4bae96d7810ddc588acd9a2211c4668b9 /sys/netinet6 | |
parent | 801d5721d10bb679d21776f0f8f4d459d302c588 (diff) | |
download | FreeBSD-src-1af840c38ec20bb93f4838a45f3df0e34d6c5660.zip FreeBSD-src-1af840c38ec20bb93f4838a45f3df0e34d6c5660.tar.gz |
Merge r281234
Evaluate packet size after the firewall had its chance
Defer the packet size check until after the firewall has had a look at it. This
means that the firewall now has the opportunity to (re-)fragment an oversized
packet.
Differential Revision: https://reviews.freebsd.org/D2821
Reviewed by: gnn
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/ip6_forward.c | 81 |
1 files changed, 41 insertions, 40 deletions
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index a22c084..caa58e6 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -423,46 +423,6 @@ again2: goto bad; } - if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) { - in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig); - if (mcopy) { - u_long mtu; -#ifdef IPSEC - struct secpolicy *sp; - int ipsecerror; - size_t ipsechdrsiz; -#endif /* IPSEC */ - - mtu = IN6_LINKMTU(rt->rt_ifp); -#ifdef IPSEC - /* - * When we do IPsec tunnel ingress, we need to play - * with the link value (decrement IPsec header size - * from mtu value). The code is much simpler than v4 - * case, as we have the outgoing interface for - * encapsulated packet as "rt->rt_ifp". - */ - sp = ipsec_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, - IP_FORWARDING, &ipsecerror); - if (sp) { - ipsechdrsiz = ipsec_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, NULL); - if (ipsechdrsiz < mtu) - mtu -= ipsechdrsiz; - } - - /* - * if mtu becomes less than minimum MTU, - * tell minimum MTU (and I'll need to fragment it). - */ - if (mtu < IPV6_MMTU) - mtu = IPV6_MMTU; -#endif /* IPSEC */ - icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu); - } - goto bad; - } - if (rt->rt_flags & RTF_GATEWAY) dst = (struct sockaddr_in6 *)rt->rt_gateway; @@ -591,6 +551,47 @@ again2: } pass: + /* See if the size was changed by the packet filter. */ + if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) { + in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig); + if (mcopy) { + u_long mtu; +#ifdef IPSEC + struct secpolicy *sp; + int ipsecerror; + size_t ipsechdrsiz; +#endif /* IPSEC */ + + mtu = IN6_LINKMTU(rt->rt_ifp); +#ifdef IPSEC + /* + * When we do IPsec tunnel ingress, we need to play + * with the link value (decrement IPsec header size + * from mtu value). The code is much simpler than v4 + * case, as we have the outgoing interface for + * encapsulated packet as "rt->rt_ifp". + */ + sp = ipsec_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, + IP_FORWARDING, &ipsecerror); + if (sp) { + ipsechdrsiz = ipsec_hdrsiz(mcopy, + IPSEC_DIR_OUTBOUND, NULL); + if (ipsechdrsiz < mtu) + mtu -= ipsechdrsiz; + } + + /* + * if mtu becomes less than minimum MTU, + * tell minimum MTU (and I'll need to fragment it). + */ + if (mtu < IPV6_MMTU) + mtu = IPV6_MMTU; +#endif /* IPSEC */ + icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu); + } + goto bad; + } + error = nd6_output(rt->rt_ifp, origifp, m, dst, rt); if (error) { in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard); |