diff options
Diffstat (limited to 'freebsd/sys/netinet/ip_fastfwd.c')
-rw-r--r-- | freebsd/sys/netinet/ip_fastfwd.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/freebsd/sys/netinet/ip_fastfwd.c b/freebsd/sys/netinet/ip_fastfwd.c index b084fdc6..05deb4d8 100644 --- a/freebsd/sys/netinet/ip_fastfwd.c +++ b/freebsd/sys/netinet/ip_fastfwd.c @@ -155,7 +155,7 @@ ip_tryforward(struct mbuf *m) struct mbuf *m0 = NULL; struct nhop4_basic nh; struct sockaddr_in dst; - struct in_addr odest, dest; + struct in_addr dest, odest, rtdest; uint16_t ip_len, ip_off; int error = 0; struct m_tag *fwd_tag = NULL; @@ -296,12 +296,31 @@ passin: #endif /* + * Next hop forced by pfil(9) hook? + */ + if ((m->m_flags & M_IP_NEXTHOP) && + ((fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL)) { + /* + * Now we will find route to forced destination. + */ + dest.s_addr = ((struct sockaddr_in *) + (fwd_tag + 1))->sin_addr.s_addr; + m_tag_delete(m, fwd_tag); + m->m_flags &= ~M_IP_NEXTHOP; + } + + /* * Find route to destination. */ if (ip_findroute(&nh, dest, m) != 0) return (NULL); /* icmp unreach already sent */ /* + * Avoid second route lookup by caching destination. + */ + rtdest.s_addr = dest.s_addr; + + /* * Step 5: outgoing firewall packet processing */ if (!PFIL_HOOKED(&V_inet_pfil_hook)) @@ -323,6 +342,8 @@ passin: */ if (m->m_flags & M_IP_NEXTHOP) fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); + else + fwd_tag = NULL; if (odest.s_addr != dest.s_addr || fwd_tag != NULL) { /* * Is it now for a local address on this host? @@ -344,7 +365,8 @@ forwardlocal: m_tag_delete(m, fwd_tag); m->m_flags &= ~M_IP_NEXTHOP; } - if (ip_findroute(&nh, dest, m) != 0) + if (dest.s_addr != rtdest.s_addr && + ip_findroute(&nh, dest, m) != 0) return (NULL); /* icmp unreach already sent */ } |