Changeset View
Standalone View
sys/netpfil/pf/pf.c
Show First 20 Lines • Show All 5,565 Lines • ▼ Show 20 Lines | if (ifp->if_flags & IFF_LOOPBACK) | ||||
m0->m_flags |= M_SKIP_FIREWALL; | m0->m_flags |= M_SKIP_FIREWALL; | ||||
ip_len = ntohs(ip->ip_len); | ip_len = ntohs(ip->ip_len); | ||||
ip_off = ntohs(ip->ip_off); | ip_off = ntohs(ip->ip_off); | ||||
/* Copied from FreeBSD 10.0-CURRENT ip_output. */ | /* Copied from FreeBSD 10.0-CURRENT ip_output. */ | ||||
m0->m_pkthdr.csum_flags |= CSUM_IP; | m0->m_pkthdr.csum_flags |= CSUM_IP; | ||||
if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA & ~ifp->if_hwassist) { | if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA & ~ifp->if_hwassist) { | ||||
m0 = mb_unmapped_to_ext(m0); | |||||
if (m0 == NULL) | |||||
goto done; | |||||
in_delayed_cksum(m0); | in_delayed_cksum(m0); | ||||
m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; | m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; | ||||
} | } | ||||
#if defined(SCTP) || defined(SCTP_SUPPORT) | #if defined(SCTP) || defined(SCTP_SUPPORT) | ||||
if (m0->m_pkthdr.csum_flags & CSUM_SCTP & ~ifp->if_hwassist) { | if (m0->m_pkthdr.csum_flags & CSUM_SCTP & ~ifp->if_hwassist) { | ||||
m0 = mb_unmapped_to_ext(m0); | |||||
if (m0 == NULL) | |||||
goto done; | |||||
sctp_delayed_cksum(m0, (uint32_t)(ip->ip_hl << 2)); | sctp_delayed_cksum(m0, (uint32_t)(ip->ip_hl << 2)); | ||||
kp: Presumably we'd have to do this here as well. | |||||
m0->m_pkthdr.csum_flags &= ~CSUM_SCTP; | m0->m_pkthdr.csum_flags &= ~CSUM_SCTP; | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* If small enough for interface, or the interface will take | * If small enough for interface, or the interface will take | ||||
* care of the fragmentation for us, we can just send directly. | * care of the fragmentation for us, we can just send directly. | ||||
*/ | */ | ||||
if (ip_len <= ifp->if_mtu || | if (ip_len <= ifp->if_mtu || | ||||
(m0->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0) { | (m0->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0) { | ||||
ip->ip_sum = 0; | ip->ip_sum = 0; | ||||
if (m0->m_pkthdr.csum_flags & CSUM_IP & ~ifp->if_hwassist) { | if (m0->m_pkthdr.csum_flags & CSUM_IP & ~ifp->if_hwassist) { | ||||
ip->ip_sum = in_cksum(m0, ip->ip_hl << 2); | ip->ip_sum = in_cksum(m0, ip->ip_hl << 2); | ||||
Not Done Inline ActionsAnd here? kp: And here? | |||||
Done Inline ActionsI believe this treatment isn't needed when we're only checksumming a protocol header. markj: I believe this treatment isn't needed when we're only checksumming a protocol header. | |||||
Not Done Inline Actions
gallatin: > And here?
| |||||
Not Done Inline ActionsNo, since this is just the IP header. Unmapped mbufs are a problem for checksums only on payload data. gallatin: No, since this is just the IP header. Unmapped mbufs are a problem for checksums only on… | |||||
m0->m_pkthdr.csum_flags &= ~CSUM_IP; | m0->m_pkthdr.csum_flags &= ~CSUM_IP; | ||||
} | } | ||||
m_clrprotoflags(m0); /* Avoid confusing lower layers. */ | m_clrprotoflags(m0); /* Avoid confusing lower layers. */ | ||||
error = (*ifp->if_output)(ifp, m0, sintosa(&dst), NULL); | error = (*ifp->if_output)(ifp, m0, sintosa(&dst), NULL); | ||||
goto done; | goto done; | ||||
} | } | ||||
/* Balk when DF bit is set or the interface didn't support TSO. */ | /* Balk when DF bit is set or the interface didn't support TSO. */ | ||||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | pf_route6(struct mbuf **m, struct pf_krule *r, int dir, struct ifnet *oifp, | ||||
} | } | ||||
if (ifp->if_flags & IFF_LOOPBACK) | if (ifp->if_flags & IFF_LOOPBACK) | ||||
m0->m_flags |= M_SKIP_FIREWALL; | m0->m_flags |= M_SKIP_FIREWALL; | ||||
if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6 & | if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6 & | ||||
~ifp->if_hwassist) { | ~ifp->if_hwassist) { | ||||
uint32_t plen = m0->m_pkthdr.len - sizeof(*ip6); | uint32_t plen = m0->m_pkthdr.len - sizeof(*ip6); | ||||
m0 = mb_unmapped_to_ext(m0); | |||||
if (m0 == NULL) | |||||
goto done; | |||||
in6_delayed_cksum(m0, plen, sizeof(struct ip6_hdr)); | in6_delayed_cksum(m0, plen, sizeof(struct ip6_hdr)); | ||||
Done Inline ActionsAnd here? kp: And here? | |||||
Not Done Inline ActionsYes. gallatin: Yes. | |||||
m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; | m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; | ||||
} | } | ||||
/* | /* | ||||
* If the packet is too large for the outgoing interface, | * If the packet is too large for the outgoing interface, | ||||
* send back an icmp6 error. | * send back an icmp6 error. | ||||
*/ | */ | ||||
if (IN6_IS_SCOPE_EMBED(&dst.sin6_addr)) | if (IN6_IS_SCOPE_EMBED(&dst.sin6_addr)) | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | case AF_INET: | ||||
m->m_data += off; | m->m_data += off; | ||||
m->m_len -= off; | m->m_len -= off; | ||||
sum = in_cksum(m, len); | sum = in_cksum(m, len); | ||||
m->m_data -= off; | m->m_data -= off; | ||||
m->m_len += off; | m->m_len += off; | ||||
} else { | } else { | ||||
if (m->m_len < sizeof(struct ip)) | if (m->m_len < sizeof(struct ip)) | ||||
return (1); | return (1); | ||||
sum = in4_cksum(m, p, off, len); | sum = in4_cksum(m, p, off, len); | ||||
Not Done Inline ActionsAnd here? kp: And here? | |||||
Done Inline ActionsThese seem a bit tricky. mb_unmapped_to_ext() frees the chain upon failure, but this function and its callers can't really do that. We are also assuming in general that the first mbuf in the chain is preserved, otherwise mb_unmapped_to_ext() would invalidate some pointers in its callers. markj: These seem a bit tricky. mb_unmapped_to_ext() frees the chain upon failure, but this function… | |||||
Not Done Inline ActionsIt's tempting to 'fix' this by calling mb_unmapped_to_ext() in pf_check_in()/pf_check_out(), so that we restore the assumption that it's safe to access packet data. Is there a straightforward way of asserting that an mbuf is or is not unmapped? Just adding an assertion here would at least make future debugging easier. kp: It's tempting to 'fix' this by calling mb_unmapped_to_ext() in pf_check_in()/pf_check_out(), so… | |||||
Not Done Inline ActionsYou have to check the entire chain to see if any mbufs in the chain have M_EXTPG set in m_flags. However, it might be nice to have some kind of M_ASSERTMAPPED(m) wrapper for that the way we have a M_ASSERTPKTHDR() macro. jhb: You have to check the entire chain to see if any mbufs in the chain have M_EXTPG set in m_flags. | |||||
} | } | ||||
break; | break; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
case AF_INET6: | case AF_INET6: | ||||
if (m->m_len < sizeof(struct ip6_hdr)) | if (m->m_len < sizeof(struct ip6_hdr)) | ||||
return (1); | return (1); | ||||
sum = in6_cksum(m, p, off, len); | sum = in6_cksum(m, p, off, len); | ||||
Not Done Inline ActionsAnd here? kp: And here? | |||||
break; | break; | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
default: | default: | ||||
return (1); | return (1); | ||||
} | } | ||||
} | } | ||||
if (sum) { | if (sum) { | ||||
switch (p) { | switch (p) { | ||||
▲ Show 20 Lines • Show All 837 Lines • Show Last 20 Lines |
Presumably we'd have to do this here as well.