summaryrefslogtreecommitdiffstats
path: root/sys/netinet
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/netinet
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/netinet')
-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
14 files changed, 707 insertions, 66 deletions
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));
OpenPOWER on IntegriCloud