diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-05-19 13:55:18 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-05-19 13:55:18 +0000 |
commit | f34c7d14a89b27b4df6f5cc19e37610111d4b13a (patch) | |
tree | 5dfbe67baa80a3c150c71e6dee72584c11ee74bb | |
parent | 97039802230c5cefdc52198b3646885c774d9f21 (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.c | 57 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 98 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 27 | ||||
-rw-r--r-- | sys/netinet6/nd6.h | 8 | ||||
-rw-r--r-- | sys/netinet6/nd6_nbr.c | 16 |
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; } |