summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ip6_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/ip6_output.c')
-rw-r--r--sys/netinet6/ip6_output.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 973689c..8516124 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_ipfw.h"
#include "opt_ipsec.h"
#include "opt_sctp.h"
#include "opt_route.h"
@@ -90,6 +91,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
@@ -229,6 +231,9 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
int segleft_org = 0;
struct secpolicy *sp = NULL;
#endif /* IPSEC */
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag;
+#endif
ip6 = mtod(m, struct ip6_hdr *);
if (ip6 == NULL) {
@@ -850,7 +855,8 @@ again:
if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) {
m->m_flags |= M_SKIP_FIREWALL;
/* If destination is now ourself drop to ip6_input(). */
- if (in6_localaddr(&ip6->ip6_dst)) {
+ if (in6_localip(&ip6->ip6_dst)) {
+ m->m_flags |= M_FASTFWD_OURS;
if (m->m_pkthdr.rcvif == NULL)
m->m_pkthdr.rcvif = V_loif;
if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
@@ -870,7 +876,33 @@ again:
goto again; /* Redo the routing table lookup. */
}
- /* XXX: IPFIREWALL_FORWARD */
+#ifdef IPFIREWALL_FORWARD
+ /* See if local, if yes, send it to netisr. */
+ if (m->m_flags & M_FASTFWD_OURS) {
+ if (m->m_pkthdr.rcvif == NULL)
+ m->m_pkthdr.rcvif = V_loif;
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ m->m_pkthdr.csum_flags |=
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
+ error = netisr_queue(NETISR_IPV6, m);
+ goto done;
+ }
+ /* Or forward to some other address? */
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag) {
+ dst = (struct sockaddr_in6 *)&ro->ro_dst;
+ bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in6));
+ m->m_flags |= M_SKIP_FIREWALL;
+ m_tag_delete(m, fwd_tag);
+ goto again;
+ }
+#endif /* IPFIREWALL_FORWARD */
passout:
/*
OpenPOWER on IntegriCloud