summaryrefslogtreecommitdiffstats
path: root/sys
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
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')
-rw-r--r--sys/conf/NOTES9
-rw-r--r--sys/conf/files43
-rw-r--r--sys/conf/options2
-rw-r--r--sys/i386/conf/LINT9
-rw-r--r--sys/i386/conf/NOTES9
-rw-r--r--sys/modules/if_disc/Makefile5
-rw-r--r--sys/net/if.c2
-rw-r--r--sys/net/if_atmsubr.c3
-rw-r--r--sys/net/if_disc.c5
-rw-r--r--sys/net/if_ethersubr.c1
-rw-r--r--sys/net/if_faith.c97
-rw-r--r--sys/net/if_fddisubr.c24
-rw-r--r--sys/net/if_gif.c468
-rw-r--r--sys/net/if_gif.h3
-rw-r--r--sys/net/if_loop.c9
-rw-r--r--sys/net/if_spppsubr.c19
-rw-r--r--sys/netinet/if_atm.c3
-rw-r--r--sys/netinet/in_gif.c311
-rw-r--r--sys/netinet/in_gif.h42
-rw-r--r--sys/netinet/in_pcb.c114
-rw-r--r--sys/netinet/in_pcb.h3
-rw-r--r--sys/netinet/in_proto.c22
-rw-r--r--sys/netinet/ip_fw.c12
-rw-r--r--sys/netinet/tcp_input.c9
-rw-r--r--sys/netinet/tcp_reass.c9
-rw-r--r--sys/netinet/tcp_subr.c4
-rw-r--r--sys/netinet/tcp_timewait.c4
-rw-r--r--sys/netinet/tcp_usrreq.c6
-rw-r--r--sys/netinet/udp_usrreq.c232
-rw-r--r--sys/netinet/udp_var.h2
-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
52 files changed, 2628 insertions, 314 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index db2f541..8ec43fc 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -437,6 +437,11 @@ device mn0 # Munich32x/Falc54 Nx64kbit/sec cards.
# included for testing purposes.
# The `tun' pseudo-device implements (user-)ppp and nos-tun
# The `streams' pseudo-device implements SysVR4 STREAMS emulation.
+# The `gif' pseudo-device implements IPv6 over IP4 tunneling,
+# IPv4 over IPv6 tunneling, IPv4 over IPv4 tunneling and
+# IPv6 over IPv6 tunneling.
+# The `faith' pseudo-device captures packets sent to it and diverts them
+# to the IPv4/IPv6 translation daemon.
#
# The PPP_BSDCOMP option enables support for compress(1) style entire
# packet compression, the PPP_DEFLATE is for zlib/gzip style compression.
@@ -459,6 +464,10 @@ options PPP_BSDCOMP #PPP BSD-compress support
options PPP_DEFLATE #PPP zlib/deflate/gzip support
options PPP_FILTER #enable bpf filtering (needs bpf)
+# for IPv6
+pseudo-device gif 4 #IPv6 and IPv4 tunneling
+pseudo-device faith 1 #for IPv6 and IPv4 translation
+
#
# Internet family options:
#
diff --git a/sys/conf/files b/sys/conf/files
index dc919b1..62700b5 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -465,7 +465,9 @@ net/if_atmsubr.c optional atm
net/if_disc.c optional disc
net/if_ethersubr.c optional ether
net/if_iso88025subr.c optional token
+net/if_faith.c optional faith
net/if_fddisubr.c optional fddi
+net/if_gif.c optional gif
net/if_loop.c optional loop
net/if_media.c standard
net/if_mib.c standard
@@ -474,6 +476,7 @@ net/if_sl.c optional sl
net/if_spppsubr.c optional sppp
net/if_tun.c optional tun
net/if_vlan.c optional vlan
+net/net_osdep.c standard
net/ppp_deflate.c optional ppp_deflate
net/ppp_tty.c optional ppp
net/radix.c standard
@@ -484,7 +487,6 @@ net/rtsock.c standard
net/slcompress.c optional ppp
net/slcompress.c optional sl
net/zlib.c optional ppp_deflate
-net/net_osdep.c standard
netatalk/aarp.c optional netatalk
netatalk/at_control.c optional netatalk
netatalk/at_proto.c optional netatalk
@@ -595,6 +597,7 @@ netgraph/ng_vjc.c optional netgraph_vjc
net/slcompress.c optional netgraph_vjc
netinet/if_atm.c optional atm
netinet/if_ether.c optional ether
+netinet/in_gif.c optional gif inet
netinet/igmp.c optional inet
netinet/in.c optional inet
#netinet/in_hostcache.c optional inet
@@ -617,34 +620,36 @@ netinet/tcp_subr.c optional inet
netinet/tcp_timer.c optional inet
netinet/tcp_usrreq.c optional inet
netinet/udp_usrreq.c optional inet
-netinet6/in6.c optional inet6
-netinet6/in6_ifattach.c optional inet6
-netinet6/in6_cksum.c optional inet6
-netinet6/in6_pcb.c optional inet6
-netinet6/in6_proto.c optional inet6
-netinet6/in6_rmx.c optional inet6
-netinet6/in6_prefix.c optional inet6
+netinet/ip_fil.c optional ipfilter inet
+netinet/fil.c optional ipfilter inet
+netinet/ip_nat.c optional ipfilter inet
+netinet/ip_frag.c optional ipfilter inet
+netinet/ip_state.c optional ipfilter inet
+netinet/ip_auth.c optional ipfilter inet
+netinet/ip_proxy.c optional ipfilter inet
+netinet/ip_log.c optional ipfilter inet
+netinet/mlfk_ipl.c optional ipfilter inet
netinet6/dest6.c optional inet6
netinet6/frag6.c optional inet6
netinet6/icmp6.c optional inet6
-netinet6/ip6_input.c optional inet6
+netinet6/in6.c optional inet6
+netinet6/in6_cksum.c optional inet6
+netinet6/in6_gif.c optional gif inet6
netinet6/ip6_forward.c optional inet6
+netinet6/in6_ifattach.c optional inet6
+netinet6/ip6_input.c optional inet6
netinet6/ip6_output.c optional inet6
-netinet6/route6.c optional inet6
+netinet6/in6_pcb.c optional inet6
+netinet6/in6_prefix.c optional inet6
+netinet6/in6_proto.c optional inet6
+netinet6/in6_rmx.c optional inet6
netinet6/mld6.c optional inet6
netinet6/nd6.c optional inet6
netinet6/nd6_nbr.c optional inet6
netinet6/nd6_rtr.c optional inet6
netinet6/raw_ip6.c optional inet6
-netinet/ip_fil.c optional ipfilter inet
-netinet/fil.c optional ipfilter inet
-netinet/ip_nat.c optional ipfilter inet
-netinet/ip_frag.c optional ipfilter inet
-netinet/ip_state.c optional ipfilter inet
-netinet/ip_auth.c optional ipfilter inet
-netinet/ip_proxy.c optional ipfilter inet
-netinet/ip_log.c optional ipfilter inet
-netinet/mlfk_ipl.c optional ipfilter inet
+netinet6/route6.c optional inet6
+netinet6/udp6_usrreq.c optional inet6
netipx/ipx.c optional ipx
netipx/ipx_cksum.c optional ipx
netipx/ipx_input.c optional ipx
diff --git a/sys/conf/options b/sys/conf/options
index ed76e00..3c7558b 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -217,7 +217,7 @@ BOOTP_WIRED_TO opt_bootp.h
BRIDGE opt_bdg.h
MROUTING opt_mrouting.h
INET opt_inet.h
-INET6 opt_inet.h
+INET6 opt_inet6.h
IPDIVERT
DUMMYNET opt_ipdn.h
IPFILTER opt_ipfilter.h
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index db2f541..8ec43fc 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -437,6 +437,11 @@ device mn0 # Munich32x/Falc54 Nx64kbit/sec cards.
# included for testing purposes.
# The `tun' pseudo-device implements (user-)ppp and nos-tun
# The `streams' pseudo-device implements SysVR4 STREAMS emulation.
+# The `gif' pseudo-device implements IPv6 over IP4 tunneling,
+# IPv4 over IPv6 tunneling, IPv4 over IPv4 tunneling and
+# IPv6 over IPv6 tunneling.
+# The `faith' pseudo-device captures packets sent to it and diverts them
+# to the IPv4/IPv6 translation daemon.
#
# The PPP_BSDCOMP option enables support for compress(1) style entire
# packet compression, the PPP_DEFLATE is for zlib/gzip style compression.
@@ -459,6 +464,10 @@ options PPP_BSDCOMP #PPP BSD-compress support
options PPP_DEFLATE #PPP zlib/deflate/gzip support
options PPP_FILTER #enable bpf filtering (needs bpf)
+# for IPv6
+pseudo-device gif 4 #IPv6 and IPv4 tunneling
+pseudo-device faith 1 #for IPv6 and IPv4 translation
+
#
# Internet family options:
#
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index db2f541..8ec43fc 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -437,6 +437,11 @@ device mn0 # Munich32x/Falc54 Nx64kbit/sec cards.
# included for testing purposes.
# The `tun' pseudo-device implements (user-)ppp and nos-tun
# The `streams' pseudo-device implements SysVR4 STREAMS emulation.
+# The `gif' pseudo-device implements IPv6 over IP4 tunneling,
+# IPv4 over IPv6 tunneling, IPv4 over IPv4 tunneling and
+# IPv6 over IPv6 tunneling.
+# The `faith' pseudo-device captures packets sent to it and diverts them
+# to the IPv4/IPv6 translation daemon.
#
# The PPP_BSDCOMP option enables support for compress(1) style entire
# packet compression, the PPP_DEFLATE is for zlib/gzip style compression.
@@ -459,6 +464,10 @@ options PPP_BSDCOMP #PPP BSD-compress support
options PPP_DEFLATE #PPP zlib/deflate/gzip support
options PPP_FILTER #enable bpf filtering (needs bpf)
+# for IPv6
+pseudo-device gif 4 #IPv6 and IPv4 tunneling
+pseudo-device faith 1 #for IPv6 and IPv4 translation
+
#
# Internet family options:
#
diff --git a/sys/modules/if_disc/Makefile b/sys/modules/if_disc/Makefile
index 63b8592..e33555d 100644
--- a/sys/modules/if_disc/Makefile
+++ b/sys/modules/if_disc/Makefile
@@ -2,7 +2,7 @@
.PATH: ${.CURDIR}/../../net
KMOD= if_disc
-SRCS= if_disc.c opt_inet.h
+SRCS= if_disc.c opt_inet.h opt_inet6.h
NOMAN=
NBPF?= 1
@@ -12,4 +12,7 @@ CFLAGS+= ${PROTOS}
opt_inet.h:
echo "#define INET 1" > opt_inet.h
+#opt_inet6.h:
+# echo "#define INET6 1" > opt_inet6.h
+
.include <bsd.kmod.mk>
diff --git a/sys/net/if.c b/sys/net/if.c
index 7c560bc..c0ba5ee 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -35,7 +35,7 @@
*/
#include "opt_compat.h"
-#include "opt_inet.h"
+#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/malloc.h>
diff --git a/sys/net/if_atmsubr.c b/sys/net/if_atmsubr.c
index 66cd09d..0a357a6 100644
--- a/sys/net/if_atmsubr.c
+++ b/sys/net/if_atmsubr.c
@@ -30,6 +30,8 @@
* 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$
*/
/*
@@ -37,6 +39,7 @@
*/
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_natm.h"
#include <sys/param.h>
diff --git a/sys/net/if_disc.c b/sys/net/if_disc.c
index b90a658..66bd5f8 100644
--- a/sys/net/if_disc.c
+++ b/sys/net/if_disc.c
@@ -52,6 +52,7 @@
#include <net/bpf.h>
#include "opt_inet.h"
+#include "opt_inet6.h"
#ifdef TINY_DSMTU
#define DSMTU (1024+512)
@@ -180,6 +181,10 @@ discioctl(ifp, cmd, data)
case AF_INET:
break;
#endif
+#ifdef INET6
+ case AF_INET6:
+ break;
+#endif
default:
error = EAFNOSUPPORT;
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index ec0f5cf..bf11e9d 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -36,6 +36,7 @@
#include "opt_atalk.h"
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_ipx.h"
#include "opt_bdg.h"
#include "opt_netgraph.h"
diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c
new file mode 100644
index 0000000..0e21af7
--- /dev/null
+++ b/sys/net/if_faith.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1982, 1986, 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.
+ *
+ * $FreeBSD$
+ */
+/*
+ * derived from
+ * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
+ * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
+ */
+
+/*
+ * Loopback interface driver for protocol testing and timing.
+ */
+
+#include "faith.h"
+#if NFAITH > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/bpf.h>
+
+extern int loioctl __P((struct ifnet *, u_long, caddr_t));
+extern int looutput __P((struct ifnet *ifp,
+ struct mbuf *m, struct sockaddr *dst, struct rtentry *rt));
+
+void faithattach __P((void *));
+PSEUDO_SET(faithattach, if_faith);
+static struct ifnet faithif[NFAITH];
+
+#define FAITHMTU 1500
+
+/* ARGSUSED */
+void
+faithattach(faith)
+ void *faith;
+{
+ register struct ifnet *ifp;
+ register int i;
+
+ for (i = 0; i < NFAITH; i++) {
+ ifp = &faithif[i];
+ bzero(ifp, sizeof(faithif[i]));
+ ifp->if_name = "faith";
+ ifp->if_unit = i;
+ ifp->if_mtu = FAITHMTU;
+ /* Change to BROADCAST experimentaly to announce its prefix. */
+ ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST;
+ ifp->if_ioctl = loioctl;
+ ifp->if_output = looutput;
+ ifp->if_type = IFT_FAITH;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ ifp->if_hdrlen = 0;
+ ifp->if_addrlen = 0;
+ if_attach(ifp);
+ bpfattach(ifp, DLT_NULL, sizeof(u_int));
+ }
+}
+#endif /* NFAITH > 0 */
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c
index eedc822..0b39131 100644
--- a/sys/net/if_fddisubr.c
+++ b/sys/net/if_fddisubr.c
@@ -38,6 +38,7 @@
#include "opt_atalk.h"
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_ipx.h"
#include <sys/param.h>
@@ -52,11 +53,14 @@
#include <net/if_dl.h>
#include <net/if_types.h>
-#ifdef INET
+#if defined(INET) || defined(INET6)
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
#endif
+#ifdef INET6
+#include <netinet6/nd6.h>
+#endif
#if defined(__FreeBSD__)
#include <netinet/if_fddi.h>
#else
@@ -186,6 +190,16 @@ fddi_output(ifp, m0, dst, rt0)
break;
}
#endif
+#ifdef INET6
+ case AF_INET6:
+ if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) {
+ /* this must be impossible, so we bark */
+ printf("nd6_storelladdr failed\n");
+ return(0);
+ }
+ type = htons(ETHERTYPE_IPV6);
+ break;
+#endif
#ifdef IPX
case AF_IPX:
type = htons(ETHERTYPE_IPX);
@@ -481,7 +495,7 @@ fddi_input(ifp, fh, m)
l = mtod(m, struct llc *);
switch (l->llc_dsap) {
-#if defined(INET) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
+#if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
case LLC_SNAP_LSAP:
{
u_int16_t type;
@@ -528,6 +542,12 @@ fddi_input(ifp, fh, m)
return;
#endif
#endif
+#ifdef INET6
+ case ETHERTYPE_IPV6:
+ schednetisr(NETISR_IPV6);
+ inq = &ip6intrq;
+ break;
+#endif
#ifdef IPX
case ETHERTYPE_IPX:
schednetisr(NETISR_IPX);
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
new file mode 100644
index 0000000..3eaa703
--- /dev/null
+++ b/sys/net/if_gif.c
@@ -0,0 +1,468 @@
+/*
+ * 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$
+ */
+
+/*
+ * gif.c
+ */
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/syslog.h>
+#include <machine/cpu.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/bpf.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/in_gif.h>
+#endif /* INET */
+
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/in6_var.h>
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/in6_gif.h>
+#endif /* INET6 */
+
+#include <net/if_gif.h>
+
+#include "gif.h"
+
+#include <net/net_osdep.h>
+
+#if NGIF > 0
+
+void gifattach __P((void *));
+
+/*
+ * gif global variable definitions
+ */
+int ngif = NGIF; /* number of interfaces */
+struct gif_softc *gif = 0;
+
+void
+gifattach(dummy)
+ void *dummy;
+{
+ register struct gif_softc *sc;
+ register int i;
+
+ gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT);
+ bzero(sc, ngif * sizeof(struct gif_softc));
+ for (i = 0; i < ngif; sc++, i++) {
+ sc->gif_if.if_name = "gif";
+ sc->gif_if.if_unit = i;
+ sc->gif_if.if_mtu = GIF_MTU;
+ sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
+ sc->gif_if.if_ioctl = gif_ioctl;
+ sc->gif_if.if_output = gif_output;
+ sc->gif_if.if_type = IFT_GIF;
+ sc->gif_if.if_snd.ifq_maxlen = ifqmaxlen;
+ if_attach(&sc->gif_if);
+ bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
+ }
+}
+
+PSEUDO_SET(gifattach, if_gif);
+
+int
+gif_output(ifp, m, dst, rt)
+ struct ifnet *ifp;
+ struct mbuf *m;
+ struct sockaddr *dst;
+ struct rtentry *rt; /* added in net2 */
+{
+ register struct gif_softc *sc = (struct gif_softc*)ifp;
+ int error = 0;
+ static int called = 0; /* XXX: MUTEX */
+ int calllimit = 10; /* XXX: adhoc */
+
+ /*
+ * gif may cause infinite recursion calls when misconfigured.
+ * We'll prevent this by introducing upper limit.
+ * XXX: this mechanism may introduce another problem about
+ * mutual exclusion of the variable CALLED, especially if we
+ * use kernel thread.
+ */
+ if (++called >= calllimit) {
+ log(LOG_NOTICE,
+ "gif_output: recursively called too many times(%d)\n",
+ called);
+ m_freem(m);
+ error = EIO; /* is there better errno? */
+ goto end;
+ }
+ getmicrotime(&ifp->if_lastchange);
+ m->m_flags &= ~(M_BCAST|M_MCAST);
+ if (!(ifp->if_flags & IFF_UP) ||
+ sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
+ m_freem(m);
+ error = ENETDOWN;
+ goto end;
+ }
+
+ if (ifp->if_bpf) {
+ /*
+ * We need to prepend the address family as
+ * a four byte field. Cons up a dummy header
+ * to pacify bpf. This is safe because bpf
+ * will only read from the mbuf (i.e., it won't
+ * try to free it or keep a pointer a to it).
+ */
+ struct mbuf m0;
+ u_int af = dst->sa_family;
+
+ m0.m_next = m;
+ m0.m_len = 4;
+ m0.m_data = (char *)&af;
+
+ bpf_mtap(ifp, &m0);
+ }
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
+
+ switch (sc->gif_psrc->sa_family) {
+#ifdef INET
+ case AF_INET:
+ error = in_gif_output(ifp, dst->sa_family, m, rt);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ error = in6_gif_output(ifp, dst->sa_family, m, rt);
+ break;
+#endif
+ default:
+ m_freem(m);
+ error = ENETDOWN;
+ }
+
+ end:
+ called = 0; /* reset recursion counter */
+ if (error) ifp->if_oerrors++;
+ return error;
+}
+
+void
+gif_input(m, af, gifp)
+ struct mbuf *m;
+ int af;
+ struct ifnet *gifp;
+{
+ int s, isr;
+ register struct ifqueue *ifq = 0;
+
+ if (gifp == NULL) {
+ /* just in case */
+ m_freem(m);
+ return;
+ }
+
+ if (m->m_pkthdr.rcvif)
+ m->m_pkthdr.rcvif = gifp;
+
+ if (gifp->if_bpf) {
+ /*
+ * We need to prepend the address family as
+ * a four byte field. Cons up a dummy header
+ * to pacify bpf. This is safe because bpf
+ * will only read from the mbuf (i.e., it won't
+ * try to free it or keep a pointer a to it).
+ */
+ struct mbuf m0;
+ u_int af = AF_INET6;
+
+ m0.m_next = m;
+ m0.m_len = 4;
+ m0.m_data = (char *)&af;
+
+ bpf_mtap(gifp, &m0);
+ }
+
+ /*
+ * Put the packet to the network layer input queue according to the
+ * specified address family.
+ * Note: older versions of gif_input directly called network layer
+ * input functions, e.g. ip6_input, here. We changed the policy to
+ * prevent too many recursive calls of such input functions, which
+ * might cause kernel panic. But the change may introduce another
+ * problem; if the input queue is full, packets are discarded.
+ * We believed it rarely occurs and changed the policy. If we find
+ * it occurs more times than we thought, we may change the policy
+ * again.
+ */
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ ifq = &ipintrq;
+ isr = NETISR_IP;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ifq = &ip6intrq;
+ isr = NETISR_IPV6;
+ break;
+#endif
+ default:
+ m_freem(m);
+ return;
+ }
+
+ s = splimp();
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq); /* update statistics */
+ m_freem(m);
+ splx(s);
+ return;
+ }
+ IF_ENQUEUE(ifq, m);
+ /* we need schednetisr since the address family may change */
+ schednetisr(isr);
+ gifp->if_ipackets++;
+ gifp->if_ibytes += m->m_pkthdr.len;
+ splx(s);
+
+ return;
+}
+
+
+int
+gif_ioctl(ifp, cmd, data)
+ struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct gif_softc *sc = (struct gif_softc*)ifp;
+ struct ifreq *ifr = (struct ifreq*)data;
+ int error = 0, size;
+ struct sockaddr *sa, *dst, *src;
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ break;
+
+ case SIOCSIFDSTADDR:
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ break;
+
+ case SIOCGIFMTU:
+ break;
+ case SIOCSIFMTU:
+ {
+ u_long mtu;
+ mtu = ifr->ifr_mtu;
+ if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
+ return (EINVAL);
+ }
+ ifp->if_mtu = mtu;
+ }
+ break;
+
+ case SIOCSIFPHYADDR:
+#ifdef INET6
+ case SIOCSIFPHYADDR_IN6:
+#endif /* INET6 */
+ switch (ifr->ifr_addr.sa_family) {
+#ifdef INET
+ case AF_INET:
+ src = (struct sockaddr *)
+ &(((struct in_aliasreq *)data)->ifra_addr);
+ dst = (struct sockaddr *)
+ &(((struct in_aliasreq *)data)->ifra_dstaddr);
+
+ /* only one gif can have dst = INADDR_ANY */
+#define satosaddr(sa) (((struct sockaddr_in *)(sa))->sin_addr.s_addr)
+
+ if (satosaddr(dst) == INADDR_ANY) {
+ int i;
+ struct gif_softc *sc2;
+
+ for (i = 0, sc2 = gif; i < ngif; i++, sc2++) {
+ if (sc2 == sc) continue;
+ if (sc2->gif_pdst &&
+ satosaddr(sc2->gif_pdst)
+ == INADDR_ANY) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ }
+ }
+ size = sizeof(struct sockaddr_in);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ src = (struct sockaddr *)
+ &(((struct in6_aliasreq *)data)->ifra_addr);
+ dst = (struct sockaddr *)
+ &(((struct in6_aliasreq *)data)->ifra_dstaddr);
+
+ /* only one gif can have dst = in6addr_any */
+#define satoin6(sa) (&((struct sockaddr_in6 *)(sa))->sin6_addr)
+
+ if (IN6_IS_ADDR_UNSPECIFIED(satoin6(dst))) {
+ int i;
+ struct gif_softc *sc2;
+
+ for (i = 0, sc2 = gif; i < ngif; i++, sc2++) {
+ if (sc2 == sc) continue;
+ if (sc2->gif_pdst &&
+ IN6_IS_ADDR_UNSPECIFIED(
+ satoin6(sc2->gif_pdst)
+ )) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ }
+ }
+ size = sizeof(struct sockaddr_in6);
+ break;
+#endif /* INET6 */
+ default:
+ error = EPROTOTYPE;
+ goto bad;
+ break;
+ }
+ if (sc->gif_psrc != NULL)
+ free((caddr_t)sc->gif_psrc, M_IFADDR);
+ if (sc->gif_pdst != NULL)
+ free((caddr_t)sc->gif_pdst, M_IFADDR);
+
+ sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
+ bzero((caddr_t)sa, size);
+ bcopy((caddr_t)src, (caddr_t)sa, size);
+ sc->gif_psrc = sa;
+
+ sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
+ bzero((caddr_t)sa, size);
+ bcopy((caddr_t)dst, (caddr_t)sa, size);
+ sc->gif_pdst = sa;
+
+ ifp->if_flags |= (IFF_UP|IFF_RUNNING);
+ if_up(ifp); /* send up RTM_IFINFO */
+
+ break;
+
+ case SIOCGIFPSRCADDR:
+#ifdef INET6
+ case SIOCGIFPSRCADDR_IN6:
+#endif /* INET6 */
+ if (sc->gif_psrc == NULL) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ src = sc->gif_psrc;
+ switch (sc->gif_psrc->sa_family) {
+#ifdef INET
+ case AF_INET:
+ dst = &ifr->ifr_addr;
+ size = sizeof(struct sockaddr_in);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ dst = (struct sockaddr *)
+ &(((struct in6_ifreq *)data)->ifr_addr);
+ size = sizeof(struct sockaddr_in6);
+ break;
+#endif /* INET6 */
+ default:
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ bcopy((caddr_t)src, (caddr_t)dst, size);
+ break;
+
+ case SIOCGIFPDSTADDR:
+#ifdef INET6
+ case SIOCGIFPDSTADDR_IN6:
+#endif /* INET6 */
+ if (sc->gif_pdst == NULL) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ src = sc->gif_pdst;
+ switch (sc->gif_pdst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ dst = &ifr->ifr_addr;
+ size = sizeof(struct sockaddr_in);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ dst = (struct sockaddr *)
+ &(((struct in6_ifreq *)data)->ifr_addr);
+ size = sizeof(struct sockaddr_in6);
+ break;
+#endif /* INET6 */
+ default:
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ bcopy((caddr_t)src, (caddr_t)dst, size);
+ break;
+
+ case SIOCSIFFLAGS:
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ bad:
+ return error;
+}
+#endif /*NGIF > 0*/
diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h
index a402471..cc26938 100644
--- a/sys/net/if_gif.h
+++ b/sys/net/if_gif.h
@@ -36,9 +36,6 @@
#ifndef _NET_IF_GIF_H_
#define _NET_IF_GIF_H_
-#include <netinet/in.h>
-/* xxx sigh, why route have struct route instead of pointer? */
-
struct gif_softc {
struct ifnet gif_if; /* common area */
struct sockaddr *gif_psrc; /* Physical src addr */
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index c57f857..a714bf1 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -42,6 +42,7 @@
#include "opt_atalk.h"
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_ipx.h"
#include <sys/param.h>
@@ -90,13 +91,13 @@
#include <netatalk/at_var.h>
#endif NETATALK
-static int loioctl __P((struct ifnet *, u_long, caddr_t));
+int loioctl __P((struct ifnet *, u_long, caddr_t));
static void lortrequest __P((int, struct rtentry *, struct sockaddr *));
static void loopattach __P((void *));
PSEUDO_SET(loopattach, if_loop);
-static int looutput __P((struct ifnet *ifp,
+int looutput __P((struct ifnet *ifp,
struct mbuf *m, struct sockaddr *dst, struct rtentry *rt));
#ifdef TINY_LOMTU
@@ -131,7 +132,7 @@ loopattach(dummy)
}
}
-static int
+int
looutput(ifp, m, dst, rt)
struct ifnet *ifp;
register struct mbuf *m;
@@ -341,7 +342,7 @@ lortrequest(cmd, rt, sa)
* Process an ioctl request.
*/
/* ARGSUSED */
-static int
+int
loioctl(ifp, cmd, data)
register struct ifnet *ifp;
u_long cmd;
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index 133af2b..e02ef90 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -24,12 +24,14 @@
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_ipx.h"
#endif
#ifdef NetBSD1_3
# if NetBSD1_3 > 6
# include "opt_inet.h"
+# include "opt_inet6.h"
# include "opt_iso.h"
# endif
#endif
@@ -572,6 +574,12 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
inq = &ipintrq;
break;
#endif
+#ifdef INET6
+ case ETHERTYPE_IPV6:
+ schednetisr (NETISR_IPV6);
+ inq = &ip6intrq;
+ break;
+#endif
#ifdef IPX
case ETHERTYPE_IPX:
schednetisr (NETISR_IPX);
@@ -741,6 +749,15 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
}
break;
#endif
+#ifdef INET6
+ case AF_INET6: /* Internet Protocol */
+ if (sp->pp_mode == IFF_CISCO)
+ h->protocol = htons (ETHERTYPE_IPV6);
+ else {
+ goto nosupport;
+ }
+ break;
+#endif
#ifdef NS
case AF_NS: /* Xerox NS Protocol */
h->protocol = htons (sp->pp_mode == IFF_CISCO ?
@@ -759,8 +776,8 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
goto nosupport;
h->protocol = htons (PPP_ISO);
break;
-nosupport:
#endif
+nosupport:
default:
m_freem (m);
++ifp->if_oerrors;
diff --git a/sys/netinet/if_atm.c b/sys/netinet/if_atm.c
index 020e5ac..04b49bf 100644
--- a/sys/netinet/if_atm.c
+++ b/sys/netinet/if_atm.c
@@ -30,6 +30,8 @@
* 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$
*/
/*
@@ -37,6 +39,7 @@
*/
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_natm.h"
#if defined(INET) || defined(INET6)
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
new file mode 100644
index 0000000..fd8317f
--- /dev/null
+++ b/sys/netinet/in_gif.c
@@ -0,0 +1,311 @@
+/*
+ * 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$
+ */
+
+/*
+ * in_gif.c
+ */
+
+#include "opt_mrouting.h"
+#include "opt_inet6.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/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/protosw.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/in_gif.h>
+
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif
+
+#ifdef MROUTING
+#include <netinet/ip_mroute.h>
+#endif /* MROUTING */
+
+#include <net/if_gif.h>
+
+#include "gif.h"
+
+#include <machine/stdarg.h>
+
+#include <net/net_osdep.h>
+
+#if NGIF > 0
+int ip_gif_ttl = GIF_TTL;
+#else
+int ip_gif_ttl = 0;
+#endif
+
+SYSCTL_DECL(_net_inet_ip);
+SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW,
+ &ip_gif_ttl, 0, "");
+
+int
+in_gif_output(ifp, family, m, rt)
+ struct ifnet *ifp;
+ int family;
+ struct mbuf *m;
+ struct rtentry *rt;
+{
+ register struct gif_softc *sc = (struct gif_softc*)ifp;
+ struct sockaddr_in *dst = (struct sockaddr_in *)&sc->gif_ro.ro_dst;
+ struct sockaddr_in *sin_src = (struct sockaddr_in *)sc->gif_psrc;
+ struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst;
+ struct ip iphdr; /* capsule IP header, host byte ordered */
+ int proto, error;
+ u_int8_t tos;
+
+ if (sin_src == NULL || sin_dst == NULL ||
+ sin_src->sin_family != AF_INET ||
+ sin_dst->sin_family != AF_INET) {
+ m_freem(m);
+ return EAFNOSUPPORT;
+ }
+
+ switch (family) {
+ 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 *);
+ tos = ip->ip_tos;
+ break;
+ }
+#ifdef INET6
+ 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 *);
+ tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
+ break;
+ }
+#endif /*INET6*/
+ default:
+#ifdef DIAGNOSTIC
+ printf("in_gif_output: warning: unknown family %d passed\n",
+ family);
+#endif
+ m_freem(m);
+ return EAFNOSUPPORT;
+ }
+
+ bzero(&iphdr, sizeof(iphdr));
+ iphdr.ip_src = sin_src->sin_addr;
+ if (ifp->if_flags & IFF_LINK0) {
+ /* multi-destination mode */
+ if (sin_dst->sin_addr.s_addr != INADDR_ANY)
+ iphdr.ip_dst = sin_dst->sin_addr;
+ else if (rt) {
+ iphdr.ip_dst = ((struct sockaddr_in *)
+ (rt->rt_gateway))->sin_addr;
+ } else {
+ m_freem(m);
+ return ENETUNREACH;
+ }
+ } else {
+ /* bidirectional configured tunnel mode */
+ if (sin_dst->sin_addr.s_addr != INADDR_ANY)
+ iphdr.ip_dst = sin_dst->sin_addr;
+ else {
+ m_freem(m);
+ return ENETUNREACH;
+ }
+ }
+ iphdr.ip_p = proto;
+ /* version will be set in ip_output() */
+ iphdr.ip_ttl = ip_gif_ttl;
+ iphdr.ip_len = m->m_pkthdr.len + sizeof(struct ip);
+
+ /* prepend new IP header */
+ M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
+ if (m && m->m_len < sizeof(struct ip))
+ m = m_pullup(m, sizeof(struct ip));
+ if (m == NULL) {
+ printf("ENOBUFS in in_gif_output %d\n", __LINE__);
+ return ENOBUFS;
+ }
+
+ *(mtod(m, struct ip *)) = iphdr;
+
+ if (dst->sin_family != sin_dst->sin_family ||
+ dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) {
+ /* cache route doesn't match */
+ dst->sin_family = sin_dst->sin_family;
+ dst->sin_len = sizeof(struct sockaddr_in);
+ dst->sin_addr = sin_dst->sin_addr;
+ if (sc->gif_ro.ro_rt) {
+ RTFREE(sc->gif_ro.ro_rt);
+ sc->gif_ro.ro_rt = NULL;
+ }
+ }
+
+ if (sc->gif_ro.ro_rt == NULL) {
+ rtalloc(&sc->gif_ro);
+ if (sc->gif_ro.ro_rt == NULL) {
+ m_freem(m);
+ return ENETUNREACH;
+ }
+ }
+
+#ifdef IPSEC
+ m->m_pkthdr.rcvif = NULL;
+#endif /*IPSEC*/
+ error = ip_output(m, 0, &sc->gif_ro, 0, 0);
+ return(error);
+}
+
+void
+#if __STDC__
+in_gif_input(struct mbuf *m, ...)
+#else
+in_gif_input(m, va_alist)
+ struct mbuf *m;
+ va_dcl
+#endif
+{
+ int off, proto;
+ struct gif_softc *sc;
+ struct ifnet *gifp = NULL;
+ struct ip *ip;
+ int i, af;
+ va_list ap;
+
+ va_start(ap, m);
+ off = va_arg(ap, int);
+ proto = va_arg(ap, int);
+ va_end(ap);
+
+ ip = mtod(m, struct ip *);
+
+ /* this code will be soon improved. */
+#define satosin(sa) ((struct sockaddr_in *)(sa))
+ for (i = 0, sc = gif; i < ngif; i++, sc++) {
+ if (sc->gif_psrc == NULL
+ || sc->gif_pdst == NULL
+ || sc->gif_psrc->sa_family != AF_INET
+ || sc->gif_pdst->sa_family != AF_INET) {
+ continue;
+ }
+
+ if ((sc->gif_if.if_flags & IFF_UP) == 0)
+ continue;
+
+ if ((sc->gif_if.if_flags & IFF_LINK0)
+ && satosin(sc->gif_psrc)->sin_addr.s_addr == ip->ip_dst.s_addr
+ && satosin(sc->gif_pdst)->sin_addr.s_addr == INADDR_ANY) {
+ gifp = &sc->gif_if;
+ continue;
+ }
+
+ if (satosin(sc->gif_psrc)->sin_addr.s_addr == ip->ip_dst.s_addr
+ && satosin(sc->gif_pdst)->sin_addr.s_addr == ip->ip_src.s_addr)
+ {
+ gifp = &sc->gif_if;
+ break;
+ }
+ }
+
+ if (gifp == NULL) {
+#ifdef MROUTING
+ /* for backward compatibility */
+ if (proto == IPPROTO_IPV4) {
+ ipip_input(m, off, proto);
+ return;
+ }
+#endif /*MROUTING*/
+ m_freem(m);
+ ipstat.ips_nogif++;
+ return;
+ }
+
+ m_adj(m, off);
+
+ switch (proto) {
+ case IPPROTO_IPV4:
+ {
+ struct ip *ip;
+ af = AF_INET;
+ if (m->m_len < sizeof(*ip)) {
+ m = m_pullup(m, sizeof(*ip));
+ if (!m)
+ return;
+ }
+ ip = mtod(m, struct ip *);
+ break;
+ }
+#ifdef INET6
+ 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;
+ }
+ ip6 = mtod(m, struct ip6_hdr *);
+ ip6->ip6_flow &= ~htonl(0xff << 20);
+ break;
+ }
+#endif /* INET6 */
+ default:
+ ipstat.ips_nogif++;
+ m_freem(m);
+ return;
+ }
+ gif_input(m, af, gifp);
+ return;
+}
diff --git a/sys/netinet/in_gif.h b/sys/netinet/in_gif.h
new file mode 100644
index 0000000..b874524
--- /dev/null
+++ b/sys/netinet/in_gif.h
@@ -0,0 +1,42 @@
+/*
+ * 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 _NETINET_IN_GIF_H_
+#define _NETINET_IN_GIF_H_
+
+#define GIF_TTL 30
+
+extern int ip_gif_ttl;
+
+void in_gif_input __P((struct mbuf *, ...));
+int in_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *));
+
+#endif /*_NETINET_IN_GIF_H_*/
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index d19d449..71d091b 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -34,10 +34,13 @@
* $FreeBSD$
*/
+#include "opt_inet6.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
+#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@@ -51,12 +54,25 @@
#include <vm/vm_zone.h>
#include <net/if.h>
+#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
+#ifdef INET6
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#endif /* INET6 */
+
+#include "faith.h"
+
+#ifdef IPSEC
+#include <netinet6/ipsec.h>
+#include <netkey/key.h>
+#include <netkey/key_debug.h>
+#endif /* IPSEC */
struct in_addr zeroin_addr;
@@ -212,13 +228,34 @@ in_pcbbind(inp, nam, p)
(t->inp_socket->so_options &
SO_REUSEPORT) == 0) &&
(so->so_cred->cr_uid !=
- t->inp_socket->so_cred->cr_uid))
+ t->inp_socket->so_cred->cr_uid)) {
+#if defined(INET6)
+ if (ip6_mapped_addr_on == 0 ||
+ ntohl(sin->sin_addr.s_addr) !=
+ INADDR_ANY ||
+ ntohl(t->inp_laddr.s_addr) !=
+ INADDR_ANY ||
+ INP_SOCKAF(so) ==
+ INP_SOCKAF(t->inp_socket))
+#endif /* defined(INET6) */
return (EADDRINUSE);
+ }
}
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
lport, prison ? 0 : wild);
- if (t && (reuseport & t->inp_socket->so_options) == 0)
+ if (t &&
+ (reuseport & t->inp_socket->so_options) == 0) {
+#if defined(INET6)
+ if (ip6_mapped_addr_on == 0 ||
+ ntohl(sin->sin_addr.s_addr) !=
+ INADDR_ANY ||
+ ntohl(t->inp_laddr.s_addr) !=
+ INADDR_ANY ||
+ INP_SOCKAF(so) ==
+ INP_SOCKAF(t->inp_socket))
+#endif /* defined(INET6) */
return (EADDRINUSE);
+ }
}
inp->inp_laddr = sin->sin_addr;
}
@@ -452,7 +489,7 @@ in_pcbconnect(inp, nam, p)
if (in_pcblookup_hash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port,
inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
- inp->inp_lport, 0) != NULL) {
+ inp->inp_lport, 0, NULL) != NULL) {
return (EADDRINUSE);
}
if (inp->inp_laddr.s_addr == INADDR_ANY) {
@@ -488,6 +525,9 @@ in_pcbdetach(inp)
struct socket *so = inp->inp_socket;
struct inpcbinfo *ipi = inp->inp_pcbinfo;
+#ifdef IPSEC
+ ipsec4_delete_pcbpolicy(inp);
+#endif /*IPSEC*/
inp->inp_gencnt = ++ipi->ipi_gencnt;
in_pcbremlists(inp);
so->so_pcb = 0;
@@ -497,6 +537,7 @@ in_pcbdetach(inp)
if (inp->inp_route.ro_rt)
rtfree(inp->inp_route.ro_rt);
ip_freemoptions(inp->inp_moptions);
+ inp->inp_vflag = 0;
zfreei(ipi->ipi_zone, inp);
}
@@ -620,6 +661,12 @@ in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
errno = inetctlerrmap[cmd];
s = splnet();
for (inp = head->lh_first; inp != NULL;) {
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV4) == NULL) {
+ inp = LIST_NEXT(inp, inp_list);
+ continue;
+ }
+#endif
if (inp->inp_faddr.s_addr != faddr.s_addr ||
inp->inp_socket == 0 ||
(lport && inp->inp_lport != lport) ||
@@ -711,6 +758,10 @@ in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
*/
head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV4) == NULL)
+ continue;
+#endif
if (inp->inp_faddr.s_addr == INADDR_ANY &&
inp->inp_laddr.s_addr == laddr.s_addr &&
inp->inp_lport == lport) {
@@ -748,6 +799,10 @@ in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
for (inp = phd->phd_pcblist.lh_first; inp != NULL;
inp = inp->inp_portlist.le_next) {
wildcard = 0;
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV4) == NULL)
+ continue;
+#endif
if (inp->inp_faddr.s_addr != INADDR_ANY)
wildcard++;
if (inp->inp_laddr.s_addr != INADDR_ANY) {
@@ -776,11 +831,13 @@ in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
* Lookup PCB in hash list.
*/
struct inpcb *
-in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard)
+in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard,
+ ifp)
struct inpcbinfo *pcbinfo;
struct in_addr faddr, laddr;
u_int fport_arg, lport_arg;
int wildcard;
+ struct ifnet *ifp;
{
struct inpcbhead *head;
register struct inpcb *inp;
@@ -791,6 +848,10 @@ in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard)
*/
head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)];
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV4) == NULL)
+ continue;
+#endif
if (inp->inp_faddr.s_addr == faddr.s_addr &&
inp->inp_laddr.s_addr == laddr.s_addr &&
inp->inp_fport == fport &&
@@ -803,17 +864,40 @@ in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard)
}
if (wildcard) {
struct inpcb *local_wild = NULL;
+#if defined(INET6)
+ struct inpcb *local_wild_mapped = NULL;
+#endif /* defined(INET6) */
head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV4) == NULL)
+ continue;
+#endif
if (inp->inp_faddr.s_addr == INADDR_ANY &&
inp->inp_lport == lport) {
+#if defined(NFAITH) && NFAITH > 0
+ if (ifp && ifp->if_type == IFT_FAITH &&
+ (inp->inp_flags & INP_FAITH) == 0)
+ continue;
+#endif
if (inp->inp_laddr.s_addr == laddr.s_addr)
return (inp);
- else if (inp->inp_laddr.s_addr == INADDR_ANY)
+ else if (inp->inp_laddr.s_addr == INADDR_ANY) {
+#if defined(INET6)
+ if (INP_CHECK_SOCKAF(inp->inp_socket,
+ AF_INET6))
+ local_wild_mapped = inp;
+ else
+#endif /* defined(INET6) */
local_wild = inp;
+ }
}
}
+#if defined(INET6)
+ if (local_wild == NULL)
+ return (local_wild_mapped);
+#endif /* defined(INET6) */
return (local_wild);
}
@@ -834,8 +918,16 @@ in_pcbinshash(inp)
struct inpcbporthead *pcbporthash;
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
struct inpcbport *phd;
+ u_int32_t hashkey_faddr;
- pcbhash = &pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr,
+#ifdef INET6
+ if (inp->inp_vflag & INP_IPV6)
+ hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */;
+ else
+#endif /* INET6 */
+ hashkey_faddr = inp->inp_faddr.s_addr;
+
+ pcbhash = &pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr,
inp->inp_lport, inp->inp_fport, pcbinfo->hashmask)];
pcbporthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(inp->inp_lport,
@@ -877,8 +969,16 @@ in_pcbrehash(inp)
struct inpcb *inp;
{
struct inpcbhead *head;
+ u_int32_t hashkey_faddr;
+
+#ifdef INET6
+ if (inp->inp_vflag & INP_IPV6)
+ hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */;
+ else
+#endif /* INET6 */
+ hashkey_faddr = inp->inp_faddr.s_addr;
- head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr,
+ head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr,
inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)];
LIST_REMOVE(inp, inp_hash);
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index adfa5fa..5aeb579 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -287,7 +287,8 @@ struct inpcb *
struct in_addr, u_int, int));
struct inpcb *
in_pcblookup_hash __P((struct inpcbinfo *,
- struct in_addr, u_int, struct in_addr, u_int, int));
+ struct in_addr, u_int, struct in_addr, u_int,
+ int, struct ifnet *));
void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int)));
void in_pcbrehash __P((struct inpcb *));
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 22647d9..b9a9e4a 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -63,6 +63,11 @@
* TCP/IP protocol family: IP, ICMP, UDP, TCP.
*/
+#include "gif.h"
+#if NGIF > 0
+#include <netinet/in_gif.h>
+#endif
+
#ifdef IPXIP
#include <netipx/ipx_ip.h>
#endif
@@ -119,12 +124,29 @@ struct protosw inetsw[] = {
0, 0, 0, 0,
&rip_usrreqs
},
+#if NGIF > 0
+{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
+ in_gif_input, 0, 0, 0,
+ 0,
+ 0, 0, 0, 0,
+ &nousrreqs
+},
+# ifdef INET6
+{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
+ in_gif_input, 0, 0, 0,
+ 0,
+ 0, 0, 0, 0,
+ &nousrreqs
+},
+#endif
+#else /*NGIF*/
{ SOCK_RAW, &inetdomain, IPPROTO_IPIP, PR_ATOMIC|PR_ADDR,
ipip_input, 0, 0, rip_ctloutput,
0,
0, 0, 0, 0,
&rip_usrreqs
},
+#endif /*NGIF*/
#ifdef IPDIVERT
{ SOCK_RAW, &inetdomain, IPPROTO_DIVERT, PR_ATOMIC|PR_ADDR,
div_input, 0, 0, ip_ctloutput,
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c
index a70822e..b897421 100644
--- a/sys/netinet/ip_fw.c
+++ b/sys/netinet/ip_fw.c
@@ -707,10 +707,12 @@ again:
if (oif)
P = in_pcblookup_hash(&tcbinfo, ip->ip_dst,
- tcp->th_dport, ip->ip_src, tcp->th_sport, 0);
+ tcp->th_dport, ip->ip_src, tcp->th_sport, 0,
+ oif);
else
P = in_pcblookup_hash(&tcbinfo, ip->ip_src,
- tcp->th_sport, ip->ip_dst, tcp->th_dport, 0);
+ tcp->th_sport, ip->ip_dst, tcp->th_dport, 0,
+ NULL);
if (P && P->inp_socket) {
if (f->fw_flg & IP_FW_F_UID) {
@@ -738,10 +740,12 @@ again:
if (oif)
P = in_pcblookup_hash(&udbinfo, ip->ip_dst,
- udp->uh_dport, ip->ip_src, udp->uh_sport, 1);
+ udp->uh_dport, ip->ip_src, udp->uh_sport, 1,
+ oif);
else
P = in_pcblookup_hash(&udbinfo, ip->ip_src,
- udp->uh_sport, ip->ip_dst, udp->uh_dport, 1);
+ udp->uh_sport, ip->ip_dst, udp->uh_dport, 1,
+ NULL);
if (P && P->inp_socket) {
if (f->fw_flg & IP_FW_F_UID) {
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 5f61ff3..909adf9 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -390,7 +390,7 @@ findpcb:
* already got one like this?
*/
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
- ti->ti_dst, ti->ti_dport, 0);
+ ti->ti_dst, ti->ti_dport, 0, m->m_pkthdr.rcvif);
if (!inp) {
/*
* No, then it's new. Try find the ambushing socket
@@ -398,12 +398,13 @@ findpcb:
if (!ip_fw_fwd_addr->sin_port) {
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src,
ti->ti_sport, ip_fw_fwd_addr->sin_addr,
- ti->ti_dport, 1);
+ ti->ti_dport, 1, m->m_pkthdr.rcvif);
} else {
inp = in_pcblookup_hash(&tcbinfo,
ti->ti_src, ti->ti_sport,
ip_fw_fwd_addr->sin_addr,
- ntohs(ip_fw_fwd_addr->sin_port), 1);
+ ntohs(ip_fw_fwd_addr->sin_port), 1,
+ m->m_pkthdr.rcvif);
}
}
ip_fw_fwd_addr = NULL;
@@ -411,7 +412,7 @@ findpcb:
#endif /* IPFIREWALL_FORWARD */
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
- ti->ti_dst, ti->ti_dport, 1);
+ ti->ti_dst, ti->ti_dport, 1, m->m_pkthdr.rcvif);
/*
* If the state is CLOSED (i.e., TCB does not exist) then
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 5f61ff3..909adf9 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -390,7 +390,7 @@ findpcb:
* already got one like this?
*/
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
- ti->ti_dst, ti->ti_dport, 0);
+ ti->ti_dst, ti->ti_dport, 0, m->m_pkthdr.rcvif);
if (!inp) {
/*
* No, then it's new. Try find the ambushing socket
@@ -398,12 +398,13 @@ findpcb:
if (!ip_fw_fwd_addr->sin_port) {
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src,
ti->ti_sport, ip_fw_fwd_addr->sin_addr,
- ti->ti_dport, 1);
+ ti->ti_dport, 1, m->m_pkthdr.rcvif);
} else {
inp = in_pcblookup_hash(&tcbinfo,
ti->ti_src, ti->ti_sport,
ip_fw_fwd_addr->sin_addr,
- ntohs(ip_fw_fwd_addr->sin_port), 1);
+ ntohs(ip_fw_fwd_addr->sin_port), 1,
+ m->m_pkthdr.rcvif);
}
}
ip_fw_fwd_addr = NULL;
@@ -411,7 +412,7 @@ findpcb:
#endif /* IPFIREWALL_FORWARD */
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
- ti->ti_dst, ti->ti_dport, 1);
+ ti->ti_dst, ti->ti_dport, 1, m->m_pkthdr.rcvif);
/*
* If the state is CLOSED (i.e., TCB does not exist) then
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index b472de5..fd3e435 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -35,7 +35,7 @@
*/
#include "opt_compat.h"
-#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_tcpdebug.h"
#include <sys/param.h>
@@ -647,7 +647,7 @@ tcp_getcred SYSCTL_HANDLER_ARGS
return (error);
s = splnet();
inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
- addrs[0].sin_addr, addrs[0].sin_port, 0);
+ addrs[0].sin_addr, addrs[0].sin_port, 0, NULL);
if (inp == NULL || inp->inp_socket == NULL) {
error = ENOENT;
goto out;
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index b472de5..fd3e435 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -35,7 +35,7 @@
*/
#include "opt_compat.h"
-#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_tcpdebug.h"
#include <sys/param.h>
@@ -647,7 +647,7 @@ tcp_getcred SYSCTL_HANDLER_ARGS
return (error);
s = splnet();
inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
- addrs[0].sin_addr, addrs[0].sin_port, 0);
+ addrs[0].sin_addr, addrs[0].sin_port, 0, NULL);
if (inp == NULL || inp->inp_socket == NULL) {
error = ENOENT;
goto out;
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 49fca1e..af43fc3 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -34,6 +34,7 @@
* $FreeBSD$
*/
+#include "opt_inet6.h"
#include "opt_tcpdebug.h"
#include <sys/param.h>
@@ -535,7 +536,7 @@ tcp_connect(tp, nam, p)
sin->sin_addr, sin->sin_port,
inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr
: ifaddr->sin_addr,
- inp->inp_lport, 0);
+ inp->inp_lport, 0, NULL);
if (oinp) {
if (oinp != inp && (otp = intotcpcb(oinp)) != NULL &&
otp->t_state == TCPS_TIME_WAIT &&
@@ -731,6 +732,9 @@ tcp_attach(so, p)
if (error)
return (error);
inp = sotoinpcb(so);
+#ifdef INET6
+ inp->inp_vflag |= INP_IPV4;
+#endif
tp = tcp_newtcpcb(inp);
if (tp == 0) {
int nofd = so->so_state & SS_NOFDREF; /* XXX */
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 2f0cb58..f49a128 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -34,11 +34,14 @@
* $FreeBSD$
*/
+#include "opt_inet6.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
+#include <sys/domain.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/socket.h>
@@ -54,14 +57,24 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
+#ifdef INET6
+#include <netinet6/ip6_var.h>
+#endif
#include <netinet/ip_icmp.h>
#include <netinet/icmp_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
+#ifdef IPSEC
+#include <netinet6/ipsec.h>
+#endif /*IPSEC*/
+
/*
* UDP protocol implementation.
* Per RFC 768, August, 1980.
@@ -83,6 +96,7 @@ SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
&blackhole, 0, "Do not send port unreachables for refused connects");
struct inpcbhead udb; /* from udp_var.h */
+#define udb6 udb /* for KAME src sync over BSD*'s */
struct inpcbinfo udbinfo;
#ifndef UDBHASHSIZE
@@ -94,7 +108,27 @@ SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD,
&udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
+#ifdef INET6
+struct udp_in6 {
+ struct sockaddr_in6 uin6_sin;
+ u_char uin6_init_done : 1;
+} udp_in6 = {
+ { sizeof(udp_in6.uin6_sin), AF_INET6 },
+ 0
+};
+struct udp_ip6 {
+ struct ip6_hdr uip6_ip6;
+ u_char uip6_init_done : 1;
+} udp_ip6;
+#endif /* INET6 */
+
+static void udp_append __P((struct inpcb *last, struct ip *ip,
+ struct mbuf *n, int off));
+#ifdef INET6
+static void ip_2_ip6_hdr __P((struct ip6_hdr *ip6, struct ip *ip));
+#endif
+static int udp_detach __P((struct socket *so));
static int udp_output __P((struct inpcb *, struct mbuf *, struct sockaddr *,
struct mbuf *, struct proc *));
@@ -111,16 +145,18 @@ udp_init()
}
void
-udp_input(m, iphlen)
+udp_input(m, off, proto)
register struct mbuf *m;
- int iphlen;
+ int off, proto;
{
+ int iphlen = off;
register struct ip *ip;
register struct udphdr *uh;
register struct inpcb *inp;
struct mbuf *opts = 0;
int len;
struct ip save_ip;
+ struct sockaddr *append_sa;
udpstat.udps_ipackets++;
@@ -205,14 +241,19 @@ udp_input(m, iphlen)
*/
udp_in.sin_port = uh->uh_sport;
udp_in.sin_addr = ip->ip_src;
- m->m_len -= sizeof (struct udpiphdr);
- m->m_data += sizeof (struct udpiphdr);
/*
* Locate pcb(s) for datagram.
* (Algorithm copied from raw_intr().)
*/
last = NULL;
- for (inp = udb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
+#ifdef INET6
+ udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0;
+#endif
+ LIST_FOREACH(inp, &udb, inp_list) {
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV4) == NULL)
+ continue;
+#endif
if (inp->inp_lport != uh->uh_dport)
continue;
if (inp->inp_laddr.s_addr != INADDR_ANY) {
@@ -230,21 +271,17 @@ udp_input(m, iphlen)
if (last != NULL) {
struct mbuf *n;
- if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
- if (last->inp_flags & INP_CONTROLOPTS
- || last->inp_socket->so_options & SO_TIMESTAMP)
- ip_savecontrol(last, &opts, ip, n);
- if (sbappendaddr(&last->inp_socket->so_rcv,
- (struct sockaddr *)&udp_in,
- n, opts) == 0) {
- m_freem(n);
- if (opts)
- m_freem(opts);
- udpstat.udps_fullsock++;
- } else
- sorwakeup(last->inp_socket);
- opts = 0;
- }
+#ifdef IPSEC
+ /* check AH/ESP integrity. */
+ if (ipsec4_in_reject_so(m, last->inp_socket))
+ ipsecstat.in_polvio++;
+ /* do not inject data to pcb */
+ else
+#endif /*IPSEC*/
+ if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
+ udp_append(last, ip, n,
+ iphlen +
+ sizeof(struct udphdr));
}
last = inp;
/*
@@ -268,23 +305,21 @@ udp_input(m, iphlen)
udpstat.udps_noportbcast++;
goto bad;
}
- if (last->inp_flags & INP_CONTROLOPTS
- || last->inp_socket->so_options & SO_TIMESTAMP)
- ip_savecontrol(last, &opts, ip, m);
- if (sbappendaddr(&last->inp_socket->so_rcv,
- (struct sockaddr *)&udp_in,
- m, opts) == 0) {
- udpstat.udps_fullsock++;
+#ifdef IPSEC
+ /* check AH/ESP integrity. */
+ if (ipsec4_in_reject_so(m, last->inp_socket)) {
+ ipsecstat.in_polvio++;
goto bad;
}
- sorwakeup(last->inp_socket);
+#endif /*IPSEC*/
+ udp_append(last, ip, m, iphlen + sizeof(struct udphdr));
return;
}
/*
* Locate pcb for datagram.
*/
inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
- ip->ip_dst, uh->uh_dport, 1);
+ ip->ip_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif);
if (inp == NULL) {
if (log_in_vain) {
char buf[4*sizeof "123"];
@@ -311,6 +346,12 @@ udp_input(m, iphlen)
goto bad;
return;
}
+#ifdef IPSEC
+ if (ipsec4_in_reject_so(m, inp->inp_socket)) {
+ ipsecstat.in_polvio++;
+ goto bad;
+ }
+#endif /*IPSEC*/
/*
* Construct sockaddr format source address.
@@ -319,14 +360,30 @@ udp_input(m, iphlen)
udp_in.sin_port = uh->uh_sport;
udp_in.sin_addr = ip->ip_src;
if (inp->inp_flags & INP_CONTROLOPTS
- || inp->inp_socket->so_options & SO_TIMESTAMP)
+ || inp->inp_socket->so_options & SO_TIMESTAMP) {
+#ifdef INET6
+ if (inp->inp_vflag & INP_IPV6) {
+ int savedflags;
+
+ ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
+ savedflags = inp->inp_flags;
+ inp->inp_flags &= ~INP_UNMAPPABLEOPTS;
+ ip6_savecontrol(inp, &opts, &udp_ip6.uip6_ip6, m);
+ inp->inp_flags = savedflags;
+ } else
+#endif
ip_savecontrol(inp, &opts, ip, m);
+ }
iphlen += sizeof(struct udphdr);
- m->m_len -= iphlen;
- m->m_pkthdr.len -= iphlen;
- m->m_data += iphlen;
- if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
- m, opts) == 0) {
+ m_adj(m, iphlen);
+#ifdef INET6
+ if (inp->inp_vflag & INP_IPV6) {
+ in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
+ append_sa = (struct sockaddr *)&udp_in6;
+ } else
+#endif
+ append_sa = (struct sockaddr *)&udp_in;
+ if (sbappendaddr(&inp->inp_socket->so_rcv, append_sa, m, opts) == 0) {
udpstat.udps_fullsock++;
goto bad;
}
@@ -336,6 +393,78 @@ bad:
m_freem(m);
if (opts)
m_freem(opts);
+ return;
+}
+
+#if defined(INET6)
+static void
+ip_2_ip6_hdr(ip6, ip)
+ struct ip6_hdr *ip6;
+ struct ip *ip;
+{
+ bzero(ip6, sizeof(*ip6));
+
+ ip6->ip6_vfc = IPV6_VERSION;
+ ip6->ip6_plen = ip->ip_len;
+ ip6->ip6_nxt = ip->ip_p;
+ ip6->ip6_hlim = ip->ip_ttl;
+ ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] =
+ IPV6_ADDR_INT32_SMP;
+ ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr;
+ ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr;
+}
+#endif
+
+/*
+ * subroutine of udp_input(), mainly for source code readability.
+ * caller must properly init udp_ip6 and udp_in6 beforehand.
+ */
+static void
+udp_append(last, ip, n, off)
+ struct inpcb *last;
+ struct ip *ip;
+ struct mbuf *n;
+ int off;
+{
+ struct sockaddr *append_sa;
+ struct mbuf *opts = 0;
+
+ if (last->inp_flags & INP_CONTROLOPTS ||
+ last->inp_socket->so_options & SO_TIMESTAMP) {
+#ifdef INET6
+ if (last->inp_vflag & INP_IPV6) {
+ int savedflags;
+
+ if (udp_ip6.uip6_init_done == 0) {
+ ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
+ udp_ip6.uip6_init_done = 1;
+ }
+ savedflags = last->inp_flags;
+ last->inp_flags &= ~INP_UNMAPPABLEOPTS;
+ ip6_savecontrol(last, &opts, &udp_ip6.uip6_ip6, n);
+ last->inp_flags = savedflags;
+ } else
+#endif
+ ip_savecontrol(last, &opts, ip, n);
+ }
+#ifdef INET6
+ if (last->inp_vflag & INP_IPV6) {
+ if (udp_in6.uin6_init_done == 0) {
+ in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
+ udp_in6.uin6_init_done = 1;
+ }
+ append_sa = (struct sockaddr *)&udp_in6.uin6_sin;
+ } else
+#endif
+ append_sa = (struct sockaddr *)&udp_in;
+ m_adj(n, off);
+ if (sbappendaddr(&last->inp_socket->so_rcv, append_sa, n, opts) == 0) {
+ m_freem(n);
+ if (opts)
+ m_freem(opts);
+ udpstat.udps_fullsock++;
+ } else
+ sorwakeup(last->inp_socket);
}
/*
@@ -473,7 +602,7 @@ udp_getcred SYSCTL_HANDLER_ARGS
return (error);
s = splnet();
inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
- addrs[0].sin_addr, addrs[0].sin_port, 1);
+ addrs[0].sin_addr, addrs[0].sin_port, 1, NULL);
if (inp == NULL || inp->inp_socket == NULL) {
error = ENOENT;
goto out;
@@ -570,6 +699,11 @@ udp_output(inp, m, addr, control, p)
((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
udpstat.udps_opackets++;
+
+#ifdef IPSEC
+ m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket;
+#endif /*IPSEC*/
+
error = ip_output(m, inp->inp_options, &inp->inp_route,
inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
inp->inp_moptions);
@@ -591,7 +725,13 @@ u_long udp_sendspace = 9216; /* really max datagram size */
SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
&udp_sendspace, 0, "Maximum outgoing UDP datagram size");
-u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
+u_long udp_recvspace = 40 * (1024 +
+#ifdef INET6
+ sizeof(struct sockaddr_in6)
+#else
+ sizeof(struct sockaddr_in)
+#endif
+ );
SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
&udp_recvspace, 0, "Maximum incoming UDP datagram size");
@@ -621,15 +761,27 @@ udp_attach(struct socket *so, int proto, struct proc *p)
if (inp != 0)
return EINVAL;
+ 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;
- error = soreserve(so, udp_sendspace, udp_recvspace);
- if (error)
+
+ inp = (struct inpcb *)so->so_pcb;
+#ifdef INET6
+ inp->inp_vflag |= INP_IPV4;
+#endif
+ inp->inp_ip_ttl = ip_defttl;
+#ifdef IPSEC
+ error = ipsec_init_policy(so, &inp->inp_sp);
+ if (error != 0) {
+ in_pcbdetach(inp);
return error;
- ((struct inpcb *) so->so_pcb)->inp_ip_ttl = ip_defttl;
+ }
+#endif /*IPSEC*/
return 0;
}
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index 0ee8258..491632e 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -115,7 +115,7 @@ extern int log_in_vain;
void udp_ctlinput __P((int, struct sockaddr *, void *));
void udp_init __P((void));
-void udp_input __P((struct mbuf *, int));
+void udp_input __P((struct mbuf *, int, int));
void udp_notify __P((struct inpcb *inp, int errno));
int udp_shutdown __P((struct socket *so));
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