summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ip6_forward.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
committerume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
commit832f8d224926758a9ae0b23a6b45353e44fbc87a (patch)
treea79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /sys/netinet6/ip6_forward.c
parent2693854b01a52b0395a91322aa3edf926bddff38 (diff)
downloadFreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.zip
FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.tar.gz
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some critical problem after the snap was out were fixed. There are many many changes since last KAME merge. TODO: - The definitions of SADB_* in sys/net/pfkeyv2.h are still different from RFC2407/IANA assignment because of binary compatibility issue. It should be fixed under 5-CURRENT. - ip6po_m member of struct ip6_pktopts is no longer used. But, it is still there because of binary compatibility issue. It should be removed under 5-CURRENT. Reviewed by: itojun Obtained from: KAME MFC after: 3 weeks
Diffstat (limited to 'sys/netinet6/ip6_forward.c')
-rw-r--r--sys/netinet6/ip6_forward.c91
1 files changed, 54 insertions, 37 deletions
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index 2664ccb..444cd2c 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: ip6_forward.c,v 1.43 2000/07/16 07:50:49 itojun Exp $ */
+/* $KAME: ip6_forward.c,v 1.69 2001/05/17 03:48:30 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -37,12 +37,14 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/time.h>
+#include <sys/kernel.h>
#include <sys/syslog.h>
#include <net/if.h>
@@ -50,15 +52,22 @@
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
#include <netinet/ip_var.h>
+#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet/icmp6.h>
#include <netinet6/nd6.h>
+#include <netinet/in_pcb.h>
+
#ifdef IPSEC
#include <netinet6/ipsec.h>
+#ifdef INET6
#include <netinet6/ipsec6.h>
+#endif
#include <netkey/key.h>
#endif /* IPSEC */
@@ -87,8 +96,8 @@ ip6_forward(m, srcrt)
int srcrt;
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- register struct sockaddr_in6 *dst;
- register struct rtentry *rt;
+ struct sockaddr_in6 *dst;
+ struct rtentry *rt;
int error, type = 0, code = 0;
struct mbuf *mcopy = NULL;
struct ifnet *origifp; /* maybe unnecessary */
@@ -111,8 +120,15 @@ ip6_forward(m, srcrt)
}
#endif /*IPSEC*/
+ /*
+ * Do not forward packets to multicast destination (should be handled
+ * by ip6_mforward().
+ * Do not forward packets with unspecified source. It was discussed
+ * in July 2000, on ipngwg mailing list.
+ */
if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
- IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
+ IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
+ IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
ip6stat.ip6s_cantforward++;
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
if (ip6_log_time + ip6_log_interval < time_second) {
@@ -150,7 +166,8 @@ ip6_forward(m, srcrt)
#ifdef IPSEC
/* get a security policy for this packet */
- sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
+ sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING,
+ &error);
if (sp == NULL) {
ipsec6stat.out_inval++;
ip6stat.ip6s_cantforward++;
@@ -238,10 +255,6 @@ ip6_forward(m, srcrt)
error = ipsec6_output_tunnel(&state, sp, 0);
m = state.m;
-#if 0 /* XXX allocate a route (ro, dst) again later */
- ro = (struct route_in6 *)state.ro;
- dst = (struct sockaddr_in6 *)state.dst;
-#endif
key_freesp(sp);
if (error) {
@@ -275,7 +288,7 @@ ip6_forward(m, srcrt)
skip_ipsec:
#endif /* IPSEC */
- dst = &ip6_forward_rt.ro_dst;
+ dst = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
if (!srcrt) {
/*
* ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst
@@ -293,7 +306,7 @@ ip6_forward(m, srcrt)
if (ip6_forward_rt.ro_rt == 0) {
ip6stat.ip6s_noroute++;
- /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute);
if (mcopy) {
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOROUTE, 0);
@@ -315,7 +328,7 @@ ip6_forward(m, srcrt)
rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
if (ip6_forward_rt.ro_rt == 0) {
ip6stat.ip6s_noroute++;
- /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute);
if (mcopy) {
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOROUTE, 0);
@@ -410,8 +423,25 @@ ip6_forward(m, srcrt)
* modified by a redirect.
*/
if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&
- (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0)
+ (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
+ if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) != 0) {
+ /*
+ * If the incoming interface is equal to the outgoing
+ * one, and the link attached to the interface is
+ * point-to-point, then it will be highly probable
+ * that a routing loop occurs. Thus, we immediately
+ * drop the packet and send an ICMPv6 error message.
+ *
+ * type/code is based on suggestion by Rich Draves.
+ * not sure if it is the best pick.
+ */
+ icmp6_error(mcopy, ICMP6_DST_UNREACH,
+ ICMP6_DST_UNREACH_ADDR, 0);
+ m_freem(m);
+ return;
+ }
type = ND_REDIRECT;
+ }
/*
* Check with the firewall...
@@ -432,8 +462,8 @@ ip6_forward(m, srcrt)
* destinaion can appear, if the originating node just sends the
* packet to us (without address resolution for the destination).
* Since both icmp6_error and icmp6_redirect_output fill the embedded
- * link identifiers, we can do this stuff after make a copy for
- * returning error.
+ * link identifiers, we can do this stuff after making a copy for
+ * returning an error.
*/
if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
/*
@@ -459,34 +489,21 @@ ip6_forward(m, srcrt)
if_name(rt->rt_ifp));
}
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
- origifp = ifindex2ifnet[ntohs(ip6->ip6_src.s6_addr16[1])];
- else if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
- origifp = ifindex2ifnet[ntohs(ip6->ip6_dst.s6_addr16[1])];
- else
- origifp = rt->rt_ifp;
+ /* we can just use rcvif in forwarding. */
+ origifp = m->m_pkthdr.rcvif;
}
else
origifp = rt->rt_ifp;
-#ifndef FAKE_LOOPBACK_IF
- if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
-#else
- if (1)
+#ifndef SCOPEDROUTING
+ /*
+ * clear embedded scope identifiers if necessary.
+ * in6_clearscope will touch the addresses only when necessary.
+ */
+ in6_clearscope(&ip6->ip6_src);
+ in6_clearscope(&ip6->ip6_dst);
#endif
- {
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
- ip6->ip6_src.s6_addr16[1] = 0;
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
- ip6->ip6_dst.s6_addr16[1] = 0;
- }
-#ifdef OLDIP6OUTPUT
- error = (*rt->rt_ifp->if_output)(rt->rt_ifp, m,
- (struct sockaddr *)dst,
- ip6_forward_rt.ro_rt);
-#else
error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
-#endif
if (error) {
in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
ip6stat.ip6s_cantforward++;
OpenPOWER on IntegriCloud