summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authoritojun <itojun@NetBSD.org>2000-05-19 01:40:18 +0000
committeritojun <itojun@NetBSD.org>2000-05-19 01:40:18 +0000
commitfa5c89d64aeff1ffe844c0c040ef7bfe351899ca (patch)
tree795cd18c9fe150fa6af0f20be197845ccee91ac2 /sys
parent4bd0bb352b966e8649614300d1fbec3b1b6f76aa (diff)
do not mistakingly forward link-local scoped packet (the bug was added
with "beyondscope" icmp6 support). "options FAKE_LOOPBACK_IF" will honor scope on loopback outputs. rcvif will be real interface, not the loopback, just like when multicast loopback. (sync with kame)
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet6/ip6_forward.c57
-rw-r--r--sys/netinet6/ip6_output.c110
-rw-r--r--sys/netinet6/nd6.c27
-rw-r--r--sys/netinet6/nd6.h8
-rw-r--r--sys/netinet6/nd6_nbr.c16
5 files changed, 152 insertions, 66 deletions
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index 4f2e48b28e5..7ef2ae795b4 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -1,10 +1,10 @@
-/* $NetBSD: ip6_forward.c,v 1.9 2000/02/26 08:39:20 itojun Exp $ */
-/* $KAME: ip6_forward.c,v 1.28 2000/02/22 14:04:20 itojun Exp $ */
+/* $NetBSD: ip6_forward.c,v 1.10 2000/05/19 01:40:18 itojun Exp $ */
+/* $KAME: ip6_forward.c,v 1.35 2000/05/18 16:31:27 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -16,7 +16,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -90,6 +90,7 @@ ip6_forward(m, srcrt)
register struct rtentry *rt;
int error, type = 0, code = 0;
struct mbuf *mcopy = NULL;
+ struct ifnet *origifp; /* maybe unnecessary */
#ifdef IPSEC_IPV6FWD
struct secpolicy *sp = NULL;
#endif
@@ -383,7 +384,7 @@ ip6_forward(m, srcrt)
}
/*
- * if mtu becomes less than minimum MTU,
+ * if mtu becomes less than minimum MTU,
* tell minimum MTU (and I'll need to fragment it).
*/
if (mtu < IPV6_MMTU)
@@ -427,13 +428,55 @@ ip6_forward(m, srcrt)
}
#endif
+ /*
+ * Fake scoped addresses. Note that even link-local source or
+ * 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.
+ */
+ if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
+ /*
+ * See corresponding comments in ip6_output.
+ * XXX: but is it possible that ip6_forward() sends a packet
+ * to a loopback interface? I don't think so, and thus
+ * I bark here. (jinmei@kame.net)
+ */
+ printf("ip6_forward: outgoing interface is loopback. "
+ "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
+ ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&ip6->ip6_dst),
+ ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif),
+ 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;
+ }
+ else
+ origifp = rt->rt_ifp;
+#ifndef FAKE_LOOPBACK_IF
+ if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0)
+#else
+ if (1)
+#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, m, dst, rt);
-#endif
+ 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++;
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index f3148160e8e..a7950894274 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1,9 +1,10 @@
-/* $NetBSD: ip6_output.c,v 1.18 2000/03/29 03:38:53 simonb Exp $ */
+/* $NetBSD: ip6_output.c,v 1.19 2000/05/19 01:40:18 itojun Exp $ */
+/* $KAME: ip6_output.c,v 1.102 2000/05/17 15:31:56 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -15,7 +16,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -143,7 +144,7 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp)
struct ifnet **ifpp; /* XXX: just for statistics */
{
struct ip6_hdr *ip6, *mhip6;
- struct ifnet *ifp;
+ struct ifnet *ifp, *origifp;
struct mbuf *m = m0;
int hlen, tlen, len, off;
struct route_in6 ip6route;
@@ -520,7 +521,7 @@ skip_ipsec2:;
exthdrs.ip6e_ip6 = m;
}
-#endif /*IPESC*/
+#endif /*IPSEC*/
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
/* Unicast */
@@ -534,7 +535,7 @@ skip_ipsec2:;
*/
if (ro->ro_rt == 0) {
/*
- * NetBSD/OpenBSD always clones routes, if parent is
+ * non-bsdi always clone routes, if parent is
* PRF_CLONING.
*/
rtalloc((struct route *)ro);
@@ -555,11 +556,11 @@ skip_ipsec2:;
in6_ifstat_inc(ifp, ifs6_out_request);
/*
- * Check if there is the outgoing interface conflicts with
- * the interface specified by ifi6_ifindex(if specified).
+ * Check if the outgoing interface conflicts with
+ * the interface specified by ifi6_ifindex (if specified).
* Note that loopback interface is always okay.
- * (this happens when we are sending packet toward my
- * interface)
+ * (this may happen when we are sending a packet to one of
+ * our own addresses.)
*/
if (opt && opt->ip6po_pktinfo
&& opt->ip6po_pktinfo->ipi6_ifindex) {
@@ -614,8 +615,7 @@ skip_ipsec2:;
/* XXX correct ifp? */
in6_ifstat_inc(ifp, ifs6_out_discard);
goto bad;
- }
- else {
+ } else {
ifp = &loif[0];
}
}
@@ -753,10 +753,38 @@ skip_ipsec2:;
mtu = nd_ifinfo[ifp->if_index].linkmtu;
}
- /*
- * Fake link-local scope-class addresses
- */
- if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
+ /* Fake scoped addresses */
+ if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
+ /*
+ * If source or destination address is a scoped address, and
+ * the packet is going to be sent to a loopback interface,
+ * we should keep the original interface.
+ */
+
+ /*
+ * XXX: this is a very experimental and temporary solution.
+ * We eventually have sockaddr_in6 and use the sin6_scope_id
+ * field of the structure here.
+ * We rely on the consistency between two scope zone ids
+ * of source add destination, which should already be assured
+ * Larger scopes than link will be supported in the near
+ * future.
+ */
+ 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 = ifp;
+ }
+ else
+ origifp = ifp;
+#ifndef FAKE_LOOPBACK_IF
+ if ((ifp->if_flags & IFF_LOOPBACK) != 0)
+#else
+ if (1)
+#endif
+ {
if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
ip6->ip6_src.s6_addr16[1] = 0;
if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
@@ -816,7 +844,7 @@ skip_ipsec2:;
#endif /* PFIL_HOOKS */
/*
* Send the packet to the outgoing interface.
- * If necessary, do IPv6 fragmentation before sending.
+ * If necessary, do IPv6 fragmentation before sending.
*/
tlen = m->m_pkthdr.len;
if (tlen <= mtu
@@ -830,7 +858,7 @@ skip_ipsec2:;
* larger than the link's MTU.
* XXX: IFF_FRAGMENTABLE (or such) flag has not been defined yet...
*/
-
+
|| ifp->if_flags & IFF_FRAGMENTABLE
#endif
)
@@ -850,7 +878,7 @@ skip_ipsec2:;
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
ro->ro_rt);
#else
- error = nd6_output(ifp, m, dst, ro->ro_rt);
+ error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
#endif
goto done;
} else if (mtu < IPV6_MMTU) {
@@ -895,16 +923,13 @@ skip_ipsec2:;
if (exthdrs.ip6e_rthdr) {
nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *);
*mtod(exthdrs.ip6e_rthdr, u_char *) = IPPROTO_FRAGMENT;
- }
- else if (exthdrs.ip6e_dest1) {
+ } else if (exthdrs.ip6e_dest1) {
nextproto = *mtod(exthdrs.ip6e_dest1, u_char *);
*mtod(exthdrs.ip6e_dest1, u_char *) = IPPROTO_FRAGMENT;
- }
- else if (exthdrs.ip6e_hbh) {
+ } else if (exthdrs.ip6e_hbh) {
nextproto = *mtod(exthdrs.ip6e_hbh, u_char *);
*mtod(exthdrs.ip6e_hbh, u_char *) = IPPROTO_FRAGMENT;
- }
- else {
+ } else {
nextproto = ip6->ip6_nxt;
ip6->ip6_nxt = IPPROTO_FRAGMENT;
}
@@ -986,10 +1011,9 @@ sendorfree:
(struct sockaddr *)dst,
ro->ro_rt);
#else
- error = nd6_output(ifp, m, dst, ro->ro_rt);
+ error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
#endif
- }
- else
+ } else
m_freem(m);
}
@@ -1052,7 +1076,7 @@ ip6_copyexthdr(mp, hdr, hlen)
}
/*
- * Insert jumbo payload option.
+ * Insert jumbo payload option.
*/
static int
ip6_insert_jumboopt(exthdrs, plen)
@@ -1078,8 +1102,7 @@ ip6_insert_jumboopt(exthdrs, plen)
optbuf = mtod(mopt, u_char *);
optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */
exthdrs->ip6e_hbh = mopt;
- }
- else {
+ } else {
struct ip6_hbh *hbh;
mopt = exthdrs->ip6e_hbh;
@@ -1096,8 +1119,7 @@ ip6_insert_jumboopt(exthdrs, plen)
bcopy(oldoptp, mtod(mopt, caddr_t), oldoptlen);
optbuf = mtod(mopt, caddr_t) + oldoptlen;
mopt->m_len = oldoptlen + JUMBOOPTLEN;
- }
- else {
+ } else {
optbuf = mtod(mopt, u_char *) + mopt->m_len;
mopt->m_len += JUMBOOPTLEN;
}
@@ -1141,8 +1163,7 @@ ip6_insertfraghdr(m0, m, hlen, frghdrp)
if (n == 0)
return(ENOBUFS);
m->m_next = n;
- }
- else
+ } else
n = m;
/* Search for the last mbuf of unfragmentable part. */
@@ -1156,8 +1177,7 @@ ip6_insertfraghdr(m0, m, hlen, frghdrp)
(struct ip6_frag *)(mtod(mlast, caddr_t) + mlast->m_len);
mlast->m_len += sizeof(struct ip6_frag);
m->m_pkthdr.len += sizeof(struct ip6_frag);
- }
- else {
+ } else {
/* allocate a new mbuf for the fragment header */
struct mbuf *mfrg;
@@ -1188,7 +1208,7 @@ ip6_ctloutput(op, so, level, optname, mp)
int error = 0;
struct proc *p = curproc; /* XXX */
- if (level == IPPROTO_IPV6)
+ if (level == IPPROTO_IPV6) {
switch (op) {
case PRCO_SETOPT:
@@ -1498,7 +1518,7 @@ ip6_ctloutput(op, so, level, optname, mp)
}
break;
}
- else {
+ } else {
error = EINVAL;
if (op == PRCO_SETOPT && *mp)
(void)m_free(*mp);
@@ -1526,8 +1546,7 @@ ip6_pcbopts(pktopt, m, so)
if (opt) {
if (opt->ip6po_m)
(void)m_free(opt->ip6po_m);
- }
- else
+ } else
opt = malloc(sizeof(*opt), M_IP6OPT, M_WAITOK);
*pktopt = 0;
@@ -1692,8 +1711,7 @@ ip6_setmoptions(optname, im6op, m)
*/
if (IN6_IS_ADDR_MC_NODELOCAL(&mreq->ipv6mr_multiaddr)) {
ifp = &loif[0];
- }
- else {
+ } else {
ro.ro_rt = NULL;
dst = (struct sockaddr_in6 *)&ro.ro_dst;
bzero(dst, sizeof(*dst));
@@ -1955,6 +1973,10 @@ ip6_setpktoptions(control, opt, priv)
return(ENXIO);
}
+ /*
+ * Check if the requested source address is indeed a
+ * unicast address assigned to the node.
+ */
if (!IN6_IS_ADDR_UNSPECIFIED(&opt->ip6po_pktinfo->ipi6_addr)) {
struct ifaddr *ia;
struct sockaddr_in6 sin6;
@@ -1993,7 +2015,9 @@ ip6_setpktoptions(control, opt, priv)
case IPV6_NEXTHOP:
if (!priv)
return(EPERM);
+
if (cm->cmsg_len < sizeof(u_char) ||
+ /* check if cmsg_len is large enough for sa_len */
cm->cmsg_len < CMSG_LEN(*CMSG_DATA(cm)))
return(EINVAL);
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index c511899df17..e6e35446d6f 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1,5 +1,5 @@
-/* $NetBSD: nd6.c,v 1.29 2000/05/09 11:51:12 itojun Exp $ */
-/* $KAME: nd6.c,v 1.62 2000/05/09 11:35:55 itojun Exp $ */
+/* $NetBSD: nd6.c,v 1.30 2000/05/19 01:40:19 itojun Exp $ */
+/* $KAME: nd6.c,v 1.63 2000/05/17 12:35:59 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -1630,7 +1630,11 @@ fail:
(*ifp->if_output)(ifp, ln->ln_hold,
rt_key(rt), rt);
#else
- nd6_output(ifp, ln->ln_hold,
+ /*
+ * we assume ifp is not a p2p here, so just
+ * set the 2nd argument as the 1st one.
+ */
+ nd6_output(ifp, ifp, ln->ln_hold,
(struct sockaddr_in6 *)rt_key(rt),
rt);
#endif
@@ -1741,8 +1745,9 @@ nd6_slowtimo(ignored_arg)
#define senderr(e) { error = (e); goto bad;}
int
-nd6_output(ifp, m0, dst, rt0)
+nd6_output(ifp, origifp, m0, dst, rt0)
register struct ifnet *ifp;
+ struct ifnet *origifp;
struct mbuf *m0;
struct sockaddr_in6 *dst;
struct rtentry *rt0;
@@ -1783,8 +1788,11 @@ nd6_output(ifp, m0, dst, rt0)
NULL)
{
rt->rt_refcnt--;
- if (rt->rt_ifp != ifp)
- return nd6_output(ifp, m0, dst, rt); /* XXX: loop care? */
+ if (rt->rt_ifp != ifp) {
+ /* XXX: loop care? */
+ return nd6_output(ifp, origifp, m0,
+ dst, rt);
+ }
} else
senderr(EHOSTUNREACH);
}
@@ -1916,6 +1924,13 @@ nd6_output(ifp, m0, dst, rt0)
return(0);
sendpkt:
+
+#ifdef FAKE_LOOPBACK_IF
+ if (ifp->if_flags & IFF_LOOPBACK) {
+ return((*ifp->if_output)(origifp, m, (struct sockaddr *)dst,
+ rt));
+ }
+#endif
return((*ifp->if_output)(ifp, m, (struct sockaddr *)dst, rt));
bad:
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index a2f69c86614..f34b7467ba0 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -1,5 +1,5 @@
-/* $NetBSD: nd6.h,v 1.13 2000/05/09 11:51:12 itojun Exp $ */
-/* $KAME: nd6.h,v 1.20 2000/04/29 04:46:41 jinmei Exp $ */
+/* $NetBSD: nd6.h,v 1.14 2000/05/19 01:40:19 itojun Exp $ */
+/* $KAME: nd6.h,v 1.21 2000/05/17 12:35:59 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -288,8 +288,8 @@ int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
struct rtentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int));
/* for test */
-int nd6_output __P((struct ifnet *, struct mbuf *, struct sockaddr_in6 *,
- struct rtentry *));
+int nd6_output __P((struct ifnet *, struct ifnet *, struct mbuf *,
+ struct sockaddr_in6 *, struct rtentry *));
int nd6_storelladdr __P((struct ifnet *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *));
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 7478f785f75..6d8bae99889 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -1,10 +1,10 @@
-/* $NetBSD: nd6_nbr.c,v 1.21 2000/03/24 04:09:05 itojun Exp $ */
-/* $KAME: nd6_nbr.c,v 1.28 2000/02/26 06:53:11 itojun Exp $ */
+/* $NetBSD: nd6_nbr.c,v 1.22 2000/05/19 01:40:19 itojun Exp $ */
+/* $KAME: nd6_nbr.c,v 1.36 2000/05/17 12:35:59 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -16,7 +16,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -758,9 +758,13 @@ nd6_na_input(m, off, icmp6len)
#ifdef OLDIP6OUTPUT
(*ifp->if_output)(ifp, ln->ln_hold, rt_key(rt), rt);
#else
- nd6_output(ifp, ln->ln_hold,
+ /*
+ * we assume ifp is not a p2p here, so just set the 2nd
+ * argument as the 1st one.
+ */
+ nd6_output(ifp, ifp, ln->ln_hold,
(struct sockaddr_in6 *)rt_key(rt), rt);
-#endif
+#endif
ln->ln_hold = 0;
}