diff options
Diffstat (limited to 'sys/netinet/ip_fastfwd.c')
-rw-r--r-- | sys/netinet/ip_fastfwd.c | 112 |
1 files changed, 32 insertions, 80 deletions
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c index 4041712..3463a33 100644 --- a/sys/netinet/ip_fastfwd.c +++ b/sys/netinet/ip_fastfwd.c @@ -110,6 +110,7 @@ #include <machine/in_cksum.h> #include <netinet/ip_fw.h> +#include <netinet/ip_divert.h> #include <netinet/ip_dummynet.h> static int ipfastforward_active = 0; @@ -130,9 +131,8 @@ ip_fastforward(struct mbuf *m) struct mbuf *m0 = NULL; #ifdef IPDIVERT struct ip *tip; - struct mbuf *teem = NULL; + struct mbuf *clone = NULL; #endif - struct mbuf *tag = NULL; struct route ro; struct sockaddr_in *dst = NULL; struct in_ifaddr *ia = NULL; @@ -150,16 +150,6 @@ ip_fastforward(struct mbuf *m) if (!ipfastforward_active || !ipforwarding) return 0; - /* - * If there is any MT_TAG we fall back to ip_input because we can't - * handle TAGs here. Should never happen as we get directly called - * from the if_output routines. - */ - if (m->m_type == MT_TAG) { - KASSERT(0, ("%s: packet with MT_TAG not expected", __func__)); - return 0; - } - M_ASSERTVALID(m); M_ASSERTPKTHDR(m); @@ -373,50 +363,39 @@ fallback: /* * See if this is a fragment */ - if (ip->ip_off & (IP_MF | IP_OFFMASK)) { - MGETHDR(tag, M_DONTWAIT, MT_TAG); - if (tag == NULL) - goto drop; - tag->m_flags = PACKET_TAG_DIVERT; - tag->m_data = (caddr_t)(intptr_t)args.divert_rule; - tag->m_next = m; - /* XXX: really bloody hack, see ip_input */ - tag->m_nextpkt = (struct mbuf *)1; - m = tag; - tag = NULL; - + if (ip->ip_off & (IP_MF | IP_OFFMASK)) goto droptoours; - } /* * Tee packet */ if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) - teem = m_dup(m, M_DONTWAIT); + clone = divert_clone(m); else - teem = m; - if (teem == NULL) + clone = m; + if (clone == NULL) goto passin; /* * Delayed checksums are not compatible */ - if (teem->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { - in_delayed_cksum(teem); - teem->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + in_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } /* * Restore packet header fields to original values */ - tip = mtod(teem, struct ip *); + tip = mtod(m, struct ip *); tip->ip_len = htons(tip->ip_len); tip->ip_off = htons(tip->ip_off); /* * Deliver packet to divert input routine */ - divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule); + divert_packet(m, 0); /* * If this was not tee, we are done */ + m = clone; if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) return 1; /* Continue if it was tee */ @@ -560,52 +539,39 @@ passin: /* * See if this is a fragment */ - if (ip->ip_off & (IP_MF | IP_OFFMASK)) { - MGETHDR(tag, M_DONTWAIT, MT_TAG); - if (tag == NULL) { - RTFREE(ro.ro_rt); - goto drop; - } - tag->m_flags = PACKET_TAG_DIVERT; - tag->m_data = (caddr_t)(intptr_t)args.divert_rule; - tag->m_next = m; - /* XXX: really bloody hack, see ip_input */ - tag->m_nextpkt = (struct mbuf *)1; - m = tag; - tag = NULL; - + if (ip->ip_off & (IP_MF | IP_OFFMASK)) goto droptoours; - } /* * Tee packet */ if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) - teem = m_dup(m, M_DONTWAIT); + clone = divert_clone(m); else - teem = m; - if (teem == NULL) + clone = m; + if (clone == NULL) goto passout; /* * Delayed checksums are not compatible with divert */ - if (teem->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { - in_delayed_cksum(teem); - teem->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + in_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } /* * Restore packet header fields to original values */ - tip = mtod(teem, struct ip *); + tip = mtod(m, struct ip *); tip->ip_len = htons(tip->ip_len); tip->ip_off = htons(tip->ip_off); /* * Deliver packet to divert input routine */ - divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule); + divert_packet(m, 0); /* * If this was not tee, we are done */ + m = clone; if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) { RTFREE(ro.ro_rt); return 1; @@ -638,38 +604,24 @@ passout: if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) { forwardlocal: if (args.next_hop) { - /* XXX leak */ - MGETHDR(tag, M_DONTWAIT, MT_TAG); - if (tag == NULL) { + struct m_tag *mtag = m_tag_get( + PACKET_TAG_IPFORWARD, + sizeof(struct sockaddr_in *), + M_NOWAIT); + if (mtag == NULL) { if (ro.ro_rt) RTFREE(ro.ro_rt); goto drop; } - tag->m_flags = PACKET_TAG_IPFORWARD; - tag->m_data = (caddr_t)args.next_hop; - tag->m_next = m; - /* XXX: really bloody hack, - * see ip_input */ - tag->m_nextpkt = (struct mbuf *)1; - m = tag; - tag = NULL; + *(struct sockaddr_in **)(mtag+1) = + args.next_hop; + m_tag_prepend(m, mtag); } #ifdef IPDIVERT droptoours: /* Used for DIVERT */ #endif - MGETHDR(tag, M_DONTWAIT, MT_TAG); - if (tag == NULL) { - if (ro.ro_rt) - RTFREE(ro.ro_rt); - goto drop; - } - tag->m_flags = PACKET_TAG_IPFASTFWD_OURS; - tag->m_data = NULL; - tag->m_next = m; - /* XXX: really bloody hack, see ip_input */ - tag->m_nextpkt = (struct mbuf *)1; - m = tag; - tag = NULL; + /* for ip_input */ + m->m_flags |= M_FASTFWD_OURS; /* ip still points to the real packet */ ip->ip_len = htons(ip->ip_len); |