summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-05-19 13:55:18 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-05-19 13:55:18 +0000
commitf34c7d14a89b27b4df6f5cc19e37610111d4b13a (patch)
tree5dfbe67baa80a3c150c71e6dee72584c11ee74bb
parent97039802230c5cefdc52198b3646885c774d9f21 (diff)
never forward packet with link-local address.
experimental support for new loopback packet handling (with FAKE_LOOPBACK_IF, rcvif will be set to real outgoing interface, not the loopback, to honor scope) sync with kame.
-rw-r--r--sys/netinet6/ip6_forward.c57
-rw-r--r--sys/netinet6/ip6_output.c98
-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, 148 insertions, 58 deletions
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index 097f868d0f7..e434ce6c6d1 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -1,10 +1,10 @@
-/* $OpenBSD: ip6_forward.c,v 1.4 2000/02/28 11:55:22 itojun Exp $ */
-/* $KAME: ip6_forward.c,v 1.29 2000/02/26 18:08:38 itojun Exp $ */
+/* $OpenBSD: ip6_forward.c,v 1.5 2000/05/19 13:55:16 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
@@ -87,6 +87,7 @@ ip6_forward(m, srcrt)
int error, type = 0, code = 0;
struct mbuf *mcopy = NULL;
long time_second = time.tv_sec;
+ struct ifnet *origifp; /* maybe unnecessary */
#ifdef IPSEC_IPV6FWD
struct secpolicy *sp = NULL;
@@ -381,7 +382,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)
@@ -425,13 +426,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 81788cfc92a..e05124aee39 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1,9 +1,10 @@
-/* $OpenBSD: ip6_output.c,v 1.5 2000/05/19 05:14:45 itojun Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.6 2000/05/19 13:55:17 itojun Exp $ */
+/* $KAME: ip6_output.c,v 1.103 2000/05/19 05:13:21 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
@@ -135,7 +136,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;
@@ -508,7 +509,7 @@ skip_ipsec2:;
exthdrs.ip6e_ip6 = m;
}
-#endif /*IPESC*/
+#endif /*IPSEC*/
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
/* Unicast */
@@ -522,7 +523,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);
@@ -543,11 +544,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) {
@@ -740,10 +741,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))
@@ -756,6 +785,7 @@ skip_ipsec2:;
*/
if (ip6_fw_chk_ptr) {
u_short port = 0;
+ m->m_pkthdr.rcvif = NULL; /*XXX*/
/* If ipfw says divert, we have to just drop packet */
if ((*ip6_fw_chk_ptr)(&ip6, ifp, &port, &m)) {
m_freem(m);
@@ -802,7 +832,7 @@ skip_ipsec2:;
/*
* 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
@@ -816,7 +846,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
)
@@ -825,7 +855,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) {
@@ -870,16 +900,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;
}
@@ -950,10 +977,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);
}
@@ -1016,7 +1042,7 @@ ip6_copyexthdr(mp, hdr, hlen)
}
/*
- * Insert jumbo payload option.
+ * Insert jumbo payload option.
*/
static int
ip6_insert_jumboopt(exthdrs, plen)
@@ -1042,8 +1068,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;
@@ -1060,8 +1085,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;
}
@@ -1105,8 +1129,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. */
@@ -1120,8 +1143,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;
@@ -1931,6 +1953,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;
@@ -1969,7 +1995,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 90db5de37ad..f0810e46125 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: nd6.c,v 1.15 2000/05/15 11:45:35 itojun Exp $ */
-/* $KAME: nd6.c,v 1.62 2000/05/09 11:35:55 itojun Exp $ */
+/* $OpenBSD: nd6.c,v 1.16 2000/05/19 13:55:17 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.
@@ -1628,7 +1628,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
@@ -1738,8 +1742,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;
@@ -1780,8 +1785,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);
}
@@ -1913,6 +1921,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 6b35a91e2e7..49e5d0d9714 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: nd6.h,v 1.6 2000/05/15 11:45:35 itojun Exp $ */
-/* $KAME: nd6.h,v 1.20 2000/04/29 04:46:41 jinmei Exp $ */
+/* $OpenBSD: nd6.h,v 1.7 2000/05/19 13:55:17 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.
@@ -291,8 +291,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 85fd4169c91..01d60abd9fb 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -1,10 +1,10 @@
-/* $OpenBSD: nd6_nbr.c,v 1.9 2000/02/28 11:55:23 itojun Exp $ */
-/* $KAME: nd6_nbr.c,v 1.29 2000/02/26 08:20:58 itojun Exp $ */
+/* $OpenBSD: nd6_nbr.c,v 1.10 2000/05/19 13:55:17 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
@@ -750,9 +750,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;
}