2002-10-16 02:10:08 +00:00
|
|
|
/* $FreeBSD$ */
|
|
|
|
/* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */
|
|
|
|
|
2005-01-07 01:45:51 +00:00
|
|
|
/*-
|
2017-11-20 19:43:44 +00:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*
|
2002-10-16 02:10:08 +00:00
|
|
|
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. Neither the name of the project nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IPsec controller part.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "opt_inet.h"
|
|
|
|
#include "opt_inet6.h"
|
|
|
|
#include "opt_ipsec.h"
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/domain.h>
|
2006-11-07 08:58:06 +00:00
|
|
|
#include <sys/priv.h>
|
2002-10-16 02:10:08 +00:00
|
|
|
#include <sys/protosw.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/socketvar.h>
|
|
|
|
#include <sys/errno.h>
|
2015-11-25 07:31:59 +00:00
|
|
|
#include <sys/hhook.h>
|
2002-10-16 02:10:08 +00:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/syslog.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
|
|
|
|
#include <net/if.h>
|
2015-11-25 07:31:59 +00:00
|
|
|
#include <net/if_enc.h>
|
2013-10-26 17:58:36 +00:00
|
|
|
#include <net/if_var.h>
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
#include <net/vnet.h>
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <netinet/ip_var.h>
|
|
|
|
#include <netinet/in_var.h>
|
|
|
|
#include <netinet/udp.h>
|
|
|
|
#include <netinet/udp_var.h>
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#include <netinet/udp.h>
|
|
|
|
|
|
|
|
#include <netinet/ip6.h>
|
|
|
|
#ifdef INET6
|
|
|
|
#include <netinet6/ip6_var.h>
|
|
|
|
#endif
|
|
|
|
#include <netinet/in_pcb.h>
|
|
|
|
#ifdef INET6
|
|
|
|
#include <netinet/icmp6.h>
|
|
|
|
#endif
|
|
|
|
|
2007-07-01 11:41:27 +00:00
|
|
|
#include <sys/types.h>
|
2002-10-16 02:10:08 +00:00
|
|
|
#include <netipsec/ipsec.h>
|
|
|
|
#ifdef INET6
|
|
|
|
#include <netipsec/ipsec6.h>
|
|
|
|
#endif
|
|
|
|
#include <netipsec/ah_var.h>
|
|
|
|
#include <netipsec/esp_var.h>
|
|
|
|
#include <netipsec/ipcomp.h> /*XXX*/
|
|
|
|
#include <netipsec/ipcomp_var.h>
|
2017-02-06 08:49:57 +00:00
|
|
|
#include <netipsec/ipsec_support.h>
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
#include <netipsec/key.h>
|
|
|
|
#include <netipsec/keydb.h>
|
|
|
|
#include <netipsec/key_debug.h>
|
|
|
|
|
|
|
|
#include <netipsec/xform.h>
|
|
|
|
|
|
|
|
#include <machine/in_cksum.h>
|
|
|
|
|
2007-03-22 22:25:25 +00:00
|
|
|
#include <opencrypto/cryptodev.h>
|
|
|
|
|
2008-12-27 22:58:16 +00:00
|
|
|
/* NB: name changed so netstat doesn't use it. */
|
2013-07-09 10:08:13 +00:00
|
|
|
VNET_PCPUSTAT_DEFINE(struct ipsecstat, ipsec4stat);
|
|
|
|
VNET_PCPUSTAT_SYSINIT(ipsec4stat);
|
|
|
|
|
|
|
|
#ifdef VIMAGE
|
|
|
|
VNET_PCPUSTAT_SYSUNINIT(ipsec4stat);
|
|
|
|
#endif /* VIMAGE */
|
|
|
|
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
/* DF bit on encap. 0: clear 1: set 2: copy */
|
|
|
|
VNET_DEFINE(int, ip4_ipsec_dfbit) = 0;
|
|
|
|
VNET_DEFINE(int, ip4_esp_trans_deflev) = IPSEC_LEVEL_USE;
|
|
|
|
VNET_DEFINE(int, ip4_esp_net_deflev) = IPSEC_LEVEL_USE;
|
|
|
|
VNET_DEFINE(int, ip4_ah_trans_deflev) = IPSEC_LEVEL_USE;
|
|
|
|
VNET_DEFINE(int, ip4_ah_net_deflev) = IPSEC_LEVEL_USE;
|
|
|
|
/* ECN ignore(-1)/forbidden(0)/allowed(1) */
|
|
|
|
VNET_DEFINE(int, ip4_ipsec_ecn) = 0;
|
|
|
|
|
2018-07-24 16:35:52 +00:00
|
|
|
VNET_DEFINE_STATIC(int, ip4_filtertunnel) = 0;
|
2017-02-06 08:49:57 +00:00
|
|
|
#define V_ip4_filtertunnel VNET(ip4_filtertunnel)
|
2018-07-24 16:35:52 +00:00
|
|
|
VNET_DEFINE_STATIC(int, check_policy_history) = 0;
|
2017-02-06 08:49:57 +00:00
|
|
|
#define V_check_policy_history VNET(check_policy_history)
|
2018-07-24 16:35:52 +00:00
|
|
|
VNET_DEFINE_STATIC(struct secpolicy *, def_policy) = NULL;
|
2014-12-24 18:34:56 +00:00
|
|
|
#define V_def_policy VNET(def_policy)
|
2017-02-06 08:49:57 +00:00
|
|
|
static int
|
|
|
|
sysctl_def_policy(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
int error, value;
|
|
|
|
|
|
|
|
value = V_def_policy->policy;
|
|
|
|
error = sysctl_handle_int(oidp, &value, 0, req);
|
|
|
|
if (error == 0) {
|
|
|
|
if (value != IPSEC_POLICY_DISCARD &&
|
|
|
|
value != IPSEC_POLICY_NONE)
|
|
|
|
return (EINVAL);
|
|
|
|
V_def_policy->policy = value;
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* Crypto support requirements:
|
|
|
|
*
|
|
|
|
* 1 require hardware support
|
|
|
|
* -1 require software support
|
|
|
|
* 0 take anything
|
|
|
|
*/
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
VNET_DEFINE(int, crypto_support) = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
|
2017-11-03 10:27:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Use asynchronous mode to parallelize crypto jobs:
|
|
|
|
*
|
|
|
|
* 0 - disabled
|
|
|
|
* 1 - enabled
|
|
|
|
*/
|
|
|
|
VNET_DEFINE(int, async_crypto) = 0;
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* TCP/UDP checksum handling policy for transport mode NAT-T (RFC3948)
|
|
|
|
*
|
|
|
|
* 0 - auto: incrementally recompute, when checksum delta is known;
|
|
|
|
* if checksum delta isn't known, reset checksum to zero for UDP,
|
|
|
|
* and mark csum_flags as valid for TCP.
|
|
|
|
* 1 - fully recompute TCP/UDP checksum.
|
|
|
|
*/
|
|
|
|
VNET_DEFINE(int, natt_cksum_policy) = 0;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2010-10-30 18:52:44 +00:00
|
|
|
FEATURE(ipsec, "Internet Protocol Security (IPsec)");
|
|
|
|
FEATURE(ipsec_natt, "UDP Encapsulation of IPsec ESP Packets ('NAT-T')");
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
SYSCTL_DECL(_net_inet_ipsec);
|
|
|
|
|
|
|
|
/* net.inet.ipsec */
|
2017-02-06 08:49:57 +00:00
|
|
|
SYSCTL_PROC(_net_inet_ipsec, IPSECCTL_DEF_POLICY, def_policy,
|
2020-02-26 14:26:36 +00:00
|
|
|
CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
|
|
0, 0, sysctl_def_policy, "I",
|
|
|
|
"IPsec default policy.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_esp_trans_deflev), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"Default ESP transport mode level");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_esp_net_deflev), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"Default ESP tunnel mode level.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ah_trans_deflev), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"AH transfer mode default level.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ah_net_deflev), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"AH tunnel mode default level.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS, ah_cleartos,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ah_cleartos), 0,
|
2017-02-06 08:49:57 +00:00
|
|
|
"If set, clear type-of-service field when doing AH computation.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT, dfbit,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ipsec_dfbit), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"Do not fragment bit on encap.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN, ecn,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ipsec_ecn), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"Explicit Congestion Notification handling.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, OID_AUTO, crypto_support,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(crypto_support), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"Crypto driver selection.");
|
2017-11-03 10:27:22 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, OID_AUTO, async_crypto,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(async_crypto), 0,
|
|
|
|
"Use asynchronous mode to parallelize crypto jobs.");
|
2017-02-06 08:49:57 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, OID_AUTO, check_policy_history,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(check_policy_history), 0,
|
|
|
|
"Use strict check of inbound packets to security policy compliance.");
|
|
|
|
SYSCTL_INT(_net_inet_ipsec, OID_AUTO, natt_cksum_policy,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(natt_cksum_policy), 0,
|
|
|
|
"Method to fix TCP/UDP checksum for transport mode IPsec after NAT.");
|
|
|
|
SYSCTL_INT(_net_inet_ipsec, OID_AUTO, filtertunnel,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_filtertunnel), 0,
|
|
|
|
"If set, filter packets from an IPsec tunnel.");
|
2013-07-09 10:08:13 +00:00
|
|
|
SYSCTL_VNET_PCPUSTAT(_net_inet_ipsec, OID_AUTO, ipsecstats, struct ipsecstat,
|
|
|
|
ipsec4stat, "IPsec IPv4 statistics.");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2006-04-10 15:04:36 +00:00
|
|
|
#ifdef REGRESSION
|
2006-04-09 19:11:45 +00:00
|
|
|
/*
|
|
|
|
* When set to 1, IPsec will send packets with the same sequence number.
|
|
|
|
* This allows to verify if the other side has proper replay attacks detection.
|
|
|
|
*/
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
VNET_DEFINE(int, ipsec_replay) = 0;
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_replay,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_replay), 0,
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
"Emulate replay attack");
|
2006-04-09 19:11:45 +00:00
|
|
|
/*
|
|
|
|
* When set 1, IPsec will send packets with corrupted HMAC.
|
|
|
|
* This allows to verify if the other side properly detects modified packets.
|
|
|
|
*/
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
VNET_DEFINE(int, ipsec_integrity) = 0;
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_integrity,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_integrity), 0,
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
"Emulate man-in-the-middle attack");
|
2006-04-10 15:04:36 +00:00
|
|
|
#endif
|
2006-04-09 19:11:45 +00:00
|
|
|
|
2007-07-01 11:41:27 +00:00
|
|
|
#ifdef INET6
|
2013-07-09 10:08:13 +00:00
|
|
|
VNET_PCPUSTAT_DEFINE(struct ipsecstat, ipsec6stat);
|
|
|
|
VNET_PCPUSTAT_SYSINIT(ipsec6stat);
|
|
|
|
|
|
|
|
#ifdef VIMAGE
|
|
|
|
VNET_PCPUSTAT_SYSUNINIT(ipsec6stat);
|
|
|
|
#endif /* VIMAGE */
|
|
|
|
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
VNET_DEFINE(int, ip6_esp_trans_deflev) = IPSEC_LEVEL_USE;
|
|
|
|
VNET_DEFINE(int, ip6_esp_net_deflev) = IPSEC_LEVEL_USE;
|
|
|
|
VNET_DEFINE(int, ip6_ah_trans_deflev) = IPSEC_LEVEL_USE;
|
|
|
|
VNET_DEFINE(int, ip6_ah_net_deflev) = IPSEC_LEVEL_USE;
|
|
|
|
VNET_DEFINE(int, ip6_ipsec_ecn) = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2018-07-24 16:35:52 +00:00
|
|
|
VNET_DEFINE_STATIC(int, ip6_filtertunnel) = 0;
|
2017-02-06 08:49:57 +00:00
|
|
|
#define V_ip6_filtertunnel VNET(ip6_filtertunnel)
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
SYSCTL_DECL(_net_inet6_ipsec6);
|
|
|
|
|
|
|
|
/* net.inet6.ipsec6 */
|
2017-02-06 08:49:57 +00:00
|
|
|
SYSCTL_PROC(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, def_policy,
|
2020-02-26 14:26:36 +00:00
|
|
|
CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
|
|
0, 0, sysctl_def_policy, "I",
|
|
|
|
"IPsec default policy.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_esp_trans_deflev), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"Default ESP transport mode level.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_esp_net_deflev), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"Default ESP tunnel mode level.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_ah_trans_deflev), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"AH transfer mode default level.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_ah_net_deflev), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"AH tunnel mode default level.");
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN, ecn,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_ipsec_ecn), 0,
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
"Explicit Congestion Notification handling.");
|
2017-02-06 08:49:57 +00:00
|
|
|
SYSCTL_INT(_net_inet6_ipsec6, OID_AUTO, filtertunnel,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_filtertunnel), 0,
|
|
|
|
"If set, filter packets from an IPsec tunnel.");
|
2013-07-09 10:08:13 +00:00
|
|
|
SYSCTL_VNET_PCPUSTAT(_net_inet6_ipsec6, IPSECCTL_STATS, ipsecstats,
|
|
|
|
struct ipsecstat, ipsec6stat, "IPsec IPv6 statistics.");
|
2002-10-16 02:10:08 +00:00
|
|
|
#endif /* INET6 */
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static int ipsec_in_reject(struct secpolicy *, struct inpcb *,
|
|
|
|
const struct mbuf *);
|
|
|
|
|
|
|
|
#ifdef INET
|
|
|
|
static void ipsec4_get_ulp(const struct mbuf *, struct secpolicyindex *, int);
|
|
|
|
static void ipsec4_setspidx_ipaddr(const struct mbuf *,
|
|
|
|
struct secpolicyindex *);
|
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
#ifdef INET6
|
2016-04-21 10:58:07 +00:00
|
|
|
static void ipsec6_get_ulp(const struct mbuf *m, struct secpolicyindex *, int);
|
2017-02-06 08:49:57 +00:00
|
|
|
static void ipsec6_setspidx_ipaddr(const struct mbuf *,
|
|
|
|
struct secpolicyindex *);
|
2002-10-16 02:10:08 +00:00
|
|
|
#endif
|
2003-09-01 05:35:55 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* Return a held reference to the default SP.
|
|
|
|
*/
|
|
|
|
static struct secpolicy *
|
2017-02-06 08:49:57 +00:00
|
|
|
key_allocsp_default(void)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
key_addref(V_def_policy);
|
|
|
|
return (V_def_policy);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static void
|
|
|
|
ipsec_invalidate_cache(struct inpcb *inp, u_int dir)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secpolicy *sp;
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
INP_WLOCK_ASSERT(inp);
|
|
|
|
if (dir == IPSEC_DIR_OUTBOUND) {
|
|
|
|
if (inp->inp_sp->flags & INP_INBOUND_POLICY)
|
|
|
|
return;
|
|
|
|
sp = inp->inp_sp->sp_in;
|
|
|
|
inp->inp_sp->sp_in = NULL;
|
|
|
|
} else {
|
|
|
|
if (inp->inp_sp->flags & INP_OUTBOUND_POLICY)
|
|
|
|
return;
|
|
|
|
sp = inp->inp_sp->sp_out;
|
|
|
|
inp->inp_sp->sp_out = NULL;
|
|
|
|
}
|
|
|
|
if (sp != NULL)
|
|
|
|
key_freesp(&sp); /* release extra reference */
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static void
|
|
|
|
ipsec_cachepolicy(struct inpcb *inp, struct secpolicy *sp, u_int dir)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2017-02-06 08:49:57 +00:00
|
|
|
uint32_t genid;
|
|
|
|
int downgrade;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
INP_LOCK_ASSERT(inp);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
if (dir == IPSEC_DIR_OUTBOUND) {
|
|
|
|
/* Do we have configured PCB policy? */
|
|
|
|
if (inp->inp_sp->flags & INP_OUTBOUND_POLICY)
|
|
|
|
return;
|
|
|
|
/* Another thread has already set cached policy */
|
|
|
|
if (inp->inp_sp->sp_out != NULL)
|
|
|
|
return;
|
|
|
|
/*
|
|
|
|
* Do not cache OUTBOUND policy if PCB isn't connected,
|
|
|
|
* i.e. foreign address is INADDR_ANY/UNSPECIFIED.
|
|
|
|
*/
|
|
|
|
#ifdef INET
|
|
|
|
if ((inp->inp_vflag & INP_IPV4) != 0 &&
|
|
|
|
inp->inp_faddr.s_addr == INADDR_ANY)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
if ((inp->inp_vflag & INP_IPV6) != 0 &&
|
|
|
|
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
/* Do we have configured PCB policy? */
|
|
|
|
if (inp->inp_sp->flags & INP_INBOUND_POLICY)
|
|
|
|
return;
|
|
|
|
/* Another thread has already set cached policy */
|
|
|
|
if (inp->inp_sp->sp_in != NULL)
|
|
|
|
return;
|
|
|
|
/*
|
|
|
|
* Do not cache INBOUND policy for listen socket,
|
|
|
|
* that is bound to INADDR_ANY/UNSPECIFIED address.
|
|
|
|
*/
|
|
|
|
#ifdef INET
|
|
|
|
if ((inp->inp_vflag & INP_IPV4) != 0 &&
|
|
|
|
inp->inp_faddr.s_addr == INADDR_ANY)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
if ((inp->inp_vflag & INP_IPV6) != 0 &&
|
|
|
|
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
|
|
|
|
return;
|
|
|
|
#endif
|
2015-07-03 15:31:56 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
downgrade = 0;
|
|
|
|
if (!INP_WLOCKED(inp)) {
|
|
|
|
if ((downgrade = INP_TRY_UPGRADE(inp)) == 0)
|
|
|
|
return;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
if (dir == IPSEC_DIR_OUTBOUND)
|
|
|
|
inp->inp_sp->sp_out = sp;
|
|
|
|
else
|
|
|
|
inp->inp_sp->sp_in = sp;
|
|
|
|
/*
|
|
|
|
* SP is already referenced by the lookup code.
|
|
|
|
* We take extra reference here to avoid race in the
|
|
|
|
* ipsec_getpcbpolicy() function - SP will not be freed in the
|
|
|
|
* time between we take SP pointer from the cache and key_addref()
|
|
|
|
* call.
|
|
|
|
*/
|
|
|
|
key_addref(sp);
|
|
|
|
genid = key_getspgen();
|
|
|
|
if (genid != inp->inp_sp->genid) {
|
|
|
|
ipsec_invalidate_cache(inp, dir);
|
|
|
|
inp->inp_sp->genid = genid;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
KEYDBG(IPSEC_STAMP,
|
|
|
|
printf("%s: PCB(%p): cached %s SP(%p)\n",
|
|
|
|
__func__, inp, dir == IPSEC_DIR_OUTBOUND ? "OUTBOUND":
|
|
|
|
"INBOUND", sp));
|
|
|
|
if (downgrade != 0)
|
|
|
|
INP_DOWNGRADE(inp);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static struct secpolicy *
|
|
|
|
ipsec_checkpolicy(struct secpolicy *sp, struct inpcb *inp, int *error)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/* Save found OUTBOUND policy into PCB SP cache. */
|
|
|
|
if (inp != NULL && inp->inp_sp != NULL && inp->inp_sp->sp_out == NULL)
|
|
|
|
ipsec_cachepolicy(inp, sp, IPSEC_DIR_OUTBOUND);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
switch (sp->policy) {
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("%s: invalid policy %u\n", __func__, sp->policy);
|
2008-12-27 22:58:16 +00:00
|
|
|
/* FALLTHROUGH */
|
2002-10-16 02:10:08 +00:00
|
|
|
case IPSEC_POLICY_DISCARD:
|
2008-12-27 22:58:16 +00:00
|
|
|
*error = -EINVAL; /* Packet is discarded by caller. */
|
2017-02-06 08:49:57 +00:00
|
|
|
/* FALLTHROUGH */
|
2002-10-16 02:10:08 +00:00
|
|
|
case IPSEC_POLICY_BYPASS:
|
|
|
|
case IPSEC_POLICY_NONE:
|
2017-02-06 08:49:57 +00:00
|
|
|
key_freesp(&sp);
|
2008-12-27 22:58:16 +00:00
|
|
|
sp = NULL; /* NB: force NULL result. */
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
case IPSEC_POLICY_IPSEC:
|
2017-02-06 08:49:57 +00:00
|
|
|
/* XXXAE: handle LARVAL SP */
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
KEYDBG(IPSEC_DUMP,
|
|
|
|
printf("%s: get SP(%p), error %d\n", __func__, sp, *error));
|
2008-12-27 22:58:16 +00:00
|
|
|
return (sp);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static struct secpolicy *
|
|
|
|
ipsec_getpcbpolicy(struct inpcb *inp, u_int dir)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2017-02-06 08:49:57 +00:00
|
|
|
struct secpolicy *sp;
|
|
|
|
int flags, downgrade;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
if (inp == NULL || inp->inp_sp == NULL)
|
|
|
|
return (NULL);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
INP_LOCK_ASSERT(inp);
|
|
|
|
|
|
|
|
flags = inp->inp_sp->flags;
|
|
|
|
if (dir == IPSEC_DIR_OUTBOUND) {
|
|
|
|
sp = inp->inp_sp->sp_out;
|
|
|
|
flags &= INP_OUTBOUND_POLICY;
|
2002-10-16 02:10:08 +00:00
|
|
|
} else {
|
2017-02-06 08:49:57 +00:00
|
|
|
sp = inp->inp_sp->sp_in;
|
|
|
|
flags &= INP_INBOUND_POLICY;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
/*
|
2017-02-06 08:49:57 +00:00
|
|
|
* Check flags. If we have PCB SP, just return it.
|
|
|
|
* Otherwise we need to check that cached SP entry isn't stale.
|
2002-10-16 02:10:08 +00:00
|
|
|
*/
|
2017-02-06 08:49:57 +00:00
|
|
|
if (flags == 0) {
|
|
|
|
if (sp == NULL)
|
|
|
|
return (NULL);
|
|
|
|
if (inp->inp_sp->genid != key_getspgen()) {
|
|
|
|
/* Invalidate the cache. */
|
|
|
|
downgrade = 0;
|
|
|
|
if (!INP_WLOCKED(inp)) {
|
|
|
|
if ((downgrade = INP_TRY_UPGRADE(inp)) == 0)
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
ipsec_invalidate_cache(inp, IPSEC_DIR_OUTBOUND);
|
|
|
|
ipsec_invalidate_cache(inp, IPSEC_DIR_INBOUND);
|
|
|
|
if (downgrade != 0)
|
|
|
|
INP_DOWNGRADE(inp);
|
|
|
|
return (NULL);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
KEYDBG(IPSEC_STAMP,
|
|
|
|
printf("%s: PCB(%p): cache hit SP(%p)\n",
|
|
|
|
__func__, inp, sp));
|
|
|
|
/* Return referenced cached policy */
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
key_addref(sp);
|
|
|
|
return (sp);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
#ifdef INET
|
2002-10-16 02:10:08 +00:00
|
|
|
static void
|
2016-04-21 10:58:07 +00:00
|
|
|
ipsec4_get_ulp(const struct mbuf *m, struct secpolicyindex *spidx,
|
|
|
|
int needport)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2017-02-06 08:49:57 +00:00
|
|
|
uint8_t nxt;
|
2002-10-16 02:10:08 +00:00
|
|
|
int off;
|
|
|
|
|
2008-12-27 22:58:16 +00:00
|
|
|
/* Sanity check. */
|
2017-02-06 08:49:57 +00:00
|
|
|
IPSEC_ASSERT(m->m_pkthdr.len >= sizeof(struct ip),
|
|
|
|
("packet too short"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2010-04-02 18:15:23 +00:00
|
|
|
if (m->m_len >= sizeof (struct ip)) {
|
2016-04-21 10:58:07 +00:00
|
|
|
const struct ip *ip = mtod(m, const struct ip *);
|
2012-10-22 21:09:03 +00:00
|
|
|
if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
|
2002-10-16 02:10:08 +00:00
|
|
|
goto done;
|
|
|
|
off = ip->ip_hl << 2;
|
|
|
|
nxt = ip->ip_p;
|
|
|
|
} else {
|
|
|
|
struct ip ih;
|
|
|
|
|
|
|
|
m_copydata(m, 0, sizeof (struct ip), (caddr_t) &ih);
|
2012-10-22 21:09:03 +00:00
|
|
|
if (ih.ip_off & htons(IP_MF | IP_OFFMASK))
|
2002-10-16 02:10:08 +00:00
|
|
|
goto done;
|
|
|
|
off = ih.ip_hl << 2;
|
|
|
|
nxt = ih.ip_p;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (off < m->m_pkthdr.len) {
|
|
|
|
struct ip6_ext ip6e;
|
|
|
|
struct tcphdr th;
|
|
|
|
struct udphdr uh;
|
|
|
|
|
|
|
|
switch (nxt) {
|
|
|
|
case IPPROTO_TCP:
|
|
|
|
spidx->ul_proto = nxt;
|
|
|
|
if (!needport)
|
|
|
|
goto done_proto;
|
|
|
|
if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
|
|
|
|
goto done;
|
|
|
|
m_copydata(m, off, sizeof (th), (caddr_t) &th);
|
|
|
|
spidx->src.sin.sin_port = th.th_sport;
|
|
|
|
spidx->dst.sin.sin_port = th.th_dport;
|
|
|
|
return;
|
|
|
|
case IPPROTO_UDP:
|
|
|
|
spidx->ul_proto = nxt;
|
|
|
|
if (!needport)
|
|
|
|
goto done_proto;
|
|
|
|
if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
|
|
|
|
goto done;
|
|
|
|
m_copydata(m, off, sizeof (uh), (caddr_t) &uh);
|
|
|
|
spidx->src.sin.sin_port = uh.uh_sport;
|
|
|
|
spidx->dst.sin.sin_port = uh.uh_dport;
|
|
|
|
return;
|
|
|
|
case IPPROTO_AH:
|
2005-03-09 15:28:48 +00:00
|
|
|
if (off + sizeof(ip6e) > m->m_pkthdr.len)
|
2002-10-16 02:10:08 +00:00
|
|
|
goto done;
|
2008-12-27 22:58:16 +00:00
|
|
|
/* XXX Sigh, this works but is totally bogus. */
|
2002-10-16 02:10:08 +00:00
|
|
|
m_copydata(m, off, sizeof(ip6e), (caddr_t) &ip6e);
|
|
|
|
off += (ip6e.ip6e_len + 2) << 2;
|
|
|
|
nxt = ip6e.ip6e_nxt;
|
|
|
|
break;
|
|
|
|
case IPPROTO_ICMP:
|
|
|
|
default:
|
2008-12-27 22:58:16 +00:00
|
|
|
/* XXX Intermediate headers??? */
|
2002-10-16 02:10:08 +00:00
|
|
|
spidx->ul_proto = nxt;
|
|
|
|
goto done_proto;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
done:
|
|
|
|
spidx->ul_proto = IPSEC_ULPROTO_ANY;
|
|
|
|
done_proto:
|
|
|
|
spidx->src.sin.sin_port = IPSEC_PORT_ANY;
|
|
|
|
spidx->dst.sin.sin_port = IPSEC_PORT_ANY;
|
2017-02-06 08:49:57 +00:00
|
|
|
KEYDBG(IPSEC_DUMP,
|
|
|
|
printf("%s: ", __func__); kdebug_secpolicyindex(spidx, NULL));
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static void
|
2016-04-21 10:58:07 +00:00
|
|
|
ipsec4_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
ipsec4_setsockaddrs(m, &spidx->src, &spidx->dst);
|
|
|
|
spidx->prefs = sizeof(struct in_addr) << 3;
|
|
|
|
spidx->prefd = sizeof(struct in_addr) << 3;
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static struct secpolicy *
|
2017-08-21 13:52:21 +00:00
|
|
|
ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
|
|
|
|
int needport)
|
2017-02-06 08:49:57 +00:00
|
|
|
{
|
|
|
|
struct secpolicyindex spidx;
|
|
|
|
struct secpolicy *sp;
|
|
|
|
|
|
|
|
sp = ipsec_getpcbpolicy(inp, dir);
|
|
|
|
if (sp == NULL && key_havesp(dir)) {
|
|
|
|
/* Make an index to look for a policy. */
|
|
|
|
ipsec4_setspidx_ipaddr(m, &spidx);
|
2017-08-21 13:52:21 +00:00
|
|
|
ipsec4_get_ulp(m, &spidx, needport);
|
2017-02-06 08:49:57 +00:00
|
|
|
spidx.dir = dir;
|
|
|
|
sp = key_allocsp(&spidx, dir);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
if (sp == NULL) /* No SP found, use system default. */
|
|
|
|
sp = key_allocsp_default();
|
|
|
|
return (sp);
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* Check security policy for *OUTBOUND* IPv4 packet.
|
|
|
|
*/
|
|
|
|
struct secpolicy *
|
2017-08-21 13:52:21 +00:00
|
|
|
ipsec4_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
|
|
|
|
int needport)
|
2017-02-06 08:49:57 +00:00
|
|
|
{
|
|
|
|
struct secpolicy *sp;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
*error = 0;
|
2017-08-21 13:52:21 +00:00
|
|
|
sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_OUTBOUND, needport);
|
2017-02-06 08:49:57 +00:00
|
|
|
if (sp != NULL)
|
|
|
|
sp = ipsec_checkpolicy(sp, inp, error);
|
|
|
|
if (sp == NULL) {
|
|
|
|
switch (*error) {
|
|
|
|
case 0: /* No IPsec required: BYPASS or NONE */
|
|
|
|
break;
|
|
|
|
case -EINVAL:
|
|
|
|
IPSECSTAT_INC(ips_out_polvio);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
IPSECSTAT_INC(ips_out_inval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
KEYDBG(IPSEC_STAMP,
|
|
|
|
printf("%s: using SP(%p), error %d\n", __func__, sp, *error));
|
|
|
|
if (sp != NULL)
|
|
|
|
KEYDBG(IPSEC_DATA, kdebug_secpolicy(sp));
|
|
|
|
return (sp);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* Check IPv4 packet against *INBOUND* security policy.
|
|
|
|
* This function is called from tcp_input(), udp_input(),
|
|
|
|
* rip_input() and sctp_input().
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ipsec4_in_reject(const struct mbuf *m, struct inpcb *inp)
|
|
|
|
{
|
|
|
|
struct secpolicy *sp;
|
|
|
|
int result;
|
|
|
|
|
2017-08-21 13:52:21 +00:00
|
|
|
sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_INBOUND, 0);
|
2017-02-06 08:49:57 +00:00
|
|
|
result = ipsec_in_reject(sp, inp, m);
|
|
|
|
key_freesp(&sp);
|
|
|
|
if (result != 0)
|
|
|
|
IPSECSTAT_INC(ips_in_polvio);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IPSEC_CAP() method implementation for IPv4.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ipsec4_capability(struct mbuf *m, u_int cap)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (cap) {
|
|
|
|
case IPSEC_CAP_BYPASS_FILTER:
|
|
|
|
/*
|
|
|
|
* Bypass packet filtering for packets previously handled
|
|
|
|
* by IPsec.
|
|
|
|
*/
|
|
|
|
if (!V_ip4_filtertunnel &&
|
|
|
|
m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
|
|
|
|
return (1);
|
|
|
|
return (0);
|
|
|
|
case IPSEC_CAP_OPERABLE:
|
|
|
|
/* Do we have active security policies? */
|
|
|
|
if (key_havesp(IPSEC_DIR_INBOUND) != 0 ||
|
|
|
|
key_havesp(IPSEC_DIR_OUTBOUND) != 0)
|
|
|
|
return (1);
|
|
|
|
return (0);
|
|
|
|
};
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* INET */
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
#ifdef INET6
|
|
|
|
static void
|
2016-04-21 10:58:07 +00:00
|
|
|
ipsec6_get_ulp(const struct mbuf *m, struct secpolicyindex *spidx,
|
|
|
|
int needport)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct tcphdr th;
|
|
|
|
struct udphdr uh;
|
2007-05-29 22:32:12 +00:00
|
|
|
struct icmp6_hdr ih;
|
2017-02-06 08:49:57 +00:00
|
|
|
int off, nxt;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
IPSEC_ASSERT(m->m_pkthdr.len >= sizeof(struct ip6_hdr),
|
|
|
|
("packet too short"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2008-12-27 22:58:16 +00:00
|
|
|
/* Set default. */
|
2002-10-16 02:10:08 +00:00
|
|
|
spidx->ul_proto = IPSEC_ULPROTO_ANY;
|
2017-02-06 08:49:57 +00:00
|
|
|
spidx->src.sin6.sin6_port = IPSEC_PORT_ANY;
|
|
|
|
spidx->dst.sin6.sin6_port = IPSEC_PORT_ANY;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
nxt = -1;
|
|
|
|
off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
|
|
|
|
if (off < 0 || m->m_pkthdr.len < off)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (nxt) {
|
|
|
|
case IPPROTO_TCP:
|
|
|
|
spidx->ul_proto = nxt;
|
|
|
|
if (!needport)
|
|
|
|
break;
|
|
|
|
if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
|
|
|
|
break;
|
|
|
|
m_copydata(m, off, sizeof(th), (caddr_t)&th);
|
2017-02-06 08:49:57 +00:00
|
|
|
spidx->src.sin6.sin6_port = th.th_sport;
|
|
|
|
spidx->dst.sin6.sin6_port = th.th_dport;
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
case IPPROTO_UDP:
|
|
|
|
spidx->ul_proto = nxt;
|
|
|
|
if (!needport)
|
|
|
|
break;
|
|
|
|
if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
|
|
|
|
break;
|
|
|
|
m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
|
2017-02-06 08:49:57 +00:00
|
|
|
spidx->src.sin6.sin6_port = uh.uh_sport;
|
|
|
|
spidx->dst.sin6.sin6_port = uh.uh_dport;
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
case IPPROTO_ICMPV6:
|
2007-05-29 22:32:12 +00:00
|
|
|
spidx->ul_proto = nxt;
|
|
|
|
if (off + sizeof(struct icmp6_hdr) > m->m_pkthdr.len)
|
|
|
|
break;
|
2017-02-06 08:49:57 +00:00
|
|
|
m_copydata(m, off, sizeof(ih), (caddr_t)&ih);
|
|
|
|
spidx->src.sin6.sin6_port = htons((uint16_t)ih.icmp6_type);
|
|
|
|
spidx->dst.sin6.sin6_port = htons((uint16_t)ih.icmp6_code);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* XXX Intermediate headers??? */
|
|
|
|
spidx->ul_proto = nxt;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
KEYDBG(IPSEC_DUMP,
|
|
|
|
printf("%s: ", __func__); kdebug_secpolicyindex(spidx, NULL));
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static void
|
|
|
|
ipsec6_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx)
|
2003-09-01 05:35:55 +00:00
|
|
|
{
|
2008-12-27 22:58:16 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
ipsec6_setsockaddrs(m, &spidx->src, &spidx->dst);
|
|
|
|
spidx->prefs = sizeof(struct in6_addr) << 3;
|
|
|
|
spidx->prefd = sizeof(struct in6_addr) << 3;
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
static struct secpolicy *
|
2017-08-21 13:52:21 +00:00
|
|
|
ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
|
|
|
|
int needport)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2017-02-06 08:49:57 +00:00
|
|
|
struct secpolicyindex spidx;
|
|
|
|
struct secpolicy *sp;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
sp = ipsec_getpcbpolicy(inp, dir);
|
|
|
|
if (sp == NULL && key_havesp(dir)) {
|
|
|
|
/* Make an index to look for a policy. */
|
|
|
|
ipsec6_setspidx_ipaddr(m, &spidx);
|
2017-08-21 13:52:21 +00:00
|
|
|
ipsec6_get_ulp(m, &spidx, needport);
|
2017-02-06 08:49:57 +00:00
|
|
|
spidx.dir = dir;
|
|
|
|
sp = key_allocsp(&spidx, dir);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
if (sp == NULL) /* No SP found, use system default. */
|
|
|
|
sp = key_allocsp_default();
|
|
|
|
return (sp);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* Check security policy for *OUTBOUND* IPv6 packet.
|
|
|
|
*/
|
|
|
|
struct secpolicy *
|
2017-08-21 13:52:21 +00:00
|
|
|
ipsec6_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
|
|
|
|
int needport)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2017-02-06 08:49:57 +00:00
|
|
|
struct secpolicy *sp;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
*error = 0;
|
2017-08-21 13:52:21 +00:00
|
|
|
sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_OUTBOUND, needport);
|
2017-02-06 08:49:57 +00:00
|
|
|
if (sp != NULL)
|
|
|
|
sp = ipsec_checkpolicy(sp, inp, error);
|
|
|
|
if (sp == NULL) {
|
|
|
|
switch (*error) {
|
|
|
|
case 0: /* No IPsec required: BYPASS or NONE */
|
|
|
|
break;
|
|
|
|
case -EINVAL:
|
|
|
|
IPSEC6STAT_INC(ips_out_polvio);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
IPSEC6STAT_INC(ips_out_inval);
|
|
|
|
}
|
2008-02-02 14:11:31 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
KEYDBG(IPSEC_STAMP,
|
|
|
|
printf("%s: using SP(%p), error %d\n", __func__, sp, *error));
|
|
|
|
if (sp != NULL)
|
|
|
|
KEYDBG(IPSEC_DATA, kdebug_secpolicy(sp));
|
|
|
|
return (sp);
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* Check IPv6 packet against inbound security policy.
|
|
|
|
* This function is called from tcp6_input(), udp6_input(),
|
|
|
|
* rip6_input() and sctp_input().
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ipsec6_in_reject(const struct mbuf *m, struct inpcb *inp)
|
|
|
|
{
|
|
|
|
struct secpolicy *sp;
|
|
|
|
int result;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-08-21 13:52:21 +00:00
|
|
|
sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_INBOUND, 0);
|
2017-02-06 08:49:57 +00:00
|
|
|
result = ipsec_in_reject(sp, inp, m);
|
|
|
|
key_freesp(&sp);
|
|
|
|
if (result)
|
|
|
|
IPSEC6STAT_INC(ips_in_polvio);
|
|
|
|
return (result);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* IPSEC_CAP() method implementation for IPv6.
|
|
|
|
*/
|
2002-10-16 02:10:08 +00:00
|
|
|
int
|
2017-02-06 08:49:57 +00:00
|
|
|
ipsec6_capability(struct mbuf *m, u_int cap)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
switch (cap) {
|
|
|
|
case IPSEC_CAP_BYPASS_FILTER:
|
|
|
|
/*
|
|
|
|
* Bypass packet filtering for packets previously handled
|
|
|
|
* by IPsec.
|
|
|
|
*/
|
|
|
|
if (!V_ip6_filtertunnel &&
|
|
|
|
m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
|
|
|
|
return (1);
|
|
|
|
return (0);
|
|
|
|
case IPSEC_CAP_OPERABLE:
|
|
|
|
/* Do we have active security policies? */
|
|
|
|
if (key_havesp(IPSEC_DIR_INBOUND) != 0 ||
|
|
|
|
key_havesp(IPSEC_DIR_OUTBOUND) != 0)
|
|
|
|
return (1);
|
|
|
|
return (0);
|
|
|
|
};
|
|
|
|
return (EOPNOTSUPP);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
#endif /* INET6 */
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
int
|
2017-02-06 08:49:57 +00:00
|
|
|
ipsec_run_hhooks(struct ipsec_ctx_data *ctx, int type)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2017-02-06 08:49:57 +00:00
|
|
|
int idx;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
switch (ctx->af) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
|
|
|
idx = HHOOK_IPSEC_INET;
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
2017-02-06 08:49:57 +00:00
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
idx = HHOOK_IPSEC_INET6;
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
2017-02-06 08:49:57 +00:00
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
default:
|
2017-02-06 08:49:57 +00:00
|
|
|
return (EPFNOSUPPORT);
|
2009-02-08 09:27:07 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
if (type == HHOOK_TYPE_IPSEC_IN)
|
|
|
|
HHOOKS_RUN_IF(V_ipsec_hhh_in[idx], ctx, NULL);
|
|
|
|
else
|
|
|
|
HHOOKS_RUN_IF(V_ipsec_hhh_out[idx], ctx, NULL);
|
|
|
|
if (*ctx->mp == NULL)
|
|
|
|
return (EACCES);
|
2008-12-27 22:58:16 +00:00
|
|
|
return (0);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-12-27 22:58:16 +00:00
|
|
|
* Return current level.
|
2002-10-16 02:10:08 +00:00
|
|
|
* Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned.
|
|
|
|
*/
|
|
|
|
u_int
|
2017-02-06 08:49:57 +00:00
|
|
|
ipsec_get_reqlevel(struct secpolicy *sp, u_int idx)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2017-02-06 08:49:57 +00:00
|
|
|
struct ipsecrequest *isr;
|
2002-10-16 02:10:08 +00:00
|
|
|
u_int esp_trans_deflev, esp_net_deflev;
|
|
|
|
u_int ah_trans_deflev, ah_net_deflev;
|
2017-02-06 08:49:57 +00:00
|
|
|
u_int level = 0;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx));
|
2008-12-27 22:58:16 +00:00
|
|
|
/* XXX Note that we have ipseclog() expanded here - code sync issue. */
|
2002-10-16 02:10:08 +00:00
|
|
|
#define IPSEC_CHECK_DEFAULT(lev) \
|
2017-02-06 08:49:57 +00:00
|
|
|
(((lev) != IPSEC_LEVEL_USE && (lev) != IPSEC_LEVEL_REQUIRE && \
|
|
|
|
(lev) != IPSEC_LEVEL_UNIQUE) \
|
|
|
|
? (V_ipsec_debug ? \
|
|
|
|
log(LOG_INFO, "fixed system default level " #lev ":%d->%d\n",\
|
|
|
|
(lev), IPSEC_LEVEL_REQUIRE) : 0), \
|
|
|
|
(lev) = IPSEC_LEVEL_REQUIRE, (lev) : (lev))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IPsec VTI uses unique security policy with fake spidx filled
|
|
|
|
* with zeroes. Just return IPSEC_LEVEL_REQUIRE instead of doing
|
|
|
|
* full level lookup for such policies.
|
|
|
|
*/
|
|
|
|
if (sp->state == IPSEC_SPSTATE_IFNET) {
|
|
|
|
IPSEC_ASSERT(sp->req[idx]->level == IPSEC_LEVEL_UNIQUE,
|
|
|
|
("Wrong IPsec request level %d", sp->req[idx]->level));
|
|
|
|
return (IPSEC_LEVEL_REQUIRE);
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2008-12-27 22:58:16 +00:00
|
|
|
/* Set default level. */
|
2017-02-06 08:49:57 +00:00
|
|
|
switch (sp->spidx.src.sa.sa_family) {
|
2002-10-16 02:10:08 +00:00
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
esp_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip4_esp_trans_deflev);
|
|
|
|
esp_net_deflev = IPSEC_CHECK_DEFAULT(V_ip4_esp_net_deflev);
|
|
|
|
ah_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip4_ah_trans_deflev);
|
|
|
|
ah_net_deflev = IPSEC_CHECK_DEFAULT(V_ip4_ah_net_deflev);
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
esp_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip6_esp_trans_deflev);
|
|
|
|
esp_net_deflev = IPSEC_CHECK_DEFAULT(V_ip6_esp_net_deflev);
|
|
|
|
ah_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip6_ah_trans_deflev);
|
|
|
|
ah_net_deflev = IPSEC_CHECK_DEFAULT(V_ip6_ah_net_deflev);
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
#endif /* INET6 */
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
panic("%s: unknown af %u",
|
2017-02-06 08:49:57 +00:00
|
|
|
__func__, sp->spidx.src.sa.sa_family);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#undef IPSEC_CHECK_DEFAULT
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
isr = sp->req[idx];
|
2008-12-27 22:58:16 +00:00
|
|
|
/* Set level. */
|
2002-10-16 02:10:08 +00:00
|
|
|
switch (isr->level) {
|
|
|
|
case IPSEC_LEVEL_DEFAULT:
|
|
|
|
switch (isr->saidx.proto) {
|
|
|
|
case IPPROTO_ESP:
|
|
|
|
if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
|
|
|
|
level = esp_net_deflev;
|
|
|
|
else
|
|
|
|
level = esp_trans_deflev;
|
|
|
|
break;
|
|
|
|
case IPPROTO_AH:
|
|
|
|
if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
|
|
|
|
level = ah_net_deflev;
|
|
|
|
else
|
|
|
|
level = ah_trans_deflev;
|
2004-01-27 17:45:28 +00:00
|
|
|
break;
|
2002-10-16 02:10:08 +00:00
|
|
|
case IPPROTO_IPCOMP:
|
|
|
|
/*
|
2008-12-27 22:58:16 +00:00
|
|
|
* We don't really care, as IPcomp document says that
|
|
|
|
* we shouldn't compress small packets.
|
2002-10-16 02:10:08 +00:00
|
|
|
*/
|
|
|
|
level = IPSEC_LEVEL_USE;
|
|
|
|
break;
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
panic("%s: Illegal protocol defined %u\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
isr->saidx.proto);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IPSEC_LEVEL_USE:
|
|
|
|
case IPSEC_LEVEL_REQUIRE:
|
|
|
|
level = isr->level;
|
|
|
|
break;
|
|
|
|
case IPSEC_LEVEL_UNIQUE:
|
|
|
|
level = IPSEC_LEVEL_REQUIRE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
panic("%s: Illegal IPsec level %u\n", __func__, isr->level);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2008-12-27 22:58:16 +00:00
|
|
|
return (level);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static int
|
|
|
|
ipsec_check_history(const struct mbuf *m, struct secpolicy *sp, u_int idx)
|
|
|
|
{
|
|
|
|
struct xform_history *xh;
|
|
|
|
struct m_tag *mtag;
|
|
|
|
|
|
|
|
mtag = NULL;
|
|
|
|
while ((mtag = m_tag_find(__DECONST(struct mbuf *, m),
|
|
|
|
PACKET_TAG_IPSEC_IN_DONE, mtag)) != NULL) {
|
|
|
|
xh = (struct xform_history *)(mtag + 1);
|
|
|
|
KEYDBG(IPSEC_DATA,
|
|
|
|
char buf[IPSEC_ADDRSTRLEN];
|
|
|
|
printf("%s: mode %s proto %u dst %s\n", __func__,
|
|
|
|
kdebug_secasindex_mode(xh->mode), xh->proto,
|
|
|
|
ipsec_address(&xh->dst, buf, sizeof(buf))));
|
|
|
|
if (xh->proto != sp->req[idx]->saidx.proto)
|
|
|
|
continue;
|
|
|
|
/* If SA had IPSEC_MODE_ANY, consider this as match. */
|
|
|
|
if (xh->mode != sp->req[idx]->saidx.mode &&
|
|
|
|
xh->mode != IPSEC_MODE_ANY)
|
|
|
|
continue;
|
|
|
|
/*
|
|
|
|
* For transport mode IPsec request doesn't contain
|
|
|
|
* addresses. We need to use address from spidx.
|
|
|
|
*/
|
|
|
|
if (sp->req[idx]->saidx.mode == IPSEC_MODE_TRANSPORT) {
|
|
|
|
if (key_sockaddrcmp_withmask(&xh->dst.sa,
|
|
|
|
&sp->spidx.dst.sa, sp->spidx.prefd) != 0)
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (key_sockaddrcmp(&xh->dst.sa,
|
|
|
|
&sp->req[idx]->saidx.dst.sa, 0) != 0)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return (0); /* matched */
|
|
|
|
}
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* Check security policy requirements against the actual
|
|
|
|
* packet contents. Return one if the packet should be
|
|
|
|
* reject as "invalid"; otherwiser return zero to have the
|
|
|
|
* packet treated as "valid".
|
|
|
|
*
|
|
|
|
* OUT:
|
|
|
|
* 0: valid
|
|
|
|
* 1: invalid
|
|
|
|
*/
|
2015-04-27 01:12:51 +00:00
|
|
|
static int
|
2017-02-06 08:49:57 +00:00
|
|
|
ipsec_in_reject(struct secpolicy *sp, struct inpcb *inp, const struct mbuf *m)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2017-02-06 08:49:57 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
KEYDBG(IPSEC_STAMP,
|
|
|
|
printf("%s: PCB(%p): using SP(%p)\n", __func__, inp, sp));
|
|
|
|
KEYDBG(IPSEC_DATA, kdebug_secpolicy(sp));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
if (inp != NULL && inp->inp_sp != NULL && inp->inp_sp->sp_in == NULL)
|
|
|
|
ipsec_cachepolicy(inp, sp, IPSEC_DIR_INBOUND);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2008-12-27 22:58:16 +00:00
|
|
|
/* Check policy. */
|
2002-10-16 02:10:08 +00:00
|
|
|
switch (sp->policy) {
|
|
|
|
case IPSEC_POLICY_DISCARD:
|
2008-12-27 22:58:16 +00:00
|
|
|
return (1);
|
2002-10-16 02:10:08 +00:00
|
|
|
case IPSEC_POLICY_BYPASS:
|
|
|
|
case IPSEC_POLICY_NONE:
|
2008-12-27 22:58:16 +00:00
|
|
|
return (0);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC,
|
|
|
|
("invalid policy %u", sp->policy));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* ipsec[46]_common_input_cb after each transform adds
|
|
|
|
* PACKET_TAG_IPSEC_IN_DONE mbuf tag. It contains SPI, proto, mode
|
|
|
|
* and destination address from saidx. We can compare info from
|
|
|
|
* these tags with requirements in SP.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < sp->tcount; i++) {
|
|
|
|
/*
|
|
|
|
* Do not check IPcomp, since IPcomp document
|
|
|
|
* says that we shouldn't compress small packets.
|
|
|
|
* IPComp policy should always be treated as being
|
|
|
|
* in "use" level.
|
|
|
|
*/
|
|
|
|
if (sp->req[i]->saidx.proto == IPPROTO_IPCOMP ||
|
|
|
|
ipsec_get_reqlevel(sp, i) != IPSEC_LEVEL_REQUIRE)
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
2017-02-06 08:49:57 +00:00
|
|
|
if (V_check_policy_history != 0 &&
|
|
|
|
ipsec_check_history(m, sp, i) != 0)
|
|
|
|
return (1);
|
|
|
|
else switch (sp->req[i]->saidx.proto) {
|
2002-10-16 02:10:08 +00:00
|
|
|
case IPPROTO_ESP:
|
|
|
|
if ((m->m_flags & M_DECRYPTED) == 0) {
|
2017-02-06 08:49:57 +00:00
|
|
|
KEYDBG(IPSEC_DUMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("%s: ESP m_flags:%x\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
m->m_flags));
|
2008-12-27 22:58:16 +00:00
|
|
|
return (1);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IPPROTO_AH:
|
|
|
|
if ((m->m_flags & M_AUTHIPHDR) == 0) {
|
2017-02-06 08:49:57 +00:00
|
|
|
KEYDBG(IPSEC_DUMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("%s: AH m_flags:%x\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
m->m_flags));
|
2008-12-27 22:58:16 +00:00
|
|
|
return (1);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-12-27 22:58:16 +00:00
|
|
|
return (0); /* Valid. */
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-12-27 22:58:16 +00:00
|
|
|
* Compute the byte size to be occupied by IPsec header.
|
|
|
|
* In case it is tunnelled, it includes the size of outer IP header.
|
2002-10-16 02:10:08 +00:00
|
|
|
*/
|
|
|
|
static size_t
|
2009-02-08 09:27:07 +00:00
|
|
|
ipsec_hdrsiz_internal(struct secpolicy *sp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2008-12-27 23:24:59 +00:00
|
|
|
size_t size;
|
2017-02-06 08:49:57 +00:00
|
|
|
int i;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
KEYDBG(IPSEC_STAMP, printf("%s: using SP(%p)\n", __func__, sp));
|
|
|
|
KEYDBG(IPSEC_DATA, kdebug_secpolicy(sp));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
switch (sp->policy) {
|
|
|
|
case IPSEC_POLICY_DISCARD:
|
|
|
|
case IPSEC_POLICY_BYPASS:
|
|
|
|
case IPSEC_POLICY_NONE:
|
2008-12-27 22:58:16 +00:00
|
|
|
return (0);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC,
|
|
|
|
("invalid policy %u", sp->policy));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* XXX: for each transform we need to lookup suitable SA
|
|
|
|
* and use info from SA to calculate headers size.
|
|
|
|
* XXX: for NAT-T we need to cosider UDP header size.
|
|
|
|
*/
|
2008-12-27 23:24:59 +00:00
|
|
|
size = 0;
|
2017-02-06 08:49:57 +00:00
|
|
|
for (i = 0; i < sp->tcount; i++) {
|
|
|
|
switch (sp->req[i]->saidx.proto) {
|
2002-10-16 02:10:08 +00:00
|
|
|
case IPPROTO_ESP:
|
2017-02-06 08:49:57 +00:00
|
|
|
size += esp_hdrsiz(NULL);
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
case IPPROTO_AH:
|
2017-02-06 08:49:57 +00:00
|
|
|
size += ah_hdrsiz(NULL);
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
case IPPROTO_IPCOMP:
|
2017-02-06 08:49:57 +00:00
|
|
|
size += sizeof(struct ipcomp);
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
if (sp->req[i]->saidx.mode == IPSEC_MODE_TUNNEL) {
|
|
|
|
switch (sp->req[i]->saidx.dst.sa.sa_family) {
|
|
|
|
#ifdef INET
|
2002-10-16 02:10:08 +00:00
|
|
|
case AF_INET:
|
2017-02-06 08:49:57 +00:00
|
|
|
size += sizeof(struct ip);
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
2017-02-06 08:49:57 +00:00
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
2017-02-06 08:49:57 +00:00
|
|
|
size += sizeof(struct ip6_hdr);
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_ERR, "%s: unknown AF %d in "
|
|
|
|
"IPsec tunnel SA\n", __func__,
|
2017-02-06 08:49:57 +00:00
|
|
|
sp->req[i]->saidx.dst.sa.sa_family));
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-27 23:24:59 +00:00
|
|
|
return (size);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* Compute ESP/AH header size for protocols with PCB, including
|
|
|
|
* outer IP header. Currently only tcp_output() uses it.
|
2009-02-08 09:27:07 +00:00
|
|
|
*/
|
2002-10-16 02:10:08 +00:00
|
|
|
size_t
|
2017-02-06 08:49:57 +00:00
|
|
|
ipsec_hdrsiz_inpcb(struct inpcb *inp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2017-02-06 08:49:57 +00:00
|
|
|
struct secpolicyindex spidx;
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secpolicy *sp;
|
2017-02-06 08:49:57 +00:00
|
|
|
size_t sz;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
sp = ipsec_getpcbpolicy(inp, IPSEC_DIR_OUTBOUND);
|
|
|
|
if (sp == NULL && key_havesp(IPSEC_DIR_OUTBOUND)) {
|
|
|
|
ipsec_setspidx_inpcb(inp, &spidx, IPSEC_DIR_OUTBOUND);
|
|
|
|
sp = key_allocsp(&spidx, IPSEC_DIR_OUTBOUND);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
if (sp == NULL)
|
|
|
|
sp = key_allocsp_default();
|
|
|
|
sz = ipsec_hdrsiz_internal(sp);
|
|
|
|
key_freesp(&sp);
|
|
|
|
return (sz);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
|
|
|
|
#define IPSEC_BITMAP_INDEX_MASK(w) (w - 1)
|
|
|
|
#define IPSEC_REDUNDANT_BIT_SHIFTS 5
|
|
|
|
#define IPSEC_REDUNDANT_BITS (1 << IPSEC_REDUNDANT_BIT_SHIFTS)
|
|
|
|
#define IPSEC_BITMAP_LOC_MASK (IPSEC_REDUNDANT_BITS - 1)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Functions below are responsible for checking and updating bitmap.
|
|
|
|
* These are used to separate ipsec_chkreplay() and ipsec_updatereplay()
|
|
|
|
* from window implementation
|
|
|
|
*
|
|
|
|
* Based on RFC 6479. Blocks are 32 bits unsigned integers
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
check_window(const struct secreplay *replay, uint64_t seq)
|
|
|
|
{
|
|
|
|
int index, bit_location;
|
|
|
|
|
|
|
|
bit_location = seq & IPSEC_BITMAP_LOC_MASK;
|
|
|
|
index = (seq >> IPSEC_REDUNDANT_BIT_SHIFTS)
|
|
|
|
& IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size);
|
|
|
|
|
|
|
|
/* This packet already seen? */
|
|
|
|
return ((replay->bitmap)[index] & (1 << bit_location));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
advance_window(const struct secreplay *replay, uint64_t seq)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
uint64_t index, index_cur, diff;
|
|
|
|
|
|
|
|
index_cur = replay->last >> IPSEC_REDUNDANT_BIT_SHIFTS;
|
|
|
|
index = seq >> IPSEC_REDUNDANT_BIT_SHIFTS;
|
|
|
|
diff = index - index_cur;
|
|
|
|
|
|
|
|
if (diff > replay->bitmap_size) {
|
|
|
|
/* something unusual in this case */
|
|
|
|
diff = replay->bitmap_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < diff; i++) {
|
|
|
|
replay->bitmap[(i + index_cur + 1)
|
|
|
|
& IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size)] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
set_window(const struct secreplay *replay, uint64_t seq)
|
|
|
|
{
|
|
|
|
int index, bit_location;
|
|
|
|
|
|
|
|
bit_location = seq & IPSEC_BITMAP_LOC_MASK;
|
|
|
|
index = (seq >> IPSEC_REDUNDANT_BIT_SHIFTS)
|
|
|
|
& IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size);
|
|
|
|
|
|
|
|
replay->bitmap[index] |= (1 << bit_location);
|
|
|
|
}
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* Check the variable replay window.
|
|
|
|
* ipsec_chkreplay() performs replay check before ICV verification.
|
|
|
|
* ipsec_updatereplay() updates replay bitmap. This must be called after
|
|
|
|
* ICV verification (it also performs replay check, which is usually done
|
|
|
|
* beforehand).
|
|
|
|
* 0 (zero) is returned if packet disallowed, 1 if packet permitted.
|
|
|
|
*
|
2020-10-16 11:24:12 +00:00
|
|
|
* Based on RFC 4303
|
2002-10-16 02:10:08 +00:00
|
|
|
*/
|
2016-11-25 14:44:49 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
int
|
2020-10-16 11:24:12 +00:00
|
|
|
ipsec_chkreplay(uint32_t seq, uint32_t *seqhigh, struct secasvar *sav)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2020-10-16 11:24:12 +00:00
|
|
|
char buf[128];
|
|
|
|
struct secreplay *replay;
|
|
|
|
uint32_t window;
|
|
|
|
uint32_t tl, th, bl;
|
|
|
|
uint32_t seqh;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sav != NULL, ("Null SA"));
|
|
|
|
IPSEC_ASSERT(sav->replay != NULL, ("Null replay state"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
replay = sav->replay;
|
|
|
|
|
2016-11-25 14:44:49 +00:00
|
|
|
/* No need to check replay if disabled. */
|
2002-10-16 02:10:08 +00:00
|
|
|
if (replay->wsize == 0)
|
2017-02-06 08:49:57 +00:00
|
|
|
return (1);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
/* Zero sequence number is not allowed. */
|
|
|
|
if (seq == 0 && replay->last == 0)
|
2017-02-06 08:49:57 +00:00
|
|
|
return (0);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
window = replay->wsize << 3; /* Size of window */
|
|
|
|
tl = (uint32_t)replay->last; /* Top of window, lower part */
|
|
|
|
th = (uint32_t)(replay->last >> 32); /* Top of window, high part */
|
|
|
|
bl = tl - window + 1; /* Bottom of window, lower part */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We keep the high part intact when:
|
|
|
|
* 1) the seq is within [bl, 0xffffffff] and the whole window is
|
|
|
|
* within one subspace;
|
|
|
|
* 2) the seq is within [0, bl) and window spans two subspaces.
|
|
|
|
*/
|
|
|
|
if ((tl >= window - 1 && seq >= bl) ||
|
|
|
|
(tl < window - 1 && seq < bl)) {
|
|
|
|
*seqhigh = th;
|
|
|
|
if (seq <= tl) {
|
|
|
|
/* Sequence number inside window - check against replay */
|
|
|
|
if (check_window(replay, seq))
|
|
|
|
return (0);
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
/* Sequence number above top of window or not found in bitmap */
|
2017-02-06 08:49:57 +00:00
|
|
|
return (1);
|
2020-10-16 11:24:12 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
/*
|
|
|
|
* If ESN is not enabled and packet with highest sequence number
|
|
|
|
* was received we should report overflow
|
|
|
|
*/
|
|
|
|
if (tl == 0xffffffff && !(sav->flags & SADB_X_SAFLAGS_ESN)) {
|
|
|
|
/* Set overflow flag. */
|
|
|
|
replay->overflow++;
|
|
|
|
|
|
|
|
if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
|
|
|
|
if (sav->sah->saidx.proto == IPPROTO_ESP)
|
|
|
|
ESPSTAT_INC(esps_wrap);
|
|
|
|
else if (sav->sah->saidx.proto == IPPROTO_AH)
|
|
|
|
AHSTAT_INC(ahs_wrap);
|
|
|
|
return (0);
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
ipseclog((LOG_WARNING, "%s: replay counter made %d cycle. %s\n",
|
|
|
|
__func__, replay->overflow,
|
|
|
|
ipsec_sa2str(sav, buf, sizeof(buf))));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Seq is within [bl, 0xffffffff] and bl is within
|
|
|
|
* [0xffffffff-window, 0xffffffff]. This means we got a seq
|
|
|
|
* which is within our replay window, but in the previous
|
|
|
|
* subspace.
|
2016-11-25 14:44:49 +00:00
|
|
|
*/
|
2020-10-16 11:24:12 +00:00
|
|
|
if (tl < window - 1 && seq >= bl) {
|
|
|
|
if (th == 0)
|
|
|
|
return (0);
|
|
|
|
*seqhigh = th - 1;
|
|
|
|
seqh = th - 1;
|
|
|
|
if (check_window(replay, seq))
|
|
|
|
return (0);
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Seq is within [0, bl) but the whole window is within one subspace.
|
|
|
|
* This means that seq has wrapped and is in next subspace
|
|
|
|
*/
|
|
|
|
*seqhigh = th + 1;
|
|
|
|
seqh = th + 1;
|
|
|
|
|
|
|
|
/* Don't let high part wrap. */
|
|
|
|
if (seqh == 0) {
|
|
|
|
/* Set overflow flag. */
|
|
|
|
replay->overflow++;
|
|
|
|
|
|
|
|
if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
|
|
|
|
if (sav->sah->saidx.proto == IPPROTO_ESP)
|
|
|
|
ESPSTAT_INC(esps_wrap);
|
|
|
|
else if (sav->sah->saidx.proto == IPPROTO_AH)
|
|
|
|
AHSTAT_INC(ahs_wrap);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
ipseclog((LOG_WARNING, "%s: replay counter made %d cycle. %s\n",
|
|
|
|
__func__, replay->overflow,
|
|
|
|
ipsec_sa2str(sav, buf, sizeof(buf))));
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
return (1);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-12-27 22:58:16 +00:00
|
|
|
* Check replay counter whether to update or not.
|
2002-10-16 02:10:08 +00:00
|
|
|
* OUT: 0: OK
|
|
|
|
* 1: NG
|
|
|
|
*/
|
|
|
|
int
|
2017-02-06 08:49:57 +00:00
|
|
|
ipsec_updatereplay(uint32_t seq, struct secasvar *sav)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secreplay *replay;
|
2020-10-16 11:24:12 +00:00
|
|
|
uint32_t window;
|
|
|
|
uint32_t tl, th, bl;
|
|
|
|
uint32_t seqh;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sav != NULL, ("Null SA"));
|
|
|
|
IPSEC_ASSERT(sav->replay != NULL, ("Null replay state"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
replay = sav->replay;
|
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
/* No need to check replay if disabled. */
|
2002-10-16 02:10:08 +00:00
|
|
|
if (replay->wsize == 0)
|
2020-10-16 11:24:12 +00:00
|
|
|
return (0);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
/* Zero sequence number is not allowed. */
|
|
|
|
if (seq == 0 && replay->last == 0)
|
2017-02-06 08:49:57 +00:00
|
|
|
return (1);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
window = replay->wsize << 3; /* Size of window */
|
|
|
|
tl = (uint32_t)replay->last; /* Top of window, lower part */
|
|
|
|
th = (uint32_t)(replay->last >> 32); /* Top of window, high part */
|
|
|
|
bl = tl - window + 1; /* Bottom of window, lower part */
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
/*
|
|
|
|
* We keep the high part intact when:
|
|
|
|
* 1) the seq is within [bl, 0xffffffff] and the whole window is
|
|
|
|
* within one subspace;
|
|
|
|
* 2) the seq is within [0, bl) and window spans two subspaces.
|
|
|
|
*/
|
|
|
|
if ((tl >= window - 1 && seq >= bl) ||
|
|
|
|
(tl < window - 1 && seq < bl)) {
|
|
|
|
seqh = th;
|
|
|
|
if (seq <= tl) {
|
|
|
|
/* Sequence number inside window - check against replay */
|
|
|
|
if (check_window(replay, seq))
|
|
|
|
return (1);
|
|
|
|
set_window(replay, seq);
|
|
|
|
} else {
|
|
|
|
advance_window(replay, ((uint64_t)seqh << 32) | seq);
|
|
|
|
set_window(replay, seq);
|
|
|
|
replay->last = ((uint64_t)seqh << 32) | seq;
|
2016-11-25 14:44:49 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
/* Sequence number above top of window or not found in bitmap */
|
|
|
|
replay->count++;
|
|
|
|
return (0);
|
2016-11-25 14:44:49 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
if (!(sav->flags & SADB_X_SAFLAGS_ESN))
|
2017-02-06 08:49:57 +00:00
|
|
|
return (1);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
/*
|
|
|
|
* Seq is within [bl, 0xffffffff] and bl is within
|
|
|
|
* [0xffffffff-window, 0xffffffff]. This means we got a seq
|
|
|
|
* which is within our replay window, but in the previous
|
|
|
|
* subspace.
|
|
|
|
*/
|
|
|
|
if (tl < window - 1 && seq >= bl) {
|
|
|
|
if (th == 0)
|
|
|
|
return (1);
|
|
|
|
if (check_window(replay, seq))
|
2017-02-06 08:49:57 +00:00
|
|
|
return (1);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
set_window(replay, seq);
|
|
|
|
replay->count++;
|
|
|
|
return (0);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2019-09-06 14:30:23 +00:00
|
|
|
|
2020-10-16 11:24:12 +00:00
|
|
|
/*
|
|
|
|
* Seq is within [0, bl) but the whole window is within one subspace.
|
|
|
|
* This means that seq has wrapped and is in next subspace
|
|
|
|
*/
|
|
|
|
seqh = th + 1;
|
|
|
|
|
|
|
|
/* Don't let high part wrap. */
|
|
|
|
if (seqh == 0)
|
|
|
|
return (1);
|
|
|
|
|
|
|
|
advance_window(replay, ((uint64_t)seqh << 32) | seq);
|
|
|
|
set_window(replay, seq);
|
|
|
|
replay->last = ((uint64_t)seqh << 32) | seq;
|
2019-09-06 14:30:23 +00:00
|
|
|
replay->count++;
|
2017-02-06 08:49:57 +00:00
|
|
|
return (0);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
int
|
2018-07-13 23:46:07 +00:00
|
|
|
ipsec_updateid(struct secasvar *sav, crypto_session_t *new,
|
|
|
|
crypto_session_t *old)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2018-07-13 23:46:07 +00:00
|
|
|
crypto_session_t tmp;
|
2008-12-27 22:58:16 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
/*
|
|
|
|
* tdb_cryptoid is initialized by xform_init().
|
|
|
|
* Then it can be changed only when some crypto error occurred or
|
|
|
|
* when SA is deleted. We stored used cryptoid in the xform_data
|
|
|
|
* structure. In case when crypto error occurred and crypto
|
|
|
|
* subsystem has reinited the session, it returns new cryptoid
|
|
|
|
* and EAGAIN error code.
|
|
|
|
*
|
|
|
|
* This function will be called when we got EAGAIN from crypto
|
|
|
|
* subsystem.
|
|
|
|
* *new is cryptoid that was returned by crypto subsystem in
|
|
|
|
* the crp_sid.
|
|
|
|
* *old is the original cryptoid that we stored in xform_data.
|
|
|
|
*
|
|
|
|
* For first failed request *old == sav->tdb_cryptoid, then
|
|
|
|
* we update sav->tdb_cryptoid and redo crypto_dispatch().
|
|
|
|
* For next failed request *old != sav->tdb_cryptoid, then
|
|
|
|
* we store cryptoid from first request into the *new variable
|
|
|
|
* and crp_sid from this second session will be returned via
|
|
|
|
* *old pointer, so caller can release second session.
|
|
|
|
*
|
|
|
|
* XXXAE: check this more carefully.
|
|
|
|
*/
|
|
|
|
KEYDBG(IPSEC_STAMP,
|
2018-07-18 00:56:25 +00:00
|
|
|
printf("%s: SA(%p) moves cryptoid %p -> %p\n",
|
|
|
|
__func__, sav, *old, *new));
|
2017-02-06 08:49:57 +00:00
|
|
|
KEYDBG(IPSEC_DATA, kdebug_secasv(sav));
|
|
|
|
SECASVAR_LOCK(sav);
|
|
|
|
if (sav->tdb_cryptoid != *old) {
|
|
|
|
/* cryptoid was already updated */
|
|
|
|
tmp = *new;
|
|
|
|
*new = sav->tdb_cryptoid;
|
|
|
|
*old = tmp;
|
|
|
|
SECASVAR_UNLOCK(sav);
|
|
|
|
return (1);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2017-02-06 08:49:57 +00:00
|
|
|
sav->tdb_cryptoid = *new;
|
|
|
|
SECASVAR_UNLOCK(sav);
|
|
|
|
return (0);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
int
|
|
|
|
ipsec_initialized(void)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
return (V_def_policy != NULL);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2004-01-27 17:45:28 +00:00
|
|
|
static void
|
2014-12-24 18:34:56 +00:00
|
|
|
def_policy_init(const void *unused __unused)
|
First pass at separating per-vnet initializer functions
from existing functions for initializing global state.
At this stage, the new per-vnet initializer functions are
directly called from the existing global initialization code,
which should in most cases result in compiler inlining those
new functions, hence yielding a near-zero functional change.
Modify the existing initializer functions which are invoked via
protosw, like ip_init() et. al., to allow them to be invoked
multiple times, i.e. per each vnet. Global state, if any,
is initialized only if such functions are called within the
context of vnet0, which will be determined via the
IS_DEFAULT_VNET(curvnet) check (currently always true).
While here, V_irtualize a few remaining global UMA zones
used by net/netinet/netipsec networking code. While it is
not yet clear to me or anybody else whether this is the right
thing to do, at this stage this makes the code more readable,
and makes it easier to track uncollected UMA-zone-backed
objects on vnet removal. In the long run, it's quite possible
that some form of shared use of UMA zone pools among multiple
vnets should be considered.
Bump __FreeBSD_version due to changes in layout of structs
vnet_ipfw, vnet_inet and vnet_net.
Approved by: julian (mentor)
2009-04-06 22:29:41 +00:00
|
|
|
{
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
V_def_policy = key_newsp();
|
|
|
|
if (V_def_policy != NULL) {
|
|
|
|
V_def_policy->policy = IPSEC_POLICY_NONE;
|
|
|
|
/* Force INPCB SP cache invalidation */
|
|
|
|
key_bumpspgen();
|
|
|
|
} else
|
|
|
|
printf("%s: failed to initialize default policy\n", __func__);
|
2004-01-27 17:45:28 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
static void
|
|
|
|
def_policy_uninit(const void *unused __unused)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2008-12-27 22:58:16 +00:00
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
if (V_def_policy != NULL) {
|
|
|
|
key_freesp(&V_def_policy);
|
|
|
|
key_bumpspgen();
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:49:57 +00:00
|
|
|
VNET_SYSINIT(def_policy_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST,
|
|
|
|
def_policy_init, NULL);
|
|
|
|
VNET_SYSUNINIT(def_policy_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST,
|
|
|
|
def_policy_uninit, NULL);
|