summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in_pcb.c14
-rw-r--r--sys/netinet/in_proto.c38
-rw-r--r--sys/netinet/ip_input.c101
-rw-r--r--sys/netinet/ip_ipsec.c249
-rw-r--r--sys/netinet/ip_ipsec.h40
-rw-r--r--sys/netinet/ip_output.c66
-rw-r--r--sys/netinet/raw_ip.c11
-rw-r--r--sys/netinet/sctp_input.c28
-rw-r--r--sys/netinet/sctp_os_bsd.h10
-rw-r--r--sys/netinet/sctp_pcb.c18
-rw-r--r--sys/netinet/tcp_input.c116
-rw-r--r--sys/netinet/tcp_output.c67
-rw-r--r--sys/netinet/tcp_stacks/fastpath.c6
-rw-r--r--sys/netinet/tcp_subr.c369
-rw-r--r--sys/netinet/tcp_syncache.c149
-rw-r--r--sys/netinet/tcp_usrreq.c30
-rw-r--r--sys/netinet/tcp_var.h30
-rw-r--r--sys/netinet/udp.h2
-rw-r--r--sys/netinet/udp_usrreq.c224
19 files changed, 311 insertions, 1257 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 7d5da0e..7eb48af 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -96,11 +96,7 @@ __FBSDID("$FreeBSD$");
#include <netinet6/ip6_var.h>
#endif /* INET6 */
-
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#include <netipsec/key.h>
-#endif /* IPSEC */
+#include <netipsec/ipsec_support.h>
#include <security/mac/mac_framework.h>
@@ -303,8 +299,8 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
goto out;
mac_inpcb_create(so, inp);
#endif
-#ifdef IPSEC
- error = ipsec_init_policy(so, &inp->inp_sp);
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+ error = ipsec_init_pcbpolicy(inp);
if (error != 0) {
#ifdef MAC
mac_inpcb_destroy(inp);
@@ -331,7 +327,7 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
refcount_init(&inp->inp_refcount, 1); /* Reference from inpcbinfo */
INP_LIST_WUNLOCK(pcbinfo);
-#if defined(IPSEC) || defined(MAC)
+#if defined(IPSEC) || defined(IPSEC_SUPPORT) || defined(MAC)
out:
if (error != 0) {
crfree(inp->inp_cred);
@@ -1278,7 +1274,7 @@ in_pcbfree(struct inpcb *inp)
INP_WLOCK_ASSERT(inp);
/* XXXRW: Do as much as possible here. */
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
if (inp->inp_sp != NULL)
ipsec_delete_pcbpolicy(inp);
#endif
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 7403ec0..363716f 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -90,10 +90,6 @@ __FBSDID("$FreeBSD$");
static struct pr_usrreqs nousrreqs;
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#endif /* IPSEC */
-
#ifdef SCTP
#include <netinet/in_pcb.h>
#include <netinet/sctp_pcb.h>
@@ -152,7 +148,7 @@ struct protosw inetsw[] = {
.pr_type = SOCK_SEQPACKET,
.pr_domain = &inetdomain,
.pr_protocol = IPPROTO_SCTP,
- .pr_flags = PR_WANTRCVD,
+ .pr_flags = PR_WANTRCVD|PR_LASTHDR,
.pr_input = sctp_input,
.pr_ctlinput = sctp_ctlinput,
.pr_ctloutput = sctp_ctloutput,
@@ -164,7 +160,7 @@ struct protosw inetsw[] = {
.pr_type = SOCK_STREAM,
.pr_domain = &inetdomain,
.pr_protocol = IPPROTO_SCTP,
- .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD,
+ .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LASTHDR,
.pr_input = sctp_input,
.pr_ctlinput = sctp_ctlinput,
.pr_ctloutput = sctp_ctloutput,
@@ -222,34 +218,6 @@ struct protosw inetsw[] = {
.pr_ctloutput = rip_ctloutput,
.pr_usrreqs = &rip_usrreqs
},
-#ifdef IPSEC
-{
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_AH,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = ah4_input,
- .pr_ctlinput = ah4_ctlinput,
- .pr_usrreqs = &nousrreqs
-},
-{
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_ESP,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = esp4_input,
- .pr_ctlinput = esp4_ctlinput,
- .pr_usrreqs = &nousrreqs
-},
-{
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_IPCOMP,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = ipcomp4_input,
- .pr_usrreqs = &nousrreqs
-},
-#endif /* IPSEC */
{
.pr_type = SOCK_RAW,
.pr_domain = &inetdomain,
@@ -366,7 +334,7 @@ SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp, CTLFLAG_RW, 0, "TCP");
SYSCTL_NODE(_net_inet, IPPROTO_SCTP, sctp, CTLFLAG_RW, 0, "SCTP");
#endif
SYSCTL_NODE(_net_inet, IPPROTO_IGMP, igmp, CTLFLAG_RW, 0, "IGMP");
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/* XXX no protocol # to use, pick something "reserved" */
SYSCTL_NODE(_net_inet, 253, ipsec, CTLFLAG_RW, 0, "IPSEC");
SYSCTL_NODE(_net_inet, IPPROTO_AH, ah, CTLFLAG_RW, 0, "AH");
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 73a155d..9f2b7df 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -77,13 +77,10 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip_options.h>
#include <machine/in_cksum.h>
#include <netinet/ip_carp.h>
-#ifdef IPSEC
-#include <netinet/ip_ipsec.h>
-#include <netipsec/ipsec.h>
-#include <netipsec/key.h>
-#endif /* IPSEC */
#include <netinet/in_rss.h>
+#include <netipsec/ipsec_support.h>
+
#include <sys/socketvar.h>
#include <security/mac/mac_framework.h>
@@ -430,6 +427,12 @@ ip_direct_input(struct mbuf *m)
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2;
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+ if (IPSEC_ENABLED(ipv4)) {
+ if (IPSEC_INPUT(ipv4, m, hlen, ip->ip_p) != 0)
+ return;
+ }
+#endif /* IPSEC */
IPSTAT_INC(ips_delivered);
(*inetsw[ip_protox[ip->ip_p]].pr_input)(&m, &hlen, ip->ip_p);
return;
@@ -559,11 +562,11 @@ tooshort:
* ip pointer.
*/
if (V_ipforwarding != 0
-#ifdef IPSEC
- && !key_havesp(IPSEC_DIR_INBOUND)
- && !key_havesp(IPSEC_DIR_OUTBOUND)
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+ && (!IPSEC_ENABLED(ipv4) ||
+ IPSEC_CAPS(ipv4, m, IPSEC_CAP_OPERABLE) == 0)
#endif
- ) {
+ ) {
if ((m = ip_tryforward(m)) == NULL)
return;
if (m->m_flags & M_FASTFWD_OURS) {
@@ -572,13 +575,16 @@ tooshort:
goto ours;
}
}
-#ifdef IPSEC
+
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/*
* Bypass packet filtering for packets previously handled by IPsec.
*/
- if (ip_ipsec_filtertunnel(m))
- goto passin;
+ if (IPSEC_ENABLED(ipv4) &&
+ IPSEC_CAPS(ipv4, m, IPSEC_CAP_BYPASS_FILTER) != 0)
+ goto passin;
#endif
+
/*
* Run through list of hooks for input packets.
*
@@ -802,14 +808,11 @@ ours:
hlen = ip->ip_hl << 2;
}
-#ifdef IPSEC
- /*
- * enforce IPsec policy checking if we are seeing last header.
- * note that we do not visit this with protocols with pcb layer
- * code - like udp/tcp/raw ip.
- */
- if (ip_ipsec_input(m, ip->ip_p) != 0)
- goto bad;
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+ if (IPSEC_ENABLED(ipv4)) {
+ if (IPSEC_INPUT(ipv4, m, hlen, ip->ip_p) != 0)
+ return;
+ }
#endif /* IPSEC */
/*
@@ -951,24 +954,14 @@ ip_forward(struct mbuf *m, int srcrt)
m_freem(m);
return;
}
-#ifdef IPSEC
- if (ip_ipsec_fwd(m) != 0) {
- IPSTAT_INC(ips_cantforward);
- m_freem(m);
- return;
- }
-#endif /* IPSEC */
+ if (
#ifdef IPSTEALTH
- if (!V_ipstealth) {
+ V_ipstealth == 0 &&
#endif
- if (ip->ip_ttl <= IPTTLDEC) {
- icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS,
- 0, 0);
- return;
- }
-#ifdef IPSTEALTH
+ ip->ip_ttl <= IPTTLDEC) {
+ icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, 0);
+ return;
}
-#endif
bzero(&ro, sizeof(ro));
sin = (struct sockaddr_in *)&ro.ro_dst;
@@ -987,19 +980,6 @@ ip_forward(struct mbuf *m, int srcrt)
ifa_ref(&ia->ia_ifa);
} else
ia = NULL;
-#ifndef IPSEC
- /*
- * 'ia' may be NULL if there is no route for this destination.
- * In case of IPsec, Don't discard it just yet, but pass it to
- * ip_output in case of outgoing IPsec policy.
- */
- if (!srcrt && ia == NULL) {
- icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
- RO_RTFREE(&ro);
- return;
- }
-#endif
-
/*
* Save the IP header and at most 8 bytes of the payload,
* in case we need to generate an ICMP message to the src.
@@ -1032,15 +1012,22 @@ ip_forward(struct mbuf *m, int srcrt)
mcopy->m_pkthdr.len = mcopy->m_len;
m_copydata(m, 0, mcopy->m_len, mtod(mcopy, caddr_t));
}
-
#ifdef IPSTEALTH
- if (!V_ipstealth) {
+ if (V_ipstealth == 0)
#endif
ip->ip_ttl -= IPTTLDEC;
-#ifdef IPSTEALTH
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+ if (IPSEC_ENABLED(ipv4)) {
+ if ((error = IPSEC_FORWARD(ipv4, m)) != 0) {
+ /* mbuf consumed by IPsec */
+ m_freem(mcopy);
+ if (error != EINPROGRESS)
+ IPSTAT_INC(ips_cantforward);
+ return;
+ }
+ /* No IPsec processing required */
}
-#endif
-
+#endif /* IPSEC */
/*
* If forwarding packet using same interface that it came in on,
* perhaps should send a redirect to sender to shortcut a hop.
@@ -1118,14 +1105,6 @@ ip_forward(struct mbuf *m, int srcrt)
case EMSGSIZE:
type = ICMP_UNREACH;
code = ICMP_UNREACH_NEEDFRAG;
-
-#ifdef IPSEC
- /*
- * If IPsec is configured for this path,
- * override any possibly mtu value set by ip_output.
- */
- mtu = ip_ipsec_mtu(mcopy, mtu);
-#endif /* IPSEC */
/*
* If the MTU was set before make sure we are below the
* interface MTU.
diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c
deleted file mode 100644
index ac1e3d5..0000000
--- a/sys/netinet/ip_ipsec.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 1988, 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.
- * 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_ipsec.h"
-#include "opt_sctp.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/errno.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 <net/if.h>
-#include <net/if_var.h>
-#include <net/vnet.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/in_pcb.h>
-#include <netinet/ip_var.h>
-#include <netinet/ip_options.h>
-#include <netinet/ip_ipsec.h>
-#ifdef SCTP
-#include <netinet/sctp_crc32.h>
-#endif
-
-#include <machine/in_cksum.h>
-
-#include <netipsec/ipsec.h>
-#include <netipsec/xform.h>
-#include <netipsec/key.h>
-
-extern struct protosw inetsw[];
-
-#ifdef IPSEC_FILTERTUNNEL
-static VNET_DEFINE(int, ip4_ipsec_filtertunnel) = 1;
-#else
-static VNET_DEFINE(int, ip4_ipsec_filtertunnel) = 0;
-#endif
-#define V_ip4_ipsec_filtertunnel VNET(ip4_ipsec_filtertunnel)
-
-SYSCTL_DECL(_net_inet_ipsec);
-SYSCTL_INT(_net_inet_ipsec, OID_AUTO, filtertunnel,
- CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ipsec_filtertunnel), 0,
- "If set filter packets from an IPsec tunnel.");
-
-/*
- * Check if we have to jump over firewall processing for this packet.
- * Called from ip_input().
- * 1 = jump over firewall, 0 = packet goes through firewall.
- */
-int
-ip_ipsec_filtertunnel(struct mbuf *m)
-{
-
- /*
- * Bypass packet filtering for packets previously handled by IPsec.
- */
- if (!V_ip4_ipsec_filtertunnel &&
- m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
- return 1;
- return 0;
-}
-
-/*
- * Check if this packet has an active SA and needs to be dropped instead
- * of forwarded.
- * Called from ip_forward().
- * 1 = drop packet, 0 = forward packet.
- */
-int
-ip_ipsec_fwd(struct mbuf *m)
-{
-
- return (ipsec4_in_reject(m, NULL));
-}
-
-/*
- * Check if protocol type doesn't have a further header and do IPSEC
- * decryption or reject right now. Protocols with further headers get
- * their IPSEC treatment within the protocol specific processing.
- * Called from ip_input().
- * 1 = drop packet, 0 = continue processing packet.
- */
-int
-ip_ipsec_input(struct mbuf *m, int nxt)
-{
- /*
- * enforce IPsec policy checking if we are seeing last header.
- * note that we do not visit this with protocols with pcb layer
- * code - like udp/tcp/raw ip.
- */
- if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0)
- return (ipsec4_in_reject(m, NULL));
- return (0);
-}
-
-/*
- * Compute the MTU for a forwarded packet that gets IPSEC encapsulated.
- * Called from ip_forward().
- * Returns MTU suggestion for ICMP needfrag reply.
- */
-int
-ip_ipsec_mtu(struct mbuf *m, int mtu)
-{
- /*
- * If the packet is routed over IPsec tunnel, tell the
- * originator the tunnel MTU.
- * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
- * XXX quickhack!!!
- */
- return (mtu - ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, NULL));
-}
-
-/*
- *
- * Called from ip_output().
- * 1 = drop packet, 0 = continue processing packet,
- * -1 = packet was reinjected and stop processing packet
- */
-int
-ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *error)
-{
- struct secpolicy *sp;
-
- if (!key_havesp(IPSEC_DIR_OUTBOUND))
- return 0;
-
- /*
- * Check the security policy (SP) for the packet and, if
- * required, do IPsec-related processing. There are two
- * cases here; the first time a packet is sent through
- * it will be untagged and handled by ipsec4_checkpolicy.
- * If the packet is resubmitted to ip_output (e.g. after
- * AH, ESP, etc. processing), there will be a tag to bypass
- * the lookup and related policy checking.
- */
- if (m_tag_find(*m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) {
- *error = 0;
- return (0);
- }
- sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, error, inp);
- /*
- * There are four return cases:
- * sp != NULL apply IPsec policy
- * sp == NULL, error == 0 no IPsec handling needed
- * sp == NULL, error == -EINVAL discard packet w/o error
- * sp == NULL, error != 0 discard packet, report error
- */
- if (sp != NULL) {
- /*
- * Do delayed checksums now because we send before
- * this is done in the normal processing path.
- */
- if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
- in_delayed_cksum(*m);
- (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
- }
-#ifdef SCTP
- if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) {
- struct ip *ip = mtod(*m, struct ip *);
-
- sctp_delayed_cksum(*m, (uint32_t)(ip->ip_hl << 2));
- (*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP;
- }
-#endif
-
- /* NB: callee frees mbuf */
- *error = ipsec4_process_packet(*m, sp->req);
- KEY_FREESP(&sp);
- if (*error == EJUSTRETURN) {
- /*
- * We had a SP with a level of 'use' and no SA. We
- * will just continue to process the packet without
- * IPsec processing and return without error.
- */
- *error = 0;
- goto done;
- }
- /*
- * Preserve KAME behaviour: ENOENT can be returned
- * when an SA acquire is in progress. Don't propagate
- * this to user-level; it confuses applications.
- *
- * XXX this will go away when the SADB is redone.
- */
- if (*error == ENOENT)
- *error = 0;
- goto reinjected;
- } else { /* sp == NULL */
-
- if (*error != 0) {
- /*
- * Hack: -EINVAL is used to signal that a packet
- * should be silently discarded. This is typically
- * because we asked key management for an SA and
- * it was delayed (e.g. kicked up to IKE).
- */
- if (*error == -EINVAL)
- *error = 0;
- goto bad;
- }
- /* No IPsec processing for this packet. */
- }
-done:
- return (0);
-reinjected:
- return (-1);
-bad:
- if (sp != NULL)
- KEY_FREESP(&sp);
- return 1;
-}
diff --git a/sys/netinet/ip_ipsec.h b/sys/netinet/ip_ipsec.h
deleted file mode 100644
index f499b74..0000000
--- a/sys/netinet/ip_ipsec.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 1988, 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.
- * 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$
- */
-
-#ifndef _NETINET_IP_IPSEC_H_
-#define _NETINET_IP_IPSEC_H_
-
-int ip_ipsec_filtertunnel(struct mbuf *);
-int ip_ipsec_fwd(struct mbuf *);
-int ip_ipsec_input(struct mbuf *, int);
-int ip_ipsec_mtu(struct mbuf *, int);
-int ip_ipsec_output(struct mbuf **, struct inpcb *, int *);
-#endif
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index b1564a2..7b59b72 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -83,10 +83,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_crc32.h>
#endif
-#ifdef IPSEC
-#include <netinet/ip_ipsec.h>
-#include <netipsec/ipsec.h>
-#endif /* IPSEC*/
+#include <netipsec/ipsec_support.h>
#include <machine/in_cksum.h>
@@ -227,7 +224,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
struct rtentry *rte; /* cache for ro->ro_rt */
uint32_t fibnum;
int have_ia_ref;
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
int no_route_but_check_spd = 0;
#endif
M_ASSERTPKTHDR(m);
@@ -382,7 +379,7 @@ again:
(rte->rt_flags & RTF_UP) == 0 ||
rte->rt_ifp == NULL ||
!RT_LINK_IS_UP(rte->rt_ifp)) {
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/*
* There is no route for this packet, but it is
* possible that a matching SPD entry exists.
@@ -552,15 +549,13 @@ again:
}
sendit:
-#ifdef IPSEC
- switch(ip_ipsec_output(&m, inp, &error)) {
- case 1:
- goto bad;
- case -1:
- goto done;
- case 0:
- default:
- break; /* Continue with packet processing. */
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+ if (IPSEC_ENABLED(ipv4)) {
+ if ((error = IPSEC_OUTPUT(ipv4, m, inp)) != 0) {
+ if (error == EINPROGRESS)
+ error = 0;
+ goto done;
+ }
}
/*
* Check if there was a route for this packet; return error if not.
@@ -1190,23 +1185,13 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
INP_WUNLOCK(inp);
break;
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
case IP_IPSEC_POLICY:
- {
- caddr_t req;
- struct mbuf *m;
-
- if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
+ if (IPSEC_ENABLED(ipv4)) {
+ error = IPSEC_PCBCTL(ipv4, inp, sopt);
break;
- if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
- break;
- req = mtod(m, caddr_t);
- error = ipsec_set_policy(inp, sopt->sopt_name, req,
- m->m_len, (sopt->sopt_td != NULL) ?
- sopt->sopt_td->td_ucred : NULL);
- m_freem(m);
- break;
- }
+ }
+ /* FALLTHROUGH */
#endif /* IPSEC */
default:
@@ -1349,24 +1334,13 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
error = inp_getmoptions(inp, sopt);
break;
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
case IP_IPSEC_POLICY:
- {
- struct mbuf *m = NULL;
- caddr_t req = NULL;
- size_t len = 0;
-
- if (m != NULL) {
- req = mtod(m, caddr_t);
- len = m->m_len;
+ if (IPSEC_ENABLED(ipv4)) {
+ error = IPSEC_PCBCTL(ipv4, inp, sopt);
+ break;
}
- error = ipsec_get_policy(sotoinpcb(so), req, len, &m);
- if (error == 0)
- error = soopt_mcopyout(sopt, m); /* XXX */
- if (error == 0)
- m_freem(m);
- break;
- }
+ /* FALLTHROUGH */
#endif /* IPSEC */
default:
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 6d40954..661bbf4 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -73,9 +73,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip_mroute.h>
#include <netinet/ip_icmp.h>
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#endif /*IPSEC*/
+#include <netipsec/ipsec_support.h>
#include <machine/stdarg.h>
#include <security/mac/mac_framework.h>
@@ -236,10 +234,11 @@ rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
INP_LOCK_ASSERT(last);
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/* check AH/ESP integrity. */
- if (ipsec4_in_reject(n, last)) {
- policyfail = 1;
+ if (IPSEC_ENABLED(ipv4)) {
+ if (IPSEC_CHECK_POLICY(ipv4, n, last) != 0)
+ policyfail = 1;
}
#endif /* IPSEC */
#ifdef MAC
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 5aa56ba..956b159 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -5790,34 +5790,6 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
} else if (stcb == NULL) {
inp_decr = inp;
}
-#ifdef IPSEC
- /*-
- * I very much doubt any of the IPSEC stuff will work but I have no
- * idea, so I will leave it in place.
- */
- if (inp != NULL) {
- switch (dst->sa_family) {
-#ifdef INET
- case AF_INET:
- if (ipsec4_in_reject(m, &inp->ip_inp.inp)) {
- SCTP_STAT_INCR(sctps_hdrops);
- goto out;
- }
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- if (ipsec6_in_reject(m, &inp->ip_inp.inp)) {
- SCTP_STAT_INCR(sctps_hdrops);
- goto out;
- }
- break;
-#endif
- default:
- break;
- }
- }
-#endif
SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n",
(void *)m, iphlen, offset, length, (void *)stcb);
if (stcb) {
diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h
index b0c92da..b439b59 100644
--- a/sys/netinet/sctp_os_bsd.h
+++ b/sys/netinet/sctp_os_bsd.h
@@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
/*
* includes
*/
-#include "opt_ipsec.h"
#include "opt_compat.h"
#include "opt_inet6.h"
#include "opt_inet.h"
@@ -82,16 +81,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip_icmp.h>
#include <netinet/icmp_var.h>
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#include <netipsec/key.h>
-#endif /* IPSEC */
-
#ifdef INET6
#include <sys/domain.h>
-#ifdef IPSEC
-#include <netipsec/ipsec6.h>
-#endif
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_pcb.h>
@@ -100,7 +91,6 @@ __FBSDID("$FreeBSD$");
#include <netinet6/scope6_var.h>
#endif /* INET6 */
-
#include <netinet/ip_options.h>
#include <crypto/sha1.h>
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index ffc3a7e..db3f39c 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2469,15 +2469,6 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
SCTP_INP_INFO_WUNLOCK();
return (ENOBUFS);
}
-#ifdef IPSEC
- error = ipsec_init_policy(so, &inp->ip_inp.inp.inp_sp);
- if (error != 0) {
- crfree(inp->ip_inp.inp.inp_cred);
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
- SCTP_INP_INFO_WUNLOCK();
- return error;
- }
-#endif /* IPSEC */
SCTP_INCR_EP_COUNT();
inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
SCTP_INP_INFO_WUNLOCK();
@@ -2504,9 +2495,6 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP);
so->so_pcb = NULL;
crfree(inp->ip_inp.inp.inp_cred);
-#ifdef IPSEC
- ipsec_delete_pcbpolicy(&inp->ip_inp.inp);
-#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
return (EOPNOTSUPP);
}
@@ -2527,9 +2515,6 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
so->so_pcb = NULL;
crfree(inp->ip_inp.inp.inp_cred);
-#ifdef IPSEC
- ipsec_delete_pcbpolicy(&inp->ip_inp.inp);
-#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
return (ENOBUFS);
}
@@ -3641,9 +3626,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* macro here since le_next will get freed as part of the
* sctp_free_assoc() call.
*/
-#ifdef IPSEC
- ipsec_delete_pcbpolicy(ip_pcb);
-#endif
if (ip_pcb->inp_options) {
(void)sctp_m_free(ip_pcb->inp_options);
ip_pcb->inp_options = 0;
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index de71c31..3c6e604 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -118,10 +118,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_offload.h>
#endif
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#include <netipsec/ipsec6.h>
-#endif /*IPSEC*/
+#include <netipsec/ipsec_support.h>
#include <machine/in_cksum.h>
@@ -474,20 +471,6 @@ cc_post_recovery(struct tcpcb *tp, struct tcphdr *th)
tp->t_bytes_acked = 0;
}
-#ifdef TCP_SIGNATURE
-static inline int
-tcp_signature_verify_input(struct mbuf *m, int off0, int tlen, int optlen,
- struct tcpopt *to, struct tcphdr *th, u_int tcpbflag)
-{
- int ret;
-
- tcp_fields_to_net(th);
- ret = tcp_signature_verify(m, off0, tlen, optlen, to, th, tcpbflag);
- tcp_fields_to_host(th);
- return (ret);
-}
-#endif
-
/*
* Indicate whether this ack should be delayed. We can delay the ack if
* following conditions are met:
@@ -598,9 +581,6 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
int drop_hdrlen;
int thflags;
int rstreason = 0; /* For badport_bandlim accounting purposes */
-#ifdef TCP_SIGNATURE
- uint8_t sig_checked = 0;
-#endif
uint8_t iptos;
struct m_tag *fwd_tag = NULL;
#ifdef INET6
@@ -931,15 +911,22 @@ findpcb:
inp->inp_flowid = m->m_pkthdr.flowid;
inp->inp_flowtype = M_HASHTYPE_GET(m);
}
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
#ifdef INET6
- if (isipv6 && ipsec6_in_reject(m, inp)) {
+ if (isipv6 && IPSEC_ENABLED(ipv6) &&
+ IPSEC_CHECK_POLICY(ipv6, m, inp) != 0) {
goto dropunlock;
- } else
+ }
+#ifdef INET
+ else
+#endif
#endif /* INET6 */
- if (ipsec4_in_reject(m, inp) != 0) {
+#ifdef INET
+ if (IPSEC_ENABLED(ipv4) &&
+ IPSEC_CHECK_POLICY(ipv4, m, inp) != 0) {
goto dropunlock;
}
+#endif /* INET */
#endif /* IPSEC */
/*
@@ -1122,7 +1109,16 @@ relocked:
* NB: syncache_expand() doesn't unlock
* inp and tcpinfo locks.
*/
- if (!syncache_expand(&inc, &to, th, &so, m)) {
+ rstreason = syncache_expand(&inc, &to, th, &so, m);
+ if (rstreason < 0) {
+ /*
+ * A failing TCP MD5 signature comparison
+ * must result in the segment being dropped
+ * and must not produce any response back
+ * to the sender.
+ */
+ goto dropunlock;
+ } else if (rstreason == 0) {
/*
* No syncache entry or ACK was not
* for our SYN/ACK. Send a RST.
@@ -1174,26 +1170,6 @@ new_tfo_socket:
tp = intotcpcb(inp);
KASSERT(tp->t_state == TCPS_SYN_RECEIVED,
("%s: ", __func__));
-#ifdef TCP_SIGNATURE
- if (sig_checked == 0) {
- tcp_dooptions(&to, optp, optlen,
- (thflags & TH_SYN) ? TO_SYN : 0);
- if (!tcp_signature_verify_input(m, off0, tlen,
- optlen, &to, th, tp->t_flags)) {
-
- /*
- * In SYN_SENT state if it receives an
- * RST, it is allowed for further
- * processing.
- */
- if ((thflags & TH_RST) == 0 ||
- (tp->t_state == TCPS_SYN_SENT) == 0)
- goto dropunlock;
- }
- sig_checked = 1;
- }
-#endif
-
/*
* Process the segment and the data it
* contains. tcp_do_segment() consumes
@@ -1423,26 +1399,18 @@ new_tfo_socket:
*/
goto dropunlock;
}
-
-#ifdef TCP_SIGNATURE
- if (sig_checked == 0) {
- tcp_dooptions(&to, optp, optlen,
- (thflags & TH_SYN) ? TO_SYN : 0);
- if (!tcp_signature_verify_input(m, off0, tlen, optlen, &to,
- th, tp->t_flags)) {
-
- /*
- * In SYN_SENT state if it receives an RST, it is
- * allowed for further processing.
- */
- if ((thflags & TH_RST) == 0 ||
- (tp->t_state == TCPS_SYN_SENT) == 0)
- goto dropunlock;
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
+ if (tp->t_flags & TF_SIGNATURE) {
+ tcp_dooptions(&to, optp, optlen, thflags);
+ if ((to.to_flags & TOF_SIGNATURE) == 0) {
+ TCPSTAT_INC(tcps_sig_err_nosigopt);
+ goto dropunlock;
}
- sig_checked = 1;
+ if (!TCPMD5_ENABLED() ||
+ TCPMD5_INPUT(m, th, to.to_signature) != 0)
+ goto dropunlock;
}
#endif
-
TCP_PROBE5(receive, NULL, tp, mtod(m, const char *), tp, th);
/*
@@ -1617,6 +1585,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
(th->th_off << 2) - sizeof(struct tcphdr),
(thflags & TH_SYN) ? TO_SYN : 0);
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
+ if ((tp->t_flags & TF_SIGNATURE) != 0 &&
+ (to.to_flags & TOF_SIGNATURE) == 0) {
+ TCPSTAT_INC(tcps_sig_err_sigopt);
+ /* XXX: should drop? */
+ }
+#endif
/*
* If echoed timestamp is later than the current time,
* fall back to non RFC1323 RTT calculation. Normalize
@@ -3378,20 +3353,19 @@ tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags)
(char *)&to->to_tsecr, sizeof(to->to_tsecr));
to->to_tsecr = ntohl(to->to_tsecr);
break;
-#ifdef TCP_SIGNATURE
- /*
- * XXX In order to reply to a host which has set the
- * TCP_SIGNATURE option in its initial SYN, we have to
- * record the fact that the option was observed here
- * for the syncache code to perform the correct response.
- */
case TCPOPT_SIGNATURE:
+ /*
+ * In order to reply to a host which has set the
+ * TCP_SIGNATURE option in its initial SYN, we have
+ * to record the fact that the option was observed
+ * here for the syncache code to perform the correct
+ * response.
+ */
if (optlen != TCPOLEN_SIGNATURE)
continue;
to->to_flags |= TOF_SIGNATURE;
to->to_signature = cp + 2;
break;
-#endif
case TCPOPT_SACK_PERMITTED:
if (optlen != TCPOLEN_SACK_PERMITTED)
continue;
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 6519f99..adb46d3 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -88,9 +88,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_offload.h>
#endif
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#endif /*IPSEC*/
+#include <netipsec/ipsec_support.h>
#include <machine/in_cksum.h>
@@ -193,7 +191,7 @@ tcp_output(struct tcpcb *tp)
struct tcphdr *th;
u_char opt[TCP_MAXOLEN];
unsigned ipoptlen, optlen, hdrlen;
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
unsigned ipsec_optlen = 0;
#endif
int idle, sendalot;
@@ -545,14 +543,23 @@ after_sack_rexmit:
* the right thing below to provide length of just ip options and thus
* checking for ipoptlen is enough to decide if ip options are present.
*/
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/*
* Pre-calculate here as we save another lookup into the darknesses
* of IPsec that way and can actually decide if TSO is ok.
*/
- ipsec_optlen = ipsec_hdrsiz_tcp(tp);
+#ifdef INET6
+ if (isipv6 && IPSEC_ENABLED(ipv6))
+ ipsec_optlen = IPSEC_HDRSIZE(ipv6, tp->t_inpcb);
+#ifdef INET
+ else
#endif
-
+#endif /* INET6 */
+#ifdef INET
+ if (IPSEC_ENABLED(ipv4))
+ ipsec_optlen = IPSEC_HDRSIZE(ipv4, tp->t_inpcb);
+#endif /* INET */
+#endif /* IPSEC */
#ifdef INET6
if (isipv6)
ipoptlen = ip6_optlen(tp->t_inpcb);
@@ -563,7 +570,7 @@ after_sack_rexmit:
offsetof(struct ipoption, ipopt_list);
else
ipoptlen = 0;
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
ipoptlen += ipsec_optlen;
#endif
@@ -831,8 +838,12 @@ send:
to.to_sacks = (u_char *)tp->sackblks;
}
}
-#ifdef TCP_SIGNATURE
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
/* TCP-MD5 (RFC2385). */
+ /*
+ * Check that TCP_MD5SIG is enabled in tcpcb to
+ * account the size needed to set this TCP option.
+ */
if (tp->t_flags & TF_SIGNATURE)
to.to_flags |= TOF_SIGNATURE;
#endif /* TCP_SIGNATURE */
@@ -1245,20 +1256,31 @@ send:
*/
tp->snd_up = tp->snd_una; /* drag it along */
-#ifdef TCP_SIGNATURE
- if (to.to_flags & TOF_SIGNATURE) {
- int sigoff = to.to_signature - opt;
- tcp_signature_compute(m, 0, len, optlen,
- (u_char *)(th + 1) + sigoff, IPSEC_DIR_OUTBOUND);
- }
-#endif
-
/*
* Put TCP length in extended header, and then
* checksum extended header and data.
*/
m->m_pkthdr.len = hdrlen + len; /* in6_cksum() need this */
m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
+ if (to.to_flags & TOF_SIGNATURE) {
+ /*
+ * Calculate MD5 signature and put it into the place
+ * determined before.
+ * NOTE: since TCP options buffer doesn't point into
+ * mbuf's data, calculate offset and use it.
+ */
+ if (!TCPMD5_ENABLED() || TCPMD5_OUTPUT(m, th,
+ (u_char *)(th + 1) + (to.to_signature - opt)) != 0) {
+ /*
+ * Do not send segment if the calculation of MD5
+ * digest has failed.
+ */
+ goto out;
+ }
+ }
+#endif
#ifdef INET6
if (isipv6) {
/*
@@ -1296,7 +1318,7 @@ send:
m->m_pkthdr.tso_segsz = tp->t_maxseg - optlen;
}
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
KASSERT(len + hdrlen + ipoptlen - ipsec_optlen == m_length(m, NULL),
("%s: mbuf chain shorter than expected: %ld + %u + %u - %u != %u",
__func__, len, hdrlen, ipoptlen, ipsec_optlen, m_length(m, NULL)));
@@ -1553,6 +1575,9 @@ timer:
}
SOCKBUF_UNLOCK_ASSERT(&so->so_snd); /* Check gotos. */
switch (error) {
+ case EACCES:
+ tp->t_softerror = error;
+ return (0);
case EPERM:
tp->t_softerror = error;
return (error);
@@ -1720,7 +1745,6 @@ tcp_addoptions(struct tcpopt *to, u_char *optp)
bcopy((u_char *)&to->to_tsecr, optp, sizeof(to->to_tsecr));
optp += sizeof(to->to_tsecr);
break;
-#ifdef TCP_SIGNATURE
case TOF_SIGNATURE:
{
int siglen = TCPOLEN_SIGNATURE - 2;
@@ -1729,8 +1753,10 @@ tcp_addoptions(struct tcpopt *to, u_char *optp)
optlen += TCPOLEN_NOP;
*optp++ = TCPOPT_NOP;
}
- if (TCP_MAXOLEN - optlen < TCPOLEN_SIGNATURE)
+ if (TCP_MAXOLEN - optlen < TCPOLEN_SIGNATURE) {
+ to->to_flags &= ~TOF_SIGNATURE;
continue;
+ }
optlen += TCPOLEN_SIGNATURE;
*optp++ = TCPOPT_SIGNATURE;
*optp++ = TCPOLEN_SIGNATURE;
@@ -1739,7 +1765,6 @@ tcp_addoptions(struct tcpopt *to, u_char *optp)
*optp++ = 0;
break;
}
-#endif
case TOF_SACK:
{
int sackblks = 0;
diff --git a/sys/netinet/tcp_stacks/fastpath.c b/sys/netinet/tcp_stacks/fastpath.c
index 4b1bfdc..b1c1507 100644
--- a/sys/netinet/tcp_stacks/fastpath.c
+++ b/sys/netinet/tcp_stacks/fastpath.c
@@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
-#include "opt_ipsec.h"
#include "opt_tcpdebug.h"
#include <sys/param.h>
@@ -113,11 +112,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_offload.h>
#endif
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#include <netipsec/ipsec6.h>
-#endif /*IPSEC*/
-
#include <machine/in_cksum.h>
#include <security/mac/mac_framework.h>
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 662c435..4fd388b 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -114,15 +114,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_offload.h>
#endif
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#include <netipsec/xform.h>
-#ifdef INET6
-#include <netipsec/ipsec6.h>
-#endif
-#include <netipsec/key.h>
-#include <sys/syslog.h>
-#endif /*IPSEC*/
+#include <netipsec/ipsec_support.h>
#include <machine/in_cksum.h>
#include <sys/md5.h>
@@ -229,12 +221,6 @@ static int tcp_soreceive_stream;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, soreceive_stream, CTLFLAG_RDTUN,
&tcp_soreceive_stream, 0, "Using soreceive_stream for TCP sockets");
-#ifdef TCP_SIGNATURE
-static int tcp_sig_checksigs = 1;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, signature_verify_input, CTLFLAG_RW,
- &tcp_sig_checksigs, 0, "Verify RFC2385 digests on inbound traffic");
-#endif
-
VNET_DEFINE(uma_zone_t, sack_hole_zone);
#define V_sack_hole_zone VNET(sack_hole_zone)
@@ -1049,12 +1035,11 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m,
to.to_tsecr = tp->ts_recent;
to.to_flags |= TOF_TS;
}
-#ifdef TCP_SIGNATURE
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
/* TCP-MD5 (RFC2385). */
if (tp->t_flags & TF_SIGNATURE)
to.to_flags |= TOF_SIGNATURE;
#endif
-
/* Add the options. */
tlen += optlen = tcp_addoptions(&to, optp);
@@ -1110,10 +1095,13 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m,
nth->th_win = htons((u_short)win);
nth->th_urp = 0;
-#ifdef TCP_SIGNATURE
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
if (to.to_flags & TOF_SIGNATURE) {
- tcp_signature_compute(m, 0, 0, optlen, to.to_signature,
- IPSEC_DIR_OUTBOUND);
+ if (!TCPMD5_ENABLED() ||
+ TCPMD5_OUTPUT(m, nth, to.to_signature) != 0) {
+ m_freem(m);
+ return;
+ }
}
#endif
@@ -2483,7 +2471,7 @@ tcp_maxseg(const struct tcpcb *tp)
optlen = TCPOLEN_TSTAMP_APPA;
else
optlen = 0;
-#ifdef TCP_SIGNATURE
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
if (tp->t_flags & TF_SIGNATURE)
optlen += PAD(TCPOLEN_SIGNATURE);
#endif
@@ -2499,7 +2487,7 @@ tcp_maxseg(const struct tcpcb *tp)
optlen = PAD(TCPOLEN_MAXSEG);
if (tp->t_flags & TF_REQ_SCALE)
optlen += PAD(TCPOLEN_WINDOW);
-#ifdef TCP_SIGNATURE
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
if (tp->t_flags & TF_SIGNATURE)
optlen += PAD(TCPOLEN_SIGNATURE);
#endif
@@ -2511,343 +2499,6 @@ tcp_maxseg(const struct tcpcb *tp)
return (tp->t_maxseg - optlen);
}
-#ifdef IPSEC
-/* compute ESP/AH header size for TCP, including outer IP header. */
-size_t
-ipsec_hdrsiz_tcp(struct tcpcb *tp)
-{
- struct inpcb *inp;
- struct mbuf *m;
- size_t hdrsiz;
- struct ip *ip;
-#ifdef INET6
- struct ip6_hdr *ip6;
-#endif
- struct tcphdr *th;
-
- if ((tp == NULL) || ((inp = tp->t_inpcb) == NULL) ||
- (!key_havesp(IPSEC_DIR_OUTBOUND)))
- return (0);
- m = m_gethdr(M_NOWAIT, MT_DATA);
- if (!m)
- return (0);
-
-#ifdef INET6
- if ((inp->inp_vflag & INP_IPV6) != 0) {
- ip6 = mtod(m, struct ip6_hdr *);
- th = (struct tcphdr *)(ip6 + 1);
- m->m_pkthdr.len = m->m_len =
- sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
- tcpip_fillheaders(inp, ip6, th);
- hdrsiz = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
- } else
-#endif /* INET6 */
- {
- ip = mtod(m, struct ip *);
- th = (struct tcphdr *)(ip + 1);
- m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr);
- tcpip_fillheaders(inp, ip, th);
- hdrsiz = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
- }
-
- m_free(m);
- return (hdrsiz);
-}
-#endif /* IPSEC */
-
-#ifdef TCP_SIGNATURE
-/*
- * Callback function invoked by m_apply() to digest TCP segment data
- * contained within an mbuf chain.
- */
-static int
-tcp_signature_apply(void *fstate, void *data, u_int len)
-{
-
- MD5Update(fstate, (u_char *)data, len);
- return (0);
-}
-
-/*
- * XXX The key is retrieved from the system's PF_KEY SADB, by keying a
- * search with the destination IP address, and a 'magic SPI' to be
- * determined by the application. This is hardcoded elsewhere to 1179
-*/
-struct secasvar *
-tcp_get_sav(struct mbuf *m, u_int direction)
-{
- union sockaddr_union dst;
- struct secasvar *sav;
- struct ip *ip;
-#ifdef INET6
- struct ip6_hdr *ip6;
- char ip6buf[INET6_ADDRSTRLEN];
-#endif
-
- /* Extract the destination from the IP header in the mbuf. */
- bzero(&dst, sizeof(union sockaddr_union));
- ip = mtod(m, struct ip *);
-#ifdef INET6
- ip6 = NULL; /* Make the compiler happy. */
-#endif
- switch (ip->ip_v) {
-#ifdef INET
- case IPVERSION:
- dst.sa.sa_len = sizeof(struct sockaddr_in);
- dst.sa.sa_family = AF_INET;
- dst.sin.sin_addr = (direction == IPSEC_DIR_INBOUND) ?
- ip->ip_src : ip->ip_dst;
- break;
-#endif
-#ifdef INET6
- case (IPV6_VERSION >> 4):
- ip6 = mtod(m, struct ip6_hdr *);
- dst.sa.sa_len = sizeof(struct sockaddr_in6);
- dst.sa.sa_family = AF_INET6;
- dst.sin6.sin6_addr = (direction == IPSEC_DIR_INBOUND) ?
- ip6->ip6_src : ip6->ip6_dst;
- break;
-#endif
- default:
- return (NULL);
- /* NOTREACHED */
- break;
- }
-
- /* Look up an SADB entry which matches the address of the peer. */
- sav = KEY_ALLOCSA(&dst, IPPROTO_TCP, htonl(TCP_SIG_SPI));
- if (sav == NULL) {
- ipseclog((LOG_ERR, "%s: SADB lookup failed for %s\n", __func__,
- (ip->ip_v == IPVERSION) ? inet_ntoa(dst.sin.sin_addr) :
-#ifdef INET6
- (ip->ip_v == (IPV6_VERSION >> 4)) ?
- ip6_sprintf(ip6buf, &dst.sin6.sin6_addr) :
-#endif
- "(unsupported)"));
- }
-
- return (sav);
-}
-
-/*
- * Compute TCP-MD5 hash of a TCP segment. (RFC2385)
- *
- * Parameters:
- * m pointer to head of mbuf chain
- * len length of TCP segment data, excluding options
- * optlen length of TCP segment options
- * buf pointer to storage for computed MD5 digest
- * sav pointer to security assosiation
- *
- * We do this over ip, tcphdr, segment data, and the key in the SADB.
- * When called from tcp_input(), we can be sure that th_sum has been
- * zeroed out and verified already.
- *
- * Releases reference to SADB key before return.
- *
- * Return 0 if successful, otherwise return -1.
- *
- */
-int
-tcp_signature_do_compute(struct mbuf *m, int len, int optlen,
- u_char *buf, struct secasvar *sav)
-{
-#ifdef INET
- struct ippseudo ippseudo;
-#endif
- MD5_CTX ctx;
- int doff;
- struct ip *ip;
-#ifdef INET
- struct ipovly *ipovly;
-#endif
- struct tcphdr *th;
-#ifdef INET6
- struct ip6_hdr *ip6;
- struct in6_addr in6;
- uint32_t plen;
- uint16_t nhdr;
-#endif
- u_short savecsum;
-
- KASSERT(m != NULL, ("NULL mbuf chain"));
- KASSERT(buf != NULL, ("NULL signature pointer"));
-
- /* Extract the destination from the IP header in the mbuf. */
- ip = mtod(m, struct ip *);
-#ifdef INET6
- ip6 = NULL; /* Make the compiler happy. */
-#endif
-
- MD5Init(&ctx);
- /*
- * Step 1: Update MD5 hash with IP(v6) pseudo-header.
- *
- * XXX The ippseudo header MUST be digested in network byte order,
- * or else we'll fail the regression test. Assume all fields we've
- * been doing arithmetic on have been in host byte order.
- * XXX One cannot depend on ipovly->ih_len here. When called from
- * tcp_output(), the underlying ip_len member has not yet been set.
- */
- switch (ip->ip_v) {
-#ifdef INET
- case IPVERSION:
- ipovly = (struct ipovly *)ip;
- ippseudo.ippseudo_src = ipovly->ih_src;
- ippseudo.ippseudo_dst = ipovly->ih_dst;
- ippseudo.ippseudo_pad = 0;
- ippseudo.ippseudo_p = IPPROTO_TCP;
- ippseudo.ippseudo_len = htons(len + sizeof(struct tcphdr) +
- optlen);
- MD5Update(&ctx, (char *)&ippseudo, sizeof(struct ippseudo));
-
- th = (struct tcphdr *)((u_char *)ip + sizeof(struct ip));
- doff = sizeof(struct ip) + sizeof(struct tcphdr) + optlen;
- break;
-#endif
-#ifdef INET6
- /*
- * RFC 2385, 2.0 Proposal
- * For IPv6, the pseudo-header is as described in RFC 2460, namely the
- * 128-bit source IPv6 address, 128-bit destination IPv6 address, zero-
- * extended next header value (to form 32 bits), and 32-bit segment
- * length.
- * Note: Upper-Layer Packet Length comes before Next Header.
- */
- case (IPV6_VERSION >> 4):
- ip6 = mtod(m, struct ip6_hdr *);
- in6 = ip6->ip6_src;
- in6_clearscope(&in6);
- MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr));
- in6 = ip6->ip6_dst;
- in6_clearscope(&in6);
- MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr));
- plen = htonl(len + sizeof(struct tcphdr) + optlen);
- MD5Update(&ctx, (char *)&plen, sizeof(uint32_t));
- nhdr = 0;
- MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
- MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
- MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
- nhdr = IPPROTO_TCP;
- MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
-
- th = (struct tcphdr *)((u_char *)ip6 + sizeof(struct ip6_hdr));
- doff = sizeof(struct ip6_hdr) + sizeof(struct tcphdr) + optlen;
- break;
-#endif
- default:
- KEY_FREESAV(&sav);
- return (-1);
- /* NOTREACHED */
- break;
- }
-
-
- /*
- * Step 2: Update MD5 hash with TCP header, excluding options.
- * The TCP checksum must be set to zero.
- */
- savecsum = th->th_sum;
- th->th_sum = 0;
- MD5Update(&ctx, (char *)th, sizeof(struct tcphdr));
- th->th_sum = savecsum;
-
- /*
- * Step 3: Update MD5 hash with TCP segment data.
- * Use m_apply() to avoid an early m_pullup().
- */
- if (len > 0)
- m_apply(m, doff, len, tcp_signature_apply, &ctx);
-
- /*
- * Step 4: Update MD5 hash with shared secret.
- */
- MD5Update(&ctx, sav->key_auth->key_data, _KEYLEN(sav->key_auth));
- MD5Final(buf, &ctx);
-
- key_sa_recordxfer(sav, m);
- KEY_FREESAV(&sav);
- return (0);
-}
-
-/*
- * Compute TCP-MD5 hash of a TCP segment. (RFC2385)
- *
- * Return 0 if successful, otherwise return -1.
- */
-int
-tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen,
- u_char *buf, u_int direction)
-{
- struct secasvar *sav;
-
- if ((sav = tcp_get_sav(m, direction)) == NULL)
- return (-1);
-
- return (tcp_signature_do_compute(m, len, optlen, buf, sav));
-}
-
-/*
- * Verify the TCP-MD5 hash of a TCP segment. (RFC2385)
- *
- * Parameters:
- * m pointer to head of mbuf chain
- * len length of TCP segment data, excluding options
- * optlen length of TCP segment options
- * buf pointer to storage for computed MD5 digest
- * direction direction of flow (IPSEC_DIR_INBOUND or OUTBOUND)
- *
- * Return 1 if successful, otherwise return 0.
- */
-int
-tcp_signature_verify(struct mbuf *m, int off0, int tlen, int optlen,
- struct tcpopt *to, struct tcphdr *th, u_int tcpbflag)
-{
- char tmpdigest[TCP_SIGLEN];
-
- if (tcp_sig_checksigs == 0)
- return (1);
- if ((tcpbflag & TF_SIGNATURE) == 0) {
- if ((to->to_flags & TOF_SIGNATURE) != 0) {
-
- /*
- * If this socket is not expecting signature but
- * the segment contains signature just fail.
- */
- TCPSTAT_INC(tcps_sig_err_sigopt);
- TCPSTAT_INC(tcps_sig_rcvbadsig);
- return (0);
- }
-
- /* Signature is not expected, and not present in segment. */
- return (1);
- }
-
- /*
- * If this socket is expecting signature but the segment does not
- * contain any just fail.
- */
- if ((to->to_flags & TOF_SIGNATURE) == 0) {
- TCPSTAT_INC(tcps_sig_err_nosigopt);
- TCPSTAT_INC(tcps_sig_rcvbadsig);
- return (0);
- }
- if (tcp_signature_compute(m, off0, tlen, optlen, &tmpdigest[0],
- IPSEC_DIR_INBOUND) == -1) {
- TCPSTAT_INC(tcps_sig_err_buildsig);
- TCPSTAT_INC(tcps_sig_rcvbadsig);
- return (0);
- }
-
- if (bcmp(to->to_signature, &tmpdigest[0], TCP_SIGLEN) != 0) {
- TCPSTAT_INC(tcps_sig_rcvbadsig);
- return (0);
- }
- TCPSTAT_INC(tcps_sig_rcvgoodsig);
- return (1);
-}
-#endif /* TCP_SIGNATURE */
-
static int
sysctl_drop(SYSCTL_HANDLER_ARGS)
{
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index ee9bf95..2c24f0e 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -96,13 +96,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/toecore.h>
#endif
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#ifdef INET6
-#include <netipsec/ipsec6.h>
-#endif
-#include <netipsec/key.h>
-#endif /*IPSEC*/
+#include <netipsec/ipsec_support.h>
#include <machine/in_cksum.h>
@@ -736,11 +730,6 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
INP_HASH_WUNLOCK(&V_tcbinfo);
goto abort;
}
-#ifdef IPSEC
- /* Copy old policy into new socket's. */
- if (ipsec_copy_policy(sotoinpcb(lso)->inp_sp, inp->inp_sp))
- printf("syncache_socket: could not copy policy\n");
-#endif
#ifdef INET6
if (sc->sc_inc.inc_flags & INC_ISIPV6) {
struct inpcb *oinp = sotoinpcb(lso);
@@ -822,6 +811,11 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
}
}
#endif /* INET */
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+ /* Copy old policy into new socket's. */
+ if (ipsec_copy_pcbpolicy(sotoinpcb(lso), inp) != 0)
+ printf("syncache_socket: could not copy policy\n");
+#endif
INP_HASH_WUNLOCK(&V_tcbinfo);
tp = intotcpcb(inp);
tcp_state_change(tp, TCPS_SYN_RECEIVED);
@@ -872,7 +866,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
tp->ts_recent_age = tcp_ts_getticks();
tp->ts_offset = sc->sc_tsoff;
}
-#ifdef TCP_SIGNATURE
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
if (sc->sc_flags & SCF_SIGNATURE)
tp->t_flags |= TF_SIGNATURE;
#endif
@@ -996,7 +990,57 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
"(probably spoofed)\n", s, __func__);
goto failed;
}
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
+ /* If received ACK has MD5 signature, check it. */
+ if ((to->to_flags & TOF_SIGNATURE) != 0 &&
+ (!TCPMD5_ENABLED() ||
+ TCPMD5_INPUT(m, th, to->to_signature) != 0)) {
+ /* Drop the ACK. */
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Segment rejected, "
+ "MD5 signature doesn't match.\n",
+ s, __func__);
+ free(s, M_TCPLOG);
+ }
+ TCPSTAT_INC(tcps_sig_err_sigopt);
+ return (-1); /* Do not send RST */
+ }
+#endif /* TCP_SIGNATURE */
} else {
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
+ /*
+ * If listening socket requested TCP digests, check that
+ * received ACK has signature and it is correct.
+ * If not, drop the ACK and leave sc entry in th cache,
+ * because SYN was received with correct signature.
+ */
+ if (sc->sc_flags & SCF_SIGNATURE) {
+ if ((to->to_flags & TOF_SIGNATURE) == 0) {
+ /* No signature */
+ TCPSTAT_INC(tcps_sig_err_nosigopt);
+ SCH_UNLOCK(sch);
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Segment "
+ "rejected, MD5 signature wasn't "
+ "provided.\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ return (-1); /* Do not send RST */
+ }
+ if (!TCPMD5_ENABLED() ||
+ TCPMD5_INPUT(m, th, to->to_signature) != 0) {
+ /* Doesn't match or no SA */
+ SCH_UNLOCK(sch);
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Segment "
+ "rejected, MD5 signature doesn't "
+ "match.\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ return (-1); /* Do not send RST */
+ }
+ }
+#endif /* TCP_SIGNATURE */
/*
* Pull out the entry to unlock the bucket row.
*
@@ -1262,6 +1306,22 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
ipopts = NULL;
#endif
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
+ /*
+ * If listening socket requested TCP digests, check that received
+ * SYN has signature and it is correct. If signature doesn't match
+ * or TCP_SIGNATURE support isn't enabled, drop the packet.
+ */
+ if (ltflags & TF_SIGNATURE) {
+ if ((to->to_flags & TOF_SIGNATURE) == 0) {
+ TCPSTAT_INC(tcps_sig_err_nosigopt);
+ goto done;
+ }
+ if (!TCPMD5_ENABLED() ||
+ TCPMD5_INPUT(m, th, to->to_signature) != 0)
+ goto done;
+ }
+#endif /* TCP_SIGNATURE */
/*
* See if we already have an entry for this connection.
* If we do, resend the SYN,ACK, and reset the retransmit timer.
@@ -1437,15 +1497,15 @@ skip_alloc:
sc->sc_flags |= SCF_WINSCALE;
}
}
-#ifdef TCP_SIGNATURE
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
/*
- * If listening socket requested TCP digests, OR received SYN
- * contains the option, flag this in the syncache so that
- * syncache_respond() will do the right thing with the SYN+ACK.
+ * If listening socket requested TCP digests, flag this in the
+ * syncache so that syncache_respond() will do the right thing
+ * with the SYN+ACK.
*/
- if (to->to_flags & TOF_SIGNATURE || ltflags & TF_SIGNATURE)
+ if (ltflags & TF_SIGNATURE)
sc->sc_flags |= SCF_SIGNATURE;
-#endif
+#endif /* TCP_SIGNATURE */
if (to->to_flags & TOF_SACKPERM)
sc->sc_flags |= SCF_SACK;
if (to->to_flags & TOF_MSS)
@@ -1527,10 +1587,6 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
#endif
-#ifdef TCP_SIGNATURE
- struct secasvar *sav;
-#endif
-
hlen =
#ifdef INET6
(sc->sc_inc.inc_flags & INC_ISIPV6) ? sizeof(struct ip6_hdr) :
@@ -1639,32 +1695,10 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
}
if (sc->sc_flags & SCF_SACK)
to.to_flags |= TOF_SACKPERM;
-#ifdef TCP_SIGNATURE
- sav = NULL;
- if (sc->sc_flags & SCF_SIGNATURE) {
- sav = tcp_get_sav(m, IPSEC_DIR_OUTBOUND);
- if (sav != NULL)
- to.to_flags |= TOF_SIGNATURE;
- else {
-
- /*
- * We've got SCF_SIGNATURE flag
- * inherited from listening socket,
- * but no SADB key for given source
- * address. Assume signature is not
- * required and remove signature flag
- * instead of silently dropping
- * connection.
- */
- if (locked == 0)
- SCH_LOCK(sch);
- sc->sc_flags &= ~SCF_SIGNATURE;
- if (locked == 0)
- SCH_UNLOCK(sch);
- }
- }
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
+ if (sc->sc_flags & SCF_SIGNATURE)
+ to.to_flags |= TOF_SIGNATURE;
#endif
-
#ifdef TCP_RFC7413
if (sc->sc_tfo_cookie) {
to.to_flags |= TOF_FASTOPEN;
@@ -1680,18 +1714,25 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
th->th_off = (sizeof(struct tcphdr) + optlen) >> 2;
m->m_len += optlen;
m->m_pkthdr.len += optlen;
-
-#ifdef TCP_SIGNATURE
- if (sc->sc_flags & SCF_SIGNATURE)
- tcp_signature_do_compute(m, 0, optlen,
- to.to_signature, sav);
-#endif
#ifdef INET6
if (sc->sc_inc.inc_flags & INC_ISIPV6)
ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) + optlen);
else
#endif
ip->ip_len = htons(ntohs(ip->ip_len) + optlen);
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
+ if (sc->sc_flags & SCF_SIGNATURE) {
+ KASSERT(to.to_flags & TOF_SIGNATURE,
+ ("tcp_addoptions() didn't set tcp_signature"));
+
+ /* NOTE: to.to_signature is inside of mbuf */
+ if (!TCPMD5_ENABLED() ||
+ TCPMD5_OUTPUT(m, th, to.to_signature) != 0) {
+ m_freem(m);
+ return (EACCES);
+ }
+ }
+#endif
} else
optlen = 0;
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index e7187fc..9a53b93 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_ipsec.h"
#include "opt_tcpdebug.h"
#include <sys/param.h>
@@ -101,6 +102,7 @@ __FBSDID("$FreeBSD$");
#ifdef TCP_OFFLOAD
#include <netinet/tcp_offload.h>
#endif
+#include <netipsec/ipsec_support.h>
/*
* TCP protocol interface to socket abstraction.
@@ -1533,21 +1535,17 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp
switch (sopt->sopt_dir) {
case SOPT_SET:
switch (sopt->sopt_name) {
-#ifdef TCP_SIGNATURE
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
case TCP_MD5SIG:
- INP_WUNLOCK(inp);
- error = sooptcopyin(sopt, &optval, sizeof optval,
- sizeof optval);
+ if (!TCPMD5_ENABLED()) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+ error = TCPMD5_PCBCTL(inp, sopt);
if (error)
return (error);
-
- INP_WLOCK_RECHECK(inp);
- if (optval > 0)
- tp->t_flags |= TF_SIGNATURE;
- else
- tp->t_flags &= ~TF_SIGNATURE;
goto unlock_and_done;
-#endif /* TCP_SIGNATURE */
+#endif /* IPSEC */
case TCP_NODELAY:
case TCP_NOOPT:
@@ -1773,11 +1771,13 @@ unlock_and_done:
case SOPT_GET:
tp = intotcpcb(inp);
switch (sopt->sopt_name) {
-#ifdef TCP_SIGNATURE
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
case TCP_MD5SIG:
- optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0;
- INP_WUNLOCK(inp);
- error = sooptcopyout(sopt, &optval, sizeof optval);
+ if (!TCPMD5_ENABLED()) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+ error = TCPMD5_PCBCTL(inp, sopt);
break;
#endif
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 7adb717..f65c2fb 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -344,21 +344,6 @@ struct tcpcb {
#define TCPOOB_HAVEDATA 0x01
#define TCPOOB_HADDATA 0x02
-#ifdef TCP_SIGNATURE
-/*
- * Defines which are needed by the xform_tcp module and tcp_[in|out]put
- * for SADB verification and lookup.
- */
-#define TCP_SIGLEN 16 /* length of computed digest in bytes */
-#define TCP_KEYLEN_MIN 1 /* minimum length of TCP-MD5 key */
-#define TCP_KEYLEN_MAX 80 /* maximum length of TCP-MD5 key */
-/*
- * Only a single SA per host may be specified at this time. An SPI is
- * needed in order for the KEY_ALLOCSA() lookup to work.
- */
-#define TCP_SIG_SPI 0x1000
-#endif /* TCP_SIGNATURE */
-
/*
* Flags for PLPMTU handling, t_flags2
*/
@@ -595,7 +580,7 @@ struct tcpstat {
/* TCP_SIGNATURE related stats */
uint64_t tcps_sig_rcvgoodsig; /* Total matching signature received */
uint64_t tcps_sig_rcvbadsig; /* Total bad signature received */
- uint64_t tcps_sig_err_buildsig; /* Mismatching signature received */
+ uint64_t tcps_sig_err_buildsig; /* Failed to make signature */
uint64_t tcps_sig_err_sigopt; /* No signature expected by socket */
uint64_t tcps_sig_err_nosigopt; /* No signature provided by segment */
@@ -812,17 +797,6 @@ void tcp_tw_zone_change(void);
int tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *,
struct mbuf *, int);
void tcp_setpersist(struct tcpcb *);
-#ifdef TCP_SIGNATURE
-struct secasvar;
-struct secasvar *tcp_get_sav(struct mbuf *, u_int);
-int tcp_signature_do_compute(struct mbuf *, int, int, u_char *,
- struct secasvar *);
-int tcp_signature_compute(struct mbuf *, int, int, int, u_char *, u_int);
-int tcp_signature_verify(struct mbuf *, int, int, int, struct tcpopt *,
- struct tcphdr *, u_int);
-int tcp_signature_check(struct mbuf *m, int off0, int tlen, int optlen,
- struct tcpopt *to, struct tcphdr *th, u_int tcpbflag);
-#endif
void tcp_slowtimo(void);
struct tcptemp *
tcpip_maketemplate(struct inpcb *);
@@ -866,7 +840,6 @@ tcp_fields_to_host(struct tcphdr *th)
th->th_urp = ntohs(th->th_urp);
}
-#ifdef TCP_SIGNATURE
static inline void
tcp_fields_to_net(struct tcphdr *th)
{
@@ -876,7 +849,6 @@ tcp_fields_to_net(struct tcphdr *th)
th->th_win = htons(th->th_win);
th->th_urp = htons(th->th_urp);
}
-#endif
#endif /* _KERNEL */
#endif /* _NETINET_TCP_VAR_H_ */
diff --git a/sys/netinet/udp.h b/sys/netinet/udp.h
index c2d638d..d8475720 100644
--- a/sys/netinet/udp.h
+++ b/sys/netinet/udp.h
@@ -58,7 +58,7 @@ struct udphdr {
*/
/* Encapsulation types. */
#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
-#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-02+ */
+#define UDP_ENCAP_ESPINUDP 2 /* RFC3948 */
/* Default ESP in UDP encapsulation port. */
#define UDP_ENCAP_ESPINUDP_PORT 500
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 3bf5c6f..c771201 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -92,10 +92,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/udplite.h>
#include <netinet/in_rss.h>
-#ifdef IPSEC
-#include <netipsec/ipsec.h>
-#include <netipsec/esp.h>
-#endif
+#include <netipsec/ipsec_support.h>
#include <machine/in_cksum.h>
@@ -166,15 +163,6 @@ static int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *,
struct mbuf *, struct thread *);
#endif
-#ifdef IPSEC
-#ifdef IPSEC_NAT_T
-#define UF_ESPINUDP_ALL (UF_ESPINUDP_NON_IKE|UF_ESPINUDP)
-#ifdef INET
-static struct mbuf *udp4_espdecap(struct inpcb *, struct mbuf *, int);
-#endif
-#endif /* IPSEC_NAT_T */
-#endif /* IPSEC */
-
static void
udp_zone_change(void *tag)
{
@@ -333,21 +321,18 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off,
off += sizeof(struct udphdr);
-#ifdef IPSEC
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/* Check AH/ESP integrity. */
- if (ipsec4_in_reject(n, inp)) {
+ if (IPSEC_ENABLED(ipv4) &&
+ IPSEC_CHECK_POLICY(ipv4, n, inp) != 0) {
m_freem(n);
return (0);
}
-#ifdef IPSEC_NAT_T
- up = intoudpcb(inp);
- KASSERT(up != NULL, ("%s: udpcb NULL", __func__));
- if (up->u_flags & UF_ESPINUDP_ALL) { /* IPSec UDP encaps. */
- n = udp4_espdecap(inp, n, off);
- if (n == NULL) /* Consumed. */
- return (0);
+ if (up->u_flags & UF_ESPINUDP) {/* IPSec UDP encaps. */
+ if (IPSEC_ENABLED(ipv4) &&
+ UDPENCAP_INPUT(n, off, AF_INET) != 0)
+ return (0); /* Consumed. */
}
-#endif /* IPSEC_NAT_T */
#endif /* IPSEC */
#ifdef MAC
if (mac_inpcb_check_deliver(inp, n) != 0) {
@@ -1013,42 +998,17 @@ udp_ctloutput(struct socket *so, struct sockopt *sopt)
switch (sopt->sopt_dir) {
case SOPT_SET:
switch (sopt->sopt_name) {
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+#ifdef INET
case UDP_ENCAP:
- INP_WUNLOCK(inp);
- error = sooptcopyin(sopt, &optval, sizeof optval,
- sizeof optval);
- if (error)
- break;
- inp = sotoinpcb(so);
- KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
- INP_WLOCK(inp);
-#ifdef IPSEC_NAT_T
- up = intoudpcb(inp);
- KASSERT(up != NULL, ("%s: up == NULL", __func__));
-#endif
- switch (optval) {
- case 0:
- /* Clear all UDP encap. */
-#ifdef IPSEC_NAT_T
- up->u_flags &= ~UF_ESPINUDP_ALL;
-#endif
- break;
-#ifdef IPSEC_NAT_T
- case UDP_ENCAP_ESPINUDP:
- case UDP_ENCAP_ESPINUDP_NON_IKE:
- up->u_flags &= ~UF_ESPINUDP_ALL;
- if (optval == UDP_ENCAP_ESPINUDP)
- up->u_flags |= UF_ESPINUDP;
- else if (optval == UDP_ENCAP_ESPINUDP_NON_IKE)
- up->u_flags |= UF_ESPINUDP_NON_IKE;
- break;
-#endif
- default:
- error = EINVAL;
- break;
+ if (!IPSEC_ENABLED(ipv4)) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
}
- INP_WUNLOCK(inp);
+ error = UDPENCAP_PCBCTL(inp, sopt);
break;
+#endif /* INET */
+#endif /* IPSEC */
case UDPLITE_SEND_CSCOV:
case UDPLITE_RECV_CSCOV:
if (!isudplite) {
@@ -1085,15 +1045,17 @@ udp_ctloutput(struct socket *so, struct sockopt *sopt)
break;
case SOPT_GET:
switch (sopt->sopt_name) {
-#ifdef IPSEC_NAT_T
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+#ifdef INET
case UDP_ENCAP:
- up = intoudpcb(inp);
- KASSERT(up != NULL, ("%s: up == NULL", __func__));
- optval = up->u_flags & UF_ESPINUDP_ALL;
- INP_WUNLOCK(inp);
- error = sooptcopyout(sopt, &optval, sizeof optval);
+ if (!IPSEC_ENABLED(ipv4)) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+ error = UDPENCAP_PCBCTL(inp, sopt);
break;
-#endif
+#endif /* INET */
+#endif /* IPSEC */
case UDPLITE_SEND_CSCOV:
case UDPLITE_RECV_CSCOV:
if (!isudplite) {
@@ -1576,142 +1538,6 @@ release:
return (error);
}
-
-#if defined(IPSEC) && defined(IPSEC_NAT_T)
-/*
- * Potentially decap ESP in UDP frame. Check for an ESP header
- * and optional marker; if present, strip the UDP header and
- * push the result through IPSec.
- *
- * Returns mbuf to be processed (potentially re-allocated) or
- * NULL if consumed and/or processed.
- */
-static struct mbuf *
-udp4_espdecap(struct inpcb *inp, struct mbuf *m, int off)
-{
- size_t minlen, payload, skip, iphlen;
- caddr_t data;
- struct udpcb *up;
- struct m_tag *tag;
- struct udphdr *udphdr;
- struct ip *ip;
-
- INP_RLOCK_ASSERT(inp);
-
- /*
- * Pull up data so the longest case is contiguous:
- * IP/UDP hdr + non ESP marker + ESP hdr.
- */
- minlen = off + sizeof(uint64_t) + sizeof(struct esp);
- if (minlen > m->m_pkthdr.len)
- minlen = m->m_pkthdr.len;
- if ((m = m_pullup(m, minlen)) == NULL) {
- IPSECSTAT_INC(ips_in_inval);
- return (NULL); /* Bypass caller processing. */
- }
- data = mtod(m, caddr_t); /* Points to ip header. */
- payload = m->m_len - off; /* Size of payload. */
-
- if (payload == 1 && data[off] == '\xff')
- return (m); /* NB: keepalive packet, no decap. */
-
- up = intoudpcb(inp);
- KASSERT(up != NULL, ("%s: udpcb NULL", __func__));
- KASSERT((up->u_flags & UF_ESPINUDP_ALL) != 0,
- ("u_flags 0x%x", up->u_flags));
-
- /*
- * Check that the payload is large enough to hold an
- * ESP header and compute the amount of data to remove.
- *
- * NB: the caller has already done a pullup for us.
- * XXX can we assume alignment and eliminate bcopys?
- */
- if (up->u_flags & UF_ESPINUDP_NON_IKE) {
- /*
- * draft-ietf-ipsec-nat-t-ike-0[01].txt and
- * draft-ietf-ipsec-udp-encaps-(00/)01.txt, ignoring
- * possible AH mode non-IKE marker+non-ESP marker
- * from draft-ietf-ipsec-udp-encaps-00.txt.
- */
- uint64_t marker;
-
- if (payload <= sizeof(uint64_t) + sizeof(struct esp))
- return (m); /* NB: no decap. */
- bcopy(data + off, &marker, sizeof(uint64_t));
- if (marker != 0) /* Non-IKE marker. */
- return (m); /* NB: no decap. */
- skip = sizeof(uint64_t) + sizeof(struct udphdr);
- } else {
- uint32_t spi;
-
- if (payload <= sizeof(struct esp)) {
- IPSECSTAT_INC(ips_in_inval);
- m_freem(m);
- return (NULL); /* Discard. */
- }
- bcopy(data + off, &spi, sizeof(uint32_t));
- if (spi == 0) /* Non-ESP marker. */
- return (m); /* NB: no decap. */
- skip = sizeof(struct udphdr);
- }
-
- /*
- * Setup a PACKET_TAG_IPSEC_NAT_T_PORT tag to remember
- * the UDP ports. This is required if we want to select
- * the right SPD for multiple hosts behind same NAT.
- *
- * NB: ports are maintained in network byte order everywhere
- * in the NAT-T code.
- */
- tag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS,
- 2 * sizeof(uint16_t), M_NOWAIT);
- if (tag == NULL) {
- IPSECSTAT_INC(ips_in_nomem);
- m_freem(m);
- return (NULL); /* Discard. */
- }
- iphlen = off - sizeof(struct udphdr);
- udphdr = (struct udphdr *)(data + iphlen);
- ((uint16_t *)(tag + 1))[0] = udphdr->uh_sport;
- ((uint16_t *)(tag + 1))[1] = udphdr->uh_dport;
- m_tag_prepend(m, tag);
-
- /*
- * Remove the UDP header (and possibly the non ESP marker)
- * IP header length is iphlen
- * Before:
- * <--- off --->
- * +----+------+-----+
- * | IP | UDP | ESP |
- * +----+------+-----+
- * <-skip->
- * After:
- * +----+-----+
- * | IP | ESP |
- * +----+-----+
- * <-skip->
- */
- ovbcopy(data, data + skip, iphlen);
- m_adj(m, skip);
-
- ip = mtod(m, struct ip *);
- ip->ip_len = htons(ntohs(ip->ip_len) - skip);
- ip->ip_p = IPPROTO_ESP;
-
- /*
- * We cannot yet update the cksums so clear any
- * h/w cksum flags as they are no longer valid.
- */
- if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID)
- m->m_pkthdr.csum_flags &= ~(CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
-
- (void) ipsec_common_input(m, iphlen, offsetof(struct ip, ip_p),
- AF_INET, ip->ip_p);
- return (NULL); /* NB: consumed, bypass processing. */
-}
-#endif /* defined(IPSEC) && defined(IPSEC_NAT_T) */
-
static void
udp_abort(struct socket *so)
{
OpenPOWER on IntegriCloud