diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-06 16:20:21 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-11 10:08:08 +0100 |
commit | 66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch) | |
tree | 48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/netinet6/ip6_forward.c | |
parent | Define __GLOBL1() and __GLOBL() (diff) | |
download | rtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2 |
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/netinet6/ip6_forward.c')
-rw-r--r-- | freebsd/sys/netinet6/ip6_forward.c | 103 |
1 files changed, 80 insertions, 23 deletions
diff --git a/freebsd/sys/netinet6/ip6_forward.c b/freebsd/sys/netinet6/ip6_forward.c index fa5d373f..2b45804f 100644 --- a/freebsd/sys/netinet6/ip6_forward.c +++ b/freebsd/sys/netinet6/ip6_forward.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> +#include <rtems/bsd/local/opt_ipfw.h> #include <rtems/bsd/local/opt_ipsec.h> #include <rtems/bsd/local/opt_ipstealth.h> @@ -52,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include <sys/syslog.h> #include <net/if.h> +#include <net/netisr.h> #include <net/route.h> #include <net/pfil.h> @@ -100,11 +102,15 @@ ip6_forward(struct mbuf *m, int srcrt) struct mbuf *mcopy = NULL; struct ifnet *origifp; /* maybe unnecessary */ u_int32_t inzone, outzone; - struct in6_addr src_in6, dst_in6; + struct in6_addr src_in6, dst_in6, odst; #ifdef IPSEC struct secpolicy *sp = NULL; int ipsecrt = 0; #endif +#ifdef SCTP + int sw_csum; +#endif + struct m_tag *fwd_tag; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; #ifdef IPSEC @@ -116,7 +122,7 @@ ip6_forward(struct mbuf *m, int srcrt) * before forwarding packet actually. */ if (ipsec6_in_reject(m, NULL)) { - V_ipsec6stat.in_polvio++; + IPSEC6STAT_INC(in_polvio); m_freem(m); return; } @@ -131,7 +137,7 @@ ip6_forward(struct mbuf *m, int srcrt) if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 || IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { - V_ip6stat.ip6s_cantforward++; + IP6STAT_INC(ip6s_cantforward); /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */ if (V_ip6_log_time + V_ip6_log_interval < time_second) { V_ip6_log_time = time_second; @@ -178,8 +184,8 @@ ip6_forward(struct mbuf *m, int srcrt) sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING, &error); if (sp == NULL) { - V_ipsec6stat.out_inval++; - V_ip6stat.ip6s_cantforward++; + IPSEC6STAT_INC(out_inval); + IP6STAT_INC(ip6s_cantforward); if (mcopy) { #if 0 /* XXX: what icmp ? */ @@ -199,8 +205,8 @@ ip6_forward(struct mbuf *m, int srcrt) /* * This packet is just discarded. */ - V_ipsec6stat.out_polvio++; - V_ip6stat.ip6s_cantforward++; + IPSEC6STAT_INC(out_polvio); + IP6STAT_INC(ip6s_cantforward); KEY_FREESP(&sp); if (mcopy) { #if 0 @@ -222,7 +228,7 @@ ip6_forward(struct mbuf *m, int srcrt) if (sp->req == NULL) { /* XXX should be panic ? */ printf("ip6_forward: No IPsec request specified.\n"); - V_ip6stat.ip6s_cantforward++; + IP6STAT_INC(ip6s_cantforward); KEY_FREESP(&sp); if (mcopy) { #if 0 @@ -306,7 +312,7 @@ ip6_forward(struct mbuf *m, int srcrt) /* don't show these error codes to the user */ break; } - V_ip6stat.ip6s_cantforward++; + IP6STAT_INC(ip6s_cantforward); if (mcopy) { #if 0 /* XXX: what icmp ? */ @@ -347,18 +353,18 @@ ip6_forward(struct mbuf *m, int srcrt) goto skip_routing; skip_ipsec: #endif - +again: bzero(&rin6, sizeof(struct route_in6)); dst = (struct sockaddr_in6 *)&rin6.ro_dst; dst->sin6_len = sizeof(struct sockaddr_in6); dst->sin6_family = AF_INET6; dst->sin6_addr = ip6->ip6_dst; - +again2: rin6.ro_rt = in6_rtalloc1((struct sockaddr *)dst, 0, 0, M_GETFIB(m)); if (rin6.ro_rt != NULL) RT_UNLOCK(rin6.ro_rt); else { - V_ip6stat.ip6s_noroute++; + IP6STAT_INC(ip6s_noroute); in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute); if (mcopy) { icmp6_error(mcopy, ICMP6_DST_UNREACH, @@ -383,13 +389,13 @@ skip_routing: src_in6 = ip6->ip6_src; if (in6_setscope(&src_in6, rt->rt_ifp, &outzone)) { /* XXX: this should not happen */ - V_ip6stat.ip6s_cantforward++; - V_ip6stat.ip6s_badscope++; + IP6STAT_INC(ip6s_cantforward); + IP6STAT_INC(ip6s_badscope); goto bad; } if (in6_setscope(&src_in6, m->m_pkthdr.rcvif, &inzone)) { - V_ip6stat.ip6s_cantforward++; - V_ip6stat.ip6s_badscope++; + IP6STAT_INC(ip6s_cantforward); + IP6STAT_INC(ip6s_badscope); goto bad; } if (inzone != outzone @@ -397,8 +403,8 @@ skip_routing: && !ipsecrt #endif ) { - V_ip6stat.ip6s_cantforward++; - V_ip6stat.ip6s_badscope++; + IP6STAT_INC(ip6s_cantforward); + IP6STAT_INC(ip6s_badscope); in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard); if (V_ip6_log_time + V_ip6_log_interval < time_second) { @@ -428,8 +434,8 @@ skip_routing: if (in6_setscope(&dst_in6, m->m_pkthdr.rcvif, &inzone) != 0 || in6_setscope(&dst_in6, rt->rt_ifp, &outzone) != 0 || inzone != outzone) { - V_ip6stat.ip6s_cantforward++; - V_ip6stat.ip6s_badscope++; + IP6STAT_INC(ip6s_cantforward); + IP6STAT_INC(ip6s_badscope); goto bad; } @@ -556,6 +562,7 @@ skip_routing: if (!PFIL_HOOKED(&V_inet6_pfil_hook)) goto pass; + odst = ip6->ip6_dst; /* Run through list of hooks for output packets. */ error = pfil_run_hooks(&V_inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT, NULL); if (error != 0) @@ -564,16 +571,66 @@ skip_routing: goto freecopy; ip6 = mtod(m, struct ip6_hdr *); + /* See if destination IP address was changed by packet filter. */ + 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_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_IPV6) { + m->m_pkthdr.csum_flags |= + CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } +#ifdef SCTP + if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) + m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; +#endif + error = netisr_queue(NETISR_IPV6, m); + goto out; + } else + goto again; /* Redo the routing table lookup. */ + } + + /* 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_IPV6) { + m->m_pkthdr.csum_flags |= + CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } +#ifdef SCTP + if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) + m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; +#endif + error = netisr_queue(NETISR_IPV6, m); + goto out; + } + /* Or forward to some other address? */ + if ((m->m_flags & M_IP6_NEXTHOP) && + (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) { + dst = (struct sockaddr_in6 *)&rin6.ro_dst; + bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in6)); + m->m_flags |= M_SKIP_FIREWALL; + m->m_flags &= ~M_IP6_NEXTHOP; + m_tag_delete(m, fwd_tag); + goto again2; + } + pass: error = nd6_output(rt->rt_ifp, origifp, m, dst, rt); if (error) { in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard); - V_ip6stat.ip6s_cantforward++; + IP6STAT_INC(ip6s_cantforward); } else { - V_ip6stat.ip6s_forward++; + IP6STAT_INC(ip6s_forward); in6_ifstat_inc(rt->rt_ifp, ifs6_out_forward); if (type) - V_ip6stat.ip6s_redirectsent++; + IP6STAT_INC(ip6s_redirectsent); else { if (mcopy) goto freecopy; |