From d9c080e0265d3557ac6fe2d2723cf4823eaa909f Mon Sep 17 00:00:00 2001 From: Jun-ichiro itojun Hagino Date: Wed, 8 Dec 1999 06:50:25 +0000 Subject: bring in KAME IPv6 code, dated 19991208. replaces NRL IPv6 layer. reuses NRL pcb layer. no IPsec-on-v6 support. see sys/netinet6/{TODO,IMPLEMENTATION} for more details. GENERIC configuration should work fine as before. GENERIC.v6 works fine as well, but you'll need KAME userland tools to play with IPv6 (will be bringed into soon). --- sys/netinet6/in6_pcb.c | 207 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 173 insertions(+), 34 deletions(-) (limited to 'sys/netinet6/in6_pcb.c') diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 0d99d5a1454..f101e229833 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -68,10 +68,9 @@ didn't get a copy, you may request one from . #include #include -#include #include -#include -#include +#include +#include #if __OpenBSD__ #undef IPSEC @@ -147,6 +146,7 @@ extern int ipport_hilastauto; * I also put it here, because, quite frankly, it belongs here, not in * ip{v6,}_input(). */ +#if 0 u_char inet6ctlerrmap[PRC_NCMDS] = { 0, 0, 0, 0, 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, @@ -155,6 +155,7 @@ u_char inet6ctlerrmap[PRC_NCMDS] = { 0, 0, 0, 0, ENOPROTOOPT }; +#endif /*---------------------------------------------------------------------- * Bind an address (or at least a port) to an PF_INET6 socket. @@ -323,7 +324,7 @@ in6_pcbbind(inp, nam) inp->inp_laddr6 = sin6->sin6_addr; if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) - inp->inp_ipv6.ipv6_versfl = htonl(0x60000000) | + inp->inp_ipv6.ip6_flow = htonl(0x60000000) | (sin6->sin6_flowinfo & htonl(0x0fffffff)); /* @@ -643,13 +644,13 @@ in6_pcbladdr(inp, nam, plocal_sin) #define ifatoi6a(ifa) ((struct in6_ifaddr *)(ifa)) struct in6_ifaddr *ti6a = NULL; - for (i6a = in6_ifaddr; i6a; i6a = i6a->i6a_next) + for (i6a = in6_ifaddr; i6a; i6a = i6a->ia_next) { /* Find first (non-link-local if possible) address for source usage. If multiple link-locals, use last one found. */ - if (IN6_IS_ADDR_LINKLOCAL(&I6A_SIN(i6a)->sin6_addr)) + if (IN6_IS_ADDR_LINKLOCAL(&IA6_SIN6(i6a)->sin6_addr)) ti6a=i6a; - else if (!IN6_IS_ADDR_LOOPBACK(&I6A_SIN(i6a)->sin6_addr)) + else if (!IN6_IS_ADDR_LOOPBACK(&IA6_SIN6(i6a)->sin6_addr)) break; } if (i6a == NULL && ti6a != NULL) @@ -658,7 +659,7 @@ in6_pcbladdr(inp, nam, plocal_sin) if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) { - register struct route6 *ro; + register struct route_in6 *ro; i6a = NULL; /* @@ -689,6 +690,7 @@ in6_pcbladdr(inp, nam, plocal_sin) rtalloc((struct route *)ro); } +#if 0 /* NRL IPv6*/ if (ro->ro_rt == NULL) { /* @@ -700,6 +702,7 @@ in6_pcbladdr(inp, nam, plocal_sin) ipv6_onlink_query((struct sockaddr_in6 *)&ro->ro_dst); rtalloc((struct route *)ro); } +#endif if (ro->ro_rt == NULL) { /* @@ -774,13 +777,13 @@ in6_pcbladdr(inp, nam, plocal_sin) { struct in6_ifaddr *ti6a = NULL; - for (i6a = in6_ifaddr; i6a; i6a = i6a->i6a_next) + for (i6a = in6_ifaddr; i6a; i6a = i6a->ia_next) { /* Find first (non-local if possible) address for source usage. If multiple locals, use last one found. */ - if (IN6_IS_ADDR_LINKLOCAL(&I6A_SIN(i6a)->sin6_addr)) + if (IN6_IS_ADDR_LINKLOCAL(&IA6_SIN6(i6a)->sin6_addr)) ti6a=i6a; - else if (!IN6_IS_ADDR_LOOPBACK(&I6A_SIN(i6a)->sin6_addr)) + else if (!IN6_IS_ADDR_LOOPBACK(&IA6_SIN6(i6a)->sin6_addr)) break; } if (i6a == NULL && ti6a != NULL) @@ -797,15 +800,15 @@ in6_pcbladdr(inp, nam, plocal_sin) if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && inp->inp_moptions6 != NULL && (inp->inp_flags & INP_IPV6_MCAST)) { - struct ipv6_moptions *i6mo; + struct ip6_hdr_moptions *im6o; struct ifnet *ifp; - i6mo = inp->inp_moptions6; - if (i6mo->i6mo_multicast_ifp != NULL) + im6o = inp->inp_moptions6; + if (im6o->im6o_multicast_ifp != NULL) { - ifp = i6mo->i6mo_multicast_ifp; - for (i6a = in6_ifaddr; i6a; i6a = i6a->i6a_next) - if (i6a->i6a_ifp == ifp) /* Linkloc vs. global? */ + ifp = im6o->im6o_multicast_ifp; + for (i6a = in6_ifaddr; i6a; i6a = i6a->ia_next) + if (i6a->ia_ifp == ifp) /* Linkloc vs. global? */ break; if (i6a == NULL) return EADDRNOTAVAIL; @@ -838,6 +841,7 @@ in6_pcbconnect(inp, nam) #else /* __FreeBSD__ */ struct mbuf *nam; #endif /* __FreeBSD__ */ +#if 0 { struct in6_ifaddr *i6a; struct sockaddr_in6 *ifaddr = NULL; @@ -944,13 +948,13 @@ in6_pcbconnect(inp, nam) #define ifatoi6a(ifa) ((struct in6_ifaddr *)(ifa)) struct in6_ifaddr *ti6a = NULL; - for (i6a = in6_ifaddr; i6a; i6a = i6a->i6a_next) + for (i6a = in6_ifaddr; i6a; i6a = i6a->ia_next) { /* Find first (non-link-local if possible) address for source usage. If multiple link-locals, use last one found. */ - if (IN6_IS_ADDR_LINKLOCAL(&I6A_SIN(i6a)->sin6_addr)) + if (IN6_IS_ADDR_LINKLOCAL(&IA6_SIN6(i6a)->sin6_addr)) ti6a=i6a; - else if (!IN6_IS_ADDR_LOOPBACK(&I6A_SIN(i6a)->sin6_addr)) + else if (!IN6_IS_ADDR_LOOPBACK(&IA6_SIN6(i6a)->sin6_addr)) break; } if (i6a == NULL && ti6a != NULL) @@ -959,8 +963,7 @@ in6_pcbconnect(inp, nam) if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) { - register struct route6 *ro; - + register struct route_in6 *ro; i6a = NULL; /* @@ -991,6 +994,7 @@ in6_pcbconnect(inp, nam) rtalloc((struct route *)ro); } +#if 0 /* NRL IPv6*/ if (ro->ro_rt == NULL) { /* @@ -1002,6 +1006,7 @@ in6_pcbconnect(inp, nam) ipv6_onlink_query((struct sockaddr_in6 *)&ro->ro_dst); rtalloc((struct route *)ro); } +#endif if (ro->ro_rt == NULL) { /* @@ -1012,6 +1017,7 @@ in6_pcbconnect(inp, nam) return ENETUNREACH; } +#if 0 /*NRL IPv6*/ if (ro->ro_rt->rt_ifa == NULL) { /* @@ -1040,6 +1046,7 @@ in6_pcbconnect(inp, nam) if (ro->ro_rt == NULL || ro->ro_rt->rt_ifa == NULL) panic("Oops2, I'm forgetting something after verify_onlink()."); } +#endif /* @@ -1076,13 +1083,13 @@ in6_pcbconnect(inp, nam) { struct in6_ifaddr *ti6a = NULL; - for (i6a = in6_ifaddr; i6a; i6a = i6a->i6a_next) + for (i6a = in6_ifaddr; i6a; i6a = i6a->ia_next) { /* Find first (non-local if possible) address for source usage. If multiple locals, use last one found. */ - if (IN6_IS_ADDR_LINKLOCAL(&I6A_SIN(i6a)->sin6_addr)) + if (IN6_IS_ADDR_LINKLOCAL(&IA6_SIN6(i6a)->sin6_addr)) ti6a=i6a; - else if (!IN6_IS_ADDR_LOOPBACK(&I6A_SIN(i6a)->sin6_addr)) + else if (!IN6_IS_ADDR_LOOPBACK(&IA6_SIN6(i6a)->sin6_addr)) break; } if (i6a == NULL && ti6a != NULL) @@ -1099,22 +1106,22 @@ in6_pcbconnect(inp, nam) if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && inp->inp_moptions6 != NULL && (inp->inp_flags & INP_IPV6_MCAST)) { - struct ipv6_moptions *i6mo; + struct ip6_moptions *im6o; struct ifnet *ifp; - i6mo = inp->inp_moptions6; - if (i6mo->i6mo_multicast_ifp != NULL) + im6o = inp->inp_moptions6; + if (im6o->im6o_multicast_ifp != NULL) { - ifp = i6mo->i6mo_multicast_ifp; - for (i6a = in6_ifaddr; i6a; i6a = i6a->i6a_next) - if (i6a->i6a_ifp == ifp) /* Linkloc vs. global? */ + ifp = im6o->im6o_multicast_ifp; + for (i6a = in6_ifaddr; i6a; i6a = i6a->ia_next) + if (i6a->ia_ifp == ifp) /* Linkloc vs. global? */ break; if (i6a == NULL) return EADDRNOTAVAIL; } } - ifaddr = (struct sockaddr_in6 *)&i6a->i6a_addr; + ifaddr = (struct sockaddr_in6 *)&i6a->ia_addr; } #if __FreeBSD__ @@ -1155,7 +1162,7 @@ in6_pcbconnect(inp, nam) /* * Assumes user specify flowinfo in network order. */ - inp->inp_ipv6.ipv6_versfl = htonl(0x60000000) | + inp->inp_ipv6.ip6_flow = htonl(0x60000000) | (sin6->sin6_flowinfo & htonl(0x0fffffff)); #if __NetBSD__ @@ -1175,6 +1182,139 @@ in6_pcbconnect(inp, nam) #endif /* __FreeBSD__ */ return 0; } +#else +{ + struct in6_addr *in6a = NULL; + struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *); + struct in6_pktinfo *pi; + struct ifnet *ifp = NULL; /* outgoing interface */ + int error = 0; + struct in6_addr mapped; + + (void)&in6a; /* XXX fool gcc */ + + if (nam->m_len != sizeof(*sin6)) + return(EINVAL); + if (sin6->sin6_family != AF_INET6) + return(EAFNOSUPPORT); + if (sin6->sin6_port == 0) + return(EADDRNOTAVAIL); + + /* sanity check for mapped address case */ + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) + inp->inp_laddr6.s6_addr16[5] = htons(0xffff); + if (!IN6_IS_ADDR_V4MAPPED(&inp->inp_laddr6)) + return EINVAL; + } else { + if (IN6_IS_ADDR_V4MAPPED(&inp->inp_laddr6)) + return EINVAL; + } + + /* + * If the scope of the destination is link-local, embed the interface + * index in the address. + */ + if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { + /* XXX boundary check is assumed to be already done. */ + /* XXX sin6_scope_id is weaker than advanced-api. */ + if (inp->inp_outputopts6 && + (pi = inp->inp_outputopts6->ip6po_pktinfo) && + pi->ipi6_ifindex) { + sin6->sin6_addr.s6_addr16[1] = htons(pi->ipi6_ifindex); + ifp = ifindex2ifnet[pi->ipi6_ifindex]; + } + else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && + inp->inp_moptions6 && + inp->inp_moptions6->im6o_multicast_ifp) { + sin6->sin6_addr.s6_addr16[1] = + htons(inp->inp_moptions6->im6o_multicast_ifp->if_index); + ifp = ifindex2ifnet[inp->inp_moptions6->im6o_multicast_ifp->if_index]; + } else if (sin6->sin6_scope_id) { + /* boundary check */ + if (sin6->sin6_scope_id < 0 + || if_index < sin6->sin6_scope_id) { + return ENXIO; /* XXX EINVAL? */ + } + sin6->sin6_addr.s6_addr16[1] + = htons(sin6->sin6_scope_id & 0xffff);/*XXX*/ + ifp = ifindex2ifnet[sin6->sin6_scope_id]; + } + } + + /* Source address selection. */ + if (IN6_IS_ADDR_V4MAPPED(&inp->inp_laddr6) + && inp->inp_laddr6.s6_addr32[3] == 0) { + struct sockaddr_in sin, *sinp; + + bzero(&sin, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + bcopy(&sin6->sin6_addr.s6_addr32[3], &sin.sin_addr, + sizeof(sin.sin_addr)); + sinp = in_selectsrc(&sin, (struct route *)&inp->inp_route6, + inp->inp_socket->so_options, NULL, &error); + if (sinp == 0) { + if (error == 0) + error = EADDRNOTAVAIL; + return(error); + } + bzero(&mapped, sizeof(mapped)); + mapped.s6_addr16[5] = htons(0xffff); + bcopy(&sinp->sin_addr, &mapped.s6_addr32[3], sizeof(sinp->sin_addr)); + in6a = &mapped; + } else { + /* + * XXX: in6_selectsrc might replace the bound local address + * with the address specified by setsockopt(IPV6_PKTINFO). + * Is it the intended behavior? + */ + in6a = in6_selectsrc(sin6, inp->inp_outputopts6, + inp->inp_moptions6, + &inp->inp_route6, + &inp->inp_laddr6, &error); + if (in6a == 0) { + if (error == 0) + error = EADDRNOTAVAIL; + return(error); + } + } + if (inp->inp_route6.ro_rt) + ifp = inp->inp_route6.ro_rt->rt_ifp; + + inp->inp_ipv6.ip6_hlim = (u_int8_t)in6_selecthlim(inp, ifp); + + if (in_pcblookup(inp->inp_table, + &sin6->sin6_addr, + sin6->sin6_port, + IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) ? + in6a : &inp->inp_laddr6, + inp->inp_lport, + INPLOOKUP_IPV6)) + return(EADDRINUSE); + if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) + || (IN6_IS_ADDR_V4MAPPED(&inp->inp_laddr6) + && inp->inp_laddr6.s6_addr32[3] == 0)) { + if (inp->inp_lport == 0) + (void)in6_pcbbind(inp, (struct mbuf *)0); + inp->inp_laddr6 = *in6a; + } + inp->inp_faddr6 = sin6->sin6_addr; + inp->inp_fport = sin6->sin6_port; + /* + * xxx kazu flowlabel is necessary for connect? + * but if this line is missing, the garbage value remains. + */ + inp->inp_ipv6.ip6_flow = sin6->sin6_flowinfo; + /* configure NRL flags properly */ + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + inp->inp_flags |= INP_IPV6_MAPPED; + inp->inp_flags &= ~INP_IPV6_UNDEC; + } + in_pcbrehash(inp); + return(0); +} +#endif /*---------------------------------------------------------------------- * Pass some notification to all connections of a protocol @@ -1356,7 +1496,6 @@ in6_setsockaddr(inp, nam) { register struct sockaddr_in6 *sin6; - #if __FreeBSD__ /* * In FreeBSD we have to allocate the sockaddr_in6 structure since we aren't -- cgit v1.2.3