diff options
author | Dan McDonald <danmcd@omniti.com> | 2017-06-12 13:56:18 -0400 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2017-08-04 21:34:36 -0400 |
commit | b7daf79982d77b491ef9662483cd4549e0e5da9a (patch) | |
tree | 525f77d873f138ad9e568d303e138e76c89b3738 /usr/src | |
parent | a9bfd41d542f15c474711abb8b0ca66a4cef9918 (diff) | |
download | illumos-joyent-b7daf79982d77b491ef9662483cd4549e0e5da9a.tar.gz |
8529 Extended and regular SADB_ACQUIREs should share address extension code
Portions contributed by: Bayard Bell <buffer.g.overflow@gmail.com>
Reviewed by: C Fraire <cfraire@me.com>
Reviewed by: Jason King <jason.king@joyent.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/pkg/manifests/system-test-ostest.mf | 7 | ||||
-rw-r--r-- | usr/src/test/os-tests/runfiles/default.run | 6 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/Makefile | 4 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/pf_key/Makefile | 55 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/pf_key/acquire-compare.sh | 170 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/pf_key/acquire-spray.sh | 99 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/pf_key/eacq-enabler.c | 111 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ipsecah.c | 171 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ipsecesp.c | 256 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/sadb.c | 1164 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/spd.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ipsecah.h | 16 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ipsecesp.h | 73 | ||||
-rw-r--r-- | usr/src/uts/common/inet/sadb.h | 5 |
14 files changed, 1250 insertions, 893 deletions
diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf index 38b5c23533..ee0d19c663 100644 --- a/usr/src/pkg/manifests/system-test-ostest.mf +++ b/usr/src/pkg/manifests/system-test-ostest.mf @@ -12,7 +12,7 @@ # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. # Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. -# Copyright 2016, Joyent, Inc. +# Copyright 2017 Joyent, Inc. # set name=pkg.fmri value=pkg:/system/test/ostest@$(PKGVERS) @@ -26,6 +26,7 @@ dir path=opt/os-tests/bin dir path=opt/os-tests/runfiles dir path=opt/os-tests/tests dir path=opt/os-tests/tests/file-locking +dir path=opt/os-tests/tests/pf_key dir path=opt/os-tests/tests/sdevfs dir path=opt/os-tests/tests/secflags dir path=opt/os-tests/tests/sigqueue @@ -39,6 +40,9 @@ file path=opt/os-tests/tests/file-locking/acquire-lock.32 mode=0555 file path=opt/os-tests/tests/file-locking/acquire-lock.64 mode=0555 file path=opt/os-tests/tests/file-locking/runtests.32 mode=0555 file path=opt/os-tests/tests/file-locking/runtests.64 mode=0555 +file path=opt/os-tests/tests/pf_key/acquire-compare mode=0555 +file path=opt/os-tests/tests/pf_key/acquire-spray mode=0555 +file path=opt/os-tests/tests/pf_key/eacq-enabler mode=0555 file path=opt/os-tests/tests/poll_test mode=0555 file path=opt/os-tests/tests/sdevfs/sdevfs_eisdir mode=0555 file path=opt/os-tests/tests/secflags/addrs-32 mode=0555 @@ -66,4 +70,5 @@ file path=opt/os-tests/tests/spoof-ras mode=0555 file path=opt/os-tests/tests/stress/dladm-kstat mode=0555 license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL +depend fmri=pkg:/network/telnet type=require depend fmri=system/test/testrunner type=require diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run index bff7ec6baa..d029b75e7b 100644 --- a/usr/src/test/os-tests/runfiles/default.run +++ b/usr/src/test/os-tests/runfiles/default.run @@ -11,7 +11,7 @@ # # Copyright (c) 2012 by Delphix. All rights reserved. -# Copyright 2016 Joyent, Inc. +# Copyright 2017 Joyent, Inc. # [DEFAULT] @@ -58,3 +58,7 @@ tests = ['runtests.32', 'runtests.64'] [/opt/os-tests/tests/sockfs] user = root tests = ['conn', 'dgram', 'drop_priv', 'nosignal', 'sockpair'] + +[/opt/os-tests/tests/pf_key] +user = root +tests = ['acquire-compare', 'acquire-spray'] diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile index 77af406120..f3af454450 100644 --- a/usr/src/test/os-tests/tests/Makefile +++ b/usr/src/test/os-tests/tests/Makefile @@ -11,8 +11,10 @@ # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. +# Copyright 2017 Joyent, Inc. # -SUBDIRS = poll secflags sigqueue spoof-ras sdevfs sockfs stress file-locking +SUBDIRS = poll secflags sigqueue spoof-ras sdevfs sockfs stress file-locking \ + pf_key include $(SRC)/test/Makefile.com diff --git a/usr/src/test/os-tests/tests/pf_key/Makefile b/usr/src/test/os-tests/tests/pf_key/Makefile new file mode 100644 index 0000000000..e35d002852 --- /dev/null +++ b/usr/src/test/os-tests/tests/pf_key/Makefile @@ -0,0 +1,55 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Joyent, Inc. +# + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/test/Makefile.com + +# Shell scripts... +PROG = acquire-spray \ + acquire-compare + +PROG += eacq-enabler + +ROOTOPTPKG = $(ROOT)/opt/os-tests +TESTDIR = $(ROOTOPTPKG)/tests/pf_key + +CMDS = $(PROG:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +LDLIBS += -lsocket + +eacq-enabler: + $(LINK.c) eacq-enabler.c -o $@ $(LDLIBS) + $(POST_PROCESS) + +all: $(PROG) + +install: all $(CMDS) + +lint: + +clobber: clean + -$(RM) $(PROG) + +clean: + -$(RM) $(CLEANFILES) + +$(CMDS): $(TESTDIR) $(PROG) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/os-tests/tests/pf_key/acquire-compare.sh b/usr/src/test/os-tests/tests/pf_key/acquire-compare.sh new file mode 100644 index 0000000000..b35a377540 --- /dev/null +++ b/usr/src/test/os-tests/tests/pf_key/acquire-compare.sh @@ -0,0 +1,170 @@ +#!/usr/bin/ksh + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2017 Joyent, Inc. +# + +if [ `id -u` -ne 0 ]; then + echo "Need to be root or have effective UID of root." + exit 255 +fi + +# NOTE: If multihomed, this may fail in interesting ways... +MY_IP=`netstat -in -f inet | egrep -v "Name|lo0" | awk '{print $4}' | head -1` +TEST_REMOTE_DST1=10.90.1.25 +TEST_REMOTE_DST2=10.19.84.2 +TEST_REMOTE_DST3=10.19.84.3 +TEST_REMOTE_DST4=10.19.84.4 + +T1_SRC=10.21.12.4 +T1_DST=10.21.12.5 +T1_PREFIX=10.21.12.0/24 +T2_SRC=10.51.50.4 +T2_DST=10.51.50.5 +T2_PREFIX=10.51.50.0/24 + +MONITOR_LOG=/tmp/ipseckey-monitor.$$ + +EACQ_PROG=/opt/os-tests/tests/pf_key/eacq-enabler + +$EACQ_PROG & +eapid=$! + +echo "Warning, this trashes IPsec policy." +ipsecconf -Fq + +# Setup the IPsec policy... +ipsecconf -qa - << EOF +# Global policy... +# Remote-port-based policy. Use different algorithms... +{ raddr $TEST_REMOTE_DST3 rport 23 ulp tcp } ipsec { encr_algs aes encr_auth_algs sha512 } + +# Unique policy... +{ raddr $TEST_REMOTE_DST4 rport 23 ulp tcp } ipsec { encr_algs aes encr_auth_algs sha256 sa unique } + +# Simple IP address policy. Use an AH + ESP for it. +{ raddr $TEST_REMOTE_DST1 } ipsec { auth_algs sha512 encr_algs aes(256) } +{ raddr $TEST_REMOTE_DST2 } ipsec { auth_algs sha384 encr_algs aes(256) } + +# Tunnel policy... +{ tunnel rush0 raddr $T1_PREFIX negotiate tunnel } ipsec { encr_algs aes-gcm(256) } +# NULL-encryption... +{ tunnel vh0 raddr $T2_PREFIX negotiate tunnel } ipsec {encr_auth_algs hmac-sha384 } +EOF + +# Plumb the tunnels +dladm create-iptun -t -T ipv4 -a local=$MY_IP -a remote=$TEST_REMOTE_DST1 rush0 +dladm create-iptun -t -T ipv4 -a local=$MY_IP -a remote=$TEST_REMOTE_DST2 vh0 +ipadm create-addr -t -T static -a local=$T1_SRC,remote=$T1_DST rush0/v4 +ipadm create-addr -t -T static -a local=$T2_SRC,remote=$T2_DST vh0/v4 +route add $T1_PREFIX $T1_DST +route add $T2_PREFIX $T2_DST + +ipseckey flush +ipseckey -np monitor > $MONITOR_LOG & +IPSECKEY_PID=$! + +# Launch pings and telnets to different addresses (each requiring an ACQUIRE). +ping -svn $TEST_REMOTE_DST1 1024 1 2>&1 > /dev/null & +p1=$! +ping -svn $TEST_REMOTE_DST2 1024 1 2>&1 > /dev/null & +p2=$! +ping -svn $T1_DST 1024 1 2>&1 > /dev/null & +p3=$! +ping -svn $T2_DST 1024 1 2>&1 > /dev/null & +p4=$! + +echo "Waiting for pings..." +pwait $p1 $p2 $p3 $p4 + +# Now try some telnets to trigger port and unique policy. +# port-only for DST3 +telnet $TEST_REMOTE_DST3 & +tpid=$! +t1port=`pfiles $tpid | grep sockname | awk '{print $5}'` +echo "First local port == $t1port" +sleep 10 ; kill $tpid +# unique for DST4 +telnet $TEST_REMOTE_DST4 & +tpid=$! +t2port=`pfiles $tpid | grep sockname | awk '{print $5}'` +echo "Second local port == $t2port" +sleep 10 ; kill $tpid +# Nothing specced for DST1 +telnet $TEST_REMOTE_DST1 & +tpid=$! +t3port=`pfiles $tpid | grep sockname | awk '{print $5}'` +echo "Third local port == $t3port" +sleep 10 ; kill $tpid + +# Clean up. +kill $IPSECKEY_PID +kill $eapid +# Unplumb the tunnels +route delete $T2_PREFIX $T2_DST +route delete $T1_PREFIX $T1_DST +ipadm delete-addr vh0/v4 +ipadm delete-addr rush0/v4 +ipadm delete-if vh0 +ipadm delete-if rush0 +dladm delete-iptun vh0 +dladm delete-iptun rush0 +# Flush policy +ipsecconf -Fq +# Use SMF to restore anything that may have been there. "restart" on +# a disabled service is a NOP, but an enabled one will get +# /etc/inet/ipsecinit.conf reloaded. +svcadm restart ipsec/policy + +# Process MONITOR_LOG's output... +echo "Checking for unique local port only in one ACQUIRE case." +egrep "$t1port|$t2port|$t3port" $MONITOR_LOG > /tmp/egrep.$$ +grep $t2port $MONITOR_LOG > /tmp/grep.$$ +diff /tmp/grep.$$ /tmp/egrep.$$ +if [[ $? != 0 ]]; then + echo "More than just the one unique port, $tport2, found in monitor output." + /bin/rm -f /tmp/grep.$$ /tmp/egrep.$$ $MONITOR_LOG + exit 1 +fi + +# Split out extended (file.0) and regular (file.1) ACQUIREs. +# NOTE: "+7" is dependent on "ipseckey monitor"'s first output where it gets +# the "PROMISC" reply. + +mkdir /tmp/raw.$$ +savedir=$PWD +cd /tmp/raw.$$ +tail +7 $MONITOR_LOG | \ + awk 'BEGIN { out=0; } /Read/ {out++;} { print >> (out % 2) }' +cd $savedir + +# Pluck out the address extension from the two ACQUIRE types. +# NOTE: Add any new in-ACQUIRE address types here if more arrive. +egrep "DST:|SRC:|INS:|IND:" /tmp/raw.$$/0 > /tmp/extended-addresses.$$ +egrep "DST:|SRC:|INS:|IND:" /tmp/raw.$$/1 > /tmp/regular-addresses.$$ + +# There should be NO differences between address fields from regular vs. +# extended ACQUIREs. If there are, it's a bug (or an older version of illumos). +diff /tmp/extended-addresses.$$ /tmp/regular-addresses.$$ +if [[ $? != 0 ]]; then + echo "Address fields in ACQUIRE differ." + rc=1 +else + rc=0 +fi + +/bin/rm -rf /tmp/*-addresses.$$ /tmp/raw.$$ +/bin/rm -f /tmp/grep.$$ /tmp/egrep.$$ /tmp/addrs.$$ $MONITOR_LOG + +exit $rc diff --git a/usr/src/test/os-tests/tests/pf_key/acquire-spray.sh b/usr/src/test/os-tests/tests/pf_key/acquire-spray.sh new file mode 100644 index 0000000000..d15c8617a6 --- /dev/null +++ b/usr/src/test/os-tests/tests/pf_key/acquire-spray.sh @@ -0,0 +1,99 @@ +#!/usr/bin/ksh + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2017 Joyent, Inc. +# + +if [ `id -u` -ne 0 ]; then + echo "Need to be root or have effective UID of root." + exit 255 +fi + +if [[ `zonename` != "global" ]]; then + echo "Need to be the in the global zone for lock detection." + exit 254 +fi + +# This test sprays many concurrent ACQUIRE messages. The idea originally +# was to view lock contention on the global netstack's IPsec algorithm lock. +# It is also useful for having multiple ACQUIRE records. + +PREFIX=10.21.12.0/24 +MONITOR_LOG=/var/run/ipseckey-monitor.$$ + +# The program that sends an extended REGISTER to enable extended ACQUIREs. +EACQ_PROG=/opt/os-tests/tests/pf_key/eacq-enabler + +$EACQ_PROG & +eapid=$! + +# Find the ipsec_alg_lock to monitor with lockstat (below). +GLOBAL_NETSTACK=`echo ::netstack | mdb -k | grep -w 0 | awk '{print $1}'` +GLOBAL_IPSEC=`echo $GLOBAL_NETSTACK::print netstack_t | mdb -k | grep -w nu_ipsec | awk '{print $3}'` +IPSEC_ALG_LOCK=`echo $GLOBAL_IPSEC::print -a ipsec_stack_t ipsec_alg_lock | mdb -k | head -1 | awk '{print $1}'` + +#echo "WARNING -- this test flushes out IPsec policy..." +#echo "GLOBAL_NETSTACK = $GLOBAL_NETSTACK" +#echo "GLOBAL_IPSEC = $GLOBAL_IPSEC" +#echo "IPSEC_ALG_LOCK = $IPSEC_ALG_LOCK" + +# Tunnels will be preserved by using -f instead of -F. +ipsecconf -qf + +# Simple one-type-of-ESP setup... +echo "{ raddr $PREFIX } ipsec { encr_algs aes encr_auth_algs sha512 }" | \ + ipsecconf -qa - +# ipsecconf -ln + +# Get monitoring PF_KEY for at least regular ACQUIREs. +ipseckey -n monitor > $MONITOR_LOG & +IPSECKEY_PID=$! + +# Flush out the SADB to make damned sure we don't have straggler acquire +# records internally. +ipseckey flush + +# Launch 254 pings to different addresses (each requiring an ACQUIRE). +i=1 +while [ $i -le 254 ]; do + truss -Topen -o /dev/null ping -svn 10.21.12.$i 1024 1 2>&1 > /dev/null & + i=$(($i + 1)) +done + +# Unleash the pings in 10 seconds, Smithers. +( sleep 10 ; prun `pgrep ping` ) & + +# Get the lockstats going now. +echo "Running: lockstat -A -l 0x$IPSEC_ALG_LOCK,8 sleep 30" +lockstat -A -l 0x$IPSEC_ALG_LOCK,8 sleep 30 +kill $IPSECKEY_PID +kill $eapid +# Use SMF to restore anything that may have been there. "restart" on +# a disabled service is a NOP, but an enabled one will get +# /etc/inet/ipsecinit.conf reloaded. +svcadm restart ipsec/policy + +# See if we have decent results. + +numacq=`grep ACQUIRE $MONITOR_LOG | wc -l | awk '{print $1}` +#rm -f $MONITOR_LOG +# Pardon the hardcoding again. +if [[ $numacq != 508 ]]; then + echo "Got $numacq ACQUIREs instead of 508" + exit 1 +else + echo "Saw expected $numacq ACQUIREs." +fi + +exit 0 diff --git a/usr/src/test/os-tests/tests/pf_key/eacq-enabler.c b/usr/src/test/os-tests/tests/pf_key/eacq-enabler.c new file mode 100644 index 0000000000..fcd46fbb33 --- /dev/null +++ b/usr/src/test/os-tests/tests/pf_key/eacq-enabler.c @@ -0,0 +1,111 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2017 Joyent, Inc. + */ + +/* + * Designed to be backgrounded and just killed. Open a PF_KEY socket, do + * an extended-REGISTER so the kernel will send extended-ACQUIRE messages, + * and then read-and-discard everything off the socket. + */ + +#include <sys/socket.h> +#include <net/pfkeyv2.h> +#include <stdio.h> +#include <errno.h> +#include <err.h> +#include <unistd.h> + +/* ARGSUSED */ +int +main(int argc, char *argv[]) +{ + int s, rc; + uint64_t buf[1024]; /* PF_KEY likes 64-bit alignment. */ + sadb_msg_t *samsg; + sadb_x_ereg_t *ereg; + boolean_t ah_ack, esp_ack; + pid_t pid = getpid(); + + s = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); + if (s == -1) + err(-1, "socket(PF_KEY)"); + + /* Base message. */ + samsg = (sadb_msg_t *)buf; + ereg = (sadb_x_ereg_t *)(samsg + 1); + samsg->sadb_msg_version = PF_KEY_V2; + samsg->sadb_msg_type = SADB_REGISTER; + samsg->sadb_msg_errno = 0; + samsg->sadb_msg_satype = SADB_SATYPE_UNSPEC; + samsg->sadb_msg_reserved = 0; + samsg->sadb_msg_seq = 1; + samsg->sadb_msg_pid = pid; + samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg) + sizeof (*ereg)); + + /* extended REGISTER so we can listen for extended ACQUIREs. */ + ereg->sadb_x_ereg_len = SADB_8TO64(sizeof (*ereg)); + ereg->sadb_x_ereg_exttype = SADB_X_EXT_EREG; + ereg->sadb_x_ereg_satypes[0] = SADB_SATYPE_ESP; + ereg->sadb_x_ereg_satypes[1] = SADB_SATYPE_AH; + ereg->sadb_x_ereg_satypes[2] = SADB_SATYPE_UNSPEC; + + rc = write(s, buf, sizeof (*samsg) + sizeof (*ereg)); + if (rc == -1) + err(-1, "Extended register write error"); + + /* + * Extended REGISTER expects a regular REGISTER reply for EACH protocol + * requested. In our case, AH and ESP. + */ + do { + + do { + rc = read(s, buf, sizeof (buf)); + if (rc == -1) + err(-1, "Extended register read error"); + + } while (samsg->sadb_msg_seq != 1 || + samsg->sadb_msg_pid != pid || + samsg->sadb_msg_type != SADB_REGISTER); + + if (samsg->sadb_msg_errno != 0) { + if (samsg->sadb_msg_errno == EPROTONOSUPPORT) { + warn("Protocol %d not supported.", + samsg->sadb_msg_satype); + } else { + errno = samsg->sadb_msg_errno; + err(-1, "Extended REGISTER returned"); + } + } + + switch (samsg->sadb_msg_satype) { + case SADB_SATYPE_ESP: + esp_ack = B_TRUE; + break; + case SADB_SATYPE_AH: + ah_ack = B_TRUE; + break; + default: + err(-1, "Bad satype in extended register ACK %d.", + samsg->sadb_msg_satype); + } + } while (!esp_ack || !ah_ack); + + /* Expect this loop to never end. This program ends via signal. */ + do { + rc = read(s, buf, sizeof (buf)); + } while (rc != -1); + + err(-1, "PF_KEY read error"); +} diff --git a/usr/src/uts/common/inet/ip/ipsecah.c b/usr/src/uts/common/inet/ip/ipsecah.c index 6b700d0346..b533d75398 100644 --- a/usr/src/uts/common/inet/ip/ipsecah.c +++ b/usr/src/uts/common/inet/ip/ipsecah.c @@ -96,20 +96,6 @@ static ipsecahparam_t lcl_param_arr[] = { { 0, 0xffffffffU, 0, "ipsecah_default_hard_usetime"}, { 0, 1, 0, "ipsecah_log_unknown_spi"}, }; -#define ipsecah_debug ipsecah_params[0].ipsecah_param_value -#define ipsecah_age_interval ipsecah_params[1].ipsecah_param_value -#define ipsecah_age_int_max ipsecah_params[1].ipsecah_param_max -#define ipsecah_reap_delay ipsecah_params[2].ipsecah_param_value -#define ipsecah_replay_size ipsecah_params[3].ipsecah_param_value -#define ipsecah_acquire_timeout ipsecah_params[4].ipsecah_param_value -#define ipsecah_larval_timeout ipsecah_params[5].ipsecah_param_value -#define ipsecah_default_soft_bytes ipsecah_params[6].ipsecah_param_value -#define ipsecah_default_hard_bytes ipsecah_params[7].ipsecah_param_value -#define ipsecah_default_soft_addtime ipsecah_params[8].ipsecah_param_value -#define ipsecah_default_hard_addtime ipsecah_params[9].ipsecah_param_value -#define ipsecah_default_soft_usetime ipsecah_params[10].ipsecah_param_value -#define ipsecah_default_hard_usetime ipsecah_params[11].ipsecah_param_value -#define ipsecah_log_unknown_spi ipsecah_params[12].ipsecah_param_value #define ah0dbg(a) printf a /* NOTE: != 0 instead of > 0 so lint doesn't complain. */ @@ -149,7 +135,6 @@ static void ah_outbound_finish(mblk_t *, ip_xmit_attr_t *); static int ipsecah_open(queue_t *, dev_t *, int, int, cred_t *); static int ipsecah_close(queue_t *); static void ipsecah_wput(queue_t *, mblk_t *); -static void ah_send_acquire(ipsacq_t *, mblk_t *, netstack_t *); static boolean_t ah_register_out(uint32_t, uint32_t, uint_t, ipsecah_stack_t *, cred_t *); static void *ipsecah_stack_init(netstackid_t stackid, netstack_t *ns); @@ -420,7 +405,6 @@ ipsecah_stack_init(netstackid_t stackid, netstack_t *ns) (void) ah_kstat_init(ahstack, stackid); ahstack->ah_sadb.s_acquire_timeout = &ahstack->ipsecah_acquire_timeout; - ahstack->ah_sadb.s_acqfn = ah_send_acquire; sadbp_init("AH", &ahstack->ah_sadb, SADB_SATYPE_AH, ah_hash_size, ahstack->ipsecah_netstack); @@ -451,7 +435,6 @@ ipsecah_stack_fini(netstackid_t stackid, void *arg) if (ahstack->ah_pfkey_q != NULL) { (void) quntimeout(ahstack->ah_pfkey_q, ahstack->ah_event); } - ahstack->ah_sadb.s_acqfn = NULL; ahstack->ah_sadb.s_acquire_timeout = NULL; sadbp_destroy(&ahstack->ah_sadb, ahstack->ipsecah_netstack); ip_drop_unregister(&ahstack->ah_dropper); @@ -1736,160 +1719,6 @@ ah_age_bytes(ipsa_t *assoc, uint64_t bytes, boolean_t inbound) return (inrc && outrc); } -/* - * Perform the really difficult work of inserting the proposed situation. - * Called while holding the algorithm lock. - */ -static void -ah_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs, - netstack_t *ns) -{ - sadb_comb_t *comb = (sadb_comb_t *)(prop + 1); - ipsec_action_t *ap; - ipsec_prot_t *prot; - ipsecah_stack_t *ahstack = ns->netstack_ipsecah; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock)); - - prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; - prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t)); - *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */ - - prop->sadb_prop_replay = ahstack->ipsecah_replay_size; - - /* - * Based upon algorithm properties, and what-not, prioritize a - * proposal, based on the ordering of the AH algorithms in the - * alternatives in the policy rule or socket that was placed - * in the acquire record. - */ - - for (ap = acqrec->ipsacq_act; ap != NULL; - ap = ap->ipa_next) { - ipsec_alginfo_t *aalg; - - if ((ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) || - (!ap->ipa_act.ipa_apply.ipp_use_ah)) - continue; - - prot = &ap->ipa_act.ipa_apply; - - ASSERT(prot->ipp_auth_alg > 0); - - aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] - [prot->ipp_auth_alg]; - if (aalg == NULL || !ALG_VALID(aalg)) - continue; - - /* XXX check aalg for duplicates??.. */ - - comb->sadb_comb_flags = 0; - comb->sadb_comb_reserved = 0; - comb->sadb_comb_encrypt = 0; - comb->sadb_comb_encrypt_minbits = 0; - comb->sadb_comb_encrypt_maxbits = 0; - - comb->sadb_comb_auth = aalg->alg_id; - comb->sadb_comb_auth_minbits = - MAX(prot->ipp_ah_minbits, aalg->alg_ef_minbits); - comb->sadb_comb_auth_maxbits = - MIN(prot->ipp_ah_maxbits, aalg->alg_ef_maxbits); - - /* - * The following may be based on algorithm - * properties, but in the meantime, we just pick - * some good, sensible numbers. Key mgmt. can - * (and perhaps should) be the place to finalize - * such decisions. - */ - - /* - * No limits on allocations, since we really don't - * support that concept currently. - */ - comb->sadb_comb_soft_allocations = 0; - comb->sadb_comb_hard_allocations = 0; - - /* - * These may want to come from policy rule.. - */ - comb->sadb_comb_soft_bytes = - ahstack->ipsecah_default_soft_bytes; - comb->sadb_comb_hard_bytes = - ahstack->ipsecah_default_hard_bytes; - comb->sadb_comb_soft_addtime = - ahstack->ipsecah_default_soft_addtime; - comb->sadb_comb_hard_addtime = - ahstack->ipsecah_default_hard_addtime; - comb->sadb_comb_soft_usetime = - ahstack->ipsecah_default_soft_usetime; - comb->sadb_comb_hard_usetime = - ahstack->ipsecah_default_hard_usetime; - - prop->sadb_prop_len += SADB_8TO64(sizeof (*comb)); - if (--combs == 0) - return; /* out of space.. */ - comb++; - } -} - -/* - * Prepare and actually send the SADB_ACQUIRE message to PF_KEY. - */ -static void -ah_send_acquire(ipsacq_t *acqrec, mblk_t *extended, netstack_t *ns) -{ - uint_t combs; - sadb_msg_t *samsg; - sadb_prop_t *prop; - mblk_t *pfkeymp, *msgmp; - ipsecah_stack_t *ahstack = ns->netstack_ipsecah; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - AH_BUMP_STAT(ahstack, acquire_requests); - - if (ahstack->ah_pfkey_q == NULL) { - mutex_exit(&acqrec->ipsacq_lock); - return; - } - - /* Set up ACQUIRE. */ - pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_AH, - ns->netstack_ipsec); - if (pfkeymp == NULL) { - ah0dbg(("sadb_setup_acquire failed.\n")); - mutex_exit(&acqrec->ipsacq_lock); - return; - } - ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock)); - combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; - msgmp = pfkeymp->b_cont; - samsg = (sadb_msg_t *)(msgmp->b_rptr); - - /* Insert proposal here. */ - - prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len); - ah_insert_prop(prop, acqrec, combs, ns); - samsg->sadb_msg_len += prop->sadb_prop_len; - msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len); - - rw_exit(&ipss->ipsec_alg_lock); - - /* - * Must mutex_exit() before sending PF_KEY message up, in - * order to avoid recursive mutex_enter() if there are no registered - * listeners. - * - * Once I've sent the message, I'm cool anyway. - */ - mutex_exit(&acqrec->ipsacq_lock); - if (extended != NULL) { - putnext(ahstack->ah_pfkey_q, extended); - } - putnext(ahstack->ah_pfkey_q, pfkeymp); -} - /* Refactor me */ /* * Handle the SADB_GETSPI message. Create a larval SA. diff --git a/usr/src/uts/common/inet/ip/ipsecesp.c b/usr/src/uts/common/inet/ip/ipsecesp.c index fb5befa432..f98207aecd 100644 --- a/usr/src/uts/common/inet/ip/ipsecesp.c +++ b/usr/src/uts/common/inet/ip/ipsecesp.c @@ -21,6 +21,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2017 Joyent, Inc. */ #include <sys/types.h> @@ -95,31 +97,6 @@ static ipsecespparam_t lcl_param_arr[] = { { 0, 2, 1, "ipsecesp_padding_check"}, { 0, 600, 20, "ipsecesp_nat_keepalive_interval"}, }; -#define ipsecesp_debug ipsecesp_params[0].ipsecesp_param_value -#define ipsecesp_age_interval ipsecesp_params[1].ipsecesp_param_value -#define ipsecesp_age_int_max ipsecesp_params[1].ipsecesp_param_max -#define ipsecesp_reap_delay ipsecesp_params[2].ipsecesp_param_value -#define ipsecesp_replay_size ipsecesp_params[3].ipsecesp_param_value -#define ipsecesp_acquire_timeout \ - ipsecesp_params[4].ipsecesp_param_value -#define ipsecesp_larval_timeout \ - ipsecesp_params[5].ipsecesp_param_value -#define ipsecesp_default_soft_bytes \ - ipsecesp_params[6].ipsecesp_param_value -#define ipsecesp_default_hard_bytes \ - ipsecesp_params[7].ipsecesp_param_value -#define ipsecesp_default_soft_addtime \ - ipsecesp_params[8].ipsecesp_param_value -#define ipsecesp_default_hard_addtime \ - ipsecesp_params[9].ipsecesp_param_value -#define ipsecesp_default_soft_usetime \ - ipsecesp_params[10].ipsecesp_param_value -#define ipsecesp_default_hard_usetime \ - ipsecesp_params[11].ipsecesp_param_value -#define ipsecesp_log_unknown_spi \ - ipsecesp_params[12].ipsecesp_param_value -#define ipsecesp_padding_check \ - ipsecesp_params[13].ipsecesp_param_value /* For ipsecesp_nat_keepalive_interval, see ipsecesp.h. */ #define esp0dbg(a) printf a @@ -133,7 +110,6 @@ static int ipsecesp_close(queue_t *); static void ipsecesp_wput(queue_t *, mblk_t *); static void *ipsecesp_stack_init(netstackid_t stackid, netstack_t *ns); static void ipsecesp_stack_fini(netstackid_t stackid, void *arg); -static void esp_send_acquire(ipsacq_t *, mblk_t *, netstack_t *); static void esp_prepare_udp(netstack_t *, mblk_t *, ipha_t *); static void esp_outbound_finish(mblk_t *, ip_xmit_attr_t *); @@ -181,52 +157,6 @@ static taskq_t *esp_taskq; * IPPROTO_ESP */ -/* - * Stats. This may eventually become a full-blown SNMP MIB once that spec - * stabilizes. - */ - -typedef struct esp_kstats_s { - kstat_named_t esp_stat_num_aalgs; - kstat_named_t esp_stat_good_auth; - kstat_named_t esp_stat_bad_auth; - kstat_named_t esp_stat_bad_padding; - kstat_named_t esp_stat_replay_failures; - kstat_named_t esp_stat_replay_early_failures; - kstat_named_t esp_stat_keysock_in; - kstat_named_t esp_stat_out_requests; - kstat_named_t esp_stat_acquire_requests; - kstat_named_t esp_stat_bytes_expired; - kstat_named_t esp_stat_out_discards; - kstat_named_t esp_stat_crypto_sync; - kstat_named_t esp_stat_crypto_async; - kstat_named_t esp_stat_crypto_failures; - kstat_named_t esp_stat_num_ealgs; - kstat_named_t esp_stat_bad_decrypt; - kstat_named_t esp_stat_sa_port_renumbers; -} esp_kstats_t; - -/* - * espstack->esp_kstats is equal to espstack->esp_ksp->ks_data if - * kstat_create_netstack for espstack->esp_ksp succeeds, but when it - * fails, it will be NULL. Note this is done for all stack instances, - * so it *could* fail. hence a non-NULL checking is done for - * ESP_BUMP_STAT and ESP_DEBUMP_STAT - */ -#define ESP_BUMP_STAT(espstack, x) \ -do { \ - if (espstack->esp_kstats != NULL) \ - (espstack->esp_kstats->esp_stat_ ## x).value.ui64++; \ -_NOTE(CONSTCOND) \ -} while (0) - -#define ESP_DEBUMP_STAT(espstack, x) \ -do { \ - if (espstack->esp_kstats != NULL) \ - (espstack->esp_kstats->esp_stat_ ## x).value.ui64--; \ -_NOTE(CONSTCOND) \ -} while (0) - static int esp_kstat_update(kstat_t *, int); static boolean_t @@ -503,6 +433,7 @@ ipsecesp_param_register(IDP *ndp, ipsecespparam_t *espp, int cnt) } return (B_TRUE); } + /* * Initialize things for ESP for each stack instance */ @@ -527,7 +458,6 @@ ipsecesp_stack_init(netstackid_t stackid, netstack_t *ns) espstack->esp_sadb.s_acquire_timeout = &espstack->ipsecesp_acquire_timeout; - espstack->esp_sadb.s_acqfn = esp_send_acquire; sadbp_init("ESP", &espstack->esp_sadb, SADB_SATYPE_ESP, esp_hash_size, espstack->ipsecesp_netstack); @@ -558,7 +488,6 @@ ipsecesp_stack_fini(netstackid_t stackid, void *arg) if (espstack->esp_pfkey_q != NULL) { (void) quntimeout(espstack->esp_pfkey_q, espstack->esp_event); } - espstack->esp_sadb.s_acqfn = NULL; espstack->esp_sadb.s_acquire_timeout = NULL; sadbp_destroy(&espstack->esp_sadb, espstack->ipsecesp_netstack); ip_drop_unregister(&espstack->esp_dropper); @@ -1181,179 +1110,6 @@ esp_inbound(mblk_t *data_mp, void *arg, ip_recv_attr_t *ira) (uint8_t *)esph - data_mp->b_rptr)); } -/* - * Perform the really difficult work of inserting the proposed situation. - * Called while holding the algorithm lock. - */ -static void -esp_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs, - netstack_t *ns) -{ - sadb_comb_t *comb = (sadb_comb_t *)(prop + 1); - ipsec_action_t *ap; - ipsec_prot_t *prot; - ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock)); - - prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; - prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t)); - *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */ - - prop->sadb_prop_replay = espstack->ipsecesp_replay_size; - - /* - * Based upon algorithm properties, and what-not, prioritize a - * proposal, based on the ordering of the ESP algorithms in the - * alternatives in the policy rule or socket that was placed - * in the acquire record. - * - * For each action in policy list - * Add combination. If I've hit limit, return. - */ - - for (ap = acqrec->ipsacq_act; ap != NULL; - ap = ap->ipa_next) { - ipsec_alginfo_t *ealg = NULL; - ipsec_alginfo_t *aalg = NULL; - - if (ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) - continue; - - prot = &ap->ipa_act.ipa_apply; - - if (!(prot->ipp_use_esp)) - continue; - - if (prot->ipp_esp_auth_alg != 0) { - aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] - [prot->ipp_esp_auth_alg]; - if (aalg == NULL || !ALG_VALID(aalg)) - continue; - } - - ASSERT(prot->ipp_encr_alg > 0); - ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR] - [prot->ipp_encr_alg]; - if (ealg == NULL || !ALG_VALID(ealg)) - continue; - - comb->sadb_comb_flags = 0; - comb->sadb_comb_reserved = 0; - comb->sadb_comb_encrypt = ealg->alg_id; - comb->sadb_comb_encrypt_minbits = - MAX(prot->ipp_espe_minbits, ealg->alg_ef_minbits); - comb->sadb_comb_encrypt_maxbits = - MIN(prot->ipp_espe_maxbits, ealg->alg_ef_maxbits); - - if (aalg == NULL) { - comb->sadb_comb_auth = 0; - comb->sadb_comb_auth_minbits = 0; - comb->sadb_comb_auth_maxbits = 0; - } else { - comb->sadb_comb_auth = aalg->alg_id; - comb->sadb_comb_auth_minbits = - MAX(prot->ipp_espa_minbits, aalg->alg_ef_minbits); - comb->sadb_comb_auth_maxbits = - MIN(prot->ipp_espa_maxbits, aalg->alg_ef_maxbits); - } - - /* - * The following may be based on algorithm - * properties, but in the meantime, we just pick - * some good, sensible numbers. Key mgmt. can - * (and perhaps should) be the place to finalize - * such decisions. - */ - - /* - * No limits on allocations, since we really don't - * support that concept currently. - */ - comb->sadb_comb_soft_allocations = 0; - comb->sadb_comb_hard_allocations = 0; - - /* - * These may want to come from policy rule.. - */ - comb->sadb_comb_soft_bytes = - espstack->ipsecesp_default_soft_bytes; - comb->sadb_comb_hard_bytes = - espstack->ipsecesp_default_hard_bytes; - comb->sadb_comb_soft_addtime = - espstack->ipsecesp_default_soft_addtime; - comb->sadb_comb_hard_addtime = - espstack->ipsecesp_default_hard_addtime; - comb->sadb_comb_soft_usetime = - espstack->ipsecesp_default_soft_usetime; - comb->sadb_comb_hard_usetime = - espstack->ipsecesp_default_hard_usetime; - - prop->sadb_prop_len += SADB_8TO64(sizeof (*comb)); - if (--combs == 0) - break; /* out of space.. */ - comb++; - } -} - -/* - * Prepare and actually send the SADB_ACQUIRE message to PF_KEY. - */ -static void -esp_send_acquire(ipsacq_t *acqrec, mblk_t *extended, netstack_t *ns) -{ - uint_t combs; - sadb_msg_t *samsg; - sadb_prop_t *prop; - mblk_t *pfkeymp, *msgmp; - ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - ESP_BUMP_STAT(espstack, acquire_requests); - - if (espstack->esp_pfkey_q == NULL) { - mutex_exit(&acqrec->ipsacq_lock); - return; - } - - /* Set up ACQUIRE. */ - pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_ESP, - ns->netstack_ipsec); - if (pfkeymp == NULL) { - esp0dbg(("sadb_setup_acquire failed.\n")); - mutex_exit(&acqrec->ipsacq_lock); - return; - } - ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock)); - combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH] * - ipss->ipsec_nalgs[IPSEC_ALG_ENCR]; - msgmp = pfkeymp->b_cont; - samsg = (sadb_msg_t *)(msgmp->b_rptr); - - /* Insert proposal here. */ - - prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len); - esp_insert_prop(prop, acqrec, combs, ns); - samsg->sadb_msg_len += prop->sadb_prop_len; - msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len); - - rw_exit(&ipss->ipsec_alg_lock); - - /* - * Must mutex_exit() before sending PF_KEY message up, in - * order to avoid recursive mutex_enter() if there are no registered - * listeners. - * - * Once I've sent the message, I'm cool anyway. - */ - mutex_exit(&acqrec->ipsacq_lock); - if (extended != NULL) { - putnext(espstack->esp_pfkey_q, extended); - } - putnext(espstack->esp_pfkey_q, pfkeymp); -} - /* XXX refactor me */ /* * Handle the SADB_GETSPI message. Create a larval SA. @@ -1811,11 +1567,9 @@ esp_log_bad_auth(mblk_t *mp, ip_recv_attr_t *ira) /* * Invoked for outbound packets after ESP processing. If the packet * also requires AH, performs the AH SA selection and AH processing. - * Returns B_TRUE if the AH processing was not needed or if it was - * performed successfully. Returns B_FALSE and consumes the passed mblk - * if AH processing was required but could not be performed. * - * Returns data_mp unless data_mp was consumed/queued. + * Returns data_mp (possibly with AH added) unless data_mp was consumed + * due to an error, or queued due to async. crypto or an ACQUIRE trigger. */ static mblk_t * esp_do_outbound_ah(mblk_t *data_mp, ip_xmit_attr_t *ixa) diff --git a/usr/src/uts/common/inet/ip/sadb.c b/usr/src/uts/common/inet/ip/sadb.c index 2f59916591..d6dfa5705f 100644 --- a/usr/src/uts/common/inet/ip/sadb.c +++ b/usr/src/uts/common/inet/ip/sadb.c @@ -22,6 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2017 Joyent, Inc. */ #include <sys/types.h> @@ -74,8 +75,7 @@ * of falling under export control, it was safe to link it in there. */ -static mblk_t *sadb_extended_acquire(ipsec_selector_t *, ipsec_policy_t *, - ipsec_action_t *, boolean_t, uint32_t, uint32_t, sadb_sens_t *, +static uint8_t *sadb_action_to_ecomb(uint8_t *, uint8_t *, ipsec_action_t *, netstack_t *); static ipsa_t *sadb_torch_assoc(isaf_t *, ipsa_t *); static void sadb_destroy_acqlist(iacqf_t **, uint_t, boolean_t, @@ -83,7 +83,6 @@ static void sadb_destroy_acqlist(iacqf_t **, uint_t, boolean_t, static void sadb_destroy(sadb_t *, netstack_t *); static mblk_t *sadb_sa2msg(ipsa_t *, sadb_msg_t *); static ts_label_t *sadb_label_from_sens(sadb_sens_t *, uint64_t *); -static sadb_sens_t *sadb_make_sens_ext(ts_label_t *tsl, int *len); static time_t sadb_add_time(time_t, uint64_t); static void lifetime_fuzz(ipsa_t *); @@ -4844,6 +4843,555 @@ sadb_checkacquire(iacqf_t *bucket, ipsec_action_t *ap, ipsec_policy_t *pp, } /* + * Generate an SADB_ACQUIRE base message mblk, including KEYSOCK_OUT metadata. + * In other words, this will return, upon success, a two-mblk chain. + */ +static inline mblk_t * +sadb_acquire_msg_base(minor_t serial, uint8_t satype, uint32_t seq, pid_t pid) +{ + mblk_t *mp; + sadb_msg_t *samsg; + + mp = sadb_keysock_out(serial); + if (mp == NULL) + return (NULL); + mp->b_cont = allocb(sizeof (sadb_msg_t), BPRI_HI); + if (mp->b_cont == NULL) { + freeb(mp); + return (NULL); + } + + samsg = (sadb_msg_t *)mp->b_cont->b_rptr; + mp->b_cont->b_wptr += sizeof (*samsg); + samsg->sadb_msg_version = PF_KEY_V2; + samsg->sadb_msg_type = SADB_ACQUIRE; + samsg->sadb_msg_errno = 0; + samsg->sadb_msg_reserved = 0; + samsg->sadb_msg_satype = satype; + samsg->sadb_msg_seq = seq; + samsg->sadb_msg_pid = pid; + + return (mp); +} + +/* + * Generate address and TX/MLS sensitivity label PF_KEY extensions that are + * common to both regular and extended ACQUIREs. + */ +static mblk_t * +sadb_acquire_msg_common(ipsec_selector_t *sel, ipsec_policy_t *pp, + ipsec_action_t *ap, boolean_t tunnel_mode, ts_label_t *tsl, + sadb_sens_t *sens) +{ + size_t len; + mblk_t *mp; + uint8_t *start, *cur, *end; + uint32_t *saddrptr, *daddrptr; + sa_family_t af; + ipsec_action_t *oldap; + ipsec_selkey_t *ipsl; + uint8_t proto, pfxlen; + uint16_t lport, rport; + int senslen = 0; + + /* + * Get action pointer set if it isn't already. + */ + oldap = ap; + if (pp != NULL) { + ap = pp->ipsp_act; + if (ap == NULL) + ap = oldap; + } + + /* + * Biggest-case scenario: + * 4x (sadb_address_t + struct sockaddr_in6) + * (src, dst, isrc, idst) + * (COMING SOON, 6x, because of triggering-packet contents.) + * sadb_x_kmc_t + * sadb_sens_t + * And wiggle room for label bitvectors. Luckily there are + * programmatic ways to find it. + */ + len = 4 * (sizeof (sadb_address_t) + sizeof (struct sockaddr_in6)); + + /* Figure out full and proper length of sensitivity labels. */ + if (sens != NULL) { + ASSERT(tsl == NULL); + senslen = SADB_64TO8(sens->sadb_sens_len); + } else if (tsl != NULL) { + senslen = sadb_sens_len_from_label(tsl); + } +#ifdef DEBUG + else { + ASSERT(senslen == 0); + } +#endif /* DEBUG */ + len += senslen; + + mp = allocb(len, BPRI_HI); + if (mp == NULL) + return (NULL); + + start = mp->b_rptr; + end = start + len; + cur = start; + + /* + * Address extensions first, from most-recently-defined to least. + * (This should immediately trigger surprise or verify robustness on + * older apps, like in.iked.) + */ + if (tunnel_mode) { + /* + * Form inner address extensions based NOT on the inner + * selectors (i.e. the packet data), but on the policy's + * selector key (i.e. the policy's selector information). + * + * NOTE: The position of IPv4 and IPv6 addresses is the + * same in ipsec_selkey_t (unless the compiler does very + * strange things with unions, consult your local C language + * lawyer for details). + */ + ASSERT(pp != NULL); + + ipsl = &(pp->ipsp_sel->ipsl_key); + if (ipsl->ipsl_valid & IPSL_IPV4) { + af = AF_INET; + ASSERT(sel->ips_protocol == IPPROTO_ENCAP); + ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6)); + } else { + af = AF_INET6; + ASSERT(sel->ips_protocol == IPPROTO_IPV6); + ASSERT(ipsl->ipsl_valid & IPSL_IPV6); + } + + if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) { + saddrptr = (uint32_t *)(&ipsl->ipsl_local); + pfxlen = ipsl->ipsl_local_pfxlen; + } else { + saddrptr = (uint32_t *)(&ipv6_all_zeros); + pfxlen = 0; + } + /* XXX What about ICMP type/code? */ + lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ? + ipsl->ipsl_lport : 0; + proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ? + ipsl->ipsl_proto : 0; + + cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC, + af, saddrptr, lport, proto, pfxlen); + if (cur == NULL) { + freeb(mp); + return (NULL); + } + + if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) { + daddrptr = (uint32_t *)(&ipsl->ipsl_remote); + pfxlen = ipsl->ipsl_remote_pfxlen; + } else { + daddrptr = (uint32_t *)(&ipv6_all_zeros); + pfxlen = 0; + } + /* XXX What about ICMP type/code? */ + rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ? + ipsl->ipsl_rport : 0; + + cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST, + af, daddrptr, rport, proto, pfxlen); + if (cur == NULL) { + freeb(mp); + return (NULL); + } + /* + * TODO - if we go to 3884's dream of transport mode IP-in-IP + * _with_ inner-packet address selectors, we'll need to further + * distinguish tunnel mode here. For now, having inner + * addresses and/or ports is sufficient. + * + * Meanwhile, whack proto/ports to reflect IP-in-IP for the + * outer addresses. + */ + proto = sel->ips_protocol; /* Either _ENCAP or _IPV6 */ + lport = rport = 0; + } else if ((ap != NULL) && (!ap->ipa_want_unique)) { + /* + * For cases when the policy calls out specific ports (or not). + */ + proto = 0; + lport = 0; + rport = 0; + if (pp != NULL) { + ipsl = &(pp->ipsp_sel->ipsl_key); + if (ipsl->ipsl_valid & IPSL_PROTOCOL) + proto = ipsl->ipsl_proto; + if (ipsl->ipsl_valid & IPSL_REMOTE_PORT) + rport = ipsl->ipsl_rport; + if (ipsl->ipsl_valid & IPSL_LOCAL_PORT) + lport = ipsl->ipsl_lport; + } + } else { + /* + * For require-unique-SA policies. + */ + proto = sel->ips_protocol; + lport = sel->ips_local_port; + rport = sel->ips_remote_port; + } + + /* + * Regular addresses. These are outer-packet ones for tunnel mode. + * Or for transport mode, the regulard address & port information. + */ + af = sel->ips_isv4 ? AF_INET : AF_INET6; + + /* + * NOTE: The position of IPv4 and IPv6 addresses is the same in + * ipsec_selector_t. + */ + cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af, + (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0); + if (cur == NULL) { + freeb(mp); + return (NULL); + } + + cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af, + (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0); + if (cur == NULL) { + freeb(mp); + return (NULL); + } + + /* + * If present, generate a sensitivity label. + */ + if (cur + senslen > end) { + freeb(mp); + return (NULL); + } + if (sens != NULL) { + /* Explicit sadb_sens_t, usually from inverse-ACQUIRE. */ + bcopy(sens, cur, senslen); + } else if (tsl != NULL) { + /* Generate sadb_sens_t from ACQUIRE source. */ + sadb_sens_from_label((sadb_sens_t *)cur, SADB_EXT_SENSITIVITY, + tsl, senslen); + } +#ifdef DEBUG + else { + ASSERT(senslen == 0); + } +#endif /* DEBUG */ + cur += senslen; + mp->b_wptr = cur; + + return (mp); +} + +/* + * Generate a regular ACQUIRE's proposal extension and KMC information.. + */ +static mblk_t * +sadb_acquire_prop(ipsec_action_t *ap, netstack_t *ns, boolean_t do_esp) +{ + ipsec_stack_t *ipss = ns->netstack_ipsec; + ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; + ipsecah_stack_t *ahstack = ns->netstack_ipsecah; + mblk_t *mp = NULL; + sadb_prop_t *prop; + sadb_comb_t *comb; + ipsec_action_t *walker; + int ncombs, allocsize, ealgid, aalgid, aminbits, amaxbits, eminbits, + emaxbits, replay; + uint64_t softbytes, hardbytes, softaddtime, hardaddtime, softusetime, + hardusetime; + uint32_t kmc = 0, kmp = 0; + + /* + * Since it's an rwlock read, AND writing to the IPsec algorithms is + * rare, just acquire it once up top, and drop it upon return. + */ + rw_enter(&ipss->ipsec_alg_lock, RW_READER); + if (do_esp) { + uint64_t num_aalgs, num_ealgs; + + if (espstack->esp_kstats == NULL) + goto bail; + + num_aalgs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; + num_ealgs = ipss->ipsec_nalgs[IPSEC_ALG_ENCR]; + if (num_ealgs == 0) + goto bail; /* IPsec not loaded yet, apparently. */ + num_aalgs++; /* No-auth or self-auth-crypto ESP. */ + + /* Use netstack's maximum loaded algorithms... */ + ncombs = num_ealgs * num_aalgs; + replay = espstack->ipsecesp_replay_size; + } else { + if (ahstack->ah_kstats == NULL) + goto bail; + + ncombs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; + + if (ncombs == 0) + goto bail; /* IPsec not loaded yet, apparently. */ + replay = ahstack->ipsecah_replay_size; + } + + allocsize = sizeof (*prop) + ncombs * sizeof (*comb) + + sizeof (sadb_x_kmc_t); + mp = allocb(allocsize, BPRI_HI); + if (mp == NULL) + goto bail; + prop = (sadb_prop_t *)mp->b_rptr; + mp->b_wptr += sizeof (*prop); + comb = (sadb_comb_t *)mp->b_wptr; + /* Decrement allocsize, if it goes to or below 0, stop. */ + allocsize -= sizeof (*prop); + prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; + prop->sadb_prop_len = SADB_8TO64(sizeof (*prop)); + *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */ + prop->sadb_prop_replay = replay; + + /* + * Based upon algorithm properties, and what-not, prioritize a + * proposal, based on the ordering of the ESP algorithms in the + * alternatives in the policy rule or socket that was placed + * in the acquire record. + * + * For each action in policy list + * Add combination. + * I should not hit it, but if I've hit limit, return. + */ + + for (walker = ap; walker != NULL; walker = walker->ipa_next) { + ipsec_alginfo_t *ealg, *aalg; + ipsec_prot_t *prot; + + if (walker->ipa_act.ipa_type != IPSEC_POLICY_APPLY) + continue; + + prot = &walker->ipa_act.ipa_apply; + if (walker->ipa_act.ipa_apply.ipp_km_proto != 0) + kmp = walker->ipa_act.ipa_apply.ipp_km_proto; + if (walker->ipa_act.ipa_apply.ipp_km_cookie != 0) + kmc = walker->ipa_act.ipa_apply.ipp_km_cookie; + if (walker->ipa_act.ipa_apply.ipp_replay_depth) { + prop->sadb_prop_replay = + walker->ipa_act.ipa_apply.ipp_replay_depth; + } + + if (do_esp) { + if (!prot->ipp_use_esp) + continue; + + if (prot->ipp_esp_auth_alg != 0) { + aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] + [prot->ipp_esp_auth_alg]; + if (aalg == NULL || !ALG_VALID(aalg)) + continue; + } else + aalg = NULL; + + ASSERT(prot->ipp_encr_alg > 0); + ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR] + [prot->ipp_encr_alg]; + if (ealg == NULL || !ALG_VALID(ealg)) + continue; + + /* + * These may want to come from policy rule.. + */ + softbytes = espstack->ipsecesp_default_soft_bytes; + hardbytes = espstack->ipsecesp_default_hard_bytes; + softaddtime = espstack->ipsecesp_default_soft_addtime; + hardaddtime = espstack->ipsecesp_default_hard_addtime; + softusetime = espstack->ipsecesp_default_soft_usetime; + hardusetime = espstack->ipsecesp_default_hard_usetime; + } else { + if (!prot->ipp_use_ah) + continue; + ealg = NULL; + aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] + [prot->ipp_auth_alg]; + if (aalg == NULL || !ALG_VALID(aalg)) + continue; + + /* + * These may want to come from policy rule.. + */ + softbytes = ahstack->ipsecah_default_soft_bytes; + hardbytes = ahstack->ipsecah_default_hard_bytes; + softaddtime = ahstack->ipsecah_default_soft_addtime; + hardaddtime = ahstack->ipsecah_default_hard_addtime; + softusetime = ahstack->ipsecah_default_soft_usetime; + hardusetime = ahstack->ipsecah_default_hard_usetime; + } + + if (ealg == NULL) { + ealgid = eminbits = emaxbits = 0; + } else { + ealgid = ealg->alg_id; + eminbits = + MAX(prot->ipp_espe_minbits, ealg->alg_ef_minbits); + emaxbits = + MIN(prot->ipp_espe_maxbits, ealg->alg_ef_maxbits); + } + + if (aalg == NULL) { + aalgid = aminbits = amaxbits = 0; + } else { + aalgid = aalg->alg_id; + aminbits = MAX(prot->ipp_espa_minbits, + aalg->alg_ef_minbits); + amaxbits = MIN(prot->ipp_espa_maxbits, + aalg->alg_ef_maxbits); + } + + comb->sadb_comb_flags = 0; + comb->sadb_comb_reserved = 0; + comb->sadb_comb_encrypt = ealgid; + comb->sadb_comb_encrypt_minbits = eminbits; + comb->sadb_comb_encrypt_maxbits = emaxbits; + comb->sadb_comb_auth = aalgid; + comb->sadb_comb_auth_minbits = aminbits; + comb->sadb_comb_auth_maxbits = amaxbits; + comb->sadb_comb_soft_allocations = 0; + comb->sadb_comb_hard_allocations = 0; + comb->sadb_comb_soft_bytes = softbytes; + comb->sadb_comb_hard_bytes = hardbytes; + comb->sadb_comb_soft_addtime = softaddtime; + comb->sadb_comb_hard_addtime = hardaddtime; + comb->sadb_comb_soft_usetime = softusetime; + comb->sadb_comb_hard_usetime = hardusetime; + + prop->sadb_prop_len += SADB_8TO64(sizeof (*comb)); + mp->b_wptr += sizeof (*comb); + allocsize -= sizeof (*comb); + /* Should never dip BELOW sizeof (KM cookie extension). */ + ASSERT3S(allocsize, >=, sizeof (sadb_x_kmc_t)); + if (allocsize <= sizeof (sadb_x_kmc_t)) + break; /* out of space.. */ + comb++; + } + + /* Don't include KMC extension if there's no room. */ + if (((kmp != 0) || (kmc != 0)) && allocsize >= sizeof (sadb_x_kmc_t)) { + if (sadb_make_kmc_ext(mp->b_wptr, + mp->b_wptr + sizeof (sadb_x_kmc_t), kmp, kmc) == NULL) { + freeb(mp); + mp = NULL; + goto bail; + } + mp->b_wptr += sizeof (sadb_x_kmc_t); + prop->sadb_prop_len += SADB_8TO64(sizeof (sadb_x_kmc_t)); + } + +bail: + rw_exit(&ipss->ipsec_alg_lock); + return (mp); +} + +/* + * Generate an extended ACQUIRE's extended-proposal extension. + */ +/* ARGSUSED */ +static mblk_t * +sadb_acquire_extended_prop(ipsec_action_t *ap, netstack_t *ns) +{ + sadb_prop_t *eprop; + uint8_t *cur, *end; + mblk_t *mp; + int allocsize, numecombs = 0, numalgdescs = 0; + uint32_t kmc = 0, kmp = 0, replay = 0; + ipsec_action_t *walker; + + allocsize = sizeof (*eprop); + + /* + * Going to walk through the action list twice. Once for allocation + * measurement, and once for actual construction. + */ + for (walker = ap; walker != NULL; walker = walker->ipa_next) { + ipsec_prot_t *ipp; + + /* + * Skip non-IPsec policies + */ + if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY) + continue; + + ipp = &walker->ipa_act.ipa_apply; + + if (walker->ipa_act.ipa_apply.ipp_km_proto) + kmp = ipp->ipp_km_proto; + if (walker->ipa_act.ipa_apply.ipp_km_cookie) + kmc = ipp->ipp_km_cookie; + if (walker->ipa_act.ipa_apply.ipp_replay_depth) + replay = ipp->ipp_replay_depth; + + if (ipp->ipp_use_ah) + numalgdescs++; + if (ipp->ipp_use_esp) { + numalgdescs++; + if (ipp->ipp_use_espa) + numalgdescs++; + } + + numecombs++; + } + ASSERT(numecombs > 0); + + allocsize += numecombs * sizeof (sadb_x_ecomb_t) + + numalgdescs * sizeof (sadb_x_algdesc_t) + sizeof (sadb_x_kmc_t); + mp = allocb(allocsize, BPRI_HI); + if (mp == NULL) + return (NULL); + eprop = (sadb_prop_t *)mp->b_rptr; + end = mp->b_rptr + allocsize; + cur = mp->b_rptr + sizeof (*eprop); + + eprop->sadb_prop_exttype = SADB_X_EXT_EPROP; + eprop->sadb_x_prop_ereserved = 0; + eprop->sadb_x_prop_numecombs = 0; + *(uint32_t *)(&eprop->sadb_prop_replay) = 0; /* Quick zero-out! */ + /* Pick ESP's replay default if need be. */ + eprop->sadb_prop_replay = (replay == 0) ? + ns->netstack_ipsecesp->ipsecesp_replay_size : replay; + + /* This time, walk through and actually allocate. */ + for (walker = ap; walker != NULL; walker = walker->ipa_next) { + /* + * Skip non-IPsec policies + */ + if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY) + continue; + cur = sadb_action_to_ecomb(cur, end, walker, ns); + if (cur == NULL) { + /* NOTE: inverse-ACQUIRE should note this as ENOMEM. */ + freeb(mp); + return (NULL); + } + eprop->sadb_x_prop_numecombs++; + } + + ASSERT(end - cur >= sizeof (sadb_x_kmc_t)); + if ((kmp != 0) || (kmc != 0)) { + cur = sadb_make_kmc_ext(cur, end, kmp, kmc); + if (cur == NULL) { + freeb(mp); + return (NULL); + } + } + mp->b_wptr = cur; + eprop->sadb_prop_len = SADB_8TO64(cur - mp->b_rptr); + + return (mp); +} + +/* * For this mblk, insert a new acquire record. Assume bucket contains addrs * of all of the same length. Give up (and drop) if memory * cannot be allocated for a new one; otherwise, invoke callback to @@ -4857,12 +5405,11 @@ void sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah, boolean_t need_esp) { - mblk_t *asyncmp; + mblk_t *asyncmp, *regular, *extended, *common, *prop, *eprop; sadbp_t *spp; sadb_t *sp; ipsacq_t *newbie; iacqf_t *bucket; - mblk_t *extended; ipha_t *ipha = (ipha_t *)datamp->b_rptr; ip6_t *ip6h = (ip6_t *)datamp->b_rptr; uint32_t *src, *dst, *isrc, *idst; @@ -4872,36 +5419,37 @@ sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah, int hashoffset; uint32_t seq; uint64_t unique_id = 0; - ipsec_selector_t sel; boolean_t tunnel_mode = (ixa->ixa_flags & IXAF_IPSEC_TUNNEL) != 0; - ts_label_t *tsl = NULL; + ts_label_t *tsl; netstack_t *ns = ixa->ixa_ipst->ips_netstack; ipsec_stack_t *ipss = ns->netstack_ipsec; - sadb_sens_t *sens = NULL; - int sens_len; + ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; + ipsecah_stack_t *ahstack = ns->netstack_ipsecah; + ipsec_selector_t sel; + queue_t *q; ASSERT((pp != NULL) || (ap != NULL)); - ASSERT(need_ah != NULL || need_esp != NULL); + ASSERT(need_ah || need_esp); /* Assign sadb pointers */ - if (need_esp) { /* ESP for AH+ESP */ - ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; - + if (need_esp) { + /* + * ESP happens first if we need both AH and ESP. + */ spp = &espstack->esp_sadb; } else { - ipsecah_stack_t *ahstack = ns->netstack_ipsecah; - spp = &ahstack->ah_sadb; } sp = (ixa->ixa_flags & IXAF_IS_IPV4) ? &spp->s_v4 : &spp->s_v6; if (is_system_labeled()) tsl = ixa->ixa_tsl; + else + tsl = NULL; if (ap == NULL) ap = pp->ipsp_act; - ASSERT(ap != NULL); if (ap->ipa_act.ipa_apply.ipp_use_unique || tunnel_mode) @@ -5031,6 +5579,13 @@ sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah, } ip_drop_output("No memory for asyncmp", datamp, NULL); freemsg(datamp); + /* + * The acquire record will be freed quickly if it's new + * (ipsacq_expire == 0), and will proceed as if no packet + * showed up if not. + */ + mutex_exit(&newbie->ipsacq_lock); + return; } else if (newbie->ipsacq_numpackets == 0) { /* First one. */ newbie->ipsacq_mp = asyncmp; @@ -5063,9 +5618,9 @@ sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah, } newbie->ipsacq_unique_id = unique_id; - if (ixa->ixa_tsl != NULL) { - label_hold(ixa->ixa_tsl); - newbie->ipsacq_tsl = ixa->ixa_tsl; + if (tsl != NULL) { + label_hold(tsl); + newbie->ipsacq_tsl = tsl; } } else { /* Scan to the end of the list & insert. */ @@ -5110,11 +5665,25 @@ sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah, return; } - if (!keysock_extended_reg(ns)) - goto punt_extended; + if (need_esp) { + ESP_BUMP_STAT(espstack, acquire_requests); + q = espstack->esp_pfkey_q; + } else { + /* + * Two cases get us here: + * 1.) AH-only policy. + * + * 2.) A continuation of an AH+ESP policy, and this is the + * post-ESP, AH-needs-to-send-a-regular-ACQUIRE case. + * (i.e. called from esp_do_outbound_ah().) + */ + AH_BUMP_STAT(ahstack, acquire_requests); + q = ahstack->ah_pfkey_q; + } + /* - * Construct an extended ACQUIRE. There are logging - * opportunities here in failure cases. + * Get selectors and other policy-expression bits needed for an + * ACQUIRE. */ bzero(&sel, sizeof (sel)); sel.ips_isv4 = (ixa->ixa_flags & IXAF_IS_IPV4) != 0; @@ -5137,45 +5706,99 @@ sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah, sel.ips_remote_addr_v6 = ip6h->ip6_dst; } - extended = sadb_keysock_out(0); - if (extended == NULL) - goto punt_extended; - if (ixa->ixa_tsl != NULL) { - /* - * XXX MLS correct condition here? - * XXX MLS other credential attributes in acquire? - * XXX malloc failure? don't fall back to original? - */ - sens = sadb_make_sens_ext(ixa->ixa_tsl, &sens_len); + /* + * 1. Generate addresses, kmc, and sensitivity. These are "common" + * and should be an mblk pointed to by common. TBD -- eventually it + * will include triggering packet contents as more address extensions. + * + * 2. Generate ACQUIRE & KEYSOCK_OUT and single-protocol proposal. + * These are "regular" and "prop". String regular->b_cont->b_cont = + * common, common->b_cont = prop. + * + * 3. If extended register got turned on, generate EXT_ACQUIRE & + * KEYSOCK_OUT and multi-protocol eprop. These are "extended" and + * "eprop". String extended->b_cont->b_cont = dupb(common) and + * extended->b_cont->b_cont->b_cont = prop. + * + * 4. Deliver: putnext(q, regular) and if there, putnext(q, extended). + */ - if (sens == NULL) { - freeb(extended); - goto punt_extended; - } - } + regular = extended = prop = eprop = NULL; - extended->b_cont = sadb_extended_acquire(&sel, pp, ap, tunnel_mode, - seq, 0, sens, ns); + common = sadb_acquire_msg_common(&sel, pp, ap, tunnel_mode, tsl, NULL); + if (common == NULL) + goto bail; - if (sens != NULL) - kmem_free(sens, sens_len); + regular = sadb_acquire_msg_base(0, (need_esp ? + SADB_SATYPE_ESP : SADB_SATYPE_AH), newbie->ipsacq_seq, 0); + if (regular == NULL) + goto bail; - if (extended->b_cont == NULL) { - freeb(extended); - goto punt_extended; - } + /* + * Pardon the boolean cleverness. At least one of need_* must be true. + * If they are equal, it's an AH & ESP policy and ESP needs to go + * first. If they aren't, just check the contents of need_esp. + */ + prop = sadb_acquire_prop(ap, ns, need_esp); + if (prop == NULL) + goto bail; + + /* Link the parts together. */ + regular->b_cont->b_cont = common; + common->b_cont = prop; + /* + * Prop is now linked, so don't freemsg() it if the extended + * construction goes off the rails. + */ + prop = NULL; + + ((sadb_msg_t *)(regular->b_cont->b_rptr))->sadb_msg_len = + SADB_8TO64(msgsize(regular->b_cont)); /* - * Send an ACQUIRE message (and possible an extended ACQUIRE) based on - * this new record. The send-acquire callback assumes that acqrec is - * already locked. + * If we need an extended ACQUIRE, build it here. */ - (*spp->s_acqfn)(newbie, extended, ns); + if (keysock_extended_reg(ns)) { + /* NOTE: "common" still points to what we need. */ + extended = sadb_acquire_msg_base(0, 0, newbie->ipsacq_seq, 0); + if (extended == NULL) { + common = NULL; + goto bail; + } + + extended->b_cont->b_cont = dupb(common); + common = NULL; + if (extended->b_cont->b_cont == NULL) + goto bail; + + eprop = sadb_acquire_extended_prop(ap, ns); + if (eprop == NULL) + goto bail; + extended->b_cont->b_cont->b_cont = eprop; + + ((sadb_msg_t *)(extended->b_cont->b_rptr))->sadb_msg_len = + SADB_8TO64(msgsize(extended->b_cont)); + } + + /* So we don't hold a lock across putnext()... */ + mutex_exit(&newbie->ipsacq_lock); + + if (extended != NULL) + putnext(q, extended); + ASSERT(regular != NULL); + putnext(q, regular); return; -punt_extended: - (*spp->s_acqfn)(newbie, NULL, ns); +bail: + /* Make this acquire record go away quickly... */ + newbie->ipsacq_expire = 0; + /* Exploit freemsg(NULL) being legal for fun & profit. */ + freemsg(common); + freemsg(prop); + freemsg(extended); + freemsg(regular); + mutex_exit(&newbie->ipsacq_lock); } /* @@ -5429,21 +6052,6 @@ sadb_sens_from_label(sadb_sens_t *sens, int exttype, ts_label_t *tsl, bcopy(&(((_bslabel_impl_t *)sl)->compartments), bitmap, _C_LEN * 4); } -static sadb_sens_t * -sadb_make_sens_ext(ts_label_t *tsl, int *len) -{ - /* XXX allocation failure? */ - int sens_len = sadb_sens_len_from_label(tsl); - - sadb_sens_t *sens = kmem_alloc(sens_len, KM_SLEEP); - - sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY, tsl, sens_len); - - *len = sens_len; - - return (sens); -} - /* * Okay, how do we report errors/invalid labels from this? * With a special designated "not a label" cred_t ? @@ -5480,392 +6088,6 @@ sadb_label_from_sens(sadb_sens_t *sens, uint64_t *bitmap) /* End XXX label-library-leakage */ /* - * Construct an extended ACQUIRE message based on a selector and the resulting - * IPsec action. - * - * NOTE: This is used by both inverse ACQUIRE and actual ACQUIRE - * generation. As a consequence, expect this function to evolve - * rapidly. - */ -static mblk_t * -sadb_extended_acquire(ipsec_selector_t *sel, ipsec_policy_t *pol, - ipsec_action_t *act, boolean_t tunnel_mode, uint32_t seq, uint32_t pid, - sadb_sens_t *sens, netstack_t *ns) -{ - mblk_t *mp; - sadb_msg_t *samsg; - uint8_t *start, *cur, *end; - uint32_t *saddrptr, *daddrptr; - sa_family_t af; - sadb_prop_t *eprop; - ipsec_action_t *ap, *an; - ipsec_selkey_t *ipsl; - uint8_t proto, pfxlen; - uint16_t lport, rport; - uint32_t kmp, kmc; - - /* - * Find the action we want sooner rather than later.. - */ - an = NULL; - if (pol == NULL) { - ap = act; - } else { - ap = pol->ipsp_act; - - if (ap != NULL) - an = ap->ipa_next; - } - - /* - * Just take a swag for the allocation for now. We can always - * alter it later. - */ -#define SADB_EXTENDED_ACQUIRE_SIZE 4096 - mp = allocb(SADB_EXTENDED_ACQUIRE_SIZE, BPRI_HI); - if (mp == NULL) - return (NULL); - - start = mp->b_rptr; - end = start + SADB_EXTENDED_ACQUIRE_SIZE; - - cur = start; - - samsg = (sadb_msg_t *)cur; - cur += sizeof (*samsg); - - samsg->sadb_msg_version = PF_KEY_V2; - samsg->sadb_msg_type = SADB_ACQUIRE; - samsg->sadb_msg_errno = 0; - samsg->sadb_msg_reserved = 0; - samsg->sadb_msg_satype = 0; - samsg->sadb_msg_seq = seq; - samsg->sadb_msg_pid = pid; - - if (tunnel_mode) { - /* - * Form inner address extensions based NOT on the inner - * selectors (i.e. the packet data), but on the policy's - * selector key (i.e. the policy's selector information). - * - * NOTE: The position of IPv4 and IPv6 addresses is the - * same in ipsec_selkey_t (unless the compiler does very - * strange things with unions, consult your local C language - * lawyer for details). - */ - ASSERT(pol != NULL); - - ipsl = &(pol->ipsp_sel->ipsl_key); - if (ipsl->ipsl_valid & IPSL_IPV4) { - af = AF_INET; - ASSERT(sel->ips_protocol == IPPROTO_ENCAP); - ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6)); - } else { - af = AF_INET6; - ASSERT(sel->ips_protocol == IPPROTO_IPV6); - ASSERT(ipsl->ipsl_valid & IPSL_IPV6); - } - - if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) { - saddrptr = (uint32_t *)(&ipsl->ipsl_local); - pfxlen = ipsl->ipsl_local_pfxlen; - } else { - saddrptr = (uint32_t *)(&ipv6_all_zeros); - pfxlen = 0; - } - /* XXX What about ICMP type/code? */ - lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ? - ipsl->ipsl_lport : 0; - proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ? - ipsl->ipsl_proto : 0; - - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC, - af, saddrptr, lport, proto, pfxlen); - if (cur == NULL) { - freeb(mp); - return (NULL); - } - - if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) { - daddrptr = (uint32_t *)(&ipsl->ipsl_remote); - pfxlen = ipsl->ipsl_remote_pfxlen; - } else { - daddrptr = (uint32_t *)(&ipv6_all_zeros); - pfxlen = 0; - } - /* XXX What about ICMP type/code? */ - rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ? - ipsl->ipsl_rport : 0; - - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST, - af, daddrptr, rport, proto, pfxlen); - if (cur == NULL) { - freeb(mp); - return (NULL); - } - /* - * TODO - if we go to 3408's dream of transport mode IP-in-IP - * _with_ inner-packet address selectors, we'll need to further - * distinguish tunnel mode here. For now, having inner - * addresses and/or ports is sufficient. - * - * Meanwhile, whack proto/ports to reflect IP-in-IP for the - * outer addresses. - */ - proto = sel->ips_protocol; /* Either _ENCAP or _IPV6 */ - lport = rport = 0; - } else if ((ap != NULL) && (!ap->ipa_want_unique)) { - proto = 0; - lport = 0; - rport = 0; - if (pol != NULL) { - ipsl = &(pol->ipsp_sel->ipsl_key); - if (ipsl->ipsl_valid & IPSL_PROTOCOL) - proto = ipsl->ipsl_proto; - if (ipsl->ipsl_valid & IPSL_REMOTE_PORT) - rport = ipsl->ipsl_rport; - if (ipsl->ipsl_valid & IPSL_LOCAL_PORT) - lport = ipsl->ipsl_lport; - } - } else { - proto = sel->ips_protocol; - lport = sel->ips_local_port; - rport = sel->ips_remote_port; - } - - af = sel->ips_isv4 ? AF_INET : AF_INET6; - - /* - * NOTE: The position of IPv4 and IPv6 addresses is the same in - * ipsec_selector_t. - */ - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af, - (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0); - - if (cur == NULL) { - freeb(mp); - return (NULL); - } - - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af, - (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0); - - if (cur == NULL) { - freeb(mp); - return (NULL); - } - - if (sens != NULL) { - uint8_t *sensext = cur; - int senslen = SADB_64TO8(sens->sadb_sens_len); - - cur += senslen; - if (cur > end) { - freeb(mp); - return (NULL); - } - bcopy(sens, sensext, senslen); - } - - /* - * This section will change a lot as policy evolves. - * For now, it'll be relatively simple. - */ - eprop = (sadb_prop_t *)cur; - cur += sizeof (*eprop); - if (cur > end) { - /* no space left */ - freeb(mp); - return (NULL); - } - - eprop->sadb_prop_exttype = SADB_X_EXT_EPROP; - eprop->sadb_x_prop_ereserved = 0; - eprop->sadb_x_prop_numecombs = 0; - eprop->sadb_prop_replay = 32; /* default */ - - kmc = kmp = 0; - - for (; ap != NULL; ap = an) { - an = (pol != NULL) ? ap->ipa_next : NULL; - - /* - * Skip non-IPsec policies - */ - if (ap->ipa_act.ipa_type != IPSEC_ACT_APPLY) - continue; - - if (ap->ipa_act.ipa_apply.ipp_km_proto) - kmp = ap->ipa_act.ipa_apply.ipp_km_proto; - if (ap->ipa_act.ipa_apply.ipp_km_cookie) - kmc = ap->ipa_act.ipa_apply.ipp_km_cookie; - if (ap->ipa_act.ipa_apply.ipp_replay_depth) { - eprop->sadb_prop_replay = - ap->ipa_act.ipa_apply.ipp_replay_depth; - } - - cur = sadb_action_to_ecomb(cur, end, ap, ns); - if (cur == NULL) { /* no space */ - freeb(mp); - return (NULL); - } - eprop->sadb_x_prop_numecombs++; - } - - if (eprop->sadb_x_prop_numecombs == 0) { - /* - * This will happen if we fail to find a policy - * allowing for IPsec processing. - * Construct an error message. - */ - samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg)); - samsg->sadb_msg_errno = ENOENT; - samsg->sadb_x_msg_diagnostic = 0; - return (mp); - } - - if ((kmp != 0) || (kmc != 0)) { - cur = sadb_make_kmc_ext(cur, end, kmp, kmc); - if (cur == NULL) { - freeb(mp); - return (NULL); - } - } - - eprop->sadb_prop_len = SADB_8TO64(cur - (uint8_t *)eprop); - samsg->sadb_msg_len = SADB_8TO64(cur - start); - mp->b_wptr = cur; - - return (mp); -} - -/* - * Generic setup of an RFC 2367 ACQUIRE message. Caller sets satype. - * - * NOTE: This function acquires alg_lock as a side-effect if-and-only-if we - * succeed (i.e. return non-NULL). Caller MUST release it. This is to - * maximize code consolidation while preventing algorithm changes from messing - * with the callers finishing touches on the ACQUIRE itself. - */ -mblk_t * -sadb_setup_acquire(ipsacq_t *acqrec, uint8_t satype, ipsec_stack_t *ipss) -{ - uint_t allocsize; - mblk_t *pfkeymp, *msgmp; - sa_family_t af; - uint8_t *cur, *end; - sadb_msg_t *samsg; - uint16_t sport_typecode; - uint16_t dport_typecode; - uint8_t check_proto; - boolean_t tunnel_mode = (acqrec->ipsacq_inneraddrfam != 0); - - ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock)); - - pfkeymp = sadb_keysock_out(0); - if (pfkeymp == NULL) - return (NULL); - - /* - * First, allocate a basic ACQUIRE message - */ - allocsize = sizeof (sadb_msg_t) + sizeof (sadb_address_t) + - sizeof (sadb_address_t) + sizeof (sadb_prop_t); - - /* Make sure there's enough to cover both AF_INET and AF_INET6. */ - allocsize += 2 * sizeof (struct sockaddr_in6); - - rw_enter(&ipss->ipsec_alg_lock, RW_READER); - /* NOTE: The lock is now held through to this function's return. */ - allocsize += ipss->ipsec_nalgs[IPSEC_ALG_AUTH] * - ipss->ipsec_nalgs[IPSEC_ALG_ENCR] * sizeof (sadb_comb_t); - - if (tunnel_mode) { - /* Tunnel mode! */ - allocsize += 2 * sizeof (sadb_address_t); - /* Enough to cover both AF_INET and AF_INET6. */ - allocsize += 2 * sizeof (struct sockaddr_in6); - } - - msgmp = allocb(allocsize, BPRI_HI); - if (msgmp == NULL) { - freeb(pfkeymp); - rw_exit(&ipss->ipsec_alg_lock); - return (NULL); - } - - pfkeymp->b_cont = msgmp; - cur = msgmp->b_rptr; - end = cur + allocsize; - samsg = (sadb_msg_t *)cur; - cur += sizeof (sadb_msg_t); - - af = acqrec->ipsacq_addrfam; - switch (af) { - case AF_INET: - check_proto = IPPROTO_ICMP; - break; - case AF_INET6: - check_proto = IPPROTO_ICMPV6; - break; - default: - /* This should never happen unless we have kernel bugs. */ - cmn_err(CE_WARN, - "sadb_setup_acquire: corrupt ACQUIRE record.\n"); - ASSERT(0); - rw_exit(&ipss->ipsec_alg_lock); - return (NULL); - } - - samsg->sadb_msg_version = PF_KEY_V2; - samsg->sadb_msg_type = SADB_ACQUIRE; - samsg->sadb_msg_satype = satype; - samsg->sadb_msg_errno = 0; - samsg->sadb_msg_pid = 0; - samsg->sadb_msg_reserved = 0; - samsg->sadb_msg_seq = acqrec->ipsacq_seq; - - ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock)); - - if ((acqrec->ipsacq_proto == check_proto) || tunnel_mode) { - sport_typecode = dport_typecode = 0; - } else { - sport_typecode = acqrec->ipsacq_srcport; - dport_typecode = acqrec->ipsacq_dstport; - } - - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af, - acqrec->ipsacq_srcaddr, sport_typecode, acqrec->ipsacq_proto, 0); - - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af, - acqrec->ipsacq_dstaddr, dport_typecode, acqrec->ipsacq_proto, 0); - - if (tunnel_mode) { - sport_typecode = acqrec->ipsacq_srcport; - dport_typecode = acqrec->ipsacq_dstport; - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC, - acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innersrc, - sport_typecode, acqrec->ipsacq_inner_proto, - acqrec->ipsacq_innersrcpfx); - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST, - acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innerdst, - dport_typecode, acqrec->ipsacq_inner_proto, - acqrec->ipsacq_innerdstpfx); - } - - /* XXX Insert identity information here. */ - - /* XXXMLS Insert sensitivity information here. */ - - if (cur != NULL) - samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr); - else - rw_exit(&ipss->ipsec_alg_lock); - - return (pfkeymp); -} - -/* * Given an SADB_GETSPI message, find an appropriately ranged SA and * allocate an SA. If there are message improprieties, return (ipsa_t *)-1. * If there was a memory allocation error, return NULL. (Assume NULL != @@ -6856,14 +7078,34 @@ ipsec_construct_inverse_acquire(sadb_msg_t *samsg, sadb_ext_t *extv[], } } - /* - * Now that we have a policy entry/widget, construct an ACQUIRE - * message based on that, fix fields where appropriate, - * and return the message. - */ - retmp = sadb_extended_acquire(&sel, pp, NULL, - (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)), - samsg->sadb_msg_seq, samsg->sadb_msg_pid, sens, ns); + ASSERT(pp != NULL); + retmp = sadb_acquire_msg_base(0, 0, samsg->sadb_msg_seq, + samsg->sadb_msg_pid); + if (retmp != NULL) { + /* Remove KEYSOCK_OUT, because caller constructs it instead. */ + mblk_t *kso = retmp; + + retmp = retmp->b_cont; + freeb(kso); + /* Append addresses... */ + retmp->b_cont = sadb_acquire_msg_common(&sel, pp, NULL, + (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)), NULL, + sens); + if (retmp->b_cont == NULL) { + freemsg(retmp); + retmp = NULL; + } + /* And the policy result. */ + retmp->b_cont->b_cont = + sadb_acquire_extended_prop(pp->ipsp_act, ns); + if (retmp->b_cont->b_cont == NULL) { + freemsg(retmp); + retmp = NULL; + } + ((sadb_msg_t *)retmp->b_rptr)->sadb_msg_len = + SADB_8TO64(msgsize(retmp)); + } + if (pp != NULL) { IPPOL_REFRELE(pp); } diff --git a/usr/src/uts/common/inet/ip/spd.c b/usr/src/uts/common/inet/ip/spd.c index cdafc151b6..841c345013 100644 --- a/usr/src/uts/common/inet/ip/spd.c +++ b/usr/src/uts/common/inet/ip/spd.c @@ -23,6 +23,7 @@ * Use is subject to license terms. * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. + * Copyright (c) 2017, Joyent, Inc. */ /* @@ -4686,8 +4687,9 @@ ipsid_fini(netstack_t *ns) } /* - * Update the minimum and maximum supported key sizes for the - * specified algorithm. Must be called while holding the algorithms lock. + * Update the minimum and maximum supported key sizes for the specified + * algorithm, which is either a member of a netstack alg array or about to be, + * and therefore must be called holding ipsec_alg_lock for write. */ void ipsec_alg_fix_min_max(ipsec_alginfo_t *alg, ipsec_algtype_t alg_type, diff --git a/usr/src/uts/common/inet/ipsecah.h b/usr/src/uts/common/inet/ipsecah.h index 62f96876b8..62f877bb8f 100644 --- a/usr/src/uts/common/inet/ipsecah.h +++ b/usr/src/uts/common/inet/ipsecah.h @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. */ #ifndef _INET_IPSECAH_H @@ -114,6 +115,21 @@ struct ipsecah_stack { }; typedef struct ipsecah_stack ipsecah_stack_t; +#define ipsecah_debug ipsecah_params[0].ipsecah_param_value +#define ipsecah_age_interval ipsecah_params[1].ipsecah_param_value +#define ipsecah_age_int_max ipsecah_params[1].ipsecah_param_max +#define ipsecah_reap_delay ipsecah_params[2].ipsecah_param_value +#define ipsecah_replay_size ipsecah_params[3].ipsecah_param_value +#define ipsecah_acquire_timeout ipsecah_params[4].ipsecah_param_value +#define ipsecah_larval_timeout ipsecah_params[5].ipsecah_param_value +#define ipsecah_default_soft_bytes ipsecah_params[6].ipsecah_param_value +#define ipsecah_default_hard_bytes ipsecah_params[7].ipsecah_param_value +#define ipsecah_default_soft_addtime ipsecah_params[8].ipsecah_param_value +#define ipsecah_default_hard_addtime ipsecah_params[9].ipsecah_param_value +#define ipsecah_default_soft_usetime ipsecah_params[10].ipsecah_param_value +#define ipsecah_default_hard_usetime ipsecah_params[11].ipsecah_param_value +#define ipsecah_log_unknown_spi ipsecah_params[12].ipsecah_param_value + #endif /* _KERNEL */ /* diff --git a/usr/src/uts/common/inet/ipsecesp.h b/usr/src/uts/common/inet/ipsecesp.h index 96e139add0..3039caf2e6 100644 --- a/usr/src/uts/common/inet/ipsecesp.h +++ b/usr/src/uts/common/inet/ipsecesp.h @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. */ #ifndef _INET_IPSECESP_H @@ -44,6 +45,52 @@ typedef struct ipsecespparam_s { } ipsecespparam_t; /* + * Stats. This may eventually become a full-blown SNMP MIB once that spec + * stabilizes. + */ + +typedef struct esp_kstats_s { + kstat_named_t esp_stat_num_aalgs; + kstat_named_t esp_stat_good_auth; + kstat_named_t esp_stat_bad_auth; + kstat_named_t esp_stat_bad_padding; + kstat_named_t esp_stat_replay_failures; + kstat_named_t esp_stat_replay_early_failures; + kstat_named_t esp_stat_keysock_in; + kstat_named_t esp_stat_out_requests; + kstat_named_t esp_stat_acquire_requests; + kstat_named_t esp_stat_bytes_expired; + kstat_named_t esp_stat_out_discards; + kstat_named_t esp_stat_crypto_sync; + kstat_named_t esp_stat_crypto_async; + kstat_named_t esp_stat_crypto_failures; + kstat_named_t esp_stat_num_ealgs; + kstat_named_t esp_stat_bad_decrypt; + kstat_named_t esp_stat_sa_port_renumbers; +} esp_kstats_t; + +/* + * espstack->esp_kstats is equal to espstack->esp_ksp->ks_data if + * kstat_create_netstack for espstack->esp_ksp succeeds, but when it + * fails, it will be NULL. Note this is done for all stack instances, + * so it *could* fail. hence a non-NULL checking is done for + * ESP_BUMP_STAT and ESP_DEBUMP_STAT + */ +#define ESP_BUMP_STAT(espstack, x) \ +do { \ + if (espstack->esp_kstats != NULL) \ + (espstack->esp_kstats->esp_stat_ ## x).value.ui64++; \ +_NOTE(CONSTCOND) \ +} while (0) + +#define ESP_DEBUMP_STAT(espstack, x) \ +do { \ + if (espstack->esp_kstats != NULL) \ + (espstack->esp_kstats->esp_stat_ ## x).value.ui64--; \ +_NOTE(CONSTCOND) \ +} while (0) + +/* * IPSECESP stack instances */ struct ipsecesp_stack { @@ -72,7 +119,31 @@ struct ipsecesp_stack { }; typedef struct ipsecesp_stack ipsecesp_stack_t; -/* Define *this* NDD variable here because we use it outside ESP proper. */ +#define ipsecesp_debug ipsecesp_params[0].ipsecesp_param_value +#define ipsecesp_age_interval ipsecesp_params[1].ipsecesp_param_value +#define ipsecesp_age_int_max ipsecesp_params[1].ipsecesp_param_max +#define ipsecesp_reap_delay ipsecesp_params[2].ipsecesp_param_value +#define ipsecesp_replay_size ipsecesp_params[3].ipsecesp_param_value +#define ipsecesp_acquire_timeout \ + ipsecesp_params[4].ipsecesp_param_value +#define ipsecesp_larval_timeout \ + ipsecesp_params[5].ipsecesp_param_value +#define ipsecesp_default_soft_bytes \ + ipsecesp_params[6].ipsecesp_param_value +#define ipsecesp_default_hard_bytes \ + ipsecesp_params[7].ipsecesp_param_value +#define ipsecesp_default_soft_addtime \ + ipsecesp_params[8].ipsecesp_param_value +#define ipsecesp_default_hard_addtime \ + ipsecesp_params[9].ipsecesp_param_value +#define ipsecesp_default_soft_usetime \ + ipsecesp_params[10].ipsecesp_param_value +#define ipsecesp_default_hard_usetime \ + ipsecesp_params[11].ipsecesp_param_value +#define ipsecesp_log_unknown_spi \ + ipsecesp_params[12].ipsecesp_param_value +#define ipsecesp_padding_check \ + ipsecesp_params[13].ipsecesp_param_value #define ipsecesp_nat_keepalive_interval \ ipsecesp_params[14].ipsecesp_param_value diff --git a/usr/src/uts/common/inet/sadb.h b/usr/src/uts/common/inet/sadb.h index 20abd4b26c..3dad99c0dd 100644 --- a/usr/src/uts/common/inet/sadb.h +++ b/usr/src/uts/common/inet/sadb.h @@ -568,15 +568,13 @@ typedef struct sadb_s } sadb_t; /* - * A pair of SADB's (one for v4, one for v6), and related state (including - * acquire callbacks). + * A pair of SADB's (one for v4, one for v6), and related state. */ typedef struct sadbp_s { uint32_t s_satype; uint32_t *s_acquire_timeout; - void (*s_acqfn)(ipsacq_t *, mblk_t *, netstack_t *); sadb_t s_v4; sadb_t s_v6; uint32_t s_addflags; @@ -773,7 +771,6 @@ void cbc_params_init(ipsa_t *, uchar_t *, uint_t, uchar_t *, ipsa_cm_mech_t *, void sadb_destroy_acquire(ipsacq_t *, netstack_t *); struct ipsec_stack; -mblk_t *sadb_setup_acquire(ipsacq_t *, uint8_t, struct ipsec_stack *); ipsa_t *sadb_getspi(keysock_in_t *, uint32_t, int *, netstack_t *, uint_t); void sadb_in_acquire(sadb_msg_t *, sadbp_t *, queue_t *, netstack_t *); boolean_t sadb_replay_check(ipsa_t *, uint32_t); |