summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorshin <shin@FreeBSD.org>1999-12-07 17:39:16 +0000
committershin <shin@FreeBSD.org>1999-12-07 17:39:16 +0000
commit70f0bdf6818a73c858bc47a23afc1e9d7c56d716 (patch)
tree446280db4239de7d7d9030c47d2c30515a265a54 /sys/netinet6
parent7bdf4b7db0db632bec3b1040d83cdfbdb35e59cd (diff)
downloadFreeBSD-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.c14
-rw-r--r--sys/netinet6/icmp6.h3
-rw-r--r--sys/netinet6/in6.c31
-rw-r--r--sys/netinet6/in6.h66
-rw-r--r--sys/netinet6/in6_gif.c263
-rw-r--r--sys/netinet6/in6_gif.h40
-rw-r--r--sys/netinet6/in6_ifattach.c10
-rw-r--r--sys/netinet6/in6_pcb.c13
-rw-r--r--sys/netinet6/in6_prefix.c21
-rw-r--r--sys/netinet6/in6_proto.c24
-rw-r--r--sys/netinet6/in6_var.h11
-rw-r--r--sys/netinet6/ip6_forward.c6
-rw-r--r--sys/netinet6/ip6_input.c10
-rw-r--r--sys/netinet6/ip6_output.c16
-rw-r--r--sys/netinet6/mld6.c2
-rw-r--r--sys/netinet6/nd6.c40
-rw-r--r--sys/netinet6/nd6.h4
-rw-r--r--sys/netinet6/nd6_nbr.c4
-rw-r--r--sys/netinet6/nd6_rtr.c40
-rw-r--r--sys/netinet6/raw_ip6.c6
-rw-r--r--sys/netinet6/udp6_usrreq.c835
-rw-r--r--sys/netinet6/udp6_var.h2
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 *));
OpenPOWER on IntegriCloud