diff options
author | shin <shin@FreeBSD.org> | 1999-12-07 17:39:16 +0000 |
---|---|---|
committer | shin <shin@FreeBSD.org> | 1999-12-07 17:39:16 +0000 |
commit | 70f0bdf6818a73c858bc47a23afc1e9d7c56d716 (patch) | |
tree | 446280db4239de7d7d9030c47d2c30515a265a54 /sys/netinet6 | |
parent | 7bdf4b7db0db632bec3b1040d83cdfbdb35e59cd (diff) | |
download | FreeBSD-src-70f0bdf6818a73c858bc47a23afc1e9d7c56d716.zip FreeBSD-src-70f0bdf6818a73c858bc47a23afc1e9d7c56d716.tar.gz |
udp IPv6 support, IPv6/IPv4 tunneling support in kernel,
packet divert at kernel for IPv6/IPv4 translater daemon
This includes queue related patch submitted by jburkhol@home.com.
Submitted by: queue related patch from jburkhol@home.com
Reviewed by: freebsd-arch, cvs-committers
Obtained from: KAME project
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/icmp6.c | 14 | ||||
-rw-r--r-- | sys/netinet6/icmp6.h | 3 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 31 | ||||
-rw-r--r-- | sys/netinet6/in6.h | 66 | ||||
-rw-r--r-- | sys/netinet6/in6_gif.c | 263 | ||||
-rw-r--r-- | sys/netinet6/in6_gif.h | 40 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 10 | ||||
-rw-r--r-- | sys/netinet6/in6_pcb.c | 13 | ||||
-rw-r--r-- | sys/netinet6/in6_prefix.c | 21 | ||||
-rw-r--r-- | sys/netinet6/in6_proto.c | 24 | ||||
-rw-r--r-- | sys/netinet6/in6_var.h | 11 | ||||
-rw-r--r-- | sys/netinet6/ip6_forward.c | 6 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 10 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 16 | ||||
-rw-r--r-- | sys/netinet6/mld6.c | 2 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 40 | ||||
-rw-r--r-- | sys/netinet6/nd6.h | 4 | ||||
-rw-r--r-- | sys/netinet6/nd6_nbr.c | 4 | ||||
-rw-r--r-- | sys/netinet6/nd6_rtr.c | 40 | ||||
-rw-r--r-- | sys/netinet6/raw_ip6.c | 6 | ||||
-rw-r--r-- | sys/netinet6/udp6_usrreq.c | 835 | ||||
-rw-r--r-- | sys/netinet6/udp6_var.h | 2 |
22 files changed, 1245 insertions, 216 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 425a5d5..943ddf7 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -64,7 +64,6 @@ * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 */ -#include "opt_inet.h" #include "opt_key.h" #include <sys/param.h> @@ -97,15 +96,10 @@ #ifdef IPSEC #include <netinet6/ipsec.h> -#ifdef INET6 #include <netinet6/ipsec6.h> -#endif /* INET6 */ #include <netkey/key.h> #ifdef KEY_DEBUG #include <netkey/key_debug.h> -#ifdef INET6 -#include <netkey/key_debug6.h> -#endif /* INET6 */ #else #define DPRINTF(lev,arg) #define DDO(lev, stmt) @@ -113,7 +107,7 @@ #endif /* KEY_DEBUG */ #endif /* IPSEC */ -/* #include "faith.h" */ +#include "faith.h" #include <net/net_osdep.h> @@ -910,8 +904,7 @@ ni6_addrs(ni6, m, ifpp) for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) { addrsofif = 0; - for (ifa = ifp->if_addrlist.tqh_first; ifa; - ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; @@ -976,8 +969,7 @@ ni6_store_addrs(ni6, nni6, ifp0, resid) for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) { - for (ifa = ifp->if_addrlist.tqh_first; ifa; - ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { docopy = 0; diff --git a/sys/netinet6/icmp6.h b/sys/netinet6/icmp6.h index 8fd63ff..2fdb28b 100644 --- a/sys/netinet6/icmp6.h +++ b/sys/netinet6/icmp6.h @@ -516,6 +516,9 @@ struct icmp6stat { #define RTF_PROBEMTU RTF_PROTO1 #ifdef _KERNEL +#ifdef SYSCTL_DECL +SYSCTL_DECL(_net_inet6_icmp6); +#endif # ifdef __STDC__ struct rtentry; struct rttimer; diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index e18b14f..a981c79 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -64,8 +64,6 @@ * @(#)in.c 8.2 (Berkeley) 11/15/93 */ -#include "opt_inet.h" - #include <sys/param.h> #include <sys/errno.h> #include <sys/malloc.h> @@ -81,10 +79,8 @@ #include <net/if.h> #include <net/if_types.h> #include <net/route.h> -/* #include "gif.h" */ -#if NGIF > 0 -#include <net/if_gif.h> -#endif +#include "gif.h" + #include <net/if_dl.h> #include <netinet/in.h> @@ -96,6 +92,9 @@ #include <netinet6/ip6_var.h> #include <netinet6/mld6_var.h> #include <netinet6/in6_ifattach.h> +#if NGIF > 0 +#include <net/if_gif.h> +#endif #include <net/net_osdep.h> @@ -348,7 +347,7 @@ in6_ifindex2scopeid(idx) return -1; ifp = ifindex2ifnet[idx]; - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; @@ -1059,9 +1058,7 @@ in6_lifaddr_ioctl(so, cmd, data, ifp, p) } } - for (ifa = ifp->if_addrlist.tqh_first; - ifa; - ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; @@ -1311,7 +1308,7 @@ in6ifa_ifpforlinklocal(ifp) { register struct ifaddr *ifa; - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr == NULL) continue; /* just for safety */ @@ -1335,7 +1332,7 @@ in6ifa_ifpwithaddr(ifp, addr) { register struct ifaddr *ifa; - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr == NULL) continue; /* just for safety */ @@ -1575,7 +1572,7 @@ in6_ifawithscope(ifp, dst) * If two or more, return one which matches the dst longest. * If none, return one of global addresses assigned other ifs. */ - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; @@ -1661,7 +1658,7 @@ in6_ifawithifp(ifp, dst) * If two or more, return one which matches the dst longest. * If none, return one of global addresses assigned other ifs. */ - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; @@ -1696,7 +1693,7 @@ in6_ifawithifp(ifp, dst) if (besta) return(besta); - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; @@ -1742,7 +1739,7 @@ in6_if_up(ifp) bzero(&ea, sizeof(ea)); sdl = NULL; - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { @@ -1789,7 +1786,7 @@ in6_if_up(ifp) dad: dad_delay = 0; - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index 1ca678e..b5266ce 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -74,6 +74,7 @@ * Identification of the network protocol stack */ #define __KAME__ +#define __KAME_VERSION "SNAP 19991101" /* * Local port number conventions: @@ -343,13 +344,6 @@ extern const struct in6_addr in6addr_linklocal_allrouters; #endif /* - * Wildcard Socket - */ -#if 0 /*pre-RFC2553*/ -#define IN6_IS_ADDR_ANY(a) IN6_IS_ADDR_UNSPECIFIED(a) -#endif - -/* * KAME Scope */ #ifdef _KERNEL /*nonstandard*/ @@ -522,65 +516,12 @@ struct in6_pktinfo { #define IPV6CTL_AUTO_FLOWLABEL 17 #define IPV6CTL_DEFMCASTHLIM 18 #define IPV6CTL_GIF_HLIM 19 /* default HLIM for gif encap packet */ +#define IPV6CTL_KAME_VERSION 20 #define IPV6CTL_USE_DEPRECATED 21 /* use deprecated addr (RFC2462 5.5.4) */ #define IPV6CTL_RR_PRUNE 22 /* walk timer for router renumbering */ #define IPV6CTL_MAPPED_ADDR 23 /* New entries should be added here from current IPV6CTL_MAXID value. */ #define IPV6CTL_MAXID 24 - -#define IPV6CTL_NAMES { \ - { 0, 0 }, \ - { "forwarding", CTLTYPE_INT }, \ - { "redirect", CTLTYPE_INT }, \ - { "hlim", CTLTYPE_INT }, \ - { "mtu", CTLTYPE_INT }, \ - { "forwsrcrt", CTLTYPE_INT }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { "mrtproto", CTLTYPE_INT }, \ - { "maxfragpackets", CTLTYPE_INT }, \ - { "sourcecheck", CTLTYPE_INT }, \ - { "sourcecheck_logint", CTLTYPE_INT }, \ - { "accept_rtadv", CTLTYPE_INT }, \ - { "keepfaith", CTLTYPE_INT }, \ - { "log_interval", CTLTYPE_INT }, \ - { "hdrnestlimit", CTLTYPE_INT }, \ - { "dad_count", CTLTYPE_INT }, \ - { "auto_flowlabel", CTLTYPE_INT }, \ - { "defmcasthlim", CTLTYPE_INT }, \ - { "gifhlim", CTLTYPE_INT }, \ - { 0, 0 }, \ - { "use_deprecated", CTLTYPE_INT }, \ - { "rr_prune", CTLTYPE_INT }, \ - { "mapped_addr", CTLTYPE_INT }, \ -} - -#define IPV6CTL_VARS { \ - 0, \ - &ip6_forwarding, \ - &ip6_sendredirects, \ - &ip6_defhlim, \ - 0, \ - &ip6_forward_srcrt, \ - 0, \ - 0, \ - 0, \ - &ip6_maxfragpackets, \ - &ip6_sourcecheck, \ - &ip6_sourcecheck_interval, \ - &ip6_accept_rtadv, \ - &ip6_keepfaith, \ - &ip6_log_interval, \ - &ip6_hdrnestlimit, \ - &ip6_dad_count, \ - &ip6_auto_flowlabel, \ - &ip6_defmcasthlim, \ - &ip6_gif_hlim, \ - 0, \ - &ip6_use_deprecated, \ - &ip6_rr_prune, \ - &ip6_mapped_addr_on, \ -} #endif /* !_XOPEN_SOURCE */ /* @@ -633,9 +574,6 @@ extern struct cmsghdr *inet6_rthdr_init __P((void *, int)); extern int inet6_rthdr_add __P((struct cmsghdr *, const struct in6_addr *, u_int)); extern int inet6_rthdr_lasthop __P((struct cmsghdr *, u_int)); -#if 0 /* not implemented yet */ -extern int inet6_rthdr_reverse __P((const struct cmsghdr *, struct cmsghdr *)); -#endif extern int inet6_rthdr_segments __P((const struct cmsghdr *)); extern struct in6_addr *inet6_rthdr_getaddr __P((struct cmsghdr *, int)); extern int inet6_rthdr_getflags __P((const struct cmsghdr *, int)); diff --git a/sys/netinet6/in6_gif.c b/sys/netinet6/in6_gif.c new file mode 100644 index 0000000..dd7cd2f --- /dev/null +++ b/sys/netinet6/in6_gif.c @@ -0,0 +1,263 @@ +/* + * 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * in6_gif.c + */ + +#include "opt_inet.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/protosw.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#ifdef INET +#include <netinet/ip.h> +#endif +#include <netinet6/ip6.h> +#include <netinet6/ip6_var.h> +#include <netinet6/in6_gif.h> +#include <netinet6/ip6.h> + +#include <net/if_gif.h> + +#include <net/net_osdep.h> + +int +in6_gif_output(ifp, family, m, rt) + struct ifnet *ifp; + int family; /* family of the packet to be encapsulate. */ + struct mbuf *m; + struct rtentry *rt; +{ + struct gif_softc *sc = (struct gif_softc*)ifp; + struct sockaddr_in6 *dst = (struct sockaddr_in6 *)&sc->gif_ro6.ro_dst; + struct sockaddr_in6 *sin6_src = (struct sockaddr_in6 *)sc->gif_psrc; + struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst; + struct ip6_hdr *ip6; + int proto; + + if (sin6_src == NULL || sin6_dst == NULL || + sin6_src->sin6_family != AF_INET6 || + sin6_dst->sin6_family != AF_INET6) { + m_freem(m); + return EAFNOSUPPORT; + } + + switch (family) { +#ifdef INET + case AF_INET: + { + struct ip *ip; + + proto = IPPROTO_IPV4; + if (m->m_len < sizeof(*ip)) { + m = m_pullup(m, sizeof(*ip)); + if (!m) + return ENOBUFS; + } + ip = mtod(m, struct ip *); + break; + } +#endif + case AF_INET6: + { + struct ip6_hdr *ip6; + proto = IPPROTO_IPV6; + if (m->m_len < sizeof(*ip6)) { + m = m_pullup(m, sizeof(*ip6)); + if (!m) + return ENOBUFS; + } + ip6 = mtod(m, struct ip6_hdr *); + break; + } + default: +#ifdef DIAGNOSTIC + printf("in6_gif_output: warning: unknown family %d passed\n", + family); +#endif + m_freem(m); + return EAFNOSUPPORT; + } + + /* prepend new IP header */ + M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); + if (m && m->m_len < sizeof(struct ip6_hdr)) + m = m_pullup(m, sizeof(struct ip6_hdr)); + if (m == NULL) { + printf("ENOBUFS in in6_gif_output %d\n", __LINE__); + return ENOBUFS; + } + + ip6 = mtod(m, struct ip6_hdr *); + ip6->ip6_flow = 0; + ip6->ip6_vfc = IPV6_VERSION; + ip6->ip6_plen = htons((u_short)m->m_pkthdr.len); + ip6->ip6_nxt = proto; + ip6->ip6_hlim = ip6_gif_hlim; + ip6->ip6_src = sin6_src->sin6_addr; + if (ifp->if_flags & IFF_LINK0) { + /* multi-destination mode */ + if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr)) + ip6->ip6_dst = sin6_dst->sin6_addr; + else if (rt) { + ip6->ip6_dst = ((struct sockaddr_in6 *)(rt->rt_gateway))->sin6_addr; + } else { + m_freem(m); + return ENETUNREACH; + } + } else { + /* bidirectional configured tunnel mode */ + if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr)) + ip6->ip6_dst = sin6_dst->sin6_addr; + else { + m_freem(m); + return ENETUNREACH; + } + } + + if (dst->sin6_family != sin6_dst->sin6_family || + !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &sin6_dst->sin6_addr)) { + /* cache route doesn't match */ + bzero(dst, sizeof(*dst)); + dst->sin6_family = sin6_dst->sin6_family; + dst->sin6_len = sizeof(struct sockaddr_in6); + dst->sin6_addr = sin6_dst->sin6_addr; + if (sc->gif_ro6.ro_rt) { + RTFREE(sc->gif_ro6.ro_rt); + sc->gif_ro6.ro_rt = NULL; + } + } + + if (sc->gif_ro6.ro_rt == NULL) { + rtalloc((struct route *)&sc->gif_ro6); + if (sc->gif_ro6.ro_rt == NULL) { + m_freem(m); + return ENETUNREACH; + } + } + +#ifdef IPSEC + m->m_pkthdr.rcvif = NULL; +#endif /*IPSEC*/ + return(ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL)); +} + +int in6_gif_input(mp, offp, proto) + struct mbuf **mp; + int *offp, proto; +{ + struct mbuf *m = *mp; + struct gif_softc *sc; + struct ifnet *gifp = NULL; + struct ip6_hdr *ip6; + int i; + int af = 0; + + ip6 = mtod(m, struct ip6_hdr *); + +#define satoin6(sa) (((struct sockaddr_in6 *)(sa))->sin6_addr) + for (i = 0, sc = gif; i < ngif; i++, sc++) { + if (sc->gif_psrc == NULL || + sc->gif_pdst == NULL || + sc->gif_psrc->sa_family != AF_INET6 || + sc->gif_pdst->sa_family != AF_INET6) { + continue; + } + if ((sc->gif_if.if_flags & IFF_UP) == 0) + continue; + if ((sc->gif_if.if_flags & IFF_LINK0) && + IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_psrc), &ip6->ip6_dst) && + IN6_IS_ADDR_UNSPECIFIED(&satoin6(sc->gif_pdst))) { + gifp = &sc->gif_if; + continue; + } + if (IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_psrc), &ip6->ip6_dst) && + IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_pdst), &ip6->ip6_src)) { + gifp = &sc->gif_if; + break; + } + } + + if (gifp == NULL) { + m_freem(m); + ip6stat.ip6s_nogif++; + return IPPROTO_DONE; + } + + m_adj(m, *offp); + + switch (proto) { +#ifdef INET + case IPPROTO_IPV4: + { + struct ip *ip; + af = AF_INET; + if (m->m_len < sizeof(*ip)) { + m = m_pullup(m, sizeof(*ip)); + if (!m) + return IPPROTO_DONE; + } + ip = mtod(m, struct ip *); + break; + } +#endif /* INET */ + case IPPROTO_IPV6: + { + struct ip6_hdr *ip6; + af = AF_INET6; + if (m->m_len < sizeof(*ip6)) { + m = m_pullup(m, sizeof(*ip6)); + if (!m) + return IPPROTO_DONE; + } + ip6 = mtod(m, struct ip6_hdr *); + break; + } + default: + ip6stat.ip6s_nogif++; + m_freem(m); + return IPPROTO_DONE; + } + + gif_input(m, af, gifp); + return IPPROTO_DONE; +} diff --git a/sys/netinet6/in6_gif.h b/sys/netinet6/in6_gif.h new file mode 100644 index 0000000..7d06c3c --- /dev/null +++ b/sys/netinet6/in6_gif.h @@ -0,0 +1,40 @@ +/* + * 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NETINET6_IN6_GIF_H_ +#define _NETINET6_IN6_GIF_H_ + +#define GIF_HLIM 30 + +int in6_gif_input __P((struct mbuf **, int *, int)); +int in6_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *)); + +#endif /*_NETINET6_IN6_GIF_H_*/ diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 85ca75f..7d332ed 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -153,13 +153,11 @@ in6_ifattach_getifid(ifp0) if (found_first_ifid) return 0; - for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) + TAILQ_FOREACH(ifp, &ifnet, if_list) { if (ifp0 != NULL && ifp0 != ifp) continue; - for (ifa = ifp->if_addrlist.tqh_first; - ifa; - ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_LINK) continue; @@ -239,7 +237,7 @@ in6_ifattach_p2p() if (found_first_ifid == 0) return; - for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) + TAILQ_FOREACH(ifp, &ifnet, if_list) { switch (ifp->if_type) { case IFT_GIF: @@ -645,7 +643,7 @@ in6_ifdetach(ifp) struct rtentry *rt; short rtflags; - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) { diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 8aee5b3..ac5b923 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -65,7 +65,6 @@ * $FreeBSD$ */ -#include "opt_inet.h" #include "opt_key.h" #include <sys/param.h> @@ -96,19 +95,14 @@ #include <netinet/in_pcb.h> #include <netinet6/in6_pcb.h> -/* #include "faith.h" */ +#include "faith.h" #ifdef IPSEC #include <netinet6/ipsec.h> -#ifdef INET6 #include <netinet6/ipsec6.h> -#endif /* INET6 */ #include <netkey/key.h> #ifdef KEY_DEBUG #include <netkey/key_debug.h> -#ifdef INET6 -#include <netkey/key_debug6.h> -#endif /* INET6 */ #else #define DPRINTF(lev,arg) #define DDO(lev, stmt) @@ -1065,7 +1059,7 @@ in6_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp) head = &pcbinfo->hashbase[INP_PCBHASH(faddr->s6_addr32[3] /* XXX */, lport, fport, pcbinfo->hashmask)]; - for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { + LIST_FOREACH(inp, head, inp_hash) { if ((inp->inp_vflag & INP_IPV6) == NULL) continue; if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) && @@ -1083,8 +1077,7 @@ in6_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp) head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)]; - for (inp = head->lh_first; inp != NULL; - inp = inp->inp_hash.le_next) { + LIST_FOREACH(inp, head, inp_hash) { if ((inp->inp_vflag & INP_IPV6) == NULL) continue; if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) && diff --git a/sys/netinet6/in6_prefix.c b/sys/netinet6/in6_prefix.c index 8da07c4..6799d0d 100644 --- a/sys/netinet6/in6_prefix.c +++ b/sys/netinet6/in6_prefix.c @@ -184,7 +184,7 @@ search_matched_prefix(struct ifnet *ifp, struct in6_prefixreq *ipr) * which matches the addr */ - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; @@ -249,7 +249,7 @@ mark_matched_prefixes(u_long cmd, struct ifnet *ifp, struct in6_rrenumreq *irr) * search matched addr, and then search prefixes * which matche the addr */ - for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { struct rr_prefix *rpp; @@ -364,8 +364,7 @@ search_ifidwithprefix(struct rr_prefix *rpp, struct in6_addr *ifid) { struct rp_addr *rap; - for (rap = rpp->rp_addrhead.lh_first; rap != NULL; - rap = rap->ra_entry.le_next) + LIST_FOREACH(rap, &rpp->rp_addrhead, ra_entry) if (rr_are_ifid_equal(ifid, &rap->ra_ifid, (sizeof(struct in6_addr) << 3) - rpp->rp_plen)) @@ -682,8 +681,7 @@ rrpr_update(struct socket *so, struct rr_prefix *new) * If it existed but not pointing to the prefix yet, * init the prefix pointer. */ - for (rap = rpp->rp_addrhead.lh_first; rap != NULL; - rap = rap->ra_entry.le_next) { + LIST_FOREACH(rap, &rpp->rp_addrhead, ra_entry) { if (rap->ra_addr != NULL) { if (rap->ra_addr->ia6_ifpr == NULL) rap->ra_addr->ia6_ifpr = rp2ifpr(rpp); @@ -771,8 +769,7 @@ init_newprefix(struct in6_rrenumreq *irr, struct ifprefix *ifpr, irr->irr_u_uselen, min(ifpr->ifpr_plen - irr->irr_u_uselen, irr->irr_u_keeplen)); - for (orap = (ifpr2rp(ifpr)->rp_addrhead).lh_first; orap != NULL; - orap = orap->ra_entry.le_next) { + LIST_FOREACH(orap, &(ifpr2rp(ifpr)->rp_addrhead), ra_entry) { struct rp_addr *rap; int error = 0; @@ -845,8 +842,7 @@ unprefer_prefix(struct rr_prefix *rpp) { struct rp_addr *rap; - for (rap = rpp->rp_addrhead.lh_first; rap != NULL; - rap = rap->ra_entry.le_next) { + LIST_FOREACH(rap, &rpp->rp_addrhead, ra_entry) { if (rap->ra_addr == NULL) continue; rap->ra_addr->ia6_lifetime.ia6t_preferred = time_second; @@ -863,7 +859,7 @@ delete_each_prefix(struct socket *so, struct rr_prefix *rpp, u_char origin) if (rpp->rp_origin > origin) return(EPERM); - while (rpp->rp_addrhead.lh_first != NULL) { + while (!LIST_EMPTY(&rpp->rp_addrhead)) { struct rp_addr *rap; int s; @@ -923,8 +919,7 @@ link_stray_ia6s(struct rr_prefix *rpp) { struct ifaddr *ifa; - for (ifa = rpp->rp_ifp->if_addrlist.tqh_first; ifa; - ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &rpp->rp_ifp->if_addrlist, ifa_list) { struct rp_addr *rap; struct rr_prefix *orpp; diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index 1d1c7a3..3f59ec2 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -64,8 +64,6 @@ * @(#)in_proto.c 8.1 (Berkeley) 6/10/93 */ -#include "opt_inet.h" - #include <sys/param.h> #include <sys/socket.h> #include <sys/socketvar.h> @@ -104,9 +102,7 @@ #ifdef IPSEC #include <netinet6/ipsec.h> -#ifdef INET6 #include <netinet6/ipsec6.h> -#endif /* INET6 */ #include <netinet6/ah.h> #ifdef IPSEC_ESP #include <netinet6/esp.h> @@ -116,7 +112,7 @@ #include <netinet6/ip6protosw.h> -/* #include "gif.h" */ +#include "gif.h" #if NGIF > 0 #include <netinet6/in6_gif.h> #endif @@ -139,6 +135,12 @@ struct ip6protosw inet6sw[] = { ip6_init, 0, frag6_slowtimo, frag6_drain, &nousrreqs, }, +{ SOCK_DGRAM, &inet6domain, IPPROTO_UDP, PR_ATOMIC | PR_ADDR, + udp6_input, 0, udp6_ctlinput, ip6_ctloutput, + 0, + 0, 0, 0, 0, + &udp6_usrreqs, +}, { SOCK_RAW, &inet6domain, IPPROTO_RAW, PR_ATOMIC | PR_ADDR, rip6_input, rip6_output, 0, rip6_ctloutput, 0, @@ -194,18 +196,16 @@ struct ip6protosw inet6sw[] = { #if NGIF > 0 { SOCK_RAW, &inet6domain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR, in6_gif_input,0, 0, 0, - 0, + 0, 0, 0, 0, 0, &nousrreqs }, -#ifdef INET6 { SOCK_RAW, &inet6domain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR, in6_gif_input,0, 0, 0, - 0, + 0, 0, 0, 0, 0, &nousrreqs }, -#endif /* INET6 */ #endif /* GIF */ /* raw wildcard */ { SOCK_RAW, &inet6domain, 0, PR_ATOMIC | PR_ADDR, @@ -334,8 +334,8 @@ sysctl_ip6_forwarding SYSCTL_HANDLER_ARGS int s = splnet(); struct nd_prefix *pr, *next; - for (pr = nd_prefix.lh_first; pr; pr = next) { - next = pr->ndpr_next; + for (pr = LIST_FIRST(&nd_prefix); pr; pr = next) { + next = LIST_NEXT(pr, ndpr_entry); if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr)) in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr); prelist_remove(pr); @@ -379,6 +379,8 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DEFMCASTHLIM, defmcasthlim, CTLFLAG_RW, &ip6_defmcasthlim, 0, ""); SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW, &ip6_gif_hlim, 0, ""); +SYSCTL_STRING(_net_inet6_ip6, IPV6CTL_KAME_VERSION, + kame_version, CTLFLAG_RD, __KAME_VERSION, 0, ""); SYSCTL_INT(_net_inet6_ip6, IPV6CTL_USE_DEPRECATED, use_deprecated, CTLFLAG_RW, &ip6_use_deprecated, 0, ""); SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RR_PRUNE, diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h index 4117c20..163c167 100644 --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -437,7 +437,7 @@ MALLOC_DECLARE(M_IPMADDR); /* struct in6_ifaddr *ia; */ \ do { \ struct ifaddr *ifa; \ - for (ifa = (ifp)->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) { \ + TAILQ_FOREACH(ifa, &(ifp)->if_addrlist, ifa_list) { \ if (!ifa->ifa_addr) \ continue; \ if (ifa->ifa_addr->sa_family == AF_INET6) \ @@ -467,6 +467,11 @@ struct in6_multi { }; #ifdef _KERNEL + +#ifdef SYSCTL_DECL +SYSCTL_DECL(_net_inet6_ip6); +#endif + extern LIST_HEAD(in6_multihead, in6_multi) in6_multihead; /* @@ -512,14 +517,14 @@ do { \ /* struct in6_multi *in6m; */ \ do { \ if (((in6m) = (step).i_in6m) != NULL) \ - (step).i_in6m = (step).i_in6m->in6m_entry.le_next; \ + (step).i_in6m = LIST_NEXT((step).i_in6m, in6m_entry); \ } while(0) #define IN6_FIRST_MULTI(step, in6m) \ /* struct in6_multistep step; */ \ /* struct in6_multi *in6m */ \ do { \ - (step).i_in6m = in6_multihead.lh_first; \ + (step).i_in6m = LIST_FIRST(&in6_multihead); \ IN6_NEXT_MULTI((step), (in6m)); \ } while(0) diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index a50ba6c..46b3188 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -29,7 +29,6 @@ * $FreeBSD$ */ -#include "opt_inet.h" #include "opt_key.h" #include <sys/param.h> @@ -56,15 +55,10 @@ #ifdef IPSEC_IPV6FWD #include <netinet6/ipsec.h> -#ifdef INET6 #include <netinet6/ipsec6.h> -#endif /* INET6 */ #include <netkey/key.h> #ifdef KEY_DEBUG #include <netkey/key_debug.h> -#ifdef INET6 -#include <netkey/key_debug6.h> -#endif /* INET6 */ #else #define DPRINTF(lev,arg) #define DDO(lev, stmt) diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 097d5a0..105b4bc 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -64,8 +64,6 @@ * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 */ -#include "opt_inet.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> @@ -88,10 +86,8 @@ #include <netinet/in.h> #include <netinet/in_systm.h> -#ifdef INET #include <netinet/ip.h> #include <netinet/ip_icmp.h> -#endif /*INET*/ #include <netinet/in_pcb.h> #include <netinet6/in6_var.h> #include <netinet6/ip6.h> @@ -113,9 +109,9 @@ /* we need it for NLOOP. */ #include "loop.h" -/* #include "faith.h" */ -/* #include "gif.h" */ +#include "faith.h" +#include "gif.h" #include <net/net_osdep.h> @@ -793,7 +789,6 @@ ip6_savecontrol(in6p, mp, ip6, m) if (p && !suser(p)) privileged++; -#ifdef SO_TIMESTAMP if (in6p->in6p_socket->so_options & SO_TIMESTAMP) { struct timeval tv; @@ -803,7 +798,6 @@ ip6_savecontrol(in6p, mp, ip6, m) if (*mp) mp = &(*mp)->m_next; } -#endif if (in6p->in6p_flags & IN6P_RECVDSTADDR) { *mp = sbcreatecontrol((caddr_t) &ip6->ip6_dst, sizeof(struct in6_addr), IPV6_RECVDSTADDR, diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index de85510..1524bc3 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -64,7 +64,6 @@ * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 */ -#include "opt_inet.h" #include "opt_key.h" #include <sys/param.h> @@ -91,15 +90,10 @@ #ifdef IPSEC #include <netinet6/ipsec.h> -#ifdef INET6 #include <netinet6/ipsec6.h> -#endif /* INET6 */ #include <netkey/key.h> #ifdef KEY_DEBUG #include <netkey/key_debug.h> -#ifdef INET6 -#include <netkey/key_debug6.h> -#endif /* INET6 */ #else #define DPRINTF(lev,arg) #define DDO(lev, stmt) @@ -1764,8 +1758,7 @@ ip6_setmoptions(optname, im6op, m) /* * See if the membership already exists. */ - for (imm = im6o->im6o_memberships.lh_first; - imm != NULL; imm = imm->i6mm_chain.le_next) + LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) if (imm->i6mm_maddr->in6m_ifp == ifp && IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, &mreq->ipv6mr_multiaddr)) @@ -1831,8 +1824,7 @@ ip6_setmoptions(optname, im6op, m) /* * Find the membership in the membership list. */ - for (imm = im6o->im6o_memberships.lh_first; - imm != NULL; imm = imm->i6mm_chain.le_next) { + LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) { if ((ifp == NULL || imm->i6mm_maddr->in6m_ifp == ifp) && IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, @@ -1864,7 +1856,7 @@ ip6_setmoptions(optname, im6op, m) if (im6o->im6o_multicast_ifp == NULL && im6o->im6o_multicast_hlim == ip6_defmcasthlim && im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP && - im6o->im6o_memberships.lh_first == NULL) { + LIST_EMPTY(&im6o->im6o_memberships)) { free(*im6op, M_IPMOPTS); *im6op = NULL; } @@ -1931,7 +1923,7 @@ ip6_freemoptions(im6o) if (im6o == NULL) return; - while ((imm = im6o->im6o_memberships.lh_first) != NULL) { + while ((imm = LIST_FIRST(&im6o->im6o_memberships)) != NULL) { LIST_REMOVE(imm, i6mm_chain); if (imm->i6mm_maddr) in6_delmulti(imm->i6mm_maddr); diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c index 43cb9b7..634f61b 100644 --- a/sys/netinet6/mld6.c +++ b/sys/netinet6/mld6.c @@ -68,8 +68,6 @@ * @(#)igmp.c 8.1 (Berkeley) 7/19/93 */ -#include "opt_inet.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 87eab9d..74787f2 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -458,17 +458,17 @@ nd6_timer(ignored_arg) } /* expire */ - dr = nd_defrouter.lh_first; + dr = LIST_FIRST(&nd_defrouter); while (dr) { if (dr->expire && dr->expire < time_second) { struct nd_defrouter *t; - t = dr->dr_next; + t = LIST_NEXT(dr, dr_entry); defrtrlist_del(dr); dr = t; } else - dr = dr->dr_next; + dr = LIST_NEXT(dr, dr_entry); } - pr = nd_prefix.lh_first; + pr = LIST_FIRST(&nd_prefix); while (pr) { struct in6_ifaddr *ia6; struct in6_addrlifetime *lt6; @@ -503,7 +503,7 @@ nd6_timer(ignored_arg) if (pr->ndpr_expire && pr->ndpr_expire + NDPR_KEEP_EXPIRED < time_second) { struct nd_prefix *t; - t = pr->ndpr_next; + t = LIST_NEXT(pr, ndpr_entry); /* * address expiration and prefix expiration are @@ -513,7 +513,7 @@ nd6_timer(ignored_arg) prelist_remove(pr); pr = t; } else - pr = pr->ndpr_next; + pr = LIST_NEXT(pr, ndpr_entry); } splx(s); } @@ -627,9 +627,7 @@ nd6_is_addr_neighbor(addr, ifp) * If the address matches one of our addresses, * it should be a neighbor. */ - for (ifa = ifp->if_addrlist.tqh_first; - ifa; - ifa = ifa->ifa_list.tqe_next) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) next: continue; @@ -967,7 +965,7 @@ nd6_ioctl(cmd, data, ifp) case SIOCGDRLST_IN6: bzero(drl, sizeof(*drl)); s = splnet(); - dr = nd_defrouter.lh_first; + dr = LIST_FIRST(&nd_defrouter); while (dr && i < DRLSTSIZ) { drl->defrouter[i].rtaddr = dr->rtaddr; if (IN6_IS_ADDR_LINKLOCAL(&drl->defrouter[i].rtaddr)) { @@ -984,14 +982,14 @@ nd6_ioctl(cmd, data, ifp) drl->defrouter[i].expire = dr->expire; drl->defrouter[i].if_index = dr->ifp->if_index; i++; - dr = dr->dr_next; + dr = LIST_NEXT(dr, dr_entry); } splx(s); break; case SIOCGPRLST_IN6: bzero(prl, sizeof(*prl)); s = splnet(); - pr = nd_prefix.lh_first; + pr = LIST_FIRST(&nd_prefix); while (pr && i < PRLSTSIZ) { struct nd_pfxrouter *pfr; int j; @@ -1004,7 +1002,7 @@ nd6_ioctl(cmd, data, ifp) prl->prefix[i].if_index = pr->ndpr_ifp->if_index; prl->prefix[i].expire = pr->ndpr_expire; - pfr = pr->ndpr_advrtrs.lh_first; + pfr = LIST_FIRST(&pr->ndpr_advrtrs); j = 0; while(pfr) { if (j < DRLSTSIZ) { @@ -1022,12 +1020,12 @@ nd6_ioctl(cmd, data, ifp) #undef RTRADDR } j++; - pfr = pfr->pfr_next; + pfr = LIST_NEXT(pfr, pfr_entry); } prl->prefix[i].advrtrs = j; i++; - pr = pr->ndpr_next; + pr = LIST_NEXT(pr, ndpr_entry); } splx(s); { @@ -1069,8 +1067,8 @@ nd6_ioctl(cmd, data, ifp) struct nd_prefix *pr, *next; s = splnet(); - for (pr = nd_prefix.lh_first; pr; pr = next) { - next = pr->ndpr_next; + for (pr = LIST_FIRST(&nd_prefix); pr; pr = next) { + next = LIST_NEXT(pr, ndpr_entry); if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr)) in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr); prelist_remove(pr); @@ -1084,16 +1082,16 @@ nd6_ioctl(cmd, data, ifp) struct nd_defrouter *dr, *next; s = splnet(); - if ((dr = nd_defrouter.lh_first) != NULL) { + if ((dr = LIST_FIRST(&nd_defrouter)) != NULL) { /* * The first entry of the list may be stored in * the routing table, so we'll delete it later. */ - for (dr = dr->dr_next; dr; dr = next) { - next = dr->dr_next; + for (dr = LIST_NEXT(dr, dr_entry); dr; dr = next) { + next = LIST_NEXT(dr, dr_entry); defrtrlist_del(dr); } - defrtrlist_del(nd_defrouter.lh_first); + defrtrlist_del(LIST_FIRST(&nd_defrouter)); } splx(s); break; diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index 2bb4fe4..756f495 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -126,7 +126,6 @@ struct in6_ndireq { struct nd_defrouter { LIST_ENTRY(nd_defrouter) dr_entry; -#define dr_next dr_entry.le_next struct in6_addr rtaddr; u_char flags; u_short rtlifetime; @@ -154,8 +153,6 @@ struct nd_prefix { } ndpr_stateflags; }; -#define ndpr_next ndpr_entry.le_next - #define ndpr_raf ndpr_flags #define ndpr_raf_onlink ndpr_flags.onlink #define ndpr_raf_auto ndpr_flags.autonomous @@ -200,7 +197,6 @@ struct inet6_ndpr_msghdr { struct nd_pfxrouter { LIST_ENTRY(nd_pfxrouter) pfr_entry; -#define pfr_next pfr_entry.le_next struct nd_defrouter *router; }; diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index de09176..840f074 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -29,8 +29,6 @@ * $FreeBSD$ */ -#include "opt_inet.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> @@ -818,7 +816,7 @@ nd6_dad_find(ifa) { struct dadq *dp; - for (dp = dadq.tqh_first; dp; dp = dp->dad_list.tqe_next) { + TAILQ_FOREACH(dp, &dadq, dad_list) { if (dp->dad_ifa == ifa) return dp; } diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index d177a66..da92879 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -374,7 +374,7 @@ defrouter_lookup(addr, ifp) { struct nd_defrouter *dr; - for(dr = nd_defrouter.lh_first; dr; dr = dr->dr_next) + LIST_FOREACH(dr, &nd_defrouter, dr_entry) if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr)) return(dr); @@ -405,8 +405,8 @@ defrouter_delreq(dr, dofree) if (dofree) free(dr, M_IP6NDP); - if (nd_defrouter.lh_first) - defrouter_addreq(nd_defrouter.lh_first); + if (!LIST_EMPTY(&nd_defrouter)) + defrouter_addreq(LIST_FIRST(&nd_defrouter)); /* * xxx update the Destination Cache entries for all @@ -430,7 +430,7 @@ defrtrlist_del(dr) rt6_flush(&dr->rtaddr, dr->ifp); } - if (dr == nd_defrouter.lh_first) + if (dr == LIST_FIRST(&nd_defrouter)) deldr = dr; /* The router is primary. */ LIST_REMOVE(dr, dr_entry); @@ -438,7 +438,7 @@ defrtrlist_del(dr) /* * Also delete all the pointers to the router in each prefix lists. */ - for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) { + LIST_FOREACH(pr, &nd_prefix, ndpr_entry) { struct nd_pfxrouter *pfxrtr; if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL) pfxrtr_del(pfxrtr); @@ -489,11 +489,11 @@ defrtrlist_update(new) } bzero(n, sizeof(*n)); *n = *new; - if (nd_defrouter.lh_first == NULL) { + if (LIST_EMPTY(&nd_defrouter)) { LIST_INSERT_HEAD(&nd_defrouter, n, dr_entry); defrouter_addreq(n); } else { - LIST_INSERT_AFTER(nd_defrouter.lh_first, n, dr_entry); + LIST_INSERT_AFTER(LIST_FIRST(&nd_defrouter), n, dr_entry); defrouter_addreq(n); } splx(s); @@ -507,8 +507,8 @@ pfxrtr_lookup(pr, dr) struct nd_defrouter *dr; { struct nd_pfxrouter *search; - - for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) { + + LIST_FOREACH(search, &pr->ndpr_advrtrs, pfr_entry) { if (search->router == dr) break; } @@ -548,7 +548,7 @@ prefix_lookup(pr) { struct nd_prefix *search; - for (search = nd_prefix.lh_first; search; search = search->ndpr_next) { + LIST_FOREACH(search, &nd_prefix, ndpr_entry) { if (pr->ndpr_ifp == search->ndpr_ifp && pr->ndpr_plen == search->ndpr_plen && in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr, @@ -611,8 +611,8 @@ prelist_remove(pr) splx(s); /* free list of routers that adversed the prefix */ - for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) { - next = pfr->pfr_next; + for (pfr = LIST_FIRST(&pr->ndpr_advrtrs); pfr; pfr = next) { + next = LIST_NEXT(pfr, pfr_entry); free(pfr, M_IP6NDP); } @@ -809,8 +809,8 @@ pfxlist_onlink_check() { struct nd_prefix *pr; - for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) - if (pr->ndpr_advrtrs.lh_first) /* pr has an available router */ + LIST_FOREACH(pr, &nd_prefix, ndpr_entry) + if (!LIST_EMPTY(&pr->ndpr_advrtrs)) /* pr has an available router */ break; if (pr) { @@ -821,21 +821,21 @@ pfxlist_onlink_check() * attached prefix and a detached prefix may have a same * interface route. */ - for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) { - if (pr->ndpr_advrtrs.lh_first == NULL && + LIST_FOREACH(pr, &nd_prefix, ndpr_entry) { + if (LIST_EMPTY(&pr->ndpr_advrtrs) && pr->ndpr_statef_onlink) { pr->ndpr_statef_onlink = 0; nd6_detach_prefix(pr); } } - for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) { - if (pr->ndpr_advrtrs.lh_first && + LIST_FOREACH(pr, &nd_prefix, ndpr_entry) { + if (!LIST_EMPTY(&pr->ndpr_advrtrs) && pr->ndpr_statef_onlink == 0) nd6_attach_prefix(pr); } } else { /* there is no prefix that has a router */ - for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) + LIST_FOREACH(pr, &nd_prefix, ndpr_entry) if (pr->ndpr_statef_onlink == 0) nd6_attach_prefix(pr); } @@ -993,7 +993,7 @@ in6_ifadd(ifp, in6, addr, prefixlen) in6_ifaddr = ia; /* link to if_addrlist */ - if (ifp->if_addrlist.tqh_first != NULL) { + if (!TAILQ_EMPTY(&ifp->if_addrlist)) { TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); } diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index c54874e..3131e41 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -64,8 +64,6 @@ * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 */ -#include "opt_inet.h" - #include <stddef.h> #include <sys/param.h> @@ -94,14 +92,12 @@ #ifdef IPSEC #include <netinet6/ipsec.h> -#ifdef INET6 #include <netinet6/ipsec6.h> -#endif /* INET6 */ #endif /*IPSEC*/ #include <machine/stdarg.h> -/* #include "faith.h" */ +#include "faith.h" #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c new file mode 100644 index 0000000..c22a719 --- /dev/null +++ b/sys/netinet6/udp6_usrreq.c @@ -0,0 +1,835 @@ +/* + * 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/sysctl.h> +#include <sys/errno.h> +#include <sys/stat.h> +#include <sys/systm.h> +#include <sys/syslog.h> +#include <sys/proc.h> + +#include <net/if.h> +#include <net/route.h> +#include <net/if_types.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/in_var.h> +#include <netinet/ip_var.h> +#include <netinet/udp.h> +#include <netinet/udp_var.h> +#include <netinet6/ip6.h> +#include <netinet6/ip6_var.h> +#include <netinet6/in6_pcb.h> +#include <netinet6/icmp6.h> +#include <netinet6/udp6_var.h> +#include <netinet6/ip6protosw.h> + +#ifdef IPSEC +#include <netinet6/ipsec.h> +#endif /*IPSEC*/ + +#include "faith.h" + +/* + * UDP protocol inplementation. + * Per RFC 768, August, 1980. + */ + +extern struct protosw inetsw[]; +static int in6_mcmatch __P((struct inpcb *, struct in6_addr *, struct ifnet *)); +static int udp6_detach __P((struct socket *so)); + +static int +in6_mcmatch(in6p, ia6, ifp) + struct inpcb *in6p; + register struct in6_addr *ia6; + struct ifnet *ifp; +{ + struct ip6_moptions *im6o = in6p->in6p_moptions; + struct in6_multi_mship *imm; + + if (im6o == NULL) + return 0; + + for (imm = im6o->im6o_memberships.lh_first; imm != NULL; + imm = imm->i6mm_chain.le_next) { + if ((ifp == NULL || + imm->i6mm_maddr->in6m_ifp == ifp) && + IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, + ia6)) + return 1; + } + return 0; +} + +int +udp6_input(mp, offp, proto) + struct mbuf **mp; + int *offp, proto; +{ + struct mbuf *m = *mp; + register struct ip6_hdr *ip6; + register struct udphdr *uh; + register struct inpcb *in6p; + struct mbuf *opts = 0; + int off = *offp; + int plen, ulen; + struct sockaddr_in6 udp_in6; + +#if defined(NFAITH) && 0 < NFAITH + if (m->m_pkthdr.rcvif) { + if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { + /* XXX send icmp6 host/port unreach? */ + m_freem(m); + return IPPROTO_DONE; + } + } +#endif + udpstat.udps_ipackets++; + + IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); + + ip6 = mtod(m, struct ip6_hdr *); + plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6); + uh = (struct udphdr *)((caddr_t)ip6 + off); + ulen = ntohs((u_short)uh->uh_ulen); + + if (plen != ulen) { + udpstat.udps_badlen++; + goto bad; + } + + /* + * Checksum extended UDP header and data. + */ + if (uh->uh_sum == 0) + udpstat.udps_nosum++; + else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) { + udpstat.udps_badsum++; + goto bad; + } + + if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { + struct inpcb *last; + + /* + * Deliver a multicast datagram to all sockets + * for which the local and remote addresses and ports match + * those of the incoming datagram. This allows more than + * one process to receive multicasts on the same port. + * (This really ought to be done for unicast datagrams as + * well, but that would cause problems with existing + * applications that open both address-specific sockets and + * a wildcard socket listening to the same port -- they would + * end up receiving duplicates of every unicast datagram. + * Those applications open the multiple sockets to overcome an + * inadequacy of the UDP socket interface, but for backwards + * compatibility we avoid the problem here rather than + * fixing the interface. Maybe 4.5BSD will remedy this?) + */ + + /* + * In a case that laddr should be set to the link-local + * address (this happens in RIPng), the multicast address + * specified in the received packet does not match with + * laddr. To cure this situation, the matching is relaxed + * if the receiving interface is the same as one specified + * in the socket and if the destination multicast address + * matches one of the multicast groups specified in the socket. + */ + + /* + * Construct sockaddr format source address. + */ + init_sin6(&udp_in6, m); /* general init */ + udp_in6.sin6_port = uh->uh_sport; + /* + * KAME note: usually we drop udphdr from mbuf here. + * We need udphdr for IPsec processing so we do that later. + */ + + /* + * Locate pcb(s) for datagram. + * (Algorithm copied from raw_intr().) + */ + last = NULL; + LIST_FOREACH(in6p, &udb, inp_list) { + if ((in6p->inp_vflag & INP_IPV6) == NULL) + continue; + if (in6p->in6p_lport != uh->uh_dport) + continue; + if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) { + if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, + &ip6->ip6_dst) && + !in6_mcmatch(in6p, &ip6->ip6_dst, + m->m_pkthdr.rcvif)) + continue; + } + if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { + if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, + &ip6->ip6_src) || + in6p->in6p_fport != uh->uh_sport) + continue; + } + + if (last != NULL) { + struct mbuf *n; + +#ifdef IPSEC + /* + * Check AH/ESP integrity. + */ + if (last != NULL && + ipsec6_in_reject_so(m, last->inp_socket)) { + ipsec6stat.in_polvio++; + /* do not inject data into pcb */ + } else +#endif /*IPSEC*/ + if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { + /* + * KAME NOTE: do not + * m_copy(m, offset, ...) above. + * sbappendaddr() expects M_PKTHDR, + * and m_copy() will copy M_PKTHDR + * only if offset is 0. + */ + if (last->in6p_flags & IN6P_CONTROLOPTS + || last->in6p_socket->so_options & SO_TIMESTAMP) + ip6_savecontrol(last, &opts, + ip6, n); + m_adj(n, off + sizeof(struct udphdr)); + if (sbappendaddr(&last->in6p_socket->so_rcv, + (struct sockaddr *)&udp_in6, + n, opts) == 0) { + m_freem(n); + if (opts) + m_freem(opts); + udpstat.udps_fullsock++; + } else + sorwakeup(last->in6p_socket); + opts = 0; + } + } + last = in6p; + /* + * Don't look for additional matches if this one does + * not have either the SO_REUSEPORT or SO_REUSEADDR + * socket options set. This heuristic avoids searching + * through all pcbs in the common case of a non-shared + * port. It assumes that an application will never + * clear these options after setting them. + */ + if ((last->in6p_socket->so_options & + (SO_REUSEPORT|SO_REUSEADDR)) == 0) + break; + } + + if (last == NULL) { + /* + * No matching pcb found; discard datagram. + * (No need to send an ICMP Port Unreachable + * for a broadcast or multicast datgram.) + */ + udpstat.udps_noport++; + udpstat.udps_noportmcast++; + goto bad; + } +#ifdef IPSEC + /* + * Check AH/ESP integrity. + */ + if (last != NULL && ipsec6_in_reject_so(m, last->inp_socket)) { + ipsec6stat.in_polvio++; + goto bad; + } +#endif /*IPSEC*/ + if (last->in6p_flags & IN6P_CONTROLOPTS + || last->in6p_socket->so_options & SO_TIMESTAMP) + ip6_savecontrol(last, &opts, ip6, m); + + m_adj(m, off + sizeof(struct udphdr)); + if (sbappendaddr(&last->in6p_socket->so_rcv, + (struct sockaddr *)&udp_in6, + m, opts) == 0) { + udpstat.udps_fullsock++; + goto bad; + } + sorwakeup(last->in6p_socket); + return IPPROTO_DONE; + } + /* + * Locate pcb for datagram. + */ + in6p = in6_pcblookup_hash(&udbinfo, &ip6->ip6_src, uh->uh_sport, + &ip6->ip6_dst, uh->uh_dport, 1, + m->m_pkthdr.rcvif); + if (in6p == 0) { + if (log_in_vain) { + char buf[INET6_ADDRSTRLEN]; + + strcpy(buf, ip6_sprintf(&ip6->ip6_dst)); + log(LOG_INFO, + "Connection attempt to UDP %s:%d from %s:%d\n", + buf, ntohs(uh->uh_dport), + ip6_sprintf(&ip6->ip6_src), ntohs(uh->uh_sport)); + } + udpstat.udps_noport++; + if (m->m_flags & M_MCAST) { + printf("UDP6: M_MCAST is set in a unicast packet.\n"); + udpstat.udps_noportmcast++; + goto bad; + } + icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); + return IPPROTO_DONE; + } +#ifdef IPSEC + /* + * Check AH/ESP integrity. + */ + if (in6p != NULL && ipsec6_in_reject_so(m, in6p->in6p_socket)) { + ipsec6stat.in_polvio++; + goto bad; + } +#endif /*IPSEC*/ + + /* + * Construct sockaddr format source address. + * Stuff source address and datagram in user buffer. + */ + init_sin6(&udp_in6, m); /* general init */ + udp_in6.sin6_port = uh->uh_sport; + if (in6p->in6p_flags & IN6P_CONTROLOPTS + || in6p->in6p_socket->so_options & SO_TIMESTAMP) + ip6_savecontrol(in6p, &opts, ip6, m); + m_adj(m, off + sizeof(struct udphdr)); + if (sbappendaddr(&in6p->in6p_socket->so_rcv, + (struct sockaddr *)&udp_in6, + m, opts) == 0) { + udpstat.udps_fullsock++; + goto bad; + } + sorwakeup(in6p->in6p_socket); + return IPPROTO_DONE; +bad: + if (m) + m_freem(m); + if (opts) + m_freem(opts); + return IPPROTO_DONE; +} + +void +udp6_ctlinput(cmd, sa, d) + int cmd; + struct sockaddr *sa; + void *d; +{ + register struct udphdr *uhp; + struct udphdr uh; + struct sockaddr_in6 sa6; + struct ip6_hdr *ip6; + struct mbuf *m; + int off; + + if (sa->sa_family != AF_INET6 || + sa->sa_len != sizeof(struct sockaddr_in6)) + return; + + if (!PRC_IS_REDIRECT(cmd) && + ((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0)) + return; + + /* if the parameter is from icmp6, decode it. */ + if (d != NULL) { + struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d; + m = ip6cp->ip6c_m; + ip6 = ip6cp->ip6c_ip6; + off = ip6cp->ip6c_off; + } else { + m = NULL; + ip6 = NULL; + } + + /* translate addresses into internal form */ + sa6 = *(struct sockaddr_in6 *)sa; + if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr)) + sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index); + + if (ip6) { + /* + * XXX: We assume that when IPV6 is non NULL, + * M and OFF are valid. + */ + struct in6_addr s; + + /* translate addresses into internal form */ + memcpy(&s, &ip6->ip6_src, sizeof(s)); + if (IN6_IS_ADDR_LINKLOCAL(&s)) + s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index); + + if (m->m_len < off + sizeof(uh)) { + /* + * this should be rare case, + * so we compromise on this copy... + */ + m_copydata(m, off, sizeof(uh), (caddr_t)&uh); + uhp = &uh; + } else + uhp = (struct udphdr *)(mtod(m, caddr_t) + off); + (void) in6_pcbnotify(&udb, (struct sockaddr *)&sa6, + uhp->uh_dport, &s, + uhp->uh_sport, cmd, udp_notify); + } else + (void) in6_pcbnotify(&udb, (struct sockaddr *)&sa6, 0, + &zeroin6_addr, 0, cmd, udp_notify); +} + +static int +udp6_getcred SYSCTL_HANDLER_ARGS +{ + struct sockaddr_in6 addrs[2]; + struct inpcb *inp; + int error, s; + + error = suser(req->p); + if (error) + return (error); + error = SYSCTL_IN(req, addrs, sizeof(addrs)); + if (error) + return (error); + s = splnet(); + inp = in6_pcblookup_hash(&udbinfo, &addrs[1].sin6_addr, + addrs[1].sin6_port, + &addrs[0].sin6_addr, addrs[0].sin6_port, + 1, NULL); + if (!inp || !inp->inp_socket || !inp->inp_socket->so_cred) { + error = ENOENT; + goto out; + } + error = SYSCTL_OUT(req, inp->inp_socket->so_cred, + sizeof(struct ucred)); + +out: + splx(s); + return (error); +} + +SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW, + 0, 0, + udp6_getcred, "S,ucred", "Get the ucred of a UDP6 connection"); + +int +udp6_output(in6p, m, addr6, control, p) + register struct inpcb *in6p; + register struct mbuf *m; + struct sockaddr *addr6; + struct mbuf *control; + struct proc *p; +{ + register int ulen = m->m_pkthdr.len; + int plen = sizeof(struct udphdr) + ulen; + struct ip6_hdr *ip6; + struct udphdr *udp6; + struct in6_addr laddr6; + int s = 0, error = 0; + struct ip6_pktopts opt, *stickyopt = in6p->in6p_outputopts; + + if (control) { + if ((error = ip6_setpktoptions(control, &opt, suser(p))) != 0) + goto release; + in6p->in6p_outputopts = &opt; + } + + if (addr6) { + laddr6 = in6p->in6p_laddr; + if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { + error = EISCONN; + goto release; + } + /* + * Must block input while temporarily connected. + */ + s = splnet(); + /* + * XXX: the user might want to overwrite the local address + * via an ancillary data. + */ + bzero(&in6p->in6p_laddr, sizeof(struct in6_addr)); + error = in6_pcbconnect(in6p, addr6, p); + if (error) { + splx(s); + goto release; + } + } else { + if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { + error = ENOTCONN; + goto release; + } + } + /* + * Calculate data length and get a mbuf + * for UDP and IP6 headers. + */ + M_PREPEND(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr), + M_DONTWAIT); + if (m == 0) { + error = ENOBUFS; + if (addr6) + splx(s); + goto release; + } + + /* + * Stuff checksum and output datagram. + */ + ip6 = mtod(m, struct ip6_hdr *); + ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK; + ip6->ip6_vfc = IPV6_VERSION; + /* ip6_plen will be filled in ip6_output. */ + ip6->ip6_nxt = IPPROTO_UDP; + ip6->ip6_hlim = in6_selecthlim(in6p, + in6p->in6p_route.ro_rt ? + in6p->in6p_route.ro_rt->rt_ifp : + NULL); + ip6->ip6_src = in6p->in6p_laddr; + ip6->ip6_dst = in6p->in6p_faddr; + + udp6 = (struct udphdr *)(ip6 + 1); + udp6->uh_sport = in6p->in6p_lport; + udp6->uh_dport = in6p->in6p_fport; + udp6->uh_ulen = htons((u_short)plen); + udp6->uh_sum = 0; + + if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP, + sizeof(struct ip6_hdr), plen)) == 0) { + udp6->uh_sum = 0xffff; + } + + udpstat.udps_opackets++; + +#ifdef IPSEC + m->m_pkthdr.rcvif = (struct ifnet *)in6p->in6p_socket; +#endif /*IPSEC*/ + error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route, + 0, in6p->in6p_moptions, NULL); + + if (addr6) { + in6_pcbdisconnect(in6p); + in6p->in6p_laddr = laddr6; + splx(s); + } + goto releaseopt; + +release: + m_freem(m); + +releaseopt: + if (control) { + in6p->in6p_outputopts = stickyopt; + m_freem(control); + } + return(error); +} + +static int +udp6_abort(struct socket *so) +{ + struct inpcb *inp; + int s; + + inp = sotoinpcb(so); + if (inp == 0) + return EINVAL; /* ??? possible? panic instead? */ + soisdisconnected(so); + s = splnet(); + in6_pcbdetach(inp); + splx(s); + return 0; +} + +static int +udp6_attach(struct socket *so, int proto, struct proc *p) +{ + struct inpcb *inp; + int s, error; + + inp = sotoinpcb(so); + if (inp != 0) + return EINVAL; + + if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { + error = soreserve(so, udp_sendspace, udp_recvspace); + if (error) + return error; + } + s = splnet(); + error = in_pcballoc(so, &udbinfo, p); + splx(s); + if (error) + return error; + inp = (struct inpcb *)so->so_pcb; + inp->inp_vflag |= INP_IPV6; + inp->in6p_hops = -1; /* use kernel default */ + inp->in6p_cksum = -1; /* just to be sure */ +#ifdef IPSEC + error = ipsec_init_policy(so, &inp->in6p_sp); + if (error != 0) { + in6_pcbdetach(inp); + return (error); + } +#endif /*IPSEC*/ + return 0; +} + +static int +udp6_bind(struct socket *so, struct sockaddr *nam, struct proc *p) +{ + struct inpcb *inp; + int s, error; + + inp = sotoinpcb(so); + if (inp == 0) + return EINVAL; + + inp->inp_vflag &= ~INP_IPV4; + inp->inp_vflag |= INP_IPV6; + if (ip6_mapped_addr_on && (inp->inp_flags & IN6P_BINDV6ONLY) == NULL) { + struct sockaddr_in6 *sin6_p; + + sin6_p = (struct sockaddr_in6 *)nam; + + if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) + inp->inp_vflag |= INP_IPV4; + else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) { + struct sockaddr_in sin; + + in6_sin6_2_sin(&sin, sin6_p); + inp->inp_vflag |= INP_IPV4; + inp->inp_vflag &= ~INP_IPV6; + s = splnet(); + error = in_pcbbind(inp, (struct sockaddr *)&sin, p); + splx(s); + return error; + } + } + + s = splnet(); + error = in6_pcbbind(inp, nam, p); + splx(s); + return error; +} + +static int +udp6_connect(struct socket *so, struct sockaddr *nam, struct proc *p) +{ + struct inpcb *inp; + int s, error; + + inp = sotoinpcb(so); + if (inp == 0) + return EINVAL; + + if (ip6_mapped_addr_on) { + struct sockaddr_in6 *sin6_p; + + sin6_p = (struct sockaddr_in6 *)nam; + if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) { + struct sockaddr_in sin; + + if (inp->inp_faddr.s_addr != INADDR_ANY) + return EISCONN; + in6_sin6_2_sin(&sin, sin6_p); + s = splnet(); + error = in_pcbconnect(inp, (struct sockaddr *)&sin, p); + splx(s); + if (error == NULL) { + inp->inp_vflag |= INP_IPV4; + inp->inp_vflag &= ~INP_IPV6; + soisconnected(so); + } + return error; + } + } + + if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) + return EISCONN; + s = splnet(); + error = in6_pcbconnect(inp, nam, p); + if (ip6_auto_flowlabel) { + inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; + inp->in6p_flowinfo |= + (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK); + } + splx(s); + if (error == NULL) { + if (ip6_mapped_addr_on) { /* should be non mapped addr */ + inp->inp_vflag &= ~INP_IPV4; + inp->inp_vflag |= INP_IPV6; + } + soisconnected(so); + } + return error; +} + +static int +udp6_detach(struct socket *so) +{ + struct inpcb *inp; + int s; + + inp = sotoinpcb(so); + if (inp == 0) + return EINVAL; + s = splnet(); + in6_pcbdetach(inp); + splx(s); + return 0; +} + +static int +udp6_disconnect(struct socket *so) +{ + struct inpcb *inp; + int s; + + inp = sotoinpcb(so); + if (inp == 0) + return EINVAL; + + if (inp->inp_vflag & INP_IPV4) { + struct pr_usrreqs *pru; + + pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; + return ((*pru->pru_disconnect)(so)); + } + + if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) + return ENOTCONN; + + s = splnet(); + in6_pcbdisconnect(inp); + inp->in6p_laddr = in6addr_any; + splx(s); + so->so_state &= ~SS_ISCONNECTED; /* XXX */ + return 0; +} + +static int +udp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, + struct mbuf *control, struct proc *p) +{ + struct inpcb *inp; + + inp = sotoinpcb(so); + if (inp == 0) { + m_freem(m); + return EINVAL; + } + + if (ip6_mapped_addr_on) { + int hasv4addr; + struct sockaddr_in6 *sin6 = 0; + + if (addr == 0) + hasv4addr = (inp->inp_vflag & INP_IPV4); + else { + sin6 = (struct sockaddr_in6 *)addr; + hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) + ? 1 : 0; + } + if (hasv4addr) { + struct pr_usrreqs *pru; + int error; + + if (sin6) + in6_sin6_2_sin_in_sock(addr); + pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; + error = ((*pru->pru_send)(so, flags, m, addr, control, + p)); + /* addr will just be freed in sendit(). */ + return error; + } + } + + return udp6_output(inp, m, addr, control, p); +} + +struct pr_usrreqs udp6_usrreqs = { + udp6_abort, pru_accept_notsupp, udp6_attach, udp6_bind, udp6_connect, + pru_connect2_notsupp, in6_control, udp6_detach, udp6_disconnect, + pru_listen_notsupp, in6_mapped_peeraddr, pru_rcvd_notsupp, + pru_rcvoob_notsupp, udp6_send, pru_sense_null, udp_shutdown, + in6_mapped_sockaddr, sosend, soreceive, sopoll +}; diff --git a/sys/netinet6/udp6_var.h b/sys/netinet6/udp6_var.h index b95bc78..e0ade7a 100644 --- a/sys/netinet6/udp6_var.h +++ b/sys/netinet6/udp6_var.h @@ -68,6 +68,8 @@ #define _NETINET6_UDP6_VAR_H_ #ifdef KERNEL +SYSCTL_DECL(_net_inet6_udp6); + extern struct pr_usrreqs udp6_usrreqs; void udp6_ctlinput __P((int, struct sockaddr *, void *)); |