From 755d70b8f2c28b016b6c0330273e7daa38038f27 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Sat, 21 Apr 2018 23:26:37 +0200 Subject: [PATCH] Remove IPsec and related code from the system. It was unmaintained ever since we inherited it from FreeBSD 4.8. In fact, we had two implementations from that time: IPSEC and FAST_IPSEC. FAST_IPSEC is the implementation to which FreeBSD has moved since, but it didn't even build in DragonFly. Fixes for dports have been committed to DeltaPorts. Requested-by: dillon Dports-testing-and-fixing: zrj --- Makefile_upgrade.inc | 24 + UPDATING | 8 + etc/defaults/rc.conf | 2 - etc/mtree/BSD.include.dist | 4 - etc/rc.d/Makefile | 3 +- etc/rc.d/ipsec | 70 - etc/rc.d/rtadvd | 9 - gnu/usr.bin/groff/tmac/fr.ISO8859-1 | 1 - gnu/usr.bin/groff/tmac/ru.KOI8-R | 1 - include/Makefile | 5 +- lib/Makefile | 1 - lib/libc/gen/sysctl.3 | 9 +- lib/libc/net/getnameinfo.c | 1 - lib/libipsec/Makefile | 56 - lib/libipsec/ipsec_dump_policy.c | 299 -- lib/libipsec/ipsec_get_policylen.c | 47 - lib/libipsec/ipsec_set_policy.3 | 277 - lib/libipsec/ipsec_strerror.3 | 88 - lib/libipsec/ipsec_strerror.c | 88 - lib/libipsec/ipsec_strerror.h | 64 - lib/libipsec/libpfkey.h | 91 - lib/libipsec/pfkey.c | 1986 ------- lib/libipsec/pfkey_dump.c | 587 -- lib/libipsec/policy_parse.y | 425 -- lib/libipsec/policy_token.l | 151 - lib/libipsec/test-policy.c | 334 -- sbin/ping/Makefile | 5 - sbin/ping/ping.8 | 11 +- sbin/ping/ping.c | 77 +- sbin/ping6/Makefile | 6 +- sbin/ping6/ping6.8 | 22 +- sbin/ping6/ping6.c | 121 +- share/initrd/sbin.libcrypto/Makefile | 1 - share/initrd/sbin/Makefile | 2 +- share/man/man4/Makefile | 2 - share/man/man4/aesni.4 | 3 +- share/man/man4/crypto.4 | 3 +- share/man/man4/fast_ipsec.4 | 107 - share/man/man4/hifn.4 | 5 +- share/man/man4/ip6.4 | 10 +- share/man/man4/ipsec.4 | 326 -- share/man/man4/padlock.4 | 9 +- share/man/man4/pfsync.4 | 22 +- share/man/man4/safe.4 | 5 +- share/man/man4/tcp.4 | 5 +- share/man/man4/txp.4 | 12 +- share/man/man4/ubsec.4 | 6 +- share/man/man5/rc.conf.5 | 15 +- share/man/man7/hier.7 | 4 +- share/man/man9/crypto.9 | 24 +- share/mk/bsd.libnames.mk | 1 - sys/conf/files | 39 - sys/conf/options | 10 +- sys/config/LINT64 | 41 +- sys/config/VKERNEL64 | 4 - sys/crypto/blowfish/bf_ecb.c | 85 - sys/net/pf/if_pfsync.c | 17 - sys/net/pfkeyv2.h | 402 -- sys/netinet/in.h | 4 +- sys/netinet/in_pcb.c | 35 - sys/netinet/in_pcb.h | 4 +- sys/netinet/in_proto.c | 116 - sys/netinet/ip_divert.c | 1 - sys/netinet/ip_icmp.c | 22 - sys/netinet/ip_input.c | 205 - sys/netinet/ip_output.c | 336 -- sys/netinet/raw_ip.c | 41 - sys/netinet/tcp_input.c | 34 - sys/netinet/tcp_output.c | 18 - sys/netinet/tcp_subr.c | 58 - sys/netinet/tcp_syncache.c | 23 - sys/netinet/tcp_usrreq.c | 5 - sys/netinet/udp_usrreq.c | 44 - sys/netinet6/ah.h | 102 - sys/netinet6/ah6.h | 63 - sys/netinet6/ah_core.c | 1537 ------ sys/netinet6/ah_input.c | 1037 ---- sys/netinet6/ah_output.c | 574 -- sys/netinet6/esp.h | 112 - sys/netinet6/esp6.h | 60 - sys/netinet6/esp_aesctr.c | 447 -- sys/netinet6/esp_camellia.c | 81 - sys/netinet6/esp_core.c | 1057 ---- sys/netinet6/esp_input.c | 978 ---- sys/netinet6/esp_output.c | 699 --- sys/netinet6/esp_rijndael.c | 109 - sys/netinet6/icmp6.c | 16 - sys/netinet6/in6.h | 4 - sys/netinet6/in6_pcb.c | 24 - sys/netinet6/in6_proto.c | 77 - sys/netinet6/ip6_forward.c | 193 - sys/netinet6/ip6_input.c | 36 - sys/netinet6/ip6_output.c | 287 +- sys/netinet6/ipcomp.h | 79 - sys/netinet6/ipcomp6.h | 56 - sys/netinet6/ipcomp_core.c | 342 -- sys/netinet6/ipcomp_input.c | 345 -- sys/netinet6/ipcomp_output.c | 363 -- sys/netinet6/ipsec.c | 3474 ------------ sys/netinet6/ipsec.h | 352 -- sys/netinet6/ipsec6.h | 87 - sys/netinet6/nd6_nbr.c | 8 - sys/netinet6/raw_ip6.c | 51 - sys/netinet6/udp6_output.c | 8 - sys/netinet6/udp6_usrreq.c | 63 - sys/netproto/ipsec/ah.h | 57 - sys/netproto/ipsec/ah_var.h | 79 - sys/netproto/ipsec/esp.h | 70 - sys/netproto/ipsec/esp_var.h | 82 - sys/netproto/ipsec/ipcomp.h | 56 - sys/netproto/ipsec/ipcomp_var.h | 68 - sys/netproto/ipsec/ipip_var.h | 66 - sys/netproto/ipsec/ipsec.c | 1854 ------- sys/netproto/ipsec/ipsec.h | 390 -- sys/netproto/ipsec/ipsec6.h | 91 - sys/netproto/ipsec/ipsec_input.c | 782 --- sys/netproto/ipsec/ipsec_mbuf.c | 479 -- sys/netproto/ipsec/ipsec_output.c | 754 --- sys/netproto/ipsec/key.c | 6966 ------------------------ sys/netproto/ipsec/key.h | 115 - sys/netproto/ipsec/key_debug.c | 725 --- sys/netproto/ipsec/key_debug.h | 89 - sys/netproto/ipsec/key_var.h | 73 - sys/netproto/ipsec/keydb.h | 182 - sys/netproto/ipsec/keysock.c | 584 -- sys/netproto/ipsec/keysock.h | 83 - sys/netproto/ipsec/xform.h | 127 - sys/netproto/ipsec/xform_ah.c | 1205 ----- sys/netproto/ipsec/xform_esp.c | 971 ---- sys/netproto/ipsec/xform_ipcomp.c | 618 --- sys/netproto/ipsec/xform_ipip.c | 707 --- sys/netproto/key/key.c | 7366 -------------------------- sys/netproto/key/key.h | 84 - sys/netproto/key/key_debug.c | 726 --- sys/netproto/key/key_debug.h | 89 - sys/netproto/key/key_var.h | 73 - sys/netproto/key/keydb.c | 195 - sys/netproto/key/keydb.h | 181 - sys/netproto/key/keysock.c | 641 --- sys/netproto/key/keysock.h | 83 - sys/platform/pc64/conf/files | 2 - sys/platform/vkernel64/conf/files | 2 - sys/sys/mbuf.h | 13 - sys/sys/param.h | 3 +- sys/sys/priv.h | 7 +- tools/tools/crypto/Makefile | 6 +- tools/tools/crypto/ipsecstats.c | 180 - usr.bin/kdump/mkioctls | 2 +- usr.bin/netstat/Makefile | 3 +- usr.bin/netstat/ipsec.c | 314 -- usr.bin/netstat/main.c | 61 +- usr.bin/netstat/netstat.1 | 8 +- usr.bin/netstat/netstat.h | 7 - usr.bin/telnet/Makefile | 4 - usr.bin/telnet/commands.c | 38 - usr.bin/telnet/externs.h | 8 - usr.bin/telnet/main.c | 28 +- usr.sbin/Makefile | 1 - usr.sbin/authpf/authpf.8 | 56 +- usr.sbin/inetd/Makefile | 7 +- usr.sbin/inetd/inetd.8 | 30 +- usr.sbin/inetd/inetd.c | 134 - usr.sbin/inetd/inetd.h | 3 - usr.sbin/mld6query/Makefile | 2 +- usr.sbin/rrenumd/Makefile | 6 +- usr.sbin/rrenumd/rrenumd.c | 160 +- usr.sbin/rtadvd/rtadvd.8 | 3 +- usr.sbin/setkey/Makefile | 54 - usr.sbin/setkey/parse.y | 937 ---- usr.sbin/setkey/sample.cf | 220 - usr.sbin/setkey/scriptdump | 56 - usr.sbin/setkey/setkey.8 | 627 --- usr.sbin/setkey/setkey.c | 635 --- usr.sbin/setkey/test-pfkey.c | 501 -- usr.sbin/setkey/test-policy.c | 161 - usr.sbin/setkey/token.l | 323 -- usr.sbin/setkey/vchar.h | 37 - usr.sbin/traceroute6/Makefile | 6 +- usr.sbin/traceroute6/traceroute6.c | 98 - 179 files changed, 163 insertions(+), 50991 deletions(-) delete mode 100644 etc/rc.d/ipsec delete mode 100644 lib/libipsec/Makefile delete mode 100644 lib/libipsec/ipsec_dump_policy.c delete mode 100644 lib/libipsec/ipsec_get_policylen.c delete mode 100644 lib/libipsec/ipsec_set_policy.3 delete mode 100644 lib/libipsec/ipsec_strerror.3 delete mode 100644 lib/libipsec/ipsec_strerror.c delete mode 100644 lib/libipsec/ipsec_strerror.h delete mode 100644 lib/libipsec/libpfkey.h delete mode 100644 lib/libipsec/pfkey.c delete mode 100644 lib/libipsec/pfkey_dump.c delete mode 100644 lib/libipsec/policy_parse.y delete mode 100644 lib/libipsec/policy_token.l delete mode 100644 lib/libipsec/test-policy.c delete mode 100644 share/man/man4/fast_ipsec.4 delete mode 100644 share/man/man4/ipsec.4 delete mode 100644 sys/crypto/blowfish/bf_ecb.c delete mode 100644 sys/net/pfkeyv2.h delete mode 100644 sys/netinet6/ah.h delete mode 100644 sys/netinet6/ah6.h delete mode 100644 sys/netinet6/ah_core.c delete mode 100644 sys/netinet6/ah_input.c delete mode 100644 sys/netinet6/ah_output.c delete mode 100644 sys/netinet6/esp.h delete mode 100644 sys/netinet6/esp6.h delete mode 100644 sys/netinet6/esp_aesctr.c delete mode 100644 sys/netinet6/esp_camellia.c delete mode 100644 sys/netinet6/esp_core.c delete mode 100644 sys/netinet6/esp_input.c delete mode 100644 sys/netinet6/esp_output.c delete mode 100644 sys/netinet6/esp_rijndael.c delete mode 100644 sys/netinet6/ipcomp.h delete mode 100644 sys/netinet6/ipcomp6.h delete mode 100644 sys/netinet6/ipcomp_core.c delete mode 100644 sys/netinet6/ipcomp_input.c delete mode 100644 sys/netinet6/ipcomp_output.c delete mode 100644 sys/netinet6/ipsec.c delete mode 100644 sys/netinet6/ipsec.h delete mode 100644 sys/netinet6/ipsec6.h delete mode 100644 sys/netproto/ipsec/ah.h delete mode 100644 sys/netproto/ipsec/ah_var.h delete mode 100644 sys/netproto/ipsec/esp.h delete mode 100644 sys/netproto/ipsec/esp_var.h delete mode 100644 sys/netproto/ipsec/ipcomp.h delete mode 100644 sys/netproto/ipsec/ipcomp_var.h delete mode 100644 sys/netproto/ipsec/ipip_var.h delete mode 100644 sys/netproto/ipsec/ipsec.c delete mode 100644 sys/netproto/ipsec/ipsec.h delete mode 100644 sys/netproto/ipsec/ipsec6.h delete mode 100644 sys/netproto/ipsec/ipsec_input.c delete mode 100644 sys/netproto/ipsec/ipsec_mbuf.c delete mode 100644 sys/netproto/ipsec/ipsec_output.c delete mode 100644 sys/netproto/ipsec/key.c delete mode 100644 sys/netproto/ipsec/key.h delete mode 100644 sys/netproto/ipsec/key_debug.c delete mode 100644 sys/netproto/ipsec/key_debug.h delete mode 100644 sys/netproto/ipsec/key_var.h delete mode 100644 sys/netproto/ipsec/keydb.h delete mode 100644 sys/netproto/ipsec/keysock.c delete mode 100644 sys/netproto/ipsec/keysock.h delete mode 100644 sys/netproto/ipsec/xform.h delete mode 100644 sys/netproto/ipsec/xform_ah.c delete mode 100644 sys/netproto/ipsec/xform_esp.c delete mode 100644 sys/netproto/ipsec/xform_ipcomp.c delete mode 100644 sys/netproto/ipsec/xform_ipip.c delete mode 100644 sys/netproto/key/key.c delete mode 100644 sys/netproto/key/key.h delete mode 100644 sys/netproto/key/key_debug.c delete mode 100644 sys/netproto/key/key_debug.h delete mode 100644 sys/netproto/key/key_var.h delete mode 100644 sys/netproto/key/keydb.c delete mode 100644 sys/netproto/key/keydb.h delete mode 100644 sys/netproto/key/keysock.c delete mode 100644 sys/netproto/key/keysock.h delete mode 100644 tools/tools/crypto/ipsecstats.c delete mode 100644 usr.bin/netstat/ipsec.c delete mode 100644 usr.sbin/setkey/Makefile delete mode 100644 usr.sbin/setkey/parse.y delete mode 100644 usr.sbin/setkey/sample.cf delete mode 100644 usr.sbin/setkey/scriptdump delete mode 100644 usr.sbin/setkey/setkey.8 delete mode 100644 usr.sbin/setkey/setkey.c delete mode 100644 usr.sbin/setkey/test-pfkey.c delete mode 100644 usr.sbin/setkey/test-policy.c delete mode 100644 usr.sbin/setkey/token.l delete mode 100644 usr.sbin/setkey/vchar.h diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index 96314346da..ec47b19d27 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -3387,6 +3387,30 @@ TO_REMOVE+=/usr/include/sys/ttychars.h TO_REMOVE+=/usr/include/sys/ttydev.h TO_REMOVE+=/usr/share/man/man3/gtty.3.gz TO_REMOVE+=/usr/share/man/man3/stty.3.gz +TO_REMOVE+=/etc/rc.d/ipsec +TO_REMOVE+=/usr/include/net/pfkeyv2.h +TO_REMOVE+=/usr/include/netinet6/ah.h +TO_REMOVE+=/usr/include/netinet6/ah6.h +TO_REMOVE+=/usr/include/netinet6/esp.h +TO_REMOVE+=/usr/include/netinet6/esp6.h +TO_REMOVE+=/usr/include/netinet6/ipcomp.h +TO_REMOVE+=/usr/include/netinet6/ipcomp6.h +TO_REMOVE+=/usr/include/netinet6/ipsec.h +TO_REMOVE+=/usr/include/netinet6/ipsec6.h +TO_REMOVE+=/usr/include/netipsec +TO_REMOVE+=/usr/include/netkey +TO_REMOVE+=/usr/include/netproto/ipsec +TO_REMOVE+=/usr/include/netproto/key +TO_REMOVE+=/usr/lib/libipsec.a +TO_REMOVE+=/usr/lib/profile/libipsec.a +TO_REMOVE+=/usr/sbin/setkey +TO_REMOVE+=/usr/share/man/man3/ipsec_dump_policy.3.gz +TO_REMOVE+=/usr/share/man/man3/ipsec_get_policylen.3.gz +TO_REMOVE+=/usr/share/man/man3/ipsec_set_policy.3.gz +TO_REMOVE+=/usr/share/man/man3/ipsec_strerror.3.gz +TO_REMOVE+=/usr/share/man/man4/fast_ipsec.4.gz +TO_REMOVE+=/usr/share/man/man4/ipsec.4.gz +TO_REMOVE+=/usr/share/man/man8/setkey.8.gz .if !defined(WANT_INSTALLER) TO_REMOVE+=/usr/sbin/dfuibe_installer diff --git a/UPDATING b/UPDATING index 835f309333..602c39d6df 100644 --- a/UPDATING +++ b/UPDATING @@ -12,6 +12,14 @@ + UPGRADING DRAGONFLY FROM 5.0 TO LATER VERSIONS + +-----------------------------------------------------------------------+ +IPSEC, IPSEC_ESP AND IPSEC_DEBUG REMOVED FROM VKERNEL64 CONFIG +-------------------------------------------------------------- + +IPsec has been removed from the system. Of our standard kernel +configurations, only the virtual kernel one had it. People running +vkernels with configuration files derived from our VKERNEL64 will +have to remove these options manually. + VIRTIO_PCI REMOVED FROM KERNEL CONFIG ------------------------------------- diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 56d7edf379..561b8fedfc 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -73,8 +73,6 @@ ipfw3_script="/etc/ipfw3.rules" # Script to run to set up the firewall rules ipfw3_modules="ipfw3 ipfw3_basic" # IPFW3 modules to be loaded ip_portrange_first="NO" # Set first dynamically allocated port ip_portrange_last="NO" # Set last dynamically allocated port -ipsec_enable="NO" # Set to YES to run setkey on ipsec_file -ipsec_file="/etc/ipsec.conf" # Name of config file for setkey natd_program="/sbin/natd" # path to natd, if you want a different one. natd_enable="NO" # Enable natd (if firewall_enable == YES). natd_interface="" # Public interface or IPaddress to use. diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index efb67fa565..d4cad98440 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -396,10 +396,6 @@ netproto 802_11 .. - ipsec - .. - key - .. mpls .. smb diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 61d3a86b5a..55eca8ae67 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -10,8 +10,7 @@ FILES= DAEMON LOGIN NETWORKING SERVERS \ bootconf bootparams btconfig bthcid ccd cleanvar cryptdisks \ cleartmp cron cryptdisks devd devfs dhclient diskless dmesg dumpon \ fixbootfile fsck ftpd hostname hotplugd \ - inetd initdiskless initrandom ip6fw ipfw ipfw3 ipsec \ - jail keyserv \ + inetd initdiskless initrandom ip6fw ipfw ipfw3 jail keyserv \ ldconfig local localdaemons lockd lpd lvm \ mixer modules motd mountcritlocal mountcritremote \ mountd moused mroute6d mrouted msgs \ diff --git a/etc/rc.d/ipsec b/etc/rc.d/ipsec deleted file mode 100644 index b280f381c9..0000000000 --- a/etc/rc.d/ipsec +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# -# $NetBSD: ipsec,v 1.7 2002/03/22 04:33:58 thorpej Exp $ -# $FreeBSD: src/etc/rc.d/ipsec,v 1.5 2003/02/16 20:46:08 mtm Exp $ -# $DragonFly: src/etc/rc.d/ipsec,v 1.5 2005/11/19 21:47:32 swildner Exp $ -# - -# PROVIDE: ipsec -# REQUIRE: root mountcritlocal tty -# BEFORE: DAEMON - -. /etc/rc.subr - -name="ipsec" -rcvar=`set_rcvar` -start_precmd="ipsec_prestart" -start_cmd="ipsec_start" -stop_precmd="test -f /etc/ipsec.conf" -stop_cmd="ipsec_stop" -reload_cmd="ipsec_reload" -extra_commands="reload" -ipsec_program="/usr/sbin/setkey" -# ipsec_file is set by rc.conf - -ipsec_prestart() -{ - if [ ! -f "$ipsec_file" ]; then - warn "$ipsec_file not readable; ipsec start aborted." - # - # If booting directly to multiuser, send SIGTERM to - # the parent (/etc/rc) to abort the boot - # - if [ "$autoboot" = yes ]; then - echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!" - kill -TERM $$ - exit 1 - fi - return 1 - fi - return 0 -} - -ipsec_start() -{ - echo "Installing ipsec manual keys/policies." - ${ipsec_program} -f $ipsec_file -} - -ipsec_stop() -{ - echo "Clearing ipsec manual keys/policies." - - # still not 100% sure if we would like to do this. - # it is very questionable to do this during shutdown session, since - # it can hang any of remaining IPv4/v6 session. - # - ${ipsec_program} -F - ${ipsec_program} -FP -} - -ipsec_reload() -{ - echo "Reloading ipsec manual keys/policies." - ${ipsec_program} -F - ${ipsec_program} -FP - ${ipsec_program} -f "$ipsec_file" -} - -load_rc_config $name -run_rc_command "$1" diff --git a/etc/rc.d/rtadvd b/etc/rc.d/rtadvd index d330b89daa..77c61def46 100644 --- a/etc/rc.d/rtadvd +++ b/etc/rc.d/rtadvd @@ -31,12 +31,6 @@ rtadvd_precmd() # router renumbering messages, specify your Router Renumbering # security policy by -R option. # - # See `man 3 ipsec_set_policy` for IPsec policy specification - # details. - # (CAUTION: This enables your routers prefix renumbering - # from another machine, so if you enable this, do it with - # enough care.) - # # If specific interfaces haven't been specified, # get a list of interfaces and enable it on them # @@ -55,9 +49,6 @@ rtadvd_precmd() ;; esac command_args="${rtadvd_interfaces}" - # Enable Router Renumbering, unicast case - # (use correct src/dst addr) - # rtadvd -R "in ipsec ah/transport/fec0:0:0:1::1-fec0:0:0:10::1/require" ${ipv6_network_interf return 0 } diff --git a/gnu/usr.bin/groff/tmac/fr.ISO8859-1 b/gnu/usr.bin/groff/tmac/fr.ISO8859-1 index ba66247f44..f6b80268f9 100644 --- a/gnu/usr.bin/groff/tmac/fr.ISO8859-1 +++ b/gnu/usr.bin/groff/tmac/fr.ISO8859-1 @@ -85,7 +85,6 @@ .ds doc-str-Lb-libfetch Biblioth\[`e]que de transfert de fichier (libfetch, \-lfetch) .\" XXX ds doc-str-Lb-libgeom Userland API Library for kernel GEOM subsystem (libgeom, \-lgeom) .ds doc-str-Lb-libi386 Biblioth\[`e]que de l'architecture i386 (libi386, \-li386) -.ds doc-str-Lb-libipsec Biblioth\[`e]que de contr\[^o]le de politique IPsec (libipsec, \-lipsec) .ds doc-str-Lb-libkvm Biblioth\[`e]que d'acc\[`e]s aux donn\['e]es du noyau (libkvm, \-lkvm) .ds doc-str-Lb-libm Biblioth\[`e]que math\['e]matique (libm, \-lm) .ds doc-str-Lb-libmd Biblioth\[`e]que de support des signatures (MD4, MD5, etc.) (libmd, \-lmd) diff --git a/gnu/usr.bin/groff/tmac/ru.KOI8-R b/gnu/usr.bin/groff/tmac/ru.KOI8-R index 2513ef76f0..f422badd3c 100644 --- a/gnu/usr.bin/groff/tmac/ru.KOI8-R +++ b/gnu/usr.bin/groff/tmac/ru.KOI8-R @@ -85,7 +85,6 @@ .ds doc-str-Lb-libfetch âÉÂÌÉÏÔÅËÁ ÆÁÊÌÏ×ÏÊ ÐÅÒÅÄÁÞÉ (libfetch, \-lfetch) .ds doc-str-Lb-libgeom ðÏÌØÚÏ×ÁÔÅÌØÓËÁÑ API ÂÉÂÌÉÏÔÅËÁ ÐÏÄÓÉÓÔÅÍÙ ÑÄÒÁ GEOM (libgeom, \-lgeom) .ds doc-str-Lb-libi386 âÉÂÌÉÏÔÅËÁ ÁÒÈÉÔÅËÔÕÒÙ i386 (libi386, \-li386) -.ds doc-str-Lb-libipsec âÉÂÌÉÏÔÅËÁ ÕÐÒÁ×ÌÅÎÉÑ IPsec Policy (libipsec, \-lipsec) .ds doc-str-Lb-libkvm âÉÂÌÉÏÔÅËÁ ÄÏÓÔÕÐÁ Ë ÄÁÎÎÙÍ ÑÄÒÁ (libkvm, \-lkvm) .ds doc-str-Lb-libm âÉÂÌÉÏÔÅËÁ ÍÁÔÅÍÁÔÉÞÅÓËÉÈ ÆÕÎËÃÉÊ (libm, \-lm) .\" XXX ds doc-str-Lb-libmd Message Digest (MD4, MD5, É Ô.Ä.) Support Library (libmd, \-lmd) diff --git a/include/Makefile b/include/Makefile index a6aa4649b6..6a0dfb59a7 100644 --- a/include/Makefile +++ b/include/Makefile @@ -84,8 +84,7 @@ LSUBDIRS= \ netgraph7/mppc netgraph7/one2many netgraph7/ppp netgraph7/pppoe \ netgraph7/pptpgre netgraph7/rfc1490 netgraph7/socket \ netgraph7/tcpmss netgraph7/tee netgraph7/tty netgraph7/vjc \ - netproto/ipsec netproto/802_11 netproto/mpls \ - netproto/key netproto/smb \ + netproto/802_11 netproto/mpls netproto/smb \ vfs/isofs/cd9660 vfs/puffs \ vfs/msdosfs vfs/nfs vfs/ntfs \ vfs/smbfs vfs/udf vfs/ufs vfs/hammer vfs/hammer2 \ @@ -136,8 +135,6 @@ INCSLINKS+= vfs ${INCLUDEDIR}/fs # It is hopefully a temporary hack until we have environments working. INCSLINKS+= vfs ${INCLUDEDIR}/ufs INCSLINKS+= ufs ${INCLUDEDIR}/vfs/ffs -INCSLINKS+= netproto/ipsec ${INCLUDEDIR}/netipsec -INCSLINKS+= netproto/key ${INCLUDEDIR}/netkey INCSLINKS+= netproto/smb ${INCLUDEDIR}/netsmb INCSLINKS+= bus/pccard ${INCLUDEDIR}/pccard # Some 3rd party software looks for diff --git a/lib/Makefile b/lib/Makefile index c021ac135c..79a1cab543 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -71,7 +71,6 @@ SUBDIR= ${SUBDIR_ORDERED} \ libftpio \ libhammer \ libipfw3 \ - libipsec \ libkcore \ libkiconv \ libkinfo \ diff --git a/lib/libc/gen/sysctl.3 b/lib/libc/gen/sysctl.3 index 9838f4b1b2..06e2a58b19 100644 --- a/lib/libc/gen/sysctl.3 +++ b/lib/libc/gen/sysctl.3 @@ -28,7 +28,7 @@ .\" @(#)sysctl.3 8.4 (Berkeley) 5/9/95 .\" $FreeBSD: src/lib/libc/gen/sysctl.3,v 1.33.2.13 2002/04/07 04:57:14 dd Exp $ .\" -.Dd June 22, 2015 +.Dd April 21, 2018 .Dt SYSCTL 3 .Os .Sh NAME @@ -625,9 +625,6 @@ This value applies to normal transport protocols, not to ICMP. .It Li udp.checksum Returns 1 when UDP checksums are being computed and checked. Disabling UDP checksums is strongly discouraged. -.Pp -For variables net.inet.*.ipsec, please refer to -.Xr ipsec 4 . .El .It Dv PF_INET6 Get or set various global information about IPv6 @@ -639,10 +636,6 @@ For variables .Li net.inet6.* , please refer to .Xr inet6 4 . -For variables -.Li net.inet6.*.ipsec6 , -please refer to -.Xr ipsec 4 . .El .Ss CTL_USER The string and integer information available for the diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c index 1c265a62dc..c42ce27841 100644 --- a/lib/libc/net/getnameinfo.c +++ b/lib/libc/net/getnameinfo.c @@ -410,7 +410,6 @@ getnameinfo_link(const struct sockaddr *sa, socklen_t salen __unused, /* * The following use IPv4 addresses as link-layer addresses: * IFT_OTHER (net/gre/if_gre.c) - * IFT_OTHER (netproto/ipsec/xform_ipip.c) */ /* default below is believed correct for all these. */ case IFT_ARCNET: diff --git a/lib/libipsec/Makefile b/lib/libipsec/Makefile deleted file mode 100644 index 9a5987e1a3..0000000000 --- a/lib/libipsec/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the project nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# $FreeBSD: src/lib/libipsec/Makefile,v 1.2.2.3 2001/04/25 10:04:30 ru Exp $ -# $DragonFly: src/lib/libipsec/Makefile,v 1.3 2005/04/21 13:42:33 joerg Exp $ - -LIB= ipsec -SHLIB_MAJOR= 2 -SHLIBDIR?= /lib -CFLAGS+=-I. -I${.CURDIR} -CFLAGS+=-DIPSEC_DEBUG -DIPSEC -.if !defined(NOINET6) -CFLAGS+=-DINET6 -.endif - -#.PATH: ${.CURDIR}/../../sys/netkey -#SRCS= pfkey.c pfkey_dump.c -SRCS+= ipsec_strerror.c policy_parse.y policy_token.l -SRCS+= ipsec_dump_policy.c ipsec_get_policylen.c -#SRCS+= key_debug.c -CLEANFILES+= y.tab.c y.tab.h -YFLAGS+=-d -p __libipsecyy -LFLAGS+=-P__libipsecyy -WARNS?= 2 - -MAN= ipsec_set_policy.3 ipsec_strerror.3 -MLINKS+=ipsec_set_policy.3 ipsec_get_policylen.3 \ - ipsec_set_policy.3 ipsec_dump_policy.3 - -SRCS+= y.tab.h -y.tab.h: policy_parse.y - -.include diff --git a/lib/libipsec/ipsec_dump_policy.c b/lib/libipsec/ipsec_dump_policy.c deleted file mode 100644 index bc03ccf2a6..0000000000 --- a/lib/libipsec/ipsec_dump_policy.c +++ /dev/null @@ -1,299 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/ipsec_dump_policy.c,v 1.1.2.1 2000/07/15 07:24:04 kris Exp $ */ -/* $KAME: ipsec_dump_policy.c,v 1.11 2000/05/07 05:29:47 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "ipsec_strerror.h" - -static const char *ipsp_dir_strs[] = { - "any", "in", "out", -}; - -static const char *ipsp_policy_strs[] = { - "discard", "none", "ipsec", "entrust", "bypass", -}; - -static char *ipsec_dump_ipsecrequest (char *, size_t, - struct sadb_x_ipsecrequest *, size_t); -static int set_addresses (char *, size_t, struct sockaddr *, - struct sockaddr *); -static char *set_address (char *, size_t, struct sockaddr *); - -/* - * policy is sadb_x_policy buffer. - * Must call free() later. - * When delimiter == NULL, alternatively ' '(space) is applied. - */ -char * -ipsec_dump_policy(caddr_t policy, char *delimiter) -{ - struct sadb_x_policy *xpl = (struct sadb_x_policy *)policy; - struct sadb_x_ipsecrequest *xisr; - size_t off, buflen; - char *buf; - char isrbuf[1024]; - char *newbuf; - - /* sanity check */ - if (policy == NULL) - return NULL; - if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) { - __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; - return NULL; - } - - /* set delimiter */ - if (delimiter == NULL) - delimiter = " "; - - switch (xpl->sadb_x_policy_dir) { - case IPSEC_DIR_ANY: - case IPSEC_DIR_INBOUND: - case IPSEC_DIR_OUTBOUND: - break; - default: - __ipsec_errcode = EIPSEC_INVAL_DIR; - return NULL; - } - - switch (xpl->sadb_x_policy_type) { - case IPSEC_POLICY_DISCARD: - case IPSEC_POLICY_NONE: - case IPSEC_POLICY_IPSEC: - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_ENTRUST: - break; - default: - __ipsec_errcode = EIPSEC_INVAL_POLICY; - return NULL; - } - - buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir]) - + 1 /* space */ - + strlen(ipsp_policy_strs[xpl->sadb_x_policy_type]) - + 1; /* NUL */ - - if ((buf = malloc(buflen)) == NULL) { - __ipsec_errcode = EIPSEC_NO_BUFS; - return NULL; - } - snprintf(buf, buflen, "%s %s", ipsp_dir_strs[xpl->sadb_x_policy_dir], - ipsp_policy_strs[xpl->sadb_x_policy_type]); - - if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) { - __ipsec_errcode = EIPSEC_NO_ERROR; - return buf; - } - - /* count length of buffer for use */ - off = sizeof(*xpl); - while (off < PFKEY_EXTLEN(xpl)) { - xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off); - off += xisr->sadb_x_ipsecrequest_len; - } - - /* validity check */ - if (off != PFKEY_EXTLEN(xpl)) { - __ipsec_errcode = EIPSEC_INVAL_SADBMSG; - free(buf); - return NULL; - } - - off = sizeof(*xpl); - while (off < PFKEY_EXTLEN(xpl)) { - xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off); - - if (ipsec_dump_ipsecrequest(isrbuf, sizeof(isrbuf), xisr, - PFKEY_EXTLEN(xpl) - off) == NULL) { - free(buf); - return NULL; - } - - buflen = strlen(buf) + strlen(delimiter) + strlen(isrbuf) + 1; - newbuf = (char *)realloc(buf, buflen); - if (newbuf == NULL) { - __ipsec_errcode = EIPSEC_NO_BUFS; - free(buf); - return NULL; - } - buf = newbuf; - snprintf(buf + strlen(buf), buflen - strlen(buf), - "%s%s", delimiter, isrbuf); - - off += xisr->sadb_x_ipsecrequest_len; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return buf; -} - -static char * -ipsec_dump_ipsecrequest(char *buf, size_t len, - struct sadb_x_ipsecrequest *xisr, size_t bound) -{ - const char *proto, *mode, *level; - char abuf[NI_MAXHOST * 2 + 2]; - - if (xisr->sadb_x_ipsecrequest_len > bound) { - __ipsec_errcode = EIPSEC_INVAL_PROTO; - return NULL; - } - - switch (xisr->sadb_x_ipsecrequest_proto) { - case IPPROTO_ESP: - proto = "esp"; - break; - case IPPROTO_AH: - proto = "ah"; - break; - case IPPROTO_IPCOMP: - proto = "ipcomp"; - break; - case IPPROTO_TCP: - proto = "tcp"; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_PROTO; - return NULL; - } - - switch (xisr->sadb_x_ipsecrequest_mode) { - case IPSEC_MODE_ANY: - mode = "any"; - break; - case IPSEC_MODE_TRANSPORT: - mode = "transport"; - break; - case IPSEC_MODE_TUNNEL: - mode = "tunnel"; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_MODE; - return NULL; - } - - abuf[0] = '\0'; - if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) { - struct sockaddr *sa1, *sa2; - caddr_t p; - - p = (caddr_t)(xisr + 1); - sa1 = (struct sockaddr *)p; - sa2 = (struct sockaddr *)(p + sa1->sa_len); - if (sizeof(*xisr) + sa1->sa_len + sa2->sa_len != - xisr->sadb_x_ipsecrequest_len) { - __ipsec_errcode = EIPSEC_INVAL_ADDRESS; - return NULL; - } - if (set_addresses(abuf, sizeof(abuf), sa1, sa2) != 0) { - __ipsec_errcode = EIPSEC_INVAL_ADDRESS; - return NULL; - } - } - - switch (xisr->sadb_x_ipsecrequest_level) { - case IPSEC_LEVEL_DEFAULT: - level = "default"; - break; - case IPSEC_LEVEL_USE: - level = "use"; - break; - case IPSEC_LEVEL_REQUIRE: - level = "require"; - break; - case IPSEC_LEVEL_UNIQUE: - level = "unique"; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_LEVEL; - return NULL; - } - - if (xisr->sadb_x_ipsecrequest_reqid == 0) - snprintf(buf, len, "%s/%s/%s/%s", proto, mode, abuf, level); - else { - int ch; - - if (xisr->sadb_x_ipsecrequest_reqid > IPSEC_MANUAL_REQID_MAX) - ch = '#'; - else - ch = ':'; - snprintf(buf, len, "%s/%s/%s/%s%c%d", proto, mode, abuf, level, - ch, xisr->sadb_x_ipsecrequest_reqid); - } - - return buf; -} - -static int -set_addresses(char *buf, size_t len, struct sockaddr *sa1, struct sockaddr *sa2) -{ - char tmp1[NI_MAXHOST], tmp2[NI_MAXHOST]; - - if (set_address(tmp1, sizeof(tmp1), sa1) == NULL || - set_address(tmp2, sizeof(tmp2), sa2) == NULL) - return -1; - if (strlen(tmp1) + 1 + strlen(tmp2) + 1 > len) - return -1; - snprintf(buf, len, "%s-%s", tmp1, tmp2); - return 0; -} - -static char * -set_address(char *buf, size_t len, struct sockaddr *sa) -{ -#ifdef NI_WITHSCOPEID - const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID; -#else - const int niflags = NI_NUMERICHOST; -#endif - - if (len < 1) - return NULL; - buf[0] = '\0'; - if (getnameinfo(sa, sa->sa_len, buf, len, NULL, 0, niflags) != 0) - return NULL; - return buf; -} diff --git a/lib/libipsec/ipsec_get_policylen.c b/lib/libipsec/ipsec_get_policylen.c deleted file mode 100644 index 39361db89d..0000000000 --- a/lib/libipsec/ipsec_get_policylen.c +++ /dev/null @@ -1,47 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/ipsec_get_policylen.c,v 1.1.2.1 2000/07/15 07:24:04 kris Exp $ */ -/* $DragonFly: src/lib/libipsec/ipsec_get_policylen.c,v 1.3 2008/09/30 16:57:05 swildner Exp $ */ -/* $KAME: ipsec_get_policylen.c,v 1.5 2000/05/07 05:25:03 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -#include -#include - -#include - -#include - -#include "ipsec_strerror.h" - -int -ipsec_get_policylen(caddr_t policy) -{ - return policy ? PFKEY_EXTLEN(policy) : -1; -} diff --git a/lib/libipsec/ipsec_set_policy.3 b/lib/libipsec/ipsec_set_policy.3 deleted file mode 100644 index 5292939f96..0000000000 --- a/lib/libipsec/ipsec_set_policy.3 +++ /dev/null @@ -1,277 +0,0 @@ -.\" $KAME: ipsec_set_policy.3,v 1.15 2001/08/17 07:21:36 itojun Exp $ -.\" $FreeBSD: src/lib/libipsec/ipsec_set_policy.3,v 1.3.2.10 2002/12/29 16:35:36 schweikh Exp $ -.\" -.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. -.\" -.Dd May 5, 1998 -.Dt IPSEC_SET_POLICY 3 -.Os -.Sh NAME -.Nm ipsec_set_policy , -.Nm ipsec_get_policylen , -.Nm ipsec_dump_policy -.Nd manipulate IPsec policy specification structure from readable string -.\" -.Sh LIBRARY -.Lb libipsec -.Sh SYNOPSIS -.In netinet6/ipsec.h -.Ft "char *" -.Fn ipsec_set_policy "char *policy" "int len" -.Ft int -.Fn ipsec_get_policylen "char *buf" -.Ft "char *" -.Fn ipsec_dump_policy "char *buf" "char *delim" -.Sh DESCRIPTION -.Fn ipsec_set_policy -generates IPsec policy specification structure, namely -.Li struct sadb_x_policy -and/or -.Li struct sadb_x_ipsecrequest -from human-readable policy specification. -Policy specification must be given as C string -.Fa policy -and length -.Fa len -of -.Fa policy . -.Fn ipsec_set_policy -will return the buffer of IPsec policy specification structure. -The buffer is dynamically allocated, and must be freed by the caller by calling -.Xr free 3 . -.Pp -You may want the length of the generated buffer such when calling -.Xr setsockopt 2 . -.Fn ipsec_get_policylen -will return the length. -.Pp -.Fn ipsec_dump_policy -converts IPsec policy structure into readable form. -Therefore, -.Fn ipsec_dump_policy -can be regarded as inverse conversion of -.Fn ipsec_set_policy . -.Fa buf -points to an IPsec policy structure, -.Li struct sadb_x_policy . -.Fa delim -is a delimiter string, which is usually a blank character. -If you set -.Fa delim -to -.Dv NULL , -single whitespace is assumed. -.Fn ipsec_dump_policy -returns pointer to dynamically allocated string. -It is caller's responsibility to reclaim the region, by using -.Xr free 3 . -.Pp -.Fa policy -is formatted as either of the following: -.Bl -tag -width "discard" -.It Ar direction Li discard -.Ar direction -must be -.Li in -or -.Li out . -.Ar direction -specifies which direction the policy needs to be applied. -With -.Li discard -policy, packets will be dropped if they match the policy. -.It Ar direction Li entrust -.Li entrust -means to consult to SPD defined by -.Xr setkey 8 . -.It Ar direction Li bypass -.Li bypass -means to be bypassed the IPsec processing. -(packet will be transmitted in clear). -This is for privileged socket. -.It Xo -.Ar direction -.Li ipsec -.Ar request ... -.Xc -.Li ipsec -means that the matching packets are subject to IPsec processing. -.Li ipsec -can be followed by one or more -.Ar request -string, which is formatted as below: -.Bl -tag -width "discard" -.It Xo -.Ar protocol -.Li / -.Ar mode -.Li / -.Ar src -.Li - -.Ar dst -.Op Ar /level -.Xc -.Ar protocol -is either -.Li ah , -.Li esp -or -.Li ipcomp . -.Pp -.Ar mode -is either -.Li transport -or -.Li tunnel . -.Pp -.Ar src -and -.Ar dst -specifies IPsec endpoint. -.Ar src -always means -.Dq sending node -and -.Ar dst -always means -.Dq receiving node . -Therefore, when -.Ar direction -is -.Li in , -.Ar dst -is this node -and -.Ar src -is the other node -(peer). -If -.Ar mode -is -.Li transport , -Both -.Ar src -and -.Ar dst -can be omitted. -.Pp -.Ar level -must be set to one of the following: -.Li default , use , require -or -.Li unique . -.Li default -means that the kernel should consult the system default policy -defined by -.Xr sysctl 8 , -such as -.Va net.inet.ipsec.esp_trans_deflev . -See -.Xr ipsec 4 -regarding the system default. -.Li use -means that a relevant SA can be used when available, -since the kernel may perform IPsec operation against packets when possible. -In this case, packets can be transmitted in clear -(when SA is not available), -or encrypted -(when SA is available). -.Li require -means that a relevant SA is required, -since the kernel must perform IPsec operation against packets. -.Li unique -is the same as -.Li require , -but adds the restriction that the SA for outbound traffic is used -only for this policy. -You may need the identifier in order to relate the policy and the SA -when you define the SA by manual keying. -You can put the decimal number as the identifier after -.Li unique -like -.Li unique : number . -.Li number -must be between 1 and 32767 . -If the -.Ar request -string is kept unambiguous, -.Ar level -and slash prior to -.Ar level -can be omitted. -However, it is encouraged to specify them explicitly -to avoid unintended behaviors. -If -.Ar level -is omitted, it will be interpreted as -.Li default . -.El -.El -.Pp -Note that there is a bit difference of specification from -.Xr setkey 8 . -In specification by -.Xr setkey 8 , -both entrust and bypass are not used. -Refer to -.Xr setkey 8 -for detail. -.Pp -Here are several examples -(long lines are wrapped for readability): -.Bd -literal -offset indent -in discard -out ipsec esp/transport//require -in ipsec ah/transport//require -out ipsec esp/tunnel/10.1.1.2-10.1.1.1/use -in ipsec ipcomp/transport//use - esp/transport//use -.Ed -.Sh RETURN VALUES -.Fn ipsec_set_policy -returns a pointer to the allocated buffer of policy specification if successful; otherwise a NULL pointer is returned. -.Fn ipsec_get_policylen -returns with positive value -(meaning the buffer size) -on success, and negative value on errors. -.Fn ipsec_dump_policy -returns a pointer to dynamically allocated region on success, -and -.Dv NULL -on errors. -.Sh SEE ALSO -.Xr ipsec_strerror 3 , -.Xr ipsec 4 , -.Xr setkey 8 -.Sh HISTORY -The functions first appeared in WIDE/KAME IPv6 protocol stack kit. -.Pp -IPv6 and IPsec support based on the KAME Project -.Pa ( http://www.kame.net/ ) -stack was initially integrated into -.Fx 4.0 diff --git a/lib/libipsec/ipsec_strerror.3 b/lib/libipsec/ipsec_strerror.3 deleted file mode 100644 index f4784fbaff..0000000000 --- a/lib/libipsec/ipsec_strerror.3 +++ /dev/null @@ -1,88 +0,0 @@ -.\" $KAME: ipsec_strerror.3,v 1.9 2001/08/17 07:21:36 itojun Exp $ -.\" $FreeBSD: src/lib/libipsec/ipsec_strerror.3,v 1.2.2.7 2002/04/28 05:40:25 suz Exp $ -.\" $DragonFly: src/lib/libipsec/ipsec_strerror.3,v 1.4 2007/08/19 18:47:47 swildner Exp $ -.\" -.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. -.\" -.Dd May 6, 1998 -.Dt IPSEC_STRERROR 3 -.Os -.\" -.Sh NAME -.Nm ipsec_strerror -.Nd error message for IPsec policy manipulation library -.\" -.Sh LIBRARY -.Lb libipsec -.Sh SYNOPSIS -.In netinet6/ipsec.h -.Ft "const char *" -.Fn ipsec_strerror "void" -.\" -.Sh DESCRIPTION -.In netinet6/ipsec.h -declares -.Pp -.Dl extern int ipsec_errcode; -.Pp -which is used to pass an error code from IPsec policy manipulation library -to an user program. -.Fn ipsec_strerror -can be used to obtain the error message string for the error code. -.Pp -The array pointed to is not to be modified by the program. -Since -.Fn ipsec_strerror -uses -.Xr strerror 3 -as underlying function, calling -.Xr strerror 3 -after -.Fn ipsec_strerror -would make the return value from -.Fn ipsec_strerror -invalid, or overwritten. -.\" -.Sh RETURN VALUES -.Fn ipsec_strerror -always return a pointer to C string. -The C string must not be overwritten by user programs. -.\" -.Sh SEE ALSO -.Xr ipsec_set_policy 3 -.\" -.Sh HISTORY -.Fn ipsec_strerror -first appeared in WIDE/KAME IPv6 protocol stack kit. -.\" -.Sh BUGS -.Fn ipsec_strerror -will return its result which may be overwritten by subsequent calls. -.Pp -.Va ipsec_errcode -is not thread safe. diff --git a/lib/libipsec/ipsec_strerror.c b/lib/libipsec/ipsec_strerror.c deleted file mode 100644 index 8282adba82..0000000000 --- a/lib/libipsec/ipsec_strerror.c +++ /dev/null @@ -1,88 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/ipsec_strerror.c,v 1.1.2.2 2001/07/03 11:01:14 ume Exp $ */ -/* $KAME: ipsec_strerror.c,v 1.7 2000/07/30 00:45:12 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -#include -#include - -#include -#include - -#include "ipsec_strerror.h" - -int __ipsec_errcode; - -static const char *ipsec_errlist[] = { -"Success", /*EIPSEC_NO_ERROR*/ -"Not supported", /*EIPSEC_NOT_SUPPORTED*/ -"Invalid argument", /*EIPSEC_INVAL_ARGUMENT*/ -"Invalid sadb message", /*EIPSEC_INVAL_SADBMSG*/ -"Invalid version", /*EIPSEC_INVAL_VERSION*/ -"Invalid security policy", /*EIPSEC_INVAL_POLICY*/ -"Invalid address specification", /*EIPSEC_INVAL_ADDRESS*/ -"Invalid ipsec protocol", /*EIPSEC_INVAL_PROTO*/ -"Invalid ipsec mode", /*EIPSEC_INVAL_MODE*/ -"Invalid ipsec level", /*EIPSEC_INVAL_LEVEL*/ -"Invalid SA type", /*EIPSEC_INVAL_SATYPE*/ -"Invalid message type", /*EIPSEC_INVAL_MSGTYPE*/ -"Invalid extension type", /*EIPSEC_INVAL_EXTTYPE*/ -"Invalid algorithm type", /*EIPSEC_INVAL_ALGS*/ -"Invalid key length", /*EIPSEC_INVAL_KEYLEN*/ -"Invalid address family", /*EIPSEC_INVAL_FAMILY*/ -"Invalid prefix length", /*EIPSEC_INVAL_PREFIXLEN*/ -"Invalid direction", /*EIPSEC_INVAL_DIR*/ -"SPI range violation", /*EIPSEC_INVAL_SPI*/ -"No protocol specified", /*EIPSEC_NO_PROTO*/ -"No algorithm specified", /*EIPSEC_NO_ALGS*/ -"No buffers available", /*EIPSEC_NO_BUFS*/ -"Must get supported algorithms list first", /*EIPSEC_DO_GET_SUPP_LIST*/ -"Protocol mismatch", /*EIPSEC_PROTO_MISMATCH*/ -"Family mismatch", /*EIPSEC_FAMILY_MISMATCH*/ -"Too few arguments", /*EIPSEC_FEW_ARGUMENTS*/ -NULL, /*EIPSEC_SYSTEM_ERROR*/ -"Unknown error", /*EIPSEC_MAX*/ -}; - -const char *ipsec_strerror(void) -{ - if (__ipsec_errcode < 0 || __ipsec_errcode > EIPSEC_MAX) - __ipsec_errcode = EIPSEC_MAX; - - return ipsec_errlist[__ipsec_errcode]; -} - -void __ipsec_set_strerror(const char *str) -{ - __ipsec_errcode = EIPSEC_SYSTEM_ERROR; - ipsec_errlist[EIPSEC_SYSTEM_ERROR] = str; - - return; -} diff --git a/lib/libipsec/ipsec_strerror.h b/lib/libipsec/ipsec_strerror.h deleted file mode 100644 index e062d47f24..0000000000 --- a/lib/libipsec/ipsec_strerror.h +++ /dev/null @@ -1,64 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/ipsec_strerror.h,v 1.1.2.2 2001/07/03 11:01:14 ume Exp $ */ -/* $DragonFly: src/lib/libipsec/ipsec_strerror.h,v 1.3 2003/11/12 20:21:30 eirikn Exp $ */ -/* $KAME: ipsec_strerror.h,v 1.8 2000/07/30 00:45:12 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -extern int __ipsec_errcode; -extern void __ipsec_set_strerror (const char *); - -#define EIPSEC_NO_ERROR 0 /*success*/ -#define EIPSEC_NOT_SUPPORTED 1 /*not supported*/ -#define EIPSEC_INVAL_ARGUMENT 2 /*invalid argument*/ -#define EIPSEC_INVAL_SADBMSG 3 /*invalid sadb message*/ -#define EIPSEC_INVAL_VERSION 4 /*invalid version*/ -#define EIPSEC_INVAL_POLICY 5 /*invalid security policy*/ -#define EIPSEC_INVAL_ADDRESS 6 /*invalid address specification*/ -#define EIPSEC_INVAL_PROTO 7 /*invalid ipsec protocol*/ -#define EIPSEC_INVAL_MODE 8 /*Invalid ipsec mode*/ -#define EIPSEC_INVAL_LEVEL 9 /*invalid ipsec level*/ -#define EIPSEC_INVAL_SATYPE 10 /*invalid SA type*/ -#define EIPSEC_INVAL_MSGTYPE 11 /*invalid message type*/ -#define EIPSEC_INVAL_EXTTYPE 12 /*invalid extension type*/ -#define EIPSEC_INVAL_ALGS 13 /*Invalid algorithm type*/ -#define EIPSEC_INVAL_KEYLEN 14 /*invalid key length*/ -#define EIPSEC_INVAL_FAMILY 15 /*invalid address family*/ -#define EIPSEC_INVAL_PREFIXLEN 16 /*SPI range violation*/ -#define EIPSEC_INVAL_DIR 17 /*Invalid direciton*/ -#define EIPSEC_INVAL_SPI 18 /*invalid prefixlen*/ -#define EIPSEC_NO_PROTO 19 /*no protocol specified*/ -#define EIPSEC_NO_ALGS 20 /*No algorithm specified*/ -#define EIPSEC_NO_BUFS 21 /*no buffers available*/ -#define EIPSEC_DO_GET_SUPP_LIST 22 /*must get supported algorithm first*/ -#define EIPSEC_PROTO_MISMATCH 23 /*protocol mismatch*/ -#define EIPSEC_FAMILY_MISMATCH 24 /*family mismatch*/ -#define EIPSEC_FEW_ARGUMENTS 25 /*Too few arguments*/ -#define EIPSEC_SYSTEM_ERROR 26 /*system error*/ -#define EIPSEC_MAX 27 /*unknown error*/ diff --git a/lib/libipsec/libpfkey.h b/lib/libipsec/libpfkey.h deleted file mode 100644 index e7705bf575..0000000000 --- a/lib/libipsec/libpfkey.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/libpfkey.h,v 1.1.2.2 2001/07/03 11:01:14 ume Exp $ */ -/* $DragonFly: src/lib/libipsec/libpfkey.h,v 1.4 2003/11/13 00:14:52 dillon Exp $ */ -/* $KAME: libpfkey.h,v 1.6 2001/03/05 18:22:17 thorpej Exp $ */ - -/* - * 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. - */ - -struct sadb_msg; -extern void pfkey_sadump (struct sadb_msg *); -extern void pfkey_spdump (struct sadb_msg *); - -struct sockaddr; -struct sadb_alg; -int ipsec_check_keylen (u_int, u_int, u_int); -int ipsec_check_keylen2 (u_int, u_int, u_int); -int ipsec_get_keylen (u_int, u_int, struct sadb_alg *); -u_int pfkey_set_softrate (u_int, u_int); -u_int pfkey_get_softrate (u_int); -int pfkey_send_getspi (int, u_int, u_int, struct sockaddr *, - struct sockaddr *, u_int32_t, u_int32_t, u_int32_t, u_int32_t); -int pfkey_send_update (int, u_int, u_int, struct sockaddr *, - struct sockaddr *, u_int32_t, u_int32_t, u_int, - caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t, - u_int64_t, u_int64_t, u_int32_t); -int pfkey_send_add (int, u_int, u_int, struct sockaddr *, - struct sockaddr *, u_int32_t, u_int32_t, u_int, - caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t, - u_int64_t, u_int64_t, u_int32_t); -int pfkey_send_delete (int, u_int, u_int, - struct sockaddr *, struct sockaddr *, u_int32_t); -int pfkey_send_delete_all (int, u_int, u_int, - struct sockaddr *, struct sockaddr *); -int pfkey_send_get (int, u_int, u_int, - struct sockaddr *, struct sockaddr *, u_int32_t); -int pfkey_send_register (int, u_int); -int pfkey_recv_register (int); -int pfkey_set_supported (struct sadb_msg *, int); -int pfkey_send_flush (int, u_int); -int pfkey_send_dump (int, u_int); -int pfkey_send_promisc_toggle (int, int); -int pfkey_send_spdadd (int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t); -int pfkey_send_spdadd2 (int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, - caddr_t, int, u_int32_t); -int pfkey_send_spdupdate (int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t); -int pfkey_send_spdupdate2 (int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, - caddr_t, int, u_int32_t); -int pfkey_send_spddelete (int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t); -int pfkey_send_spddelete2 (int, u_int32_t); -int pfkey_send_spdget (int, u_int32_t); -int pfkey_send_spdsetidx (int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t); -int pfkey_send_spdflush (int); -int pfkey_send_spddump (int); - -int pfkey_open (void); -void pfkey_close (int); -struct sadb_msg *pfkey_recv (int); -int pfkey_send (int, struct sadb_msg *, int); -int pfkey_align (struct sadb_msg *, caddr_t *); -int pfkey_check (caddr_t *); diff --git a/lib/libipsec/pfkey.c b/lib/libipsec/pfkey.c deleted file mode 100644 index 8baec1bc0e..0000000000 --- a/lib/libipsec/pfkey.c +++ /dev/null @@ -1,1986 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/pfkey.c,v 1.1.2.2 2001/07/03 11:01:14 ume Exp $ */ -/* $KAME: pfkey.c,v 1.39 2001/03/05 18:22:17 thorpej Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "ipsec_strerror.h" -#include "libpfkey.h" - -#define CALLOC(size, cast) (cast)calloc(1, (size)) - -static int findsupportedmap (int); -static int setsupportedmap (struct sadb_supported *); -static struct sadb_alg *findsupportedalg (u_int, u_int); -static int pfkey_send_x1 (int, u_int, u_int, u_int, struct sockaddr *, - struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t, - u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t, - u_int32_t, u_int32_t, u_int32_t); -static int pfkey_send_x2 (int, u_int, u_int, u_int, - struct sockaddr *, struct sockaddr *, u_int32_t); -static int pfkey_send_x3 (int, u_int, u_int); -static int pfkey_send_x4 (int, u_int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, - char *, int, u_int32_t); -static int pfkey_send_x5 (int, u_int, u_int32_t); - -static caddr_t pfkey_setsadbmsg (caddr_t, caddr_t, u_int, u_int, - u_int, u_int32_t, pid_t); -static caddr_t pfkey_setsadbsa (caddr_t, caddr_t, u_int32_t, u_int, - u_int, u_int, u_int32_t); -static caddr_t pfkey_setsadbaddr (caddr_t, caddr_t, u_int, - struct sockaddr *, u_int, u_int); -static caddr_t pfkey_setsadbkey (caddr_t, caddr_t, u_int, caddr_t, u_int); -static caddr_t pfkey_setsadblifetime (caddr_t, caddr_t, u_int, u_int32_t, - u_int32_t, u_int32_t, u_int32_t); -static caddr_t pfkey_setsadbxsa2 (caddr_t, caddr_t, u_int32_t, u_int32_t); - -/* - * make and search supported algorithm structure. - */ -static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, NULL}; - -static int supported_map[] = { - SADB_SATYPE_AH, - SADB_SATYPE_ESP, - SADB_X_SATYPE_IPCOMP, - SADB_X_SATYPE_TCPSIGNATURE, -}; - -static int -findsupportedmap(int satype) -{ - int i; - - for (i = 0; i < NELEM(supported_map); i++) - if (supported_map[i] == satype) - return i; - return -1; -} - -static struct sadb_alg * -findsupportedalg(u_int satype, u_int alg_id) -{ - int algno; - int tlen; - caddr_t p; - - /* validity check */ - algno = findsupportedmap(satype); - if (algno == -1) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return NULL; - } - if (ipsec_supported[algno] == NULL) { - __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST; - return NULL; - } - - tlen = ipsec_supported[algno]->sadb_supported_len - - sizeof(struct sadb_supported); - p = (caddr_t)(ipsec_supported[algno] + 1); - while (tlen > 0) { - if (tlen < sizeof(struct sadb_alg)) { - /* invalid format */ - break; - } - if (((struct sadb_alg *)p)->sadb_alg_id == alg_id) - return (struct sadb_alg *)p; - - tlen -= sizeof(struct sadb_alg); - p += sizeof(struct sadb_alg); - } - - __ipsec_errcode = EIPSEC_NOT_SUPPORTED; - return NULL; -} - -static int -setsupportedmap(struct sadb_supported *sup) -{ - struct sadb_supported **ipsup; - - switch (sup->sadb_supported_exttype) { - case SADB_EXT_SUPPORTED_AUTH: - ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)]; - break; - case SADB_EXT_SUPPORTED_ENCRYPT: - ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)]; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - if (*ipsup) - free(*ipsup); - - *ipsup = malloc(sup->sadb_supported_len); - if (!*ipsup) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - memcpy(*ipsup, sup, sup->sadb_supported_len); - - return 0; -} - -/* - * check key length against algorithm specified. - * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the - * augument, and only calls to ipsec_check_keylen2(); - * keylen is the unit of bit. - * OUT: - * -1: invalid. - * 0: valid. - */ -int -ipsec_check_keylen(u_int supported, u_int alg_id, u_int keylen) -{ - int satype; - - /* validity check */ - switch (supported) { - case SADB_EXT_SUPPORTED_AUTH: - satype = SADB_SATYPE_AH; - break; - case SADB_EXT_SUPPORTED_ENCRYPT: - satype = SADB_SATYPE_ESP; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - return ipsec_check_keylen2(satype, alg_id, keylen); -} - -/* - * check key length against algorithm specified. - * satype is one of satype defined at pfkeyv2.h. - * keylen is the unit of bit. - * OUT: - * -1: invalid. - * 0: valid. - */ -int -ipsec_check_keylen2(u_int satype, u_int alg_id, u_int keylen) -{ - struct sadb_alg *alg; - - alg = findsupportedalg(satype, alg_id); - if (!alg) - return -1; - - if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) { - __ipsec_errcode = EIPSEC_INVAL_KEYLEN; - return -1; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -/* - * get max/min key length against algorithm specified. - * satype is one of satype defined at pfkeyv2.h. - * keylen is the unit of bit. - * OUT: - * -1: invalid. - * 0: valid. - */ -int -ipsec_get_keylen(u_int supported, u_int alg_id, struct sadb_alg *alg0) -{ - struct sadb_alg *alg; - u_int satype; - - /* validity check */ - if (!alg0) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - switch (supported) { - case SADB_EXT_SUPPORTED_AUTH: - satype = SADB_SATYPE_AH; - break; - case SADB_EXT_SUPPORTED_ENCRYPT: - satype = SADB_SATYPE_ESP; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - alg = findsupportedalg(satype, alg_id); - if (!alg) - return -1; - - memcpy(alg0, alg, sizeof(*alg0)); - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -/* - * set the rate for SOFT lifetime against HARD one. - * If rate is more than 100 or equal to zero, then set to 100. - */ -static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE; -static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE; -static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE; -static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE; - -u_int -pfkey_set_softrate(u_int type, u_int rate) -{ - __ipsec_errcode = EIPSEC_NO_ERROR; - - if (rate > 100 || rate == 0) - rate = 100; - - switch (type) { - case SADB_X_LIFETIME_ALLOCATIONS: - soft_lifetime_allocations_rate = rate; - return 0; - case SADB_X_LIFETIME_BYTES: - soft_lifetime_bytes_rate = rate; - return 0; - case SADB_X_LIFETIME_ADDTIME: - soft_lifetime_addtime_rate = rate; - return 0; - case SADB_X_LIFETIME_USETIME: - soft_lifetime_usetime_rate = rate; - return 0; - } - - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return 1; -} - -/* - * get current rate for SOFT lifetime against HARD one. - * ATTENTION: ~0 is returned if invalid type was passed. - */ -u_int -pfkey_get_softrate(u_int type) -{ - switch (type) { - case SADB_X_LIFETIME_ALLOCATIONS: - return soft_lifetime_allocations_rate; - case SADB_X_LIFETIME_BYTES: - return soft_lifetime_bytes_rate; - case SADB_X_LIFETIME_ADDTIME: - return soft_lifetime_addtime_rate; - case SADB_X_LIFETIME_USETIME: - return soft_lifetime_usetime_rate; - } - - return ~0; -} - -/* - * sending SADB_GETSPI message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_getspi(int so, u_int satype, u_int mode, struct sockaddr *src, - struct sockaddr *dst, u_int32_t min, u_int32_t max, u_int32_t reqid, - u_int32_t seq) -{ - struct sadb_msg *newmsg; - caddr_t ep; - int len; - int need_spirange = 0; - caddr_t p; - int plen; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - if (min > max || (min > 0 && min <= 255)) { - __ipsec_errcode = EIPSEC_INVAL_SPI; - return -1; - } - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - /* create new sadb_msg to send. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_x_sa2) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(dst->sa_len); - - if (min > 255 && max < ~0) { - need_spirange++; - len += sizeof(struct sadb_spirange); - } - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_GETSPI, - len, satype, seq, getpid()); - if (!p) { - free(newmsg); - return -1; - } - - p = pfkey_setsadbxsa2(p, ep, mode, reqid); - if (!p) { - free(newmsg); - return -1; - } - - /* set sadb_address for source */ - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - - /* set sadb_address for destination */ - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - - /* proccessing spi range */ - if (need_spirange) { - struct sadb_spirange spirange; - - if (p + sizeof(spirange) > ep) { - free(newmsg); - return -1; - } - - memset(&spirange, 0, sizeof(spirange)); - spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange)); - spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; - spirange.sadb_spirange_min = min; - spirange.sadb_spirange_max = max; - - memcpy(p, &spirange, sizeof(spirange)); - - p += sizeof(spirange); - } - if (p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * sending SADB_UPDATE message to the kernel. - * The length of key material is a_keylen + e_keylen. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_update(int so, u_int satype, u_int mode, struct sockaddr *src, - struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize, - caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, u_int a_keylen, - u_int flags,u_int32_t l_alloc, u_int64_t l_bytes, u_int64_t l_addtime, - u_int64_t l_usetime, u_int32_t seq) -{ - int len; - if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi, - reqid, wsize, - keymat, e_type, e_keylen, a_type, a_keylen, flags, - l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_ADD message to the kernel. - * The length of key material is a_keylen + e_keylen. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_add(int so, u_int satype, u_int mode, struct sockaddr *src, - struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize, - caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, u_int a_keylen, - u_int flags, u_int32_t l_alloc, u_int64_t l_bytes, u_int64_t l_addtime, - u_int64_t l_usetime, u_int32_t seq) -{ - int len; - if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi, - reqid, wsize, - keymat, e_type, e_keylen, a_type, a_keylen, flags, - l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_DELETE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_delete(int so, u_int satype, u_int mode, struct sockaddr *src, - struct sockaddr *dst, u_int32_t spi) -{ - int len; - if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_DELETE without spi to the kernel. This is - * the "delete all" request (an extension also present in - * Solaris). - * - * OUT: - * positive: success and return length sent - * -1 : error occured, and set errno - */ -int -pfkey_send_delete_all(int so, u_int satype, u_int mode, struct sockaddr *src, - struct sockaddr *dst) -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - int plen; - caddr_t ep; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(dst->sa_len); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_DELETE, len, satype, 0, - getpid()); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, - IPSEC_ULPROTO_ANY); - if (!p || p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * sending SADB_GET message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_get(int so, u_int satype, u_int mode, struct sockaddr *src, - struct sockaddr *dst, u_int32_t spi) -{ - int len; - if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_REGISTER message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_register(int so, u_int satype) -{ - int len, algno; - - if (satype == PF_UNSPEC) { - for (algno = 0; algno < NELEM(supported_map); algno++) { - if (ipsec_supported[algno]) { - free(ipsec_supported[algno]); - ipsec_supported[algno] = NULL; - } - } - } else { - algno = findsupportedmap(satype); - if (algno == -1) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - if (ipsec_supported[algno]) { - free(ipsec_supported[algno]); - ipsec_supported[algno] = NULL; - } - } - - if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0) - return -1; - - return len; -} - -/* - * receiving SADB_REGISTER message from the kernel, and copy buffer for - * sadb_supported returned into ipsec_supported. - * OUT: - * 0: success and return length sent. - * -1: error occured, and set errno. - */ -int -pfkey_recv_register(int so) -{ - pid_t pid = getpid(); - struct sadb_msg *newmsg; - int error = -1; - - /* receive message */ - do { - if ((newmsg = pfkey_recv(so)) == NULL) - return -1; - } while (newmsg->sadb_msg_type != SADB_REGISTER - || newmsg->sadb_msg_pid != pid); - - /* check and fix */ - newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len); - - error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len); - free(newmsg); - - if (error == 0) - __ipsec_errcode = EIPSEC_NO_ERROR; - - return error; -} - -/* - * receiving SADB_REGISTER message from the kernel, and copy buffer for - * sadb_supported returned into ipsec_supported. - * NOTE: sadb_msg_len must be host order. - * IN: - * tlen: msg length, it's to makeing sure. - * OUT: - * 0: success and return length sent. - * -1: error occured, and set errno. - */ -int -pfkey_set_supported(struct sadb_msg *msg, int tlen) -{ - struct sadb_supported *sup; - caddr_t p; - caddr_t ep; - - /* validity */ - if (msg->sadb_msg_len != tlen) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - p = (caddr_t)msg; - ep = p + tlen; - - p += sizeof(struct sadb_msg); - - while (p < ep) { - sup = (struct sadb_supported *)p; - if (ep < p + sizeof(*sup) || - PFKEY_EXTLEN(sup) < sizeof(*sup) || - ep < p + sup->sadb_supported_len) { - /* invalid format */ - break; - } - - switch (sup->sadb_supported_exttype) { - case SADB_EXT_SUPPORTED_AUTH: - case SADB_EXT_SUPPORTED_ENCRYPT: - break; - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - /* fixed length */ - sup->sadb_supported_len = PFKEY_EXTLEN(sup); - - /* set supported map */ - if (setsupportedmap(sup) != 0) - return -1; - - p += sup->sadb_supported_len; - } - - if (p != ep) { - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - - return 0; -} - -/* - * sending SADB_FLUSH message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_flush(int so, u_int satype) -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_DUMP message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_dump(int so, u_int satype) -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_PROMISC message to the kernel. - * NOTE that this function handles promisc mode toggle only. - * IN: - * flag: set promisc off if zero, set promisc on if non-zero. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - * 0 : error occured, and set errno. - * others: a pointer to new allocated buffer in which supported - * algorithms is. - */ -int -pfkey_send_promisc_toggle(int so, int flag) -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDADD message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdadd(int so, struct sockaddr *src, u_int prefs, - struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, - int policylen, u_int32_t seq) -{ - int len; - - if ((len = pfkey_send_x4(so, SADB_X_SPDADD, - src, prefs, dst, prefd, proto, - 0, 0, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDADD message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdadd2(int so, struct sockaddr *src, u_int prefs, - struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime, - u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq) -{ - int len; - - if ((len = pfkey_send_x4(so, SADB_X_SPDADD, - src, prefs, dst, prefd, proto, - ltime, vtime, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDUPDATE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdupdate(int so, struct sockaddr *src, u_int prefs, - struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, - int policylen, u_int32_t seq) -{ - int len; - - if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, - src, prefs, dst, prefd, proto, - 0, 0, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDUPDATE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdupdate2(int so, struct sockaddr *src, u_int prefs, - struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime, - u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq) -{ - int len; - - if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, - src, prefs, dst, prefd, proto, - ltime, vtime, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDDELETE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spddelete(int so, struct sockaddr *src, u_int prefs, - struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, - int policylen, u_int32_t seq) -{ - int len; - - if (policylen != sizeof(struct sadb_x_policy)) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE, - src, prefs, dst, prefd, proto, - 0, 0, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDDELETE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spddelete2(int so, u_int32_t spid) -{ - int len; - - if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDGET message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdget(int so, u_int32_t spid) -{ - int len; - - if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDSETIDX message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdsetidx(int so, struct sockaddr *src, u_int prefs, - struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, - int policylen, u_int32_t seq) -{ - int len; - - if (policylen != sizeof(struct sadb_x_policy)) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX, - src, prefs, dst, prefd, proto, - 0, 0, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_SPDFLUSH message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdflush(int so) -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_SPDDUMP message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spddump(int so) -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0) - return -1; - - return len; -} - -/* sending SADB_ADD or SADB_UPDATE message to the kernel */ -static int -pfkey_send_x1(int so, u_int type, u_int satype, u_int mode, - struct sockaddr *src, struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, - u_int wsize, caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, - u_int a_keylen, u_int flags,u_int32_t l_alloc, u_int32_t l_bytes, - u_int32_t l_addtime, u_int32_t l_usetime, u_int32_t seq) -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - int plen; - caddr_t ep; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - switch (satype) { - case SADB_SATYPE_ESP: - if (e_type == SADB_EALG_NONE) { - __ipsec_errcode = EIPSEC_NO_ALGS; - return -1; - } - break; - case SADB_SATYPE_AH: - if (e_type != SADB_EALG_NONE) { - __ipsec_errcode = EIPSEC_INVAL_ALGS; - return -1; - } - if (a_type == SADB_AALG_NONE) { - __ipsec_errcode = EIPSEC_NO_ALGS; - return -1; - } - break; - case SADB_X_SATYPE_IPCOMP: - if (e_type == SADB_X_CALG_NONE) { - __ipsec_errcode = EIPSEC_INVAL_ALGS; - return -1; - } - if (a_type != SADB_AALG_NONE) { - __ipsec_errcode = EIPSEC_NO_ALGS; - return -1; - } - break; - case SADB_X_SATYPE_TCPSIGNATURE: - if (e_type != SADB_EALG_NONE) { - __ipsec_errcode = EIPSEC_INVAL_ALGS; - return -1; - } - if (a_type != SADB_X_AALG_TCP_MD5) { - __ipsec_errcode = EIPSEC_INVAL_ALGS; - return -1; - } - break; - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_sa) - + sizeof(struct sadb_x_sa2) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(dst->sa_len) - + sizeof(struct sadb_lifetime) - + sizeof(struct sadb_lifetime); - - if (e_type != SADB_EALG_NONE) - len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen)); - if (a_type != SADB_AALG_NONE) - len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen)); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, - satype, seq, getpid()); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbxsa2(p, ep, mode, reqid); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - - if (e_type != SADB_EALG_NONE) { - p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT, - keymat, e_keylen); - if (!p) { - free(newmsg); - return -1; - } - } - if (a_type != SADB_AALG_NONE) { - p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH, - keymat + e_keylen, a_keylen); - if (!p) { - free(newmsg); - return -1; - } - } - - /* set sadb_lifetime for destination */ - p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, - l_alloc, l_bytes, l_addtime, l_usetime); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT, - l_alloc, l_bytes, l_addtime, l_usetime); - if (!p || p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* sending SADB_DELETE or SADB_GET message to the kernel */ -static int -pfkey_send_x2(int so, u_int type, u_int satype, u_int mode, - struct sockaddr *src, struct sockaddr *dst, u_int32_t spi) -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - int plen; - caddr_t ep; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_sa) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(dst->sa_len); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, - getpid()); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, - IPSEC_ULPROTO_ANY); - if (!p || p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message - * to the kernel - */ -static int -pfkey_send_x3(int so, u_int type, u_int satype) -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - caddr_t ep; - - /* validity check */ - switch (type) { - case SADB_X_PROMISC: - if (satype != 0 && satype != 1) { - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - break; - default: - switch (satype) { - case SADB_SATYPE_UNSPEC: - case SADB_SATYPE_AH: - case SADB_SATYPE_ESP: - case SADB_X_SATYPE_IPCOMP: - case SADB_X_SATYPE_TCPSIGNATURE: - break; - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - } - - /* create new sadb_msg to send. */ - len = sizeof(struct sadb_msg); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, - getpid()); - if (!p || p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* sending SADB_X_SPDADD message to the kernel */ -static int -pfkey_send_x4(int so, u_int type, struct sockaddr *src, u_int prefs, - struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime, - u_int64_t vtime, char *policy, int policylen, u_int32_t seq) -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - int plen; - caddr_t ep; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - if (prefs > plen || prefd > plen) { - __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN; - return -1; - } - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_lifetime) - + policylen; - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, - SADB_SATYPE_UNSPEC, seq, getpid()); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, - 0, 0, ltime, vtime); - if (!p || p + policylen != ep) { - free(newmsg); - return -1; - } - memcpy(p, policy, policylen); - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */ -static int -pfkey_send_x5(int so, u_int type, u_int32_t spid) -{ - struct sadb_msg *newmsg; - struct sadb_x_policy xpl; - int len; - caddr_t p; - caddr_t ep; - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(xpl); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, - SADB_SATYPE_UNSPEC, 0, getpid()); - if (!p) { - free(newmsg); - return -1; - } - - if (p + sizeof(xpl) != ep) { - free(newmsg); - return -1; - } - memset(&xpl, 0, sizeof(xpl)); - xpl.sadb_x_policy_len = PFKEY_UNUNIT64(sizeof(xpl)); - xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY; - xpl.sadb_x_policy_id = spid; - memcpy(p, &xpl, sizeof(xpl)); - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * open a socket. - * OUT: - * -1: fail. - * others : success and return value of socket. - */ -int -pfkey_open(void) -{ - int so; - const int bufsiz = 128 * 1024; /*is 128K enough?*/ - - if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - - /* - * This is a temporary workaround for KAME PR 154. - * Don't really care even if it fails. - */ - (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)); - (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)); - - __ipsec_errcode = EIPSEC_NO_ERROR; - return so; -} - -/* - * close a socket. - * OUT: - * 0: success. - * -1: fail. - */ -void -pfkey_close(int so) -{ - (void)close(so); - - __ipsec_errcode = EIPSEC_NO_ERROR; - return; -} - -/* - * receive sadb_msg data, and return pointer to new buffer allocated. - * Must free this buffer later. - * OUT: - * NULL : error occured. - * others : a pointer to sadb_msg structure. - * - * XXX should be rewritten to pass length explicitly - */ -struct sadb_msg * -pfkey_recv(int so) -{ - struct sadb_msg buf, *newmsg; - int len, reallen; - - while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) { - if (errno == EINTR) - continue; - __ipsec_set_strerror(strerror(errno)); - return NULL; - } - - if (len < sizeof(buf)) { - recv(so, (caddr_t)&buf, sizeof(buf), 0); - __ipsec_errcode = EIPSEC_MAX; - return NULL; - } - - /* read real message */ - reallen = PFKEY_UNUNIT64(buf.sadb_msg_len); - if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return NULL; - } - - while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) { - if (errno == EINTR) - continue; - __ipsec_set_strerror(strerror(errno)); - free(newmsg); - return NULL; - } - - if (len != reallen) { - __ipsec_errcode = EIPSEC_SYSTEM_ERROR; - free(newmsg); - return NULL; - } - - /* don't trust what the kernel says, validate! */ - if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) { - __ipsec_errcode = EIPSEC_SYSTEM_ERROR; - free(newmsg); - return NULL; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return newmsg; -} - -/* - * send message to a socket. - * OUT: - * others: success and return length sent. - * -1 : fail. - */ -int -pfkey_send(int so, struct sadb_msg *msg, int len) -{ - if ((len = send(so, (caddr_t)msg, len, 0)) < 0) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * %%% Utilities - * NOTE: These functions are derived from netkey/key.c in KAME. - */ -/* - * set the pointer to each header in this message buffer. - * IN: msg: pointer to message buffer. - * mhp: pointer to the buffer initialized like below: - * caddr_t mhp[SADB_EXT_MAX + 1]; - * OUT: -1: invalid. - * 0: valid. - * - * XXX should be rewritten to obtain length explicitly - */ -int -pfkey_align(struct sadb_msg *msg, caddr_t *mhp) -{ - struct sadb_ext *ext; - int i; - caddr_t p; - caddr_t ep; /* XXX should be passed from upper layer */ - - /* validity check */ - if (msg == NULL || mhp == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - /* initialize */ - for (i = 0; i < SADB_EXT_MAX + 1; i++) - mhp[i] = NULL; - - mhp[0] = (caddr_t)msg; - - /* initialize */ - p = (caddr_t) msg; - ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len); - - /* skip base header */ - p += sizeof(struct sadb_msg); - - while (p < ep) { - ext = (struct sadb_ext *)p; - if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) || - ep < p + PFKEY_EXTLEN(ext)) { - /* invalid format */ - break; - } - - /* duplicate check */ - /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/ - if (mhp[ext->sadb_ext_type] != NULL) { - __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; - return -1; - } - - /* set pointer */ - switch (ext->sadb_ext_type) { - case SADB_EXT_SA: - case SADB_EXT_LIFETIME_CURRENT: - case SADB_EXT_LIFETIME_HARD: - case SADB_EXT_LIFETIME_SOFT: - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - case SADB_EXT_KEY_AUTH: - /* XXX should to be check weak keys. */ - case SADB_EXT_KEY_ENCRYPT: - /* XXX should to be check weak keys. */ - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - case SADB_EXT_SENSITIVITY: - case SADB_EXT_PROPOSAL: - case SADB_EXT_SUPPORTED_AUTH: - case SADB_EXT_SUPPORTED_ENCRYPT: - case SADB_EXT_SPIRANGE: - case SADB_X_EXT_POLICY: - case SADB_X_EXT_SA2: - mhp[ext->sadb_ext_type] = (caddr_t)ext; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; - return -1; - } - - p += PFKEY_EXTLEN(ext); - } - - if (p != ep) { - __ipsec_errcode = EIPSEC_INVAL_SADBMSG; - return -1; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -/* - * check basic usage for sadb_msg, - * NOTE: This routine is derived from netkey/key.c in KAME. - * IN: msg: pointer to message buffer. - * mhp: pointer to the buffer initialized like below: - * - * caddr_t mhp[SADB_EXT_MAX + 1]; - * - * OUT: -1: invalid. - * 0: valid. - */ -int -pfkey_check(caddr_t *mhp) -{ - struct sadb_msg *msg; - - /* validity check */ - if (mhp == NULL || mhp[0] == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - msg = (struct sadb_msg *)mhp[0]; - - /* check version */ - if (msg->sadb_msg_version != PF_KEY_V2) { - __ipsec_errcode = EIPSEC_INVAL_VERSION; - return -1; - } - - /* check type */ - if (msg->sadb_msg_type > SADB_MAX) { - __ipsec_errcode = EIPSEC_INVAL_MSGTYPE; - return -1; - } - - /* check SA type */ - switch (msg->sadb_msg_satype) { - case SADB_SATYPE_UNSPEC: - switch (msg->sadb_msg_type) { - case SADB_GETSPI: - case SADB_UPDATE: - case SADB_ADD: - case SADB_DELETE: - case SADB_GET: - case SADB_ACQUIRE: - case SADB_EXPIRE: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - break; - case SADB_SATYPE_ESP: - case SADB_SATYPE_AH: - case SADB_X_SATYPE_IPCOMP: - case SADB_X_SATYPE_TCPSIGNATURE: - switch (msg->sadb_msg_type) { - case SADB_X_SPDADD: - case SADB_X_SPDDELETE: - case SADB_X_SPDGET: - case SADB_X_SPDDUMP: - case SADB_X_SPDFLUSH: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - break; - case SADB_SATYPE_RSVP: - case SADB_SATYPE_OSPFV2: - case SADB_SATYPE_RIPV2: - case SADB_SATYPE_MIP: - __ipsec_errcode = EIPSEC_NOT_SUPPORTED; - return -1; - case 1: /* XXX: What does it do ? */ - if (msg->sadb_msg_type == SADB_X_PROMISC) - break; - /*FALLTHROUGH*/ - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - /* check field of upper layer protocol and address family */ - if (mhp[SADB_EXT_ADDRESS_SRC] != NULL - && mhp[SADB_EXT_ADDRESS_DST] != NULL) { - struct sadb_address *src0, *dst0; - - src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]); - - if (src0->sadb_address_proto != dst0->sadb_address_proto) { - __ipsec_errcode = EIPSEC_PROTO_MISMATCH; - return -1; - } - - if (PFKEY_ADDR_SADDR(src0)->sa_family - != PFKEY_ADDR_SADDR(dst0)->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - - switch (PFKEY_ADDR_SADDR(src0)->sa_family) { - case AF_INET: - case AF_INET6: - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - /* - * prefixlen == 0 is valid because there must be the case - * all addresses are matched. - */ - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -/* - * set data into sadb_msg. - * `buf' must has been allocated sufficiently. - */ -static caddr_t -pfkey_setsadbmsg(caddr_t buf, caddr_t lim, u_int type, u_int tlen, - u_int satype, u_int32_t seq, pid_t pid) -{ - struct sadb_msg *p; - u_int len; - - p = (struct sadb_msg *)buf; - len = sizeof(struct sadb_msg); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_msg_version = PF_KEY_V2; - p->sadb_msg_type = type; - p->sadb_msg_errno = 0; - p->sadb_msg_satype = satype; - p->sadb_msg_len = PFKEY_UNIT64(tlen); - p->sadb_msg_reserved = 0; - p->sadb_msg_seq = seq; - p->sadb_msg_pid = (u_int32_t)pid; - - return(buf + len); -} - -/* - * copy secasvar data into sadb_address. - * `buf' must has been allocated sufficiently. - */ -static caddr_t -pfkey_setsadbsa(caddr_t buf, caddr_t lim, u_int32_t spi, u_int wsize, - u_int auth, u_int enc, u_int32_t flags) -{ - struct sadb_sa *p; - u_int len; - - p = (struct sadb_sa *)buf; - len = sizeof(struct sadb_sa); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_sa_len = PFKEY_UNIT64(len); - p->sadb_sa_exttype = SADB_EXT_SA; - p->sadb_sa_spi = spi; - p->sadb_sa_replay = wsize; - p->sadb_sa_state = SADB_SASTATE_LARVAL; - p->sadb_sa_auth = auth; - p->sadb_sa_encrypt = enc; - p->sadb_sa_flags = flags; - - return(buf + len); -} - -/* - * set data into sadb_address. - * `buf' must has been allocated sufficiently. - * prefixlen is in bits. - */ -static caddr_t -pfkey_setsadbaddr(caddr_t buf, caddr_t lim, u_int exttype, - struct sockaddr *saddr, u_int prefixlen, u_int ul_proto) -{ - struct sadb_address *p; - u_int len; - - p = (struct sadb_address *)buf; - len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_address_len = PFKEY_UNIT64(len); - p->sadb_address_exttype = exttype & 0xffff; - p->sadb_address_proto = ul_proto & 0xff; - p->sadb_address_prefixlen = prefixlen; - p->sadb_address_reserved = 0; - - memcpy(p + 1, saddr, saddr->sa_len); - - return(buf + len); -} - -/* - * set sadb_key structure after clearing buffer with zero. - * OUT: the pointer of buf + len. - */ -static caddr_t -pfkey_setsadbkey(caddr_t buf, caddr_t lim, u_int type, caddr_t key, - u_int keylen) -{ - struct sadb_key *p; - u_int len; - - p = (struct sadb_key *)buf; - len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_key_len = PFKEY_UNIT64(len); - p->sadb_key_exttype = type; - p->sadb_key_bits = keylen << 3; - p->sadb_key_reserved = 0; - - memcpy(p + 1, key, keylen); - - return buf + len; -} - -/* - * set sadb_lifetime structure after clearing buffer with zero. - * OUT: the pointer of buf + len. - */ -static caddr_t -pfkey_setsadblifetime(caddr_t buf, caddr_t lim, u_int type, u_int32_t l_alloc, - u_int32_t l_bytes, u_int32_t l_addtime, u_int32_t l_usetime) -{ - struct sadb_lifetime *p; - u_int len; - - p = (struct sadb_lifetime *)buf; - len = sizeof(struct sadb_lifetime); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_lifetime_len = PFKEY_UNIT64(len); - p->sadb_lifetime_exttype = type; - - switch (type) { - case SADB_EXT_LIFETIME_SOFT: - p->sadb_lifetime_allocations - = (l_alloc * soft_lifetime_allocations_rate) /100; - p->sadb_lifetime_bytes - = (l_bytes * soft_lifetime_bytes_rate) /100; - p->sadb_lifetime_addtime - = (l_addtime * soft_lifetime_addtime_rate) /100; - p->sadb_lifetime_usetime - = (l_usetime * soft_lifetime_usetime_rate) /100; - break; - case SADB_EXT_LIFETIME_HARD: - p->sadb_lifetime_allocations = l_alloc; - p->sadb_lifetime_bytes = l_bytes; - p->sadb_lifetime_addtime = l_addtime; - p->sadb_lifetime_usetime = l_usetime; - break; - } - - return buf + len; -} - -/* - * copy secasvar data into sadb_address. - * `buf' must has been allocated sufficiently. - */ -static caddr_t -pfkey_setsadbxsa2(caddr_t buf, caddr_t lim, u_int32_t mode0, u_int32_t reqid) -{ - struct sadb_x_sa2 *p; - u_int8_t mode = mode0 & 0xff; - u_int len; - - p = (struct sadb_x_sa2 *)buf; - len = sizeof(struct sadb_x_sa2); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_x_sa2_len = PFKEY_UNIT64(len); - p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; - p->sadb_x_sa2_mode = mode; - p->sadb_x_sa2_reqid = reqid; - - return(buf + len); -} diff --git a/lib/libipsec/pfkey_dump.c b/lib/libipsec/pfkey_dump.c deleted file mode 100644 index 326617d5f4..0000000000 --- a/lib/libipsec/pfkey_dump.c +++ /dev/null @@ -1,587 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/pfkey_dump.c,v 1.1.2.4 2003/04/27 00:03:36 sumikawa Exp $ */ -/* $KAME: pfkey_dump.c,v 1.28 2001/06/27 10:46:51 sakane Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "ipsec_strerror.h" -#include "libpfkey.h" - -/* cope with old kame headers - ugly */ -#ifndef SADB_X_AALG_MD5 -#define SADB_X_AALG_MD5 SADB_AALG_MD5 -#endif -#ifndef SADB_X_AALG_SHA -#define SADB_X_AALG_SHA SADB_AALG_SHA -#endif -#ifndef SADB_X_AALG_NULL -#define SADB_X_AALG_NULL SADB_AALG_NULL -#endif - -#ifndef SADB_X_EALG_BLOWFISHCBC -#define SADB_X_EALG_BLOWFISHCBC SADB_EALG_BLOWFISHCBC -#endif -#ifndef SADB_X_EALG_CAST128CBC -#define SADB_X_EALG_CAST128CBC SADB_EALG_CAST128CBC -#endif -#ifndef SADB_X_EALG_RC5CBC -#ifdef SADB_EALG_RC5CBC -#define SADB_X_EALG_RC5CBC SADB_EALG_RC5CBC -#endif -#endif - -#define GETMSGSTR(str, num) \ -do { \ - if (sizeof((str)[0]) == 0 \ - || num >= sizeof(str)/sizeof((str)[0])) \ - printf("%d ", (num)); \ - else if (strlen((str)[(num)]) == 0) \ - printf("%d ", (num)); \ - else \ - printf("%s ", (str)[(num)]); \ -} while (0) - -#define GETMSGV2S(v2s, num) \ -do { \ - struct val2str *p; \ - for (p = (v2s); p && p->str; p++) { \ - if (p->val == (num)) \ - break; \ - } \ - if (p && p->str) \ - printf("%s ", p->str); \ - else \ - printf("%d ", (num)); \ -} while (0) - -static char *str_ipaddr (struct sockaddr *); -static char *str_prefport (u_int, u_int, u_int); -static char *str_time (time_t); -static void str_lifetime_byte (struct sadb_lifetime *, char *); - -struct val2str { - int val; - const char *str; -}; - -/* - * Must to be re-written about following strings. - */ -static char *str_satype[] = { - "unspec", - "unknown", - "ah", - "esp", - "unknown", - "rsvp", - "ospfv2", - "ripv2", - "mip", - "ipcomp", - "policy", - "tcp", -}; - -static char *str_mode[] = { - "any", - "transport", - "tunnel", -}; - -static char *str_upper[] = { -/*0*/ "ip", "icmp", "igmp", "ggp", "ip4", - "", "tcp", "", "egp", "", -/*10*/ "", "", "", "", "", - "", "", "udp", "", "", -/*20*/ "", "", "idp", "", "", - "", "", "", "", "tp", -/*30*/ "", "", "", "", "", - "", "", "", "", "", -/*40*/ "", "ip6", "", "rt6", "frag6", - "", "rsvp", "gre", "", "", -/*50*/ "esp", "ah", "", "", "", - "", "", "", "icmp6", "none", -/*60*/ "dst6", -}; - -static char *str_state[] = { - "larval", - "mature", - "dying", - "dead", -}; - -static struct val2str str_alg_auth[] = { - { SADB_AALG_NONE, "none", }, - { SADB_AALG_MD5HMAC, "hmac-md5", }, - { SADB_AALG_SHA1HMAC, "hmac-sha1", }, - { SADB_X_AALG_MD5, "md5", }, - { SADB_X_AALG_SHA, "sha", }, - { SADB_X_AALG_NULL, "null", }, - { SADB_X_AALG_TCP_MD5, "tcp-md5", }, -#ifdef SADB_X_AALG_SHA2_256 - { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, -#endif -#ifdef SADB_X_AALG_SHA2_384 - { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, -#endif -#ifdef SADB_X_AALG_SHA2_512 - { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, -#endif - { -1, NULL, }, -}; - -static struct val2str str_alg_enc[] = { - { SADB_EALG_NONE, "none", }, - { SADB_EALG_DESCBC, "des-cbc", }, - { SADB_EALG_3DESCBC, "3des-cbc", }, - { SADB_EALG_NULL, "null", }, -#ifdef SADB_X_EALG_RC5CBC - { SADB_X_EALG_RC5CBC, "rc5-cbc", }, -#endif - { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, - { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, -#ifdef SADB_X_EALG_RIJNDAELCBC - { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, -#endif -#ifdef SADB_X_EALG_TWOFISHCBC - { SADB_X_EALG_TWOFISHCBC, "twofish-cbc", }, -#endif - { -1, NULL, }, -}; - -static struct val2str str_alg_comp[] = { - { SADB_X_CALG_NONE, "none", }, - { SADB_X_CALG_OUI, "oui", }, - { SADB_X_CALG_DEFLATE, "deflate", }, - { SADB_X_CALG_LZS, "lzs", }, - { -1, NULL, }, -}; - -/* - * dump SADB_MSG formated. For debugging, you should use kdebug_sadb(). - */ -void -pfkey_sadump(struct sadb_msg *m) -{ - caddr_t mhp[SADB_EXT_MAX + 1]; - struct sadb_sa *m_sa; - struct sadb_x_sa2 *m_sa2; - struct sadb_lifetime *m_lftc, *m_lfth, *m_lfts; - struct sadb_address *m_saddr, *m_daddr; - struct sadb_key *m_auth, *m_enc; - - /* check pfkey message. */ - if (pfkey_align(m, mhp)) { - printf("%s\n", ipsec_strerror()); - return; - } - if (pfkey_check(mhp)) { - printf("%s\n", ipsec_strerror()); - return; - } - - m_sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; - m_sa2 = (struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2]; - m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; - m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; - m_lfts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; - m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; - m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; - m_auth = (struct sadb_key *)mhp[SADB_EXT_KEY_AUTH]; - m_enc = (struct sadb_key *)mhp[SADB_EXT_KEY_ENCRYPT]; - - /* source address */ - if (m_saddr == NULL) { - printf("no ADDRESS_SRC extension.\n"); - return; - } - printf("%s ", str_ipaddr((struct sockaddr *)(m_saddr + 1))); - - /* destination address */ - if (m_daddr == NULL) { - printf("no ADDRESS_DST extension.\n"); - return; - } - printf("%s ", str_ipaddr((struct sockaddr *)(m_daddr + 1))); - - /* SA type */ - if (m_sa == NULL) { - printf("no SA extension.\n"); - return; - } - if (m_sa2 == NULL) { - printf("no SA2 extension.\n"); - return; - } - printf("\n\t"); - - GETMSGSTR(str_satype, m->sadb_msg_satype); - - printf("mode="); - GETMSGSTR(str_mode, m_sa2->sadb_x_sa2_mode); - - printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n", - (u_int32_t)ntohl(m_sa->sadb_sa_spi), - (u_int32_t)ntohl(m_sa->sadb_sa_spi), - (u_int32_t)m_sa2->sadb_x_sa2_reqid, - (u_int32_t)m_sa2->sadb_x_sa2_reqid); - - /* encryption key */ - if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) { - printf("\tC: "); - GETMSGV2S(str_alg_comp, m_sa->sadb_sa_encrypt); - } else if (m->sadb_msg_satype == SADB_SATYPE_ESP) { - if (m_enc != NULL) { - printf("\tE: "); - GETMSGV2S(str_alg_enc, m_sa->sadb_sa_encrypt); - ipsec_hexdump((caddr_t)m_enc + sizeof(*m_enc), - m_enc->sadb_key_bits / 8); - printf("\n"); - } - } - - /* authentication key */ - if (m_auth != NULL) { - printf("\tA: "); - GETMSGV2S(str_alg_auth, m_sa->sadb_sa_auth); - ipsec_hexdump((caddr_t)m_auth + sizeof(*m_auth), - m_auth->sadb_key_bits / 8); - printf("\n"); - } - - /* replay windoe size & flags */ - printf("\tseq=0x%08x replay=%u flags=0x%08x ", - m_sa2->sadb_x_sa2_sequence, - m_sa->sadb_sa_replay, - m_sa->sadb_sa_flags); - - /* state */ - printf("state="); - GETMSGSTR(str_state, m_sa->sadb_sa_state); - printf("\n"); - - /* lifetime */ - if (m_lftc != NULL) { - time_t tmp_time = time(0); - - printf("\tcreated: %s", - str_time(m_lftc->sadb_lifetime_addtime)); - printf("\tcurrent: %s\n", str_time(tmp_time)); - printf("\tdiff: %lu(s)", - (u_long)(m_lftc->sadb_lifetime_addtime == 0 ? - 0 : (tmp_time - m_lftc->sadb_lifetime_addtime))); - - printf("\thard: %lu(s)", - (u_long)(m_lfth == NULL ? - 0 : m_lfth->sadb_lifetime_addtime)); - printf("\tsoft: %lu(s)\n", - (u_long)(m_lfts == NULL ? - 0 : m_lfts->sadb_lifetime_addtime)); - - printf("\tlast: %s", - str_time(m_lftc->sadb_lifetime_usetime)); - printf("\thard: %lu(s)", - (u_long)(m_lfth == NULL ? - 0 : m_lfth->sadb_lifetime_usetime)); - printf("\tsoft: %lu(s)\n", - (u_long)(m_lfts == NULL ? - 0 : m_lfts->sadb_lifetime_usetime)); - - str_lifetime_byte(m_lftc, "current"); - str_lifetime_byte(m_lfth, "hard"); - str_lifetime_byte(m_lfts, "soft"); - printf("\n"); - - printf("\tallocated: %lu", - (unsigned long)m_lftc->sadb_lifetime_allocations); - printf("\thard: %lu", - (u_long)(m_lfth == NULL ? - 0 : m_lfth->sadb_lifetime_allocations)); - printf("\tsoft: %lu\n", - (u_long)(m_lfts == NULL ? - 0 : m_lfts->sadb_lifetime_allocations)); - } - - printf("\tsadb_seq=%lu pid=%lu ", - (u_long)m->sadb_msg_seq, - (u_long)m->sadb_msg_pid); - - /* XXX DEBUG */ - printf("refcnt=%u\n", m->sadb_msg_reserved); - - return; -} - -void -pfkey_spdump(struct sadb_msg *m) -{ - char pbuf[NI_MAXSERV]; - caddr_t mhp[SADB_EXT_MAX + 1]; - struct sadb_address *m_saddr, *m_daddr; - struct sadb_x_policy *m_xpl; - struct sadb_lifetime *m_lft = NULL; - struct sockaddr *sa; - u_int16_t port; - - /* check pfkey message. */ - if (pfkey_align(m, mhp)) { - printf("%s\n", ipsec_strerror()); - return; - } - if (pfkey_check(mhp)) { - printf("%s\n", ipsec_strerror()); - return; - } - - m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; - m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; - m_xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; - m_lft = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; - - /* source address */ - if (m_saddr == NULL) { - printf("no ADDRESS_SRC extension.\n"); - return; - } - sa = (struct sockaddr *)(m_saddr + 1); - switch (sa->sa_family) { - case AF_INET: - case AF_INET6: - if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf), - NI_NUMERICSERV) != 0) - port = 0; /*XXX*/ - else - port = atoi(pbuf); - printf("%s%s ", str_ipaddr(sa), - str_prefport(sa->sa_family, - m_saddr->sadb_address_prefixlen, port)); - break; - default: - printf("unknown-af "); - break; - } - - /* destination address */ - if (m_daddr == NULL) { - printf("no ADDRESS_DST extension.\n"); - return; - } - sa = (struct sockaddr *)(m_daddr + 1); - switch (sa->sa_family) { - case AF_INET: - case AF_INET6: - if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf), - NI_NUMERICSERV) != 0) - port = 0; /*XXX*/ - else - port = atoi(pbuf); - printf("%s%s ", str_ipaddr(sa), - str_prefport(sa->sa_family, - m_daddr->sadb_address_prefixlen, port)); - break; - default: - printf("unknown-af "); - break; - } - - /* upper layer protocol */ - if (m_saddr->sadb_address_proto != m_daddr->sadb_address_proto) { - printf("upper layer protocol mismatched.\n"); - return; - } - if (m_saddr->sadb_address_proto == IPSEC_ULPROTO_ANY) - printf("any"); - else - GETMSGSTR(str_upper, m_saddr->sadb_address_proto); - - /* policy */ - { - char *d_xpl; - - if (m_xpl == NULL) { - printf("no X_POLICY extension.\n"); - return; - } - d_xpl = ipsec_dump_policy((char *)m_xpl, "\n\t"); - - /* dump SPD */ - printf("\n\t%s\n", d_xpl); - free(d_xpl); - } - - /* lifetime */ - if (m_lft) { - printf("\tlifetime:%lu validtime:%lu\n", - (u_long)m_lft->sadb_lifetime_addtime, - (u_long)m_lft->sadb_lifetime_usetime); - } - - printf("\tspid=%ld seq=%ld pid=%ld\n", - (u_long)m_xpl->sadb_x_policy_id, - (u_long)m->sadb_msg_seq, - (u_long)m->sadb_msg_pid); - - /* XXX TEST */ - printf("\trefcnt=%u\n", m->sadb_msg_reserved); - - return; -} - -/* - * set "ipaddress" to buffer. - */ -static char * -str_ipaddr(struct sockaddr *sa) -{ - static char buf[NI_MAXHOST]; -#ifdef NI_WITHSCOPEID - const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; -#else - const int niflag = NI_NUMERICHOST; -#endif - - if (sa == NULL) - return ""; - - if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, niflag) == 0) - return buf; - return NULL; -} - -/* - * set "/prefix[port number]" to buffer. - */ -static char * -str_prefport(u_int family, u_int pref, u_int port) -{ - static char buf[128]; - char prefbuf[128]; - char portbuf[128]; - int plen; - - switch (family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - return "?"; - } - - if (pref == plen) - prefbuf[0] = '\0'; - else - snprintf(prefbuf, sizeof(prefbuf), "/%u", pref); - - if (port == IPSEC_PORT_ANY) - snprintf(portbuf, sizeof(portbuf), "[%s]", "any"); - else - snprintf(portbuf, sizeof(portbuf), "[%u]", port); - - snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf); - - return buf; -} - -/* - * set "Mon Day Time Year" to buffer - */ -static char * -str_time(time_t t) -{ - static char buf[128]; - - if (t == 0) { - int i = 0; - for (;i < 20;) buf[i++] = ' '; - } else { - char *t0; - t0 = ctime(&t); - memcpy(buf, t0 + 4, 20); - } - - buf[20] = '\0'; - - return(buf); -} - -static void -str_lifetime_byte(struct sadb_lifetime *x, char *str) -{ - double y; - char *unit; - int w; - - if (x == NULL) { - printf("\t%s: 0(bytes)", str); - return; - } - -#if 0 - if ((x->sadb_lifetime_bytes) / 1024 / 1024) { - y = (x->sadb_lifetime_bytes) * 1.0 / 1024 / 1024; - unit = "M"; - w = 1; - } else if ((x->sadb_lifetime_bytes) / 1024) { - y = (x->sadb_lifetime_bytes) * 1.0 / 1024; - unit = "K"; - w = 1; - } else { - y = (x->sadb_lifetime_bytes) * 1.0; - unit = ""; - w = 0; - } -#else - y = (x->sadb_lifetime_bytes) * 1.0; - unit = ""; - w = 0; -#endif - printf("\t%s: %.*f(%sbytes)", str, w, y, unit); -} diff --git a/lib/libipsec/policy_parse.y b/lib/libipsec/policy_parse.y deleted file mode 100644 index 4954d82667..0000000000 --- a/lib/libipsec/policy_parse.y +++ /dev/null @@ -1,425 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/policy_parse.y,v 1.1.2.1 2000/07/15 07:24:04 kris Exp $ */ -/* $DragonFly: src/lib/libipsec/policy_parse.y,v 1.4 2008/09/30 16:57:05 swildner Exp $ */ -/* $KAME: policy_parse.y,v 1.10 2000/05/07 05:25:03 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -/* - * IN/OUT bound policy configuration take place such below: - * in - * out - * - * is one of following: - * "discard", "none", "ipsec ", "entrust", "bypass", - * - * The following requests are accepted as : - * - * protocol/mode/src-dst/level - * protocol/mode/src-dst parsed as protocol/mode/src-dst/default - * protocol/mode/src-dst/ parsed as protocol/mode/src-dst/default - * protocol/transport parsed as protocol/mode/any-any/default - * protocol/transport//level parsed as protocol/mode/any-any/level - * - * You can concatenate these requests with either ' '(single space) or '\n'. - */ - -%{ -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "ipsec_strerror.h" - -#define ATOX(c) \ - (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) )) - -static caddr_t pbuf = NULL; /* sadb_x_policy buffer */ -static int tlen = 0; /* total length of pbuf */ -static int offset = 0; /* offset of pbuf */ -static int p_dir, p_type, p_protocol, p_mode, p_level, p_reqid; -static struct sockaddr *p_src = NULL; -static struct sockaddr *p_dst = NULL; - -struct _val; -extern void yyerror (char *msg); -static struct sockaddr *parse_sockaddr (struct _val *buf); -static int rule_check (void); -static int init_x_policy (void); -static int set_x_request (struct sockaddr *src, struct sockaddr *dst); -static int set_sockaddr (struct sockaddr *addr); -static void policy_parse_request_init (void); -static caddr_t policy_parse (char *msg, int msglen); - -extern void __policy__strbuffer__init__ (char *msg); -extern int yyparse (void); -extern int yylex (void); - -%} - -%union { - u_int num; - struct _val { - int len; - char *buf; - } val; -} - -%token DIR ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY -%token IPADDRESS -%token ME ANY -%token SLASH HYPHEN -%type DIR ACTION PROTOCOL MODE LEVEL -%type IPADDRESS LEVEL_SPECIFY - -%% -policy_spec - : DIR ACTION - { - p_dir = $1; - p_type = $2; - - if (init_x_policy()) - return -1; - } - rules - | DIR - { - p_dir = $1; - p_type = 0; /* ignored it by kernel */ - - if (init_x_policy()) - return -1; - } - ; - -rules - : /*NOTHING*/ - | rules rule { - if (rule_check() < 0) - return -1; - - if (set_x_request(p_src, p_dst) < 0) - return -1; - - policy_parse_request_init(); - } - ; - -rule - : protocol SLASH mode SLASH addresses SLASH level - | protocol SLASH mode SLASH addresses SLASH - | protocol SLASH mode SLASH addresses - | protocol SLASH mode SLASH - | protocol SLASH mode SLASH SLASH level - | protocol SLASH mode - | protocol SLASH { - __ipsec_errcode = EIPSEC_FEW_ARGUMENTS; - return -1; - } - | protocol { - __ipsec_errcode = EIPSEC_FEW_ARGUMENTS; - return -1; - } - ; - -protocol - : PROTOCOL { p_protocol = $1; } - ; - -mode - : MODE { p_mode = $1; } - ; - -level - : LEVEL { - p_level = $1; - p_reqid = 0; - } - | LEVEL_SPECIFY { - p_level = IPSEC_LEVEL_UNIQUE; - p_reqid = atol($1.buf); /* atol() is good. */ - } - ; - -addresses - : IPADDRESS { - p_src = parse_sockaddr(&$1); - if (p_src == NULL) - return -1; - } - HYPHEN - IPADDRESS { - p_dst = parse_sockaddr(&$4); - if (p_dst == NULL) - return -1; - } - | ME HYPHEN ANY { - if (p_dir != IPSEC_DIR_OUTBOUND) { - __ipsec_errcode = EIPSEC_INVAL_DIR; - return -1; - } - } - | ANY HYPHEN ME { - if (p_dir != IPSEC_DIR_INBOUND) { - __ipsec_errcode = EIPSEC_INVAL_DIR; - return -1; - } - } - /* - | ME HYPHEN ME - */ - ; - -%% - -void -yyerror(char *msg) -{ - extern char *__libipsecyytext; /*XXX*/ - - fprintf(stderr, "libipsec: %s while parsing \"%s\"\n", - msg, __libipsecyytext); - - return; -} - -static struct sockaddr * -parse_sockaddr(struct _val *buf) -{ - struct addrinfo hints, *res; - char *serv = NULL; - int error; - struct sockaddr *newaddr = NULL; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - error = getaddrinfo(buf->buf, serv, &hints, &res); - if (error != 0) { - yyerror("invalid IP address"); - __ipsec_set_strerror(gai_strerror(error)); - return NULL; - } - - if (res->ai_addr == NULL) { - yyerror("invalid IP address"); - __ipsec_set_strerror(gai_strerror(error)); - return NULL; - } - - newaddr = malloc(res->ai_addr->sa_len); - if (newaddr == NULL) { - __ipsec_errcode = EIPSEC_NO_BUFS; - freeaddrinfo(res); - return NULL; - } - memcpy(newaddr, res->ai_addr, res->ai_addr->sa_len); - - freeaddrinfo(res); - - __ipsec_errcode = EIPSEC_NO_ERROR; - return newaddr; -} - -static int -rule_check(void) -{ - if (p_type == IPSEC_POLICY_IPSEC) { - if (p_protocol == IPPROTO_IP) { - __ipsec_errcode = EIPSEC_NO_PROTO; - return -1; - } - - if (p_mode != IPSEC_MODE_TRANSPORT - && p_mode != IPSEC_MODE_TUNNEL) { - __ipsec_errcode = EIPSEC_INVAL_MODE; - return -1; - } - - if (p_src == NULL && p_dst == NULL) { - if (p_mode != IPSEC_MODE_TRANSPORT) { - __ipsec_errcode = EIPSEC_INVAL_ADDRESS; - return -1; - } - } - else if (p_src->sa_family != p_dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -static int -init_x_policy(void) -{ - struct sadb_x_policy *p; - - tlen = sizeof(struct sadb_x_policy); - - pbuf = malloc(tlen); - if (pbuf == NULL) { - __ipsec_errcode = EIPSEC_NO_BUFS; - return -1; - } - p = (struct sadb_x_policy *)pbuf; - p->sadb_x_policy_len = 0; /* must update later */ - p->sadb_x_policy_exttype = SADB_X_EXT_POLICY; - p->sadb_x_policy_type = p_type; - p->sadb_x_policy_dir = p_dir; - p->sadb_x_policy_reserved = 0; - offset = tlen; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -static int -set_x_request(struct sockaddr *src, struct sockaddr *dst) -{ - struct sadb_x_ipsecrequest *p; - int reqlen; - - reqlen = sizeof(*p) - + (src ? src->sa_len : 0) - + (dst ? dst->sa_len : 0); - tlen += reqlen; /* increment to total length */ - - pbuf = realloc(pbuf, tlen); - if (pbuf == NULL) { - __ipsec_errcode = EIPSEC_NO_BUFS; - return -1; - } - p = (struct sadb_x_ipsecrequest *)&pbuf[offset]; - p->sadb_x_ipsecrequest_len = reqlen; - p->sadb_x_ipsecrequest_proto = p_protocol; - p->sadb_x_ipsecrequest_mode = p_mode; - p->sadb_x_ipsecrequest_level = p_level; - p->sadb_x_ipsecrequest_reqid = p_reqid; - offset += sizeof(*p); - - if (set_sockaddr(src) || set_sockaddr(dst)) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -static int -set_sockaddr(struct sockaddr *addr) -{ - if (addr == NULL) { - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; - } - - /* tlen has already incremented */ - - memcpy(&pbuf[offset], addr, addr->sa_len); - - offset += addr->sa_len; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -static void -policy_parse_request_init(void) -{ - p_protocol = IPPROTO_IP; - p_mode = IPSEC_MODE_ANY; - p_level = IPSEC_LEVEL_DEFAULT; - p_reqid = 0; - if (p_src != NULL) { - free(p_src); - p_src = NULL; - } - if (p_dst != NULL) { - free(p_dst); - p_dst = NULL; - } - - return; -} - -static caddr_t -policy_parse(char *msg, int msglen) -{ - int error; - pbuf = NULL; - tlen = 0; - - /* initialize */ - p_dir = IPSEC_DIR_INVALID; - p_type = IPSEC_POLICY_DISCARD; - policy_parse_request_init(); - __policy__strbuffer__init__(msg); - - error = yyparse(); /* it must be set errcode. */ - if (error) { - if (pbuf != NULL) - free(pbuf); - return NULL; - } - - /* update total length */ - ((struct sadb_x_policy *)pbuf)->sadb_x_policy_len = PFKEY_UNIT64(tlen); - - __ipsec_errcode = EIPSEC_NO_ERROR; - - return pbuf; -} - -caddr_t -ipsec_set_policy(char *msg, int msglen) -{ - caddr_t policy; - - policy = policy_parse(msg, msglen); - if (policy == NULL) { - if (__ipsec_errcode == EIPSEC_NO_ERROR) - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return NULL; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return policy; -} - diff --git a/lib/libipsec/policy_token.l b/lib/libipsec/policy_token.l deleted file mode 100644 index 77ff00b493..0000000000 --- a/lib/libipsec/policy_token.l +++ /dev/null @@ -1,151 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/policy_token.l,v 1.2.2.2 2001/07/03 11:01:15 ume Exp $ */ -/* $DragonFly: src/lib/libipsec/policy_token.l,v 1.4 2008/09/30 16:57:05 swildner Exp $ */ -/* $KAME: policy_token.l,v 1.11 2000/12/01 10:08:29 sakane Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -%{ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define YY_NO_INPUT - -#ifndef __NetBSD__ -#include "y.tab.h" -#else -#include "policy_parse.h" -#endif -#define yylval __libipsecyylval /* XXX */ - -int yylex (void); -%} - -%option noyywrap -%option nounput - -/* common section */ -nl \n -ws [ \t]+ -digit [0-9] -hexdigit [0-9A-Fa-f] -special [()+\|\?\*,] -dot \. -comma \, -hyphen \- -colon \: -slash \/ -bcl \{ -ecl \} -blcl \[ -elcl \] -percent \% -semi \; -usec {dot}{digit}{1,6} -comment \#.* -ccomment "/*" -bracketstring \<[^>]*\> -quotedstring \"[^"]*\" -decstring {digit}+ -hexpair {hexdigit}{hexdigit} -hexstring 0[xX]{hexdigit}+ -octetstring {octet}({dot}{octet})+ -ipaddress [a-zA-Z0-9:\._][a-zA-Z0-9:\._]*(%[a-zA-Z0-9]+)? - -%% - -in { yylval.num = IPSEC_DIR_INBOUND; return(DIR); } -out { yylval.num = IPSEC_DIR_OUTBOUND; return(DIR); } - -discard { yylval.num = IPSEC_POLICY_DISCARD; return(ACTION); } -none { yylval.num = IPSEC_POLICY_NONE; return(ACTION); } -ipsec { yylval.num = IPSEC_POLICY_IPSEC; return(ACTION); } -bypass { yylval.num = IPSEC_POLICY_BYPASS; return(ACTION); } -entrust { yylval.num = IPSEC_POLICY_ENTRUST; return(ACTION); } - -esp { yylval.num = IPPROTO_ESP; return(PROTOCOL); } -ah { yylval.num = IPPROTO_AH; return(PROTOCOL); } -ipcomp { yylval.num = IPPROTO_IPCOMP; return(PROTOCOL); } -tcp { yylval.num = IPPROTO_TCP; return(PROTOCOL); } - -transport { yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); } -tunnel { yylval.num = IPSEC_MODE_TUNNEL; return(MODE); } - -me { return(ME); } -any { return(ANY); } - -default { yylval.num = IPSEC_LEVEL_DEFAULT; return(LEVEL); } -use { yylval.num = IPSEC_LEVEL_USE; return(LEVEL); } -require { yylval.num = IPSEC_LEVEL_REQUIRE; return(LEVEL); } -unique{colon}{decstring} { - yylval.val.len = strlen(yytext + 7); - yylval.val.buf = yytext + 7; - return(LEVEL_SPECIFY); - } -unique { yylval.num = IPSEC_LEVEL_UNIQUE; return(LEVEL); } -{slash} { return(SLASH); } - -{ipaddress} { - yylval.val.len = strlen(yytext); - yylval.val.buf = yytext; - return(IPADDRESS); - } - -{hyphen} { return(HYPHEN); } - -{ws} { ; } -{nl} { ; } - -%% - -void __policy__strbuffer__init__ (char *); - -void -__policy__strbuffer__init__(char *msg) -{ - YY_BUFFER_STATE yyb; - - yyb = (YY_BUFFER_STATE)yy_scan_string(msg); - yy_switch_to_buffer(yyb); - - return; -} - diff --git a/lib/libipsec/test-policy.c b/lib/libipsec/test-policy.c deleted file mode 100644 index 865d24394b..0000000000 --- a/lib/libipsec/test-policy.c +++ /dev/null @@ -1,334 +0,0 @@ -/* $FreeBSD: src/lib/libipsec/test-policy.c,v 1.2.2.2 2001/07/03 11:01:15 ume Exp $ */ -/* $KAME: test-policy.c,v 1.14 2000/12/27 11:38:11 sakane Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "libpfkey.h" - -struct req_t { - int result; /* expected result; 0:ok 1:ng */ - char *str; -} reqs[] = { -{ 0, "out ipsec" }, -{ 1, "must_error" }, -{ 1, "in ipsec must_error" }, -{ 1, "out ipsec esp/must_error" }, -{ 1, "out discard" }, -{ 1, "out none" }, -{ 0, "in entrust" }, -{ 0, "out entrust" }, -{ 1, "out ipsec esp" }, -{ 0, "in ipsec ah/transport" }, -{ 1, "in ipsec ah/tunnel" }, -{ 0, "out ipsec ah/transport/" }, -{ 1, "out ipsec ah/tunnel/" }, -{ 0, "in ipsec esp / transport / 10.0.0.1-10.0.0.2" }, -{ 0, "in ipsec esp/tunnel/::1-::2" }, -{ 1, "in ipsec esp/tunnel/10.0.0.1-::2" }, -{ 0, "in ipsec esp/tunnel/::1-::2/require" }, -{ 0, "out ipsec ah/transport//use" }, -{ 1, "out ipsec ah/transport esp/use" }, -{ 1, "in ipsec ah/transport esp/tunnel" }, -{ 0, "in ipsec ah/transport esp/tunnel/::1-::1" }, -{ 0, "in ipsec - ah / transport - esp / tunnel / ::1-::2" }, -{ 0, "out ipsec - ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require - ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require - ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require - " }, -{ 0, "out ipsec esp/transport/fec0::10-fec0::11/use" }, -}; - -int test1 (void); -int test1sub1 (struct req_t *); -int test1sub2 (char *, int); -int test2 (void); -int test2sub (int); - -int -main(ac, av) - int ac; - char **av; -{ - test1(); - test2(); - - exit(0); -} - -int -test1() -{ - int i; - int result; - - printf("TEST1\n"); - for (i = 0; i < NELEM(reqs); i++) { - printf("#%d [%s]\n", i + 1, reqs[i].str); - - result = test1sub1(&reqs[i]); - if (result == 0 && reqs[i].result == 1) { - warnx("ERROR: expecting failure.\n"); - } else if (result == 1 && reqs[i].result == 0) { - warnx("ERROR: expecting success.\n"); - } - } - - return 0; -} - -int -test1sub1(req) - struct req_t *req; -{ - char *buf; - - buf = ipsec_set_policy(req->str, strlen(req->str)); - if (buf == NULL) { - printf("ipsec_set_policy: %s\n", ipsec_strerror()); - return 1; - } - - if (test1sub2(buf, PF_INET) != 0 - || test1sub2(buf, PF_INET6) != 0) { - free(buf); - return 1; - } -#if 0 - kdebug_sadb_x_policy((struct sadb_ext *)buf); -#endif - - free(buf); - return 0; -} - -int -test1sub2(policy, family) - char *policy; - int family; -{ - int so; - int proto = 0, optname = 0; - int len; - char getbuf[1024]; - - switch (family) { - case PF_INET: - proto = IPPROTO_IP; - optname = IP_IPSEC_POLICY; - break; - case PF_INET6: - proto = IPPROTO_IPV6; - optname = IPV6_IPSEC_POLICY; - break; - } - - if ((so = socket(family, SOCK_DGRAM, 0)) < 0) - err(1, "socket"); - - len = ipsec_get_policylen(policy); -#if 0 - printf("\tsetlen:%d\n", len); -#endif - - if (setsockopt(so, proto, optname, policy, len) < 0) { - printf("fail to set sockopt; %s\n", strerror(errno)); - close(so); - return 1; - } - - memset(getbuf, 0, sizeof(getbuf)); - memcpy(getbuf, policy, sizeof(struct sadb_x_policy)); - if (getsockopt(so, proto, optname, getbuf, &len) < 0) { - printf("fail to get sockopt; %s\n", strerror(errno)); - close(so); - return 1; - } - - { - char *buf = NULL; - -#if 0 - printf("\tgetlen:%d\n", len); -#endif - - if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL) { - printf("%s\n", ipsec_strerror()); - close(so); - return 1; - } -#if 0 - printf("\t[%s]\n", buf); -#endif - free(buf); - } - - close (so); - return 0; -} - -char addr[] = { - 28, 28, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, -}; - -int -test2() -{ - int so; - char *pol1 = "out ipsec"; - char *pol2 = "out ipsec ah/transport//use"; - char *sp1, *sp2; - int splen1, splen2; - int spid; - struct sadb_msg *m; - - printf("TEST2\n"); - if (getuid() != 0) - errx(1, "root privilege required.\n"); - - sp1 = ipsec_set_policy(pol1, strlen(pol1)); - splen1 = ipsec_get_policylen(sp1); - sp2 = ipsec_set_policy(pol2, strlen(pol2)); - splen2 = ipsec_get_policylen(sp2); - - if ((so = pfkey_open()) < 0) - errx(1, "ERROR: %s\n", ipsec_strerror()); - - printf("spdflush()\n"); - if (pfkey_send_spdflush(so) < 0) - errx(1, "ERROR: %s\n", ipsec_strerror()); - m = pfkey_recv(so); - free(m); - -#if 0 - printf("spdsetidx()\n"); - if (pfkey_send_spdsetidx(so, (struct sockaddr *)addr, 128, - (struct sockaddr *)addr, 128, - 255, sp1, splen1, 0) < 0) - errx(1, "ERROR: %s\n", ipsec_strerror()); - m = pfkey_recv(so); - free(m); - - printf("spdupdate()\n"); - if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128, - (struct sockaddr *)addr, 128, - 255, sp2, splen2, 0) < 0) - errx(1, "ERROR: %s\n", ipsec_strerror()); - m = pfkey_recv(so); - free(m); - - sleep(4); - - printf("spddelete()\n"); - if (pfkey_send_spddelete(so, (struct sockaddr *)addr, 128, - (struct sockaddr *)addr, 128, - 255, sp1, splen1, 0) < 0) - errx(1, "ERROR: %s\n", ipsec_strerror()); - m = pfkey_recv(so); - free(m); - - printf("spdadd()\n"); - if (pfkey_send_spdadd(so, (struct sockaddr *)addr, 128, - (struct sockaddr *)addr, 128, - 255, sp2, splen2, 0) < 0) - errx(1, "ERROR: %s\n", ipsec_strerror()); - spid = test2sub(so); - - printf("spdget(%u)\n", spid); - if (pfkey_send_spdget(so, spid) < 0) - errx(1, "ERROR: %s\n", ipsec_strerror()); - m = pfkey_recv(so); - free(m); - - sleep(4); - - printf("spddelete2()\n"); - if (pfkey_send_spddelete2(so, spid) < 0) - errx(1, "ERROR: %s\n", ipsec_strerror()); - m = pfkey_recv(so); - free(m); -#endif - - printf("spdadd() with lifetime's 10(s)\n"); - if (pfkey_send_spdadd2(so, (struct sockaddr *)addr, 128, - (struct sockaddr *)addr, 128, - 255, 0, 10, sp2, splen2, 0) < 0) - errx(1, "ERROR: %s\n", ipsec_strerror()); - spid = test2sub(so); - -#if 0 - /* expecting failure */ - printf("spdupdate()\n"); - if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128, - (struct sockaddr *)addr, 128, - 255, sp2, splen2, 0) == 0) { - warnx("ERROR: expecting failure.\n"); - } -#endif - - return 0; -} - -int -test2sub(so) - int so; -{ - struct sadb_msg *msg; - caddr_t mhp[SADB_EXT_MAX + 1]; - - if ((msg = pfkey_recv(so)) == NULL) - errx(1, "ERROR: pfkey_recv failure.\n"); - if (pfkey_align(msg, mhp) < 0) - errx(1, "ERROR: pfkey_align failure.\n"); - - return ((struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY])->sadb_x_policy_id; -} - diff --git a/sbin/ping/Makefile b/sbin/ping/Makefile index bb0e34505d..892d73056b 100644 --- a/sbin/ping/Makefile +++ b/sbin/ping/Makefile @@ -1,6 +1,5 @@ # @(#)Makefile 8.1 (Berkeley) 6/5/93 # $FreeBSD: src/sbin/ping/Makefile,v 1.12.2.4 2001/12/19 04:49:11 dd Exp $ -# $DragonFly: src/sbin/ping/Makefile,v 1.4 2006/10/17 00:55:43 pavalos Exp $ PROG= ping MAN= ping.8 @@ -8,8 +7,4 @@ BINMODE=4555 DPADD= ${LIBM} LDADD= -lm -CFLAGS+=-DIPSEC -DPADD+= ${LIBIPSEC} -LDADD+= -lipsec - .include diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8 index 4c4347ea0f..7053d33e20 100644 --- a/sbin/ping/ping.8 +++ b/sbin/ping/ping.8 @@ -28,7 +28,7 @@ .\" @(#)ping.8 8.2 (Berkeley) 12/11/93 .\" $FreeBSD: src/sbin/ping/ping.8,v 1.54 2006/04/05 12:30:42 glebius Exp $ .\" -.Dd April 4, 2006 +.Dd April 21, 2018 .Dt PING 8 .Os .Sh NAME @@ -47,7 +47,6 @@ packets to network hosts .Op Fl l Ar preload .Op Fl M Cm mask | time .Op Fl m Ar ttl -.Op Fl P Ar policy .Op Fl p Ar pattern .Op Fl S Ar src_addr .Op Fl s Ar packetsize @@ -63,7 +62,6 @@ packets to network hosts .Op Fl l Ar preload .Op Fl M Cm mask | time .Op Fl m Ar ttl -.Op Fl P Ar policy .Op Fl p Ar pattern .Op Fl S Ar src_addr .Op Fl s Ar packetsize @@ -215,13 +213,6 @@ Numeric output only. No attempt will be made to lookup symbolic names for host addresses. .It Fl o Exit successfully after receiving one reply packet. -.It Fl P Ar policy -.Ar policy -specifies IPsec policy for the ping session. -For details please refer to -.Xr ipsec 4 -and -.Xr ipsec_set_policy 3 . .It Fl p Ar pattern You may specify up to 16 .Dq pad diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c index 2dd549b16f..1097f58221 100644 --- a/sbin/ping/ping.c +++ b/sbin/ping/ping.c @@ -32,7 +32,6 @@ * @(#) Copyright (c) 1989, 1993 The Regents of the University of California. All rights reserved. * @(#)ping.c 8.1 (Berkeley) 6/5/93 * $FreeBSD: src/sbin/ping/ping.c,v 1.111 2007/05/21 14:38:45 cognet Exp $ - * $DragonFly: src/sbin/ping/ping.c,v 1.8 2008/09/04 21:00:28 swildner Exp $ */ /* @@ -66,10 +65,6 @@ #include #include -#ifdef IPSEC -#include -#endif /*IPSEC*/ - #include #include #include @@ -122,11 +117,6 @@ int options; #define F_MTTL 0x0800 #define F_MIF 0x1000 #define F_AUDIBLE 0x2000 -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC -#define F_POLICY 0x4000 -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ #define F_TTL 0x8000 #define F_MISSED 0x10000 #define F_ONCE 0x20000 @@ -218,9 +208,6 @@ main(int argc, char **argv) u_char *datap, packet[IP_MAXPACKET] __aligned(4); char *ep, *source, *target, *payload; struct hostent *hp; -#ifdef IPSEC_POLICY_IPSEC - char *policy_in, *policy_out; -#endif struct sockaddr_in *to; double t; u_long alarmtimeout, ultmp; @@ -234,9 +221,6 @@ main(int argc, char **argv) unsigned char loop, mttl; payload = source = NULL; -#ifdef IPSEC_POLICY_IPSEC - policy_in = policy_out = NULL; -#endif /* * Do the stuff that we need root priv's for *first*, and @@ -252,15 +236,7 @@ main(int argc, char **argv) alarmtimeout = df = preload = tos = 0; outpack = outpackhdr + sizeof(struct ip); - while ((ch = getopt(argc, argv, - "Aac:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:" -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - "P:" -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ - )) != -1) - { + while ((ch = getopt(argc, argv, "Aac:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:")) != -1) { switch(ch) { case 'A': options |= F_MISSED; @@ -395,19 +371,6 @@ main(int argc, char **argv) case 'o': options |= F_ONCE; break; -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - case 'P': - options |= F_POLICY; - if (!strncmp("in", optarg, 2)) - policy_in = strdup(optarg); - else if (!strncmp("out", optarg, 3)) - policy_out = strdup(optarg); - else - errx(1, "invalid security policy"); - break; -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ case 'p': /* fill buffer with user pattern */ options |= F_PINGFILLED; payload = optarg; @@ -594,35 +557,6 @@ main(int argc, char **argv) if (options & F_SO_DONTROUTE) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold)); -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - if (options & F_POLICY) { - char *buf; - if (policy_in != NULL) { - buf = ipsec_set_policy(policy_in, strlen(policy_in)); - if (buf == NULL) - errx(EX_CONFIG, "%s", ipsec_strerror()); - if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, - buf, ipsec_get_policylen(buf)) < 0) - err(EX_CONFIG, - "ipsec policy cannot be configured"); - free(buf); - } - - if (policy_out != NULL) { - buf = ipsec_set_policy(policy_out, strlen(policy_out)); - if (buf == NULL) - errx(EX_CONFIG, "%s", ipsec_strerror()); - if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, - buf, ipsec_get_policylen(buf)) < 0) - err(EX_CONFIG, - "ipsec policy cannot be configured"); - free(buf); - } - } -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ - if (options & F_HDRINCL) { ip = (struct ip*)outpackhdr; if (!(options & (F_TTL | F_MTTL))) { @@ -1669,11 +1603,6 @@ fill(char *bp, char *patp) } } -#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) -#define SECOPT " [-P policy]" -#else -#define SECOPT "" -#endif static void usage(void) { @@ -1681,10 +1610,10 @@ usage(void) fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", "usage: ping [-AaDdfnoQqRrv] [-c count] [-G sweepmaxsize] [-g sweepminsize]", " [-h sweepincrsize] [-i wait] [-l preload] [-M mask | time] [-m ttl]", -" " SECOPT " [-p pattern] [-S src_addr] [-s packetsize] [-t timeout]", +" [-p pattern] [-S src_addr] [-s packetsize] [-t timeout]", " [-W waittime] [-z tos] host", " ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait] [-l preload]", -" [-M mask | time] [-m ttl]" SECOPT " [-p pattern] [-S src_addr]", +" [-M mask | time] [-m ttl] [-p pattern] [-S src_addr]", " [-s packetsize] [-T ttl] [-t timeout] [-W waittime]", " [-z tos] mcast-group"); exit(EX_USAGE); diff --git a/sbin/ping6/Makefile b/sbin/ping6/Makefile index 50462bca99..fa3a1407de 100644 --- a/sbin/ping6/Makefile +++ b/sbin/ping6/Makefile @@ -3,13 +3,13 @@ PROG= ping6 MAN= ping6.8 -CFLAGS+=-DINET6 -DIPSEC -DHAVE_POLL_H -DHAVE_ARC4RANDOM -DUSE_RFC3542 +CFLAGS+=-DINET6 -DHAVE_POLL_H -DHAVE_ARC4RANDOM -DUSE_RFC3542 BINOWN= root BINMODE=4555 -LDADD= -lipsec -lm -lmd -lprivate_crypto -DPADD= ${LIBIPSEC} ${LIBM} ${LIBMD} ${LIBCRYPTO} +LDADD= -lm -lmd -lprivate_crypto +DPADD= ${LIBM} ${LIBMD} ${LIBCRYPTO} LDFLAGS+= ${PRIVATELIB_LDFLAGS} CFLAGS+= -I${.CURDIR}/../../crypto/libressl/include NO_STRICT_ALIASING= diff --git a/sbin/ping6/ping6.8 b/sbin/ping6/ping6.8 index d12a65e9af..bc7e3d82a4 100644 --- a/sbin/ping6/ping6.8 +++ b/sbin/ping6/ping6.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD: src/sbin/ping6/ping6.8,v 1.3.2.12 2003/02/24 00:56:42 trhodes Exp $ .\" -.Dd May 17, 1998 +.Dd April 21, 2018 .Dt PING6 8 .Os .Sh NAME @@ -39,10 +39,7 @@ packets to network hosts .Sh SYNOPSIS .Nm -.\" without ipsec, or new ipsec .Op Fl dfHnNqRtvwW -.\" old ipsec -.\" .Op Fl AdEfnNqRtvwW .Bk -words .Op Fl a Ar addrtype .Ek @@ -68,10 +65,6 @@ packets to network hosts .Op Fl p Ar pattern .Ek .Bk -words -.\" new ipsec -.Op Fl P Ar policy -.Ek -.Bk -words .Op Fl S Ar sourceaddr .Ek .Bk -words @@ -100,10 +93,6 @@ and header formatted as documented in RFC 2463. The options are as follows: .Bl -tag -width Ds -.\" old ipsec -.\" .It Fl A -.\" Enables transport-mode IPsec authentication header -.\" (experimental). .It Fl a Ar addrtype Generate ICMPv6 Node Information Node Addresses query, rather than echo-request. .Ar addrtype @@ -142,9 +131,6 @@ packets. Set the .Dv SO_DEBUG option on the socket being used. -.\" .It Fl E -.\" Enables transport-mode IPsec encapsulated security payload -.\" (experimental). .It Fl f Flood ping. Outputs packets as fast as they come back or one hundred times per second, @@ -214,10 +200,6 @@ For example, .Dq Li \-p ff will cause the sent packet to be filled with all ones. -.\" new ipsec -.It Fl P Ar policy -.Ar policy -specifies IPsec policy to be used for the probe. .It Fl q Quiet output. Nothing is displayed except the summary lines at startup time and @@ -465,7 +447,7 @@ The utility with IPv6 support first appeared in WIDE Hydrangea IPv6 protocol stack kit. .Pp -IPv6 and IPsec support based on the KAME Project +IPv6 support based on the KAME Project .Pa ( http://www.kame.net/ ) stack was initially integrated into .Fx 4.0 diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c index 8fa42bd8e1..0b9fa568d7 100644 --- a/sbin/ping6/ping6.c +++ b/sbin/ping6/ping6.c @@ -119,11 +119,6 @@ #include #endif -#ifdef IPSEC -#include -#include -#endif - #include struct tv32 { @@ -157,14 +152,6 @@ struct tv32 { #define F_RROUTE 0x0020 #define F_SO_DEBUG 0x0040 #define F_VERBOSE 0x0100 -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC -#define F_POLICY 0x0400 -#else -#define F_AUTHHDR 0x0200 -#define F_ENCRYPT 0x0400 -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ #define F_NODEADDR 0x0800 #define F_FQDN 0x1000 #define F_INTERFACE 0x2000 @@ -305,10 +292,6 @@ main(int argc, char **argv) #ifdef USE_RFC3542 struct ip6_rthdr *rthdr = NULL; #endif -#ifdef IPSEC_POLICY_IPSEC - char *policy_in = NULL; - char *policy_out = NULL; -#endif #ifdef IPV6_USE_MIN_MTU int mflag = 0; #endif @@ -320,18 +303,7 @@ main(int argc, char **argv) preload = 0; datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN]; -#ifndef IPSEC -#define ADDOPTS -#else -#ifdef IPSEC_POLICY_IPSEC -#define ADDOPTS "P:" -#else -#define ADDOPTS "AE" -#endif /*IPSEC_POLICY_IPSEC*/ -#endif - while ((ch = getopt(argc, argv, - "a:b:c:dfHg:h:I:i:l:mnNp:qS:s:tvwW" ADDOPTS)) != -1) { -#undef ADDOPTS + while ((ch = getopt(argc, argv, "a:b:c:dfHg:h:I:i:l:mnNp:qS:s:tvwW")) != -1) { switch (ch) { case 'a': { @@ -524,28 +496,6 @@ main(int argc, char **argv) options &= ~F_NOUSERDATA; options |= F_FQDNOLD; break; -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - case 'P': - options |= F_POLICY; - if (!strncmp("in", optarg, 2)) { - if ((policy_in = strdup(optarg)) == NULL) - errx(1, "strdup"); - } else if (!strncmp("out", optarg, 3)) { - if ((policy_out = strdup(optarg)) == NULL) - errx(1, "strdup"); - } else - errx(1, "invalid security policy"); - break; -#else - case 'A': - options |= F_AUTHHDR; - break; - case 'E': - options |= F_ENCRYPT; - break; -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ default: usage(); /*NOTREACHED*/ @@ -732,36 +682,6 @@ main(int argc, char **argv) #endif /* IPV6_RECVPATHMTU */ #endif /* IPV6_USE_MIN_MTU */ -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - if (options & F_POLICY) { - if (setpolicy(s, policy_in) < 0) - errx(1, "%s", ipsec_strerror()); - if (setpolicy(s, policy_out) < 0) - errx(1, "%s", ipsec_strerror()); - } -#else - if (options & F_AUTHHDR) { - optval = IPSEC_LEVEL_REQUIRE; -#ifdef IPV6_AUTH_TRANS_LEVEL - if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, - &optval, sizeof(optval)) == -1) - err(1, "setsockopt(IPV6_AUTH_TRANS_LEVEL)"); -#else /* old def */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_LEVEL, - &optval, sizeof(optval)) == -1) - err(1, "setsockopt(IPV6_AUTH_LEVEL)"); -#endif - } - if (options & F_ENCRYPT) { - optval = IPSEC_LEVEL_REQUIRE; - if (setsockopt(s, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, - &optval, sizeof(optval)) == -1) - err(1, "setsockopt(IPV6_ESP_TRANS_LEVEL)"); - } -#endif /*IPSEC_POLICY_IPSEC*/ -#endif - #ifdef ICMP6_FILTER { struct icmp6_filter filt; @@ -2448,13 +2368,6 @@ pr_retip(struct ip6_hdr *ip6, u_char *end) hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3; nh = ((struct ip6_rthdr *)cp)->ip6r_nxt; break; -#ifdef IPSEC - case IPPROTO_AH: - printf("AH "); - hlen = (((struct ah *)cp)->ah_len+2) << 2; - nh = ((struct ah *)cp)->ah_nxt; - break; -#endif case IPPROTO_ICMPV6: printf("ICMP6: type = %d, code = %d\n", *cp, *(cp + 1)); @@ -2522,29 +2435,6 @@ fill(char *bp, char *patp) } } -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC -int -setpolicy(int so __unused, char *policy) -{ - char *buf; - - if (policy == NULL) - return 0; /* ignore */ - - buf = ipsec_set_policy(policy, strlen(policy)); - if (buf == NULL) - errx(1, "%s", ipsec_strerror()); - if (setsockopt(s, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf, - ipsec_get_policylen(buf)) < 0) - warnx("Unable to set IPsec policy"); - free(buf); - - return 0; -} -#endif -#endif - char * nigroup(char *name) { @@ -2593,14 +2483,8 @@ void usage(void) { fprintf(stderr, -#if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) - "A" -#endif "usage: ping6 [-" "d" -#if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) - "E" -#endif "fH" #ifdef IPV6_USE_MIN_MTU "m" @@ -2608,9 +2492,6 @@ usage(void) "nNqtvwW] " "[-a addrtype] [-b bufsiz] [-c count] [-g gateway]\n" " [-h hoplimit] [-I interface] [-i wait] [-l preload]" -#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) - " [-P policy]" -#endif "\n" " [-p pattern] [-S sourceaddr] [-s packetsize] " "[hops ...] host\n"); diff --git a/share/initrd/sbin.libcrypto/Makefile b/share/initrd/sbin.libcrypto/Makefile index d74e8066a8..579fd89a5c 100644 --- a/share/initrd/sbin.libcrypto/Makefile +++ b/share/initrd/sbin.libcrypto/Makefile @@ -24,7 +24,6 @@ CRUNCH_ALIAS_md5= rmd160 CRUNCH_SRCDIRS+= usr.sbin/802_11 CRUNCH_PROGS_usr.sbin/802_11= wpa_supplicant CRUNCH_LIBS+= -lpcap -lprivate_ssl -lmd -lprivate_crypto -CRUNCH_LIBS+= -lipsec CRUNCH_LIBS+= ${PRIVATELIB_LDFLAGS} .include diff --git a/share/initrd/sbin/Makefile b/share/initrd/sbin/Makefile index a7413a0f30..d461682763 100644 --- a/share/initrd/sbin/Makefile +++ b/share/initrd/sbin/Makefile @@ -66,7 +66,7 @@ CRUNCH_ALIAS_swapon= swapoff swapctl CRUNCH_LIBS+= -lcam -lsbuf -lutil -lkvm -lm -lhammer -lkiconv CRUNCH_LIBS+= -lprivate_edit -lprivate_ncurses -ldevstat -lprop -lpthread -CRUNCH_LIBS+= -lbsdxml -lipsec +CRUNCH_LIBS+= -lbsdxml CRUNCH_LIBS+= ${PRIVATELIB_LDFLAGS} CRUNCH_SRCDIRS+= usr.sbin diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 49d5feb94e..0be891f0c1 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -93,7 +93,6 @@ MAN= aac.4 \ em.4 \ et.4 \ exca.4 \ - fast_ipsec.4 \ fd.4 \ fdc.4 \ firewire.4 \ @@ -136,7 +135,6 @@ MAN= aac.4 \ ipheth.4 \ ipmi.4 \ ips.4 \ - ipsec.4 \ isa.4 \ iscsi_initiator.4 \ isp.4 \ diff --git a/share/man/man4/aesni.4 b/share/man/man4/aesni.4 index 6af4b1c551..e914440d60 100644 --- a/share/man/man4/aesni.4 +++ b/share/man/man4/aesni.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD: src/share/man/man4/aesni.4,v 1.3 2010/09/09 21:37:05 brueffer Exp $ .\" -.Dd October 12, 2010 +.Dd April 21, 2018 .Dt AESNI 4 .Os .Sh NAME @@ -73,7 +73,6 @@ implementations. .Xr crypt 3 , .Xr crypto 4 , .Xr intro 4 , -.Xr ipsec 4 , .Xr padlock 4 , .Xr random 4 , .Xr crypto 9 diff --git a/share/man/man4/crypto.4 b/share/man/man4/crypto.4 index 244d15f1da..2791816c75 100644 --- a/share/man/man4/crypto.4 +++ b/share/man/man4/crypto.4 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD: src/share/man/man4/crypto.4,v 1.9 2009/03/03 07:58:01 brueffer Exp $ .\" -.Dd August 21, 2010 +.Dd April 21, 2018 .Dt CRYPTO 4 .Os .Sh NAME @@ -119,7 +119,6 @@ crypto access device .Sh SEE ALSO .Xr aesni 4 , .Xr hifn 4 , -.Xr ipsec 4 , .Xr padlock 4 , .Xr safe 4 , .Xr ubsec 4 , diff --git a/share/man/man4/fast_ipsec.4 b/share/man/man4/fast_ipsec.4 deleted file mode 100644 index 2cd037c86f..0000000000 --- a/share/man/man4/fast_ipsec.4 +++ /dev/null @@ -1,107 +0,0 @@ -.\" Copyright (c) 2003 -.\" Sam Leffler . All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Bill Paul. -.\" 4. Neither the name of the author nor the names of any co-contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY Sam Leffler 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 Bill Paul OR THE VOICES IN HIS HEAD -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -.\" THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD: src/share/man/man4/fast_ipsec.4,v 1.1.2.1 2003/01/24 05:12:59 sam Exp $ -.\" $DragonFly: src/share/man/man4/fast_ipsec.4,v 1.5 2007/05/12 21:22:10 swildner Exp $ -.\" -.Dd January 20, 2003 -.Dt FAST_IPSEC 4 -.Os -.Sh NAME -.Nm "Fast IPsec" -.Nd Hardware-accelerated IP Security Protocols -.Sh SYNOPSIS -.Cd "options FAST_IPSEC" -.Cd "device crypto" -.Pp -.Cd net.inet.esp.enable -.Cd net.inet.ah.enable -.Cd net.inet.ipcomp.enable -.Sh DESCRIPTION -.Tn IPsec -is a set of protocols, -.Tn ESP -(for Encapsulating Security Payload) -.Tn AH -(for Authentication Header), -and -.Tn IPComp -(for IP Payload Compression Protocol) -that provide security services for IP datagrams. -.Tn Fast IPsec -is an experimental implementation of these protocols that uses the -.Xr crypto 4 -subsystem to carry out cryptographic operations. -This means, in particular, that cryptograph hardware devices are -employed whenever possible to optimize the performance of these protocols. -.Pp -In general the -.Tn Fast IPsec -implementation is intended to be compatible with the -KAME -.Tn IPsec -implementation. -This documentation concentrates on differences from that software. -The user should refer to -.Xr ipsec 4 -for basic information on setting up and using these protocols. -.Pp -System configuration requires the crypto subsystem. -When the -.Tn Fast IPsec -protocols are configured for use all protocols are included in the system. -To selectively enable/disable protocols use -.Xr sysctl 8 . -.Sh DIAGNOSTICS -To be added. -.Sh SEE ALSO -.Xr ipsec 4 , -.Xr setkey 8 , -.Xr sysctl 8 -.Sh HISTORY -The protocols draw heavily on the -.Ox -implementation of the -.Tn IPsec -protocols. -The policy management code is derived from the KAME implementation found -in their -.Tn IPsec -protocols. -The -.Tn Fast IPsec -protocols first appeared in -.Fx 5.0 . -.Sh BUGS -There is presently no support for IPv6. -The IPcomp protocol support does not work. -Certain legacy authentication algorithms are not supported because of -issues with the crypto subsystem. -This documentation is incomplete. diff --git a/share/man/man4/hifn.4 b/share/man/man4/hifn.4 index 55313261e7..b0ab104de0 100644 --- a/share/man/man4/hifn.4 +++ b/share/man/man4/hifn.4 @@ -25,7 +25,7 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd February 14, 2010 +.Dd April 21, 2018 .Dt HIFN 4 .Os .Sh NAME @@ -58,8 +58,6 @@ The driver registers itself to accelerate DES, Triple-DES, AES (7955 and 7956 only), ARC4, MD5, MD5-HMAC, SHA1, and SHA1-HMAC operations for -.Xr ipsec 4 -and .Xr crypto 4 . .Pp The Hifn @@ -103,7 +101,6 @@ Contains a 7955 and supports symmetric and random number operations. .Xr crypt 3 , .Xr crypto 4 , .Xr intro 4 , -.Xr ipsec 4 , .Xr random 4 , .Xr crypto 9 .Sh CAVEATS diff --git a/share/man/man4/ip6.4 b/share/man/man4/ip6.4 index f02639279e..49fe613b46 100644 --- a/share/man/man4/ip6.4 +++ b/share/man/man4/ip6.4 @@ -29,7 +29,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 25, 2017 +.Dd April 21, 2018 .Dt IP6 4 .Os .Sh NAME @@ -384,14 +384,6 @@ the socket option cannot be set to 0 (which will result in returning Get or set whether the minimal IPv6 maximum transmission unit (MTU) size will be used to avoid fragmentation from occurring for subsequent outgoing datagrams. -.It Dv IPV6_AUTH_LEVEL Fa "int *" -Get or set the -.Xr ipsec 4 -authentication level. -.It Dv IPV6_ESP_TRANS_LEVEL Fa "int *" -Get or set the ESP transport level. -.It Dv IPV6_ESP_NETWORK_LEVEL Fa "int *" -Get or set the ESP encapsulation level. .It Dv IPV6_IPCOMP_LEVEL Fa "int *" Get or set the .Xr ipcomp 4 diff --git a/share/man/man4/ipsec.4 b/share/man/man4/ipsec.4 deleted file mode 100644 index 705d6b7fe2..0000000000 --- a/share/man/man4/ipsec.4 +++ /dev/null @@ -1,326 +0,0 @@ -.\" $FreeBSD: src/share/man/man4/ipsec.4,v 1.3.2.10 2001/12/17 11:30:12 ru Exp $ -.\" $DragonFly: src/share/man/man4/ipsec.4,v 1.3 2007/11/23 23:16:37 swildner Exp $ -.\" $KAME: ipsec.4,v 1.17 2001/06/27 15:25:10 itojun Exp $ -.\" -.\" 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. -.\" -.Dd January 29, 1999 -.Dt IPSEC 4 -.Os -.Sh NAME -.Nm ipsec -.Nd IP security protocol -.Sh SYNOPSIS -.In sys/types.h -.In netinet/in.h -.In netinet6/ipsec.h -.Sh DESCRIPTION -.Nm -is a security protocol in Internet Protocol layer. -.Nm -is defined for both IPv4 and IPv6 -.Xr ( inet 4 -and -.Xr inet6 4 ) . -.Nm -consists of two sub-protocols, namely -ESP -(encapsulated security payload) -and AH -(authentication header). -ESP protects IP payload from wire-tapping by encrypting it by -secret key cryptography algorithms. -AH guarantees integrity of IP packet -and protects it from intermediate alteration or impersonation, -by attaching cryptographic checksum computed by one-way hash functions. -.Nm -has two operation modes: transport mode and tunnel mode. -Transport mode is for protecting peer-to-peer communication between end nodes. -Tunnel mode includes IP-in-IP encapsulation operation -and is designed for security gateways, like VPN configurations. -.\" -.Ss Kernel interface -.Nm -is controlled by key management engine and policy engine, -in the operating system kernel. -.Pp -Key management engine can be accessed from the userland by using -.Dv PF_KEY -sockets. -The -.Dv PF_KEY -socket API is defined in RFC 2367. -.Pp -Policy engine can be controlled by extended part of -.Dv PF_KEY -API, -.Xr setsockopt 2 -operations, and -.Xr sysctl 3 -interface. -The kernel implements -extended version of -.Dv PF_KEY -interface, and allows you to define IPsec policy like per-packet filters. -.Xr setsockopt 2 -interface is used to define per-socket behavior, and -.Xr sysctl 3 -interface is used to define host-wide default behavior. -.Pp -The kernel code does not implement dynamic encryption key exchange protocol -like IKE -(Internet Key Exchange). -That should be implemented as userland programs -(usually as daemons), -by using the above described APIs. -.\" -.Ss Policy management -The kernel implements experimental policy management code. -You can manage the IPsec policy in two ways. -One is to configure per-socket policy using -.Xr setsockopt 2 . -The other is to configure kernel packet filter-based policy using -.Dv PF_KEY -interface, via -.Xr setkey 8 . -In both cases, IPsec policy must be specified with syntax described in -.Xr ipsec_set_policy 3 . -.Pp -With -.Xr setsockopt 2 , -you can define IPsec policy in per-socket basis. -You can enforce particular IPsec policy onto packets that go through -particular socket. -.Pp -With -.Xr setkey 8 -you can define IPsec policy against packets, -using sort of packet filtering rule. -Refer to -.Xr setkey 8 -on how to use it. -.Pp -In the latter case, -.Dq Li default -policy is allowed for use with -.Xr setkey 8 . -By configuring policy to -.Li default , -you can refer system-wide -.Xr sysctl 8 -variable for default settings. -The following variables are available. -.Li 1 -means -.Dq Li use , -and -.Li 2 -means -.Dq Li require -in the syntax. -.Bl -column net.inet6.ipsec6.esp_trans_deflev integerxxx -.It Sy "Name Type Changeable" -.It "net.inet.ipsec.esp_trans_deflev integer yes" -.It "net.inet.ipsec.esp_net_deflev integer yes" -.It "net.inet.ipsec.ah_trans_deflev integer yes" -.It "net.inet.ipsec.ah_net_deflev integer yes" -.It "net.inet6.ipsec6.esp_trans_deflev integer yes" -.It "net.inet6.ipsec6.esp_net_deflev integer yes" -.It "net.inet6.ipsec6.ah_trans_deflev integer yes" -.It "net.inet6.ipsec6.ah_net_deflev integer yes" -.El -.Pp -If kernel finds no matching policy system wide default value is applied. -System wide default is specified by the following -.Xr sysctl 8 -variables. -.Li 0 -means -.Dq Li discard -which asks the kernel to drop the packet. -.Li 1 -means -.Dq Li none . -.Bl -column net.inet6.ipsec6.def_policy integerxxx -.It Sy "Name Type Changeable" -.It "net.inet.ipsec.def_policy integer yes" -.It "net.inet6.ipsec6.def_policy integer yes" -.El -.\" -.Ss Miscellaneous sysctl variables -The following variables are accessible via -.Xr sysctl 8 , -for tweaking kernel IPsec behavior: -.Bl -column net.inet6.ipsec6.inbonud_call_ike integerxxx -.It Sy "Name Type Changeable" -.It "net.inet.ipsec.ah_cleartos integer yes" -.It "net.inet.ipsec.ah_offsetmask integer yes" -.It "net.inet.ipsec.dfbit integer yes" -.It "net.inet.ipsec.ecn integer yes" -.It "net.inet.ipsec.debug integer yes" -.It "net.inet6.ipsec6.ecn integer yes" -.It "net.inet6.ipsec6.debug integer yes" -.El -.Pp -The variables are interpreted as follows: -.Bl -tag -width 6n -.It Li ipsec.ah_cleartos -If set to non-zero, the kernel clears type-of-service field in the IPv4 header -during AH authentication data computation. -The variable is for tweaking AH behavior to interoperate with devices that -implement RFC 1826 AH. -It should be set to non-zero -(clear the type-of-service field) -for RFC 2402 conformance. -.It Li ipsec.ah_offsetmask -During AH authentication data computation, the kernel will include -16bit fragment offset field -(including flag bits) -in IPv4 header, after computing logical AND with the variable. -The variable is for tweaking AH behavior to interoperate with devices that -implement RFC 1826 AH. -It should be set to zero -(clear the fragment offset field during computation) -for RFC 2402 conformance. -.It Li ipsec.dfbit -The variable configures the kernel behavior on IPv4 IPsec tunnel encapsulation. -If set to 0, DF bit on the outer IPv4 header will be cleared. -1 means that the outer DF bit is set regardless from the inner DF bit. -2 means that the DF bit is copied from the inner header to the outer. -The variable is supplied to conform to RFC 2401 chapter 6.1. -.It Li ipsec.ecn -If set to non-zero, IPv4 IPsec tunnel encapsulation/decapsulation behavior will -be friendly to ECN -(explicit congestion notification), -as documented in -.Li draft-ietf-ipsec-ecn-02.txt . -.Xr gif 4 -talks more about the behavior. -.It Li ipsec.debug -If set to non-zero, debug messages will be generated via -.Xr syslog 3 . -.El -.Pp -Variables under -.Li net.inet6.ipsec6 -tree has similar meaning as the -.Li net.inet.ipsec -counterpart. -.\" -.Sh PROTOCOLS -The -.Nm -protocol works like plug-in to -.Xr inet 4 -and -.Xr inet6 4 -protocols. -Therefore, -.Nm -supports most of the protocols defined upon those IP-layer protocols. -Some of the protocols, like -.Xr icmp 4 -or -.Xr icmp6 4 , -may behave differently with -.Nm . -This is because -.Nm -can prevent -.Xr icmp 4 -or -.Xr icmp6 4 -routines from looking into IP payload. -.\" -.Sh SEE ALSO -.Xr ioctl 2 , -.Xr socket 2 , -.Xr ipsec_set_policy 3 , -.Xr icmp6 4 , -.Xr intro 4 , -.Xr ip6 4 , -.Xr setkey 8 , -.Xr sysctl 8 -.\".Xr racoon 8 -.Sh STANDARDS -.Rs -.%A Daniel L. McDonald -.%A Craig Metz -.%A Bao G. Phan -.%T "PF_KEY Key Management API, Version 2" -.%R RFC -.%N 2367 -.Re -.Pp -.Rs -.%A "D. L. McDonald" -.%T "A Simple IP Security API Extension to BSD Sockets" -.%R internet draft -.%N "draft-mcdonald-simple-ipsec-api-03.txt" -.%O work in progress material -.Re -.Sh HISTORY -The implementation described herein appeared in WIDE/KAME IPv6/IPsec stack. -.Sh BUGS -The IPsec support is subject to change as the IPsec protocols develop. -.Pp -There is no single standard for policy engine API, -so the policy engine API described herein is just for KAME implementation. -.Pp -AH and tunnel mode encapsulation may not work as you might expect. -If you configure inbound -.Dq require -policy against AH tunnel or any IPsec encapsulating policy with AH -(like -.Dq Li esp/tunnel/A-B/use ah/transport/A-B/require ) , -tunnelled packets will be rejected. -This is because we enforce policy check on inner packet on reception, -and AH authenticates encapsulating -(outer) -packet, not the encapsulated -(inner) -packet -(so for the receiving kernel there's no sign of authenticity). -The issue will be solved when we revamp our policy engine to keep all the -packet decapsulation history. -.Pp -Under certain condition, -truncated result may be raised from the kernel -against -.Dv SADB_DUMP -and -.Dv SADB_SPDDUMP -operation on -.Dv PF_KEY -socket. -This occurs if there are too many database entries in the kernel -and socket buffer for the -.Dv PF_KEY -socket is insufficient. -If you manipulate many IPsec key/policy database entries, -increase the size of socket buffer. diff --git a/share/man/man4/padlock.4 b/share/man/man4/padlock.4 index da5d2b5815..c6c9f21f2d 100644 --- a/share/man/man4/padlock.4 +++ b/share/man/man4/padlock.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD: src/share/man/man4/man4.i386/padlock.4,v 1.8 2007/08/02 08:04:48 bz Exp $ .\" -.Dd October 3, 2009 +.Dd April 21, 2018 .Dt PADLOCK 4 .Os .Sh NAME @@ -58,10 +58,8 @@ and HMAC/SHA256 for .Xr crypto 4 . It also registers itself to accelerate other HMAC algorithms, although there is no hardware acceleration for those algorithms. -This is only needed so -.Nm -can work with -.Xr ipsec 4 . +This is due to historical reasons, so that padlock could work with +.Em IPsec . .Pp The hardware random number generator supplies data for the kernel .Xr random 4 @@ -70,7 +68,6 @@ subsystem. .Xr crypt 3 , .Xr crypto 4 , .Xr intro 4 , -.Xr ipsec 4 , .Xr random 4 , .Xr crypto 9 .Sh HISTORY diff --git a/share/man/man4/pfsync.4 b/share/man/man4/pfsync.4 index adbbbe36fc..aa02eec32d 100644 --- a/share/man/man4/pfsync.4 +++ b/share/man/man4/pfsync.4 @@ -24,7 +24,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 2, 2011 +.Dd April 21, 2018 .Dt PFSYNC 4 .Os .Sh NAME @@ -105,26 +105,17 @@ By default, state change messages are sent out on the synchronisation interface using IP multicast packets. The protocol is IP protocol 240, PFSYNC, and the multicast group used is 224.0.0.240. -When a peer address is specified using the +An alternative destination address for +.Nm +packets can be specified using the .Ic syncpeer -keyword, the peer address is used as a destination for the pfsync traffic, -and the traffic can then be protected using -.Xr ipsec 4 . -In such a configuration, the syncdev should be set to the -.Xr enc 4 -interface, as this is where the traffic arrives when it is decapsulated, -e.g.: -.Bd -literal -offset indent -# ifconfig pfsync0 syncpeer 10.0.0.2 syncdev enc0 -.Ed +keyword. .Pp It is important that the pfsync traffic be well secured as there is no authentication on the protocol and it would be trivial to spoof packets which create states, bypassing the pf ruleset. Either run the pfsync protocol on a trusted network \- ideally a network -dedicated to pfsync messages such as a crossover cable between two firewalls, -or specify a peer address and protect the traffic with -.Xr ipsec 4 . +dedicated to pfsync messages such as a crossover cable between two firewalls. .Pp There is a one-to-one correspondence between packets seen by .Xr bpf 4 @@ -216,7 +207,6 @@ net.inet.carp.preempt=1 .Xr carp 4 , .Xr inet 4 , .Xr inet6 4 , -.Xr ipsec 4 , .Xr netintro 4 , .Xr pf 4 , .Xr pf.conf 5 , diff --git a/share/man/man4/safe.4 b/share/man/man4/safe.4 index 0ca6313c36..0b62b36cdb 100644 --- a/share/man/man4/safe.4 +++ b/share/man/man4/safe.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD: src/share/man/man4/safe.4,v 1.7 2006/04/01 10:56:36 brueffer Exp $ .\" -.Dd August 28, 2011 +.Dd April 21, 2018 .Dt SAFE 4 .Os .Sh NAME @@ -62,8 +62,6 @@ The .Nm driver registers itself to accelerate DES, Triple-DES, AES, MD5-HMAC, SHA1-HMAC, and NULL operations for -.Xr ipsec 4 -and .Xr crypto 4 . .Pp On all models, the driver registers itself to provide random data to the @@ -122,7 +120,6 @@ A faster version of the 1141. .Xr crypt 3 , .Xr crypto 4 , .Xr intro 4 , -.Xr ipsec 4 , .Xr random 4 , .Xr crypto 9 .Sh BUGS diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4 index 15d5d5b06c..1c6ab855be 100644 --- a/share/man/man4/tcp.4 +++ b/share/man/man4/tcp.4 @@ -28,7 +28,7 @@ .\" From: @(#)tcp.4 8.1 (Berkeley) 6/5/93 .\" $FreeBSD: src/share/man/man4/tcp.4,v 1.11.2.14 2002/12/29 16:35:38 schweikh Exp $ .\" -.Dd April 17, 2018 +.Dd April 21, 2018 .Dt TCP 4 .Os .Sh NAME @@ -475,8 +475,7 @@ address. .Xr blackhole 4 , .Xr inet 4 , .Xr intro 4 , -.Xr ip 4 , -.Xr setkey 8 +.Xr ip 4 .Rs .%A V. Jacobson .%A R. Braden diff --git a/share/man/man4/txp.4 b/share/man/man4/txp.4 index a5b10fce77..4dc085922f 100644 --- a/share/man/man4/txp.4 +++ b/share/man/man4/txp.4 @@ -1,6 +1,5 @@ .\" $OpenBSD: txp.4,v 1.8 2001/06/26 02:09:11 pjanzen Exp $ .\" $FreeBSD: src/share/man/man4/txp.4,v 1.1.2.2 2001/08/17 13:08:39 ru Exp $ -.\" $DragonFly: src/share/man/man4/txp.4,v 1.4 2007/02/25 12:03:07 swildner Exp $ .\" .\" Copyright (c) 2001 Jason L. Wright (jason@thought.net) .\" All rights reserved. @@ -31,7 +30,7 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd April 15, 2001 +.Dd April 21, 2018 .Dt TXP 4 .Os .Sh NAME @@ -75,16 +74,13 @@ and transmit .Xr ip 4 checksum offloading. -There is currently no support for -transmit +There is currently no support for transmit .Xr tcp 4 or .Xr udp 4 -checksum offloading, +checksum offloading, nor .Xr tcp 4 -segmentation, nor -.Xr ipsec 4 -acceleration. +segmentation. Note that hardware checksumming is only used when the interface is not in .Xr bridge 4 diff --git a/share/man/man4/ubsec.4 b/share/man/man4/ubsec.4 index e345ed3414..dfb504df0c 100644 --- a/share/man/man4/ubsec.4 +++ b/share/man/man4/ubsec.4 @@ -1,6 +1,5 @@ .\" $OpenBSD: ubsec.4,v 1.18 2002/09/26 07:55:41 miod Exp $ .\" $FreeBSD: src/share/man/man4/ubsec.4,v 1.1.2.1 2002/11/21 23:57:24 sam Exp $ -.\" $DragonFly: src/share/man/man4/ubsec.4,v 1.4 2007/05/12 21:22:10 swildner Exp $ .\" .\" Copyright (c) 2000 Jason L. Wright (jason@thought.net) .\" All rights reserved. @@ -31,7 +30,7 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd November 21, 2002 +.Dd April 21, 2018 .Dt UBSEC 4 .Os .Sh NAME @@ -72,8 +71,6 @@ The .Nm driver registers itself to accelerate DES, Triple-DES, MD5-HMAC, and SHA1-HMAC operations for -.Xr ipsec 4 -and .Xr crypto 4 . .Pp On those models which contain a public key engine (almost all of the @@ -89,7 +86,6 @@ subsystem. .Xr crypt 3 , .Xr crypto 4 , .Xr intro 4 , -.Xr ipsec 4 , .Xr random 4 , .Xr crypto 9 .Sh HISTORY diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index 4ec0a11d1f..66f3eda025 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD: src/share/man/man5/rc.conf.5,v 1.197 2003/07/28 13:56:00 mbr Exp $ .\" -.Dd March 29, 2018 +.Dd April 21, 2018 .Dt RC.CONF 5 .Os .Sh NAME @@ -2477,19 +2477,6 @@ should be large enough to fill as many of the entropy pools in the kernel CSPRNG as possible. By default, it is set to 16384, which should be able to seed all 32 entropy pools in the Fortuna CSPRNG. -.It Va ipsec_enable -.Pq Vt bool -Set to -.Dq Li YES -to run -.Xr setkey 8 -on -.Va ipsec_file -at boot time. -.It Va ipsec_file -.Pq Vt str -Configuration file for -.Xr setkey 8 . .It Va dmesg_enable .Pq Vt bool Set to diff --git a/share/man/man7/hier.7 b/share/man/man7/hier.7 index f10293875c..f30cf29b36 100644 --- a/share/man/man7/hier.7 +++ b/share/man/man7/hier.7 @@ -28,7 +28,7 @@ .\" @(#)hier.7 8.1 (Berkeley) 6/5/93 .\" $FreeBSD: src/share/man/man7/hier.7,v 1.29.2.17 2003/01/13 21:43:50 ceri Exp $ .\" -.Dd November 25, 2017 +.Dd April 21, 2018 .Dt HIER 7 .Os .Sh NAME @@ -233,8 +233,6 @@ see C include files for Internet protocol version 6; see .Xr inet6 4 -.It Pa netkey/ -kernel key-management service .It Pa netsmb/ SMB/CIFS requester .It Pa nfs/ diff --git a/share/man/man9/crypto.9 b/share/man/man9/crypto.9 index 4b0074f85c..7eb6d0ea9e 100644 --- a/share/man/man9/crypto.9 +++ b/share/man/man9/crypto.9 @@ -17,7 +17,7 @@ .\" .\" $FreeBSD: src/share/man/man9/crypto.9,v 1.14 2007/09/19 16:28:46 brueffer Exp $ .\" -.Dd August 21, 2010 +.Dd April 21, 2018 .Dt CRYPTO 9 .Os .Sh NAME @@ -166,9 +166,8 @@ For session initialization and teardown there is no callback mechanism used. .Pp The .Fn crypto_newsession -routine is called by consumers of cryptographic services (such as the -.Xr ipsec 4 -stack) that wish to establish a new session with the framework. +routine is called by consumers of cryptographic services +that wish to establish a new session with the framework. On success, the first argument will contain the Session Identifier (SID). The second argument contains all the necessary information for the driver to establish the session. @@ -233,9 +232,7 @@ by the device driver processing the request. Contains a pointer to another .Vt cryptoini structure. -Multiple such structures may be linked to establish multi-algorithm sessions -.Xr ( ipsec 4 -is an example consumer of such a feature). +Multiple such structures may be linked to establish multi-algorithm sessions. .El .Pp The @@ -391,9 +388,7 @@ at the location pointed to by The IV length is assumed to be equal to the blocksize of the encryption algorithm. Some applications that do special -.Dq "IV cooking" , -such as the half-IV mode in -.Xr ipsec 4 , +.Dq "IV cooking" can use this flag to indicate that the IV should not be written on the packet. This flag is typically used in conjunction with the .Dv CRD_F_IV_EXPLICIT @@ -410,9 +405,8 @@ operations it is pointed to by the field. This flag is typically used when the IV is calculated .Dq "on the fly" -by the consumer, and does not precede the data (some -.Xr ipsec 4 -configurations, and the encrypted swap are two such examples). +by the consumer, and does not precede the data +(encrypted swap being an example). .It Dv CRD_F_KEY_EXPLICIT For encryption and authentication (MAC) algorithms, this bit is set when the key is explicitly provided by the consumer in the @@ -437,8 +431,7 @@ framework may re-route requests as a result of full queues or hardware failure, as described above. .It Va crd_next Point to the next descriptor. -Linked operations are useful in protocols such as -.Xr ipsec 4 , +Linked operations are useful in protocols where multiple cryptographic transforms may be applied on the same block of data. .El @@ -658,7 +651,6 @@ field. most of the framework code .El .Sh SEE ALSO -.Xr ipsec 4 , .Xr kmalloc 9 , .Xr sleep 9 .Sh HISTORY diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index 4760495079..b920d0ceeb 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -37,7 +37,6 @@ LIBFL?= "don't use LIBFL, use LIBL" LIBFSID?= ${DESTDIR}${LIBDIR}/libfsid.a LIBFTPIO?= ${DESTDIR}${LIBDIR}/libftpio.a LIBHAMMER?= ${DESTDIR}${LIBDIR}/libhammer.a -LIBIPSEC?= ${DESTDIR}${LIBDIR}/libipsec.a LIBKCORE?= ${DESTDIR}${LIBDIR}/libkcore.a LIBKICONV?= ${DESTDIR}${LIBDIR}/libkiconv.a LIBKINFO?= ${DESTDIR}${LIBDIR}/libkinfo.a diff --git a/sys/conf/files b/sys/conf/files index 5498b794f5..c60537886d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -66,16 +66,7 @@ dev/disk/iscsi/initiator/isc_subr.c optional iscsi_initiator scbus dev/disk/iscsi/initiator/iscsi.c optional iscsi_initiator scbus dev/disk/iscsi/initiator/iscsi_subr.c optional iscsi_initiator scbus -crypto/blowfish/bf_skey.c optional ipsec ipsec_esp -crypto/des/des_ecb.c optional ipsec ipsec_esp -crypto/des/des_setkey.c optional ipsec ipsec_esp -crypto/rijndael/rijndael-alg-fst.c optional ipsec ipsec_esp -crypto/rijndael/rijndael-api-fst.c optional ipsec ipsec_esp -crypto/camellia/camellia.c optional ipsec ipsec_esp -crypto/camellia/camellia-api.c optional ipsec ipsec_esp -crypto/sha1.c optional ipsec crypto/sha1.c optional carp -opencrypto/cast.c optional ipsec ipsec_esp ddb/db_access.c optional ddb ddb/db_kld.c optional ddb ddb/db_break.c optional ddb @@ -1562,7 +1553,6 @@ net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rtsock.c standard -net/zlib.c optional ipsec netbt/bt_input.c optional bluetooth netbt/bt_proto.c optional bluetooth netbt/hci_event.c optional bluetooth @@ -1797,16 +1787,6 @@ netinet/tcp_syncache.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet netinet/udp_usrreq.c optional inet -netinet6/ah_core.c optional ipsec -netinet6/ah_input.c optional ipsec -netinet6/ah_output.c optional ipsec -netinet6/esp_core.c optional ipsec ipsec_esp -netinet6/esp_input.c optional ipsec ipsec_esp -netinet6/esp_output.c optional ipsec ipsec_esp -netinet6/esp_rijndael.c optional ipsec ipsec_esp -netinet6/esp_camellia.c optional ipsec ipsec_esp -netinet6/esp_aesctr.c optional ipsec ipsec_esp -netinet6/ipsec.c optional ipsec netinet6/dest6.c optional inet6 netinet6/frag6.c optional inet6 netinet6/icmp6.c optional inet6 @@ -1821,9 +1801,6 @@ netinet6/ip6_input.c optional inet6 netinet6/ip6_mroute.c optional inet6 netinet6/ip6_output.c optional inet6 netinet6/in6_src.c optional inet6 -netinet6/ipcomp_core.c optional ipsec -netinet6/ipcomp_input.c optional ipsec -netinet6/ipcomp_output.c optional ipsec netinet6/in6_pcb.c optional inet6 netinet6/in6_proto.c optional inet6 netinet6/in6_rmx.c optional inet6 @@ -1836,21 +1813,6 @@ netinet6/route6.c optional inet6 netinet6/scope6.c optional inet6 netinet6/udp6_output.c optional inet6 netinet6/udp6_usrreq.c optional inet6 -netproto/ipsec/ipsec.c optional fast_ipsec -netproto/ipsec/ipsec_input.c optional fast_ipsec -netproto/ipsec/ipsec_mbuf.c optional fast_ipsec -netproto/ipsec/ipsec_output.c optional fast_ipsec -netproto/ipsec/key.c optional fast_ipsec -netproto/ipsec/key_debug.c optional fast_ipsec -netproto/ipsec/keysock.c optional fast_ipsec -netproto/ipsec/xform_ah.c optional fast_ipsec -netproto/ipsec/xform_esp.c optional fast_ipsec -netproto/ipsec/xform_ipcomp.c optional fast_ipsec -netproto/ipsec/xform_ipip.c optional fast_ipsec -netproto/key/key.c optional ipsec -netproto/key/key_debug.c optional ipsec -netproto/key/keydb.c optional ipsec -netproto/key/keysock.c optional ipsec netproto/mpls/mpls_demux.c optional mpls netproto/mpls/mpls_input.c optional mpls netproto/mpls/mpls_output.c optional mpls @@ -2239,7 +2201,6 @@ libprop/prop_object.c standard libprop/prop_stack.c standard libprop/prop_string.c standard libprop/prop_rb.c standard -crypto/blowfish/bf_ecb.c optional ipsec ipsec_esp crypto/blowfish/bf_skey.c optional crypto crypto/camellia/camellia.c optional crypto crypto/camellia/camellia-api.c optional crypto diff --git a/sys/conf/options b/sys/conf/options index 7ed7fe0e8f..db30ea7b03 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -249,11 +249,6 @@ MROUTING opt_mrouting.h PIM opt_mrouting.h INET opt_inet.h INET6 opt_inet6.h -IPSEC opt_ipsec.h -IPSEC_ESP opt_ipsec.h -IPSEC_DEBUG opt_ipsec.h -IPSEC_FILTERGIF opt_ipsec.h -FAST_IPSEC opt_ipsec.h IPDIVERT DUMMYNET opt_ipdn.h DUMMYNET_DEBUG opt_ipdn.h @@ -681,3 +676,8 @@ EVDEV_DEBUG opt_evdev.h # Obsolete options (will be removed in the future) # FFS_ROOT opt_dontuse.h +FAST_IPSEC opt_dontuse.h +IPSEC opt_dontuse.h +IPSEC_DEBUG opt_dontuse.h +IPSEC_ESP opt_dontuse.h +IPSEC_FILTERGIF opt_dontuse.h diff --git a/sys/config/LINT64 b/sys/config/LINT64 index 5cad5c9cc3..63fc2b7e1c 100644 --- a/sys/config/LINT64 +++ b/sys/config/LINT64 @@ -218,36 +218,9 @@ options UCONSOLE # # Protocol families: # Only the INET (Internet) family is officially supported in DragonFly. -# Source code for the NS (Xerox Network Service) is provided for amusement -# value. # options INET #Internet communications protocols options INET6 #IPv6 communications protocols -options IPSEC #IP security -options IPSEC_ESP #IP security (crypto; define w/ IPSEC) -options IPSEC_DEBUG #debug for IP security -# -# Set IPSEC_FILTERGIF to force packets coming through a gif tunnel -# to be processed by any configured packet filtering (ipfw). -# The default is that packets coming from a tunnel are _not_ processed; -# they are assumed trusted. -# -# Note that enabling this can be problematic as there are no mechanisms -# in place for distinguishing packets coming out of a tunnel (e.g. no -# encX devices as found on openbsd). -# -#options IPSEC_FILTERGIF #filter ipsec packets from a tunnel - -# -# Experimental IPsec implementation that uses the kernel crypto -# framework. This cannot be configured together with IPSEC and -# (currently) supports only IPv4. To use this you must also -# configure the crypto device (see below). Note that with this -# you get all the IPsec protocols (e.g. there is no FAST_IPSEC_ESP). -# IPSEC_DEBUG is used, as above, to configure debugging support -# within the IPsec protocols. -# -#options FAST_IPSEC #new IPsec options MPLS #Multi-Protocol Label Switching @@ -417,15 +390,13 @@ options ACCEPT_FILTER_DATA options ACCEPT_FILTER_HTTP # TCP_SIGNATURE adds support for RFC 2385 (TCP-MD5) digests. These are -# carried in TCP option 19. This option is commonly used to protect -# TCP sessions (e.g. BGP) where IPSEC is not available nor desirable. +# carried in TCP option 19. # This is enabled on a per-socket basis using the TCP_SIGNATURE_ENABLE # socket option. -# This requires the use of 'device crypto', 'options IPSEC' -# or 'device cryptodev'. +# This requires the use of 'device crypto' or 'device cryptodev'. # -# XXX disabled for now until building with it (which broke after removing -# IPSEC) is fixed +# XXX disabled for now until building with it is fixed, which broke +* after removing IPsec. # #options TCP_SIGNATURE #include support for RFC 2385 @@ -2031,8 +2002,8 @@ options DCONS_FORCE_GDB=1 # force to be the gdb device # crypto subsystem # # This is a port of the openbsd crypto framework. Include this when -# configuring IPsec and when you have a h/w crypto device to accelerate -# user applications that link to openssl. +# you have a h/w crypto device to accelerate user applications that +# link to openssl. # # Drivers are ports from openbsd with some simple enhancements that have # been fed back to openbsd (and hopefully will be included). diff --git a/sys/config/VKERNEL64 b/sys/config/VKERNEL64 index 9d73176ad4..feac3e9901 100644 --- a/sys/config/VKERNEL64 +++ b/sys/config/VKERNEL64 @@ -32,10 +32,6 @@ options ALTQ_FAIRQ #fair queue #options ALTQ_NOPCC #don't use processor cycle counter options ALTQ_DEBUG #for debugging -options IPSEC #IP security -options IPSEC_ESP #IP security (crypto; define w/ IPSEC) -options IPSEC_DEBUG #debug for IP security - options HAMMER options HAMMER2 #HAMMER2 filesystem options NULLFS #NULL filesystem diff --git a/sys/crypto/blowfish/bf_ecb.c b/sys/crypto/blowfish/bf_ecb.c deleted file mode 100644 index adf4dbdde2..0000000000 --- a/sys/crypto/blowfish/bf_ecb.c +++ /dev/null @@ -1,85 +0,0 @@ -/* $FreeBSD: src/sys/crypto/blowfish/bf_ecb.c,v 1.1 2003/10/13 19:26:08 ume Exp $ */ - -/* crypto/bf/bf_ecb.c */ - -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * 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 copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#include -#include -#include - -/* Blowfish as implemented from 'Blowfish: Springer-Verlag paper' - * (From LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, - * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) - */ - -void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, - BF_KEY *key, int encrypt) - { - BF_LONG l,d[2]; - - n2l(in,l); d[0]=l; - n2l(in,l); d[1]=l; - if (encrypt) - BF_encrypt(d,key); - else - BF_decrypt(d,key); - l=d[0]; l2n(l,out); - l=d[1]; l2n(l,out); - l=d[0]=d[1]=0; - } diff --git a/sys/net/pf/if_pfsync.c b/sys/net/pf/if_pfsync.c index d927af2876..a0d2579bfe 100644 --- a/sys/net/pf/if_pfsync.c +++ b/sys/net/pf/if_pfsync.c @@ -470,9 +470,6 @@ pfsync_input(struct mbuf *m, ...) struct pfsync_state_clr *cp; struct pfsync_state_upd_req *rup; struct pfsync_state_bus *bus; -#ifdef IPSEC - struct pfsync_tdb *pt; -#endif struct in_addr src; struct mbuf *mp; int iplen, action, error, i, count, offp, sfail, stale = 0; @@ -997,20 +994,6 @@ pfsync_input(struct mbuf *m, ...) break; } break; -#ifdef IPSEC - case PFSYNC_ACT_TDB_UPD: - if ((mp = m_pulldown(m, iplen + sizeof(*ph), - count * sizeof(*pt), &offp)) == NULL) { - pfsyncstats.pfsyncs_badlen++; - return; - } - crit_enter(); - for (i = 0, pt = (struct pfsync_tdb *)(mp->m_data + offp); - i < count; i++, pt++) - pfsync_update_net_tdb(pt); - crit_exit(); - break; -#endif } done: diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h deleted file mode 100644 index e94e123fc3..0000000000 --- a/sys/net/pfkeyv2.h +++ /dev/null @@ -1,402 +0,0 @@ -/* $FreeBSD: src/sys/net/pfkeyv2.h,v 1.14.2.1 2007/12/07 08:45:28 gnn Exp $ */ -/* $KAME: pfkeyv2.h,v 1.37 2003/09/06 05:15:43 itojun Exp $ */ - -/*- - * 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. - */ - -/* - * This file has been derived rfc 2367, - * And added some flags of SADB_KEY_FLAGS_ as SADB_X_EXT_. - * sakane@ydc.co.jp - */ - -#ifndef _NET_PFKEYV2_H_ -#define _NET_PFKEYV2_H_ - -#ifndef _SYS_TYPES_H_ -#include -#endif - -/* -This file defines structures and symbols for the PF_KEY Version 2 -key management interface. It was written at the U.S. Naval Research -Laboratory. This file is in the public domain. The authors ask that -you leave this credit intact on any copies of this file. -*/ -#ifndef __PFKEY_V2_H -#define __PFKEY_V2_H 1 - -#define PF_KEY_V2 2 -#define PFKEYV2_REVISION 199806L - -#define SADB_RESERVED 0 -#define SADB_GETSPI 1 -#define SADB_UPDATE 2 -#define SADB_ADD 3 -#define SADB_DELETE 4 -#define SADB_GET 5 -#define SADB_ACQUIRE 6 -#define SADB_REGISTER 7 -#define SADB_EXPIRE 8 -#define SADB_FLUSH 9 -#define SADB_DUMP 10 -#define SADB_X_PROMISC 11 -#define SADB_X_PCHANGE 12 - -#define SADB_X_SPDUPDATE 13 -#define SADB_X_SPDADD 14 -#define SADB_X_SPDDELETE 15 /* by policy index */ -#define SADB_X_SPDGET 16 -#define SADB_X_SPDACQUIRE 17 -#define SADB_X_SPDDUMP 18 -#define SADB_X_SPDFLUSH 19 -#define SADB_X_SPDSETIDX 20 -#define SADB_X_SPDEXPIRE 21 -#define SADB_X_SPDDELETE2 22 /* by policy id */ -#define SADB_MAX 22 - -struct sadb_msg { - u_int8_t sadb_msg_version; - u_int8_t sadb_msg_type; - u_int8_t sadb_msg_errno; - u_int8_t sadb_msg_satype; - u_int16_t sadb_msg_len; - u_int16_t sadb_msg_reserved; - u_int32_t sadb_msg_seq; - u_int32_t sadb_msg_pid; -}; - -struct sadb_ext { - u_int16_t sadb_ext_len; - u_int16_t sadb_ext_type; -}; - -struct sadb_sa { - u_int16_t sadb_sa_len; - u_int16_t sadb_sa_exttype; - u_int32_t sadb_sa_spi; - u_int8_t sadb_sa_replay; - u_int8_t sadb_sa_state; - u_int8_t sadb_sa_auth; - u_int8_t sadb_sa_encrypt; - u_int32_t sadb_sa_flags; -}; - -struct sadb_lifetime { - u_int16_t sadb_lifetime_len; - u_int16_t sadb_lifetime_exttype; - u_int32_t sadb_lifetime_allocations; - u_int64_t sadb_lifetime_bytes; - u_int64_t sadb_lifetime_addtime; - u_int64_t sadb_lifetime_usetime; -}; - -struct sadb_address { - u_int16_t sadb_address_len; - u_int16_t sadb_address_exttype; - u_int8_t sadb_address_proto; - u_int8_t sadb_address_prefixlen; - u_int16_t sadb_address_reserved; -}; - -struct sadb_key { - u_int16_t sadb_key_len; - u_int16_t sadb_key_exttype; - u_int16_t sadb_key_bits; - u_int16_t sadb_key_reserved; -}; - -struct sadb_ident { - u_int16_t sadb_ident_len; - u_int16_t sadb_ident_exttype; - u_int16_t sadb_ident_type; - u_int16_t sadb_ident_reserved; - u_int64_t sadb_ident_id; -}; - -struct sadb_sens { - u_int16_t sadb_sens_len; - u_int16_t sadb_sens_exttype; - u_int32_t sadb_sens_dpd; - u_int8_t sadb_sens_sens_level; - u_int8_t sadb_sens_sens_len; - u_int8_t sadb_sens_integ_level; - u_int8_t sadb_sens_integ_len; - u_int32_t sadb_sens_reserved; -}; - -struct sadb_prop { - u_int16_t sadb_prop_len; - u_int16_t sadb_prop_exttype; - u_int8_t sadb_prop_replay; - u_int8_t sadb_prop_reserved[3]; -}; - -struct sadb_comb { - u_int8_t sadb_comb_auth; - u_int8_t sadb_comb_encrypt; - u_int16_t sadb_comb_flags; - u_int16_t sadb_comb_auth_minbits; - u_int16_t sadb_comb_auth_maxbits; - u_int16_t sadb_comb_encrypt_minbits; - u_int16_t sadb_comb_encrypt_maxbits; - u_int32_t sadb_comb_reserved; - u_int32_t sadb_comb_soft_allocations; - u_int32_t sadb_comb_hard_allocations; - u_int64_t sadb_comb_soft_bytes; - u_int64_t sadb_comb_hard_bytes; - u_int64_t sadb_comb_soft_addtime; - u_int64_t sadb_comb_hard_addtime; - u_int64_t sadb_comb_soft_usetime; - u_int64_t sadb_comb_hard_usetime; -}; - -struct sadb_supported { - u_int16_t sadb_supported_len; - u_int16_t sadb_supported_exttype; - u_int32_t sadb_supported_reserved; -}; - -struct sadb_alg { - u_int8_t sadb_alg_id; - u_int8_t sadb_alg_ivlen; - u_int16_t sadb_alg_minbits; - u_int16_t sadb_alg_maxbits; - u_int16_t sadb_alg_reserved; -}; - -struct sadb_spirange { - u_int16_t sadb_spirange_len; - u_int16_t sadb_spirange_exttype; - u_int32_t sadb_spirange_min; - u_int32_t sadb_spirange_max; - u_int32_t sadb_spirange_reserved; -}; - -struct sadb_x_kmprivate { - u_int16_t sadb_x_kmprivate_len; - u_int16_t sadb_x_kmprivate_exttype; - u_int32_t sadb_x_kmprivate_reserved; -}; - -/* - * XXX Additional SA Extension. - * mode: tunnel or transport - * reqid: to make SA unique nevertheless the address pair of SA are same. - * Mainly it's for VPN. - */ -struct sadb_x_sa2 { - u_int16_t sadb_x_sa2_len; - u_int16_t sadb_x_sa2_exttype; - u_int8_t sadb_x_sa2_mode; - u_int8_t sadb_x_sa2_reserved1; - u_int16_t sadb_x_sa2_reserved2; - u_int32_t sadb_x_sa2_sequence; /* lowermost 32bit of sequence number */ - u_int32_t sadb_x_sa2_reqid; -}; - -/* XXX Policy Extension */ -/* sizeof(struct sadb_x_policy) == 16 */ -struct sadb_x_policy { - u_int16_t sadb_x_policy_len; - u_int16_t sadb_x_policy_exttype; - u_int16_t sadb_x_policy_type; /* See policy type of ipsec.h */ - u_int8_t sadb_x_policy_dir; /* direction, see ipsec.h */ - u_int8_t sadb_x_policy_reserved; - u_int32_t sadb_x_policy_id; - u_int32_t sadb_x_policy_reserved2; -}; -/* - * When policy_type == IPSEC, it is followed by some of - * the ipsec policy request. - * [total length of ipsec policy requests] - * = (sadb_x_policy_len * sizeof(uint64_t) - sizeof(struct sadb_x_policy)) - */ - -/* XXX IPsec Policy Request Extension */ -/* - * This structure is aligned 8 bytes. - */ -struct sadb_x_ipsecrequest { - u_int16_t sadb_x_ipsecrequest_len; /* structure length in 64 bits. */ - u_int16_t sadb_x_ipsecrequest_proto; /* See ipsec.h */ - u_int8_t sadb_x_ipsecrequest_mode; /* See IPSEC_MODE_XX in ipsec.h. */ - u_int8_t sadb_x_ipsecrequest_level; /* See IPSEC_LEVEL_XX in ipsec.h */ - u_int16_t sadb_x_ipsecrequest_reqid; /* See ipsec.h */ - - /* - * followed by source IP address of SA, and immediately followed by - * destination IP address of SA. These encoded into two of sockaddr - * structure without any padding. Must set each sa_len exactly. - * Each of length of the sockaddr structure are not aligned to 64bits, - * but sum of x_request and addresses is aligned to 64bits. - */ -}; - -#define SADB_EXT_RESERVED 0 -#define SADB_EXT_SA 1 -#define SADB_EXT_LIFETIME_CURRENT 2 -#define SADB_EXT_LIFETIME_HARD 3 -#define SADB_EXT_LIFETIME_SOFT 4 -#define SADB_EXT_ADDRESS_SRC 5 -#define SADB_EXT_ADDRESS_DST 6 -#define SADB_EXT_ADDRESS_PROXY 7 -#define SADB_EXT_KEY_AUTH 8 -#define SADB_EXT_KEY_ENCRYPT 9 -#define SADB_EXT_IDENTITY_SRC 10 -#define SADB_EXT_IDENTITY_DST 11 -#define SADB_EXT_SENSITIVITY 12 -#define SADB_EXT_PROPOSAL 13 -#define SADB_EXT_SUPPORTED_AUTH 14 -#define SADB_EXT_SUPPORTED_ENCRYPT 15 -#define SADB_EXT_SPIRANGE 16 -#define SADB_X_EXT_KMPRIVATE 17 -#define SADB_X_EXT_POLICY 18 -#define SADB_X_EXT_SA2 19 -#define SADB_EXT_MAX 19 - -#define SADB_SATYPE_UNSPEC 0 -#define SADB_SATYPE_AH 2 -#define SADB_SATYPE_ESP 3 -#define SADB_SATYPE_RSVP 5 -#define SADB_SATYPE_OSPFV2 6 -#define SADB_SATYPE_RIPV2 7 -#define SADB_SATYPE_MIP 8 -#define SADB_X_SATYPE_IPCOMP 9 -/*#define SADB_X_SATYPE_POLICY 10 obsolete, do not reuse */ -#define SADB_X_SATYPE_TCPSIGNATURE 11 -#define SADB_SATYPE_MAX 12 - -#define SADB_SASTATE_LARVAL 0 -#define SADB_SASTATE_MATURE 1 -#define SADB_SASTATE_DYING 2 -#define SADB_SASTATE_DEAD 3 -#define SADB_SASTATE_MAX 3 - -#define SADB_SAFLAGS_PFS 1 - -/* RFC2367 numbers - meets RFC2407 */ -#define SADB_AALG_NONE 0 -#define SADB_AALG_MD5HMAC 2 -#define SADB_AALG_SHA1HMAC 3 -#define SADB_AALG_MAX 252 -/* private allocations - based on RFC2407/IANA assignment */ -#define SADB_X_AALG_SHA2_256 5 -#define SADB_X_AALG_SHA2_384 6 -#define SADB_X_AALG_SHA2_512 7 -#define SADB_X_AALG_RIPEMD160HMAC 8 -#define SADB_X_AALG_AES_XCBC_MAC 9 /* draft-ietf-ipsec-ciph-aes-xcbc-mac-04 */ -/* private allocations should use 249-255 (RFC2407) */ -#define SADB_X_AALG_MD5 249 /* Keyed MD5 */ -#define SADB_X_AALG_SHA 250 /* Keyed SHA */ -#define SADB_X_AALG_NULL 251 /* null authentication */ -#define SADB_X_AALG_TCP_MD5 252 /* Keyed TCP-MD5 (RFC2385) */ - -/* RFC2367 numbers - meets RFC2407 */ -#define SADB_EALG_NONE 0 -#define SADB_EALG_DESCBC 2 -#define SADB_EALG_3DESCBC 3 -#define SADB_EALG_NULL 11 -#define SADB_EALG_MAX 250 -/* private allocations - based on RFC2407/IANA assignment */ -#define SADB_X_EALG_CAST128CBC 6 -#define SADB_X_EALG_BLOWFISHCBC 7 -#define SADB_X_EALG_RIJNDAELCBC 12 -#define SADB_X_EALG_AES 12 -/* private allocations - based on RFC4312/IANA assignment */ -#define SADB_X_EALG_CAMELLIACBC 22 - -/* private allocations should use 249-255 (RFC2407) */ -#define SADB_X_EALG_SKIPJACK 249 /*250*/ /* for FAST_IPSEC */ -#define SADB_X_EALG_AESCTR 250 /*249*/ /* draft-ietf-ipsec-ciph-aes-ctr-03 */ - -/* private allocations - based on RFC2407/IANA assignment */ -#define SADB_X_CALG_NONE 0 -#define SADB_X_CALG_OUI 1 -#define SADB_X_CALG_DEFLATE 2 -#define SADB_X_CALG_LZS 3 -#define SADB_X_CALG_MAX 4 - -#define SADB_IDENTTYPE_RESERVED 0 -#define SADB_IDENTTYPE_PREFIX 1 -#define SADB_IDENTTYPE_FQDN 2 -#define SADB_IDENTTYPE_USERFQDN 3 -#define SADB_X_IDENTTYPE_ADDR 4 -#define SADB_IDENTTYPE_MAX 4 - -/* `flags' in sadb_sa structure holds followings */ -#define SADB_X_EXT_NONE 0x0000 /* i.e. new format. */ -#define SADB_X_EXT_OLD 0x0001 /* old format. */ - -#define SADB_X_EXT_IV4B 0x0010 /* IV length of 4 bytes in use */ -#define SADB_X_EXT_DERIV 0x0020 /* DES derived */ -#define SADB_X_EXT_CYCSEQ 0x0040 /* allowing to cyclic sequence. */ - - /* three of followings are exclusive flags each them */ -#define SADB_X_EXT_PSEQ 0x0000 /* sequencial padding for ESP */ -#define SADB_X_EXT_PRAND 0x0100 /* random padding for ESP */ -#define SADB_X_EXT_PZERO 0x0200 /* zero padding for ESP */ -#define SADB_X_EXT_PMASK 0x0300 /* mask for padding flag */ - -#if 1 -#define SADB_X_EXT_RAWCPI 0x0080 /* use well known CPI (IPComp) */ -#endif - -#define SADB_KEY_FLAGS_MAX 0x0fff - -/* SPI size for PF_KEYv2 */ -#define PFKEY_SPI_SIZE sizeof(u_int32_t) - -/* Identifier for menber of lifetime structure */ -#define SADB_X_LIFETIME_ALLOCATIONS 0 -#define SADB_X_LIFETIME_BYTES 1 -#define SADB_X_LIFETIME_ADDTIME 2 -#define SADB_X_LIFETIME_USETIME 3 - -/* The rate for SOFT lifetime against HARD one. */ -#define PFKEY_SOFT_LIFETIME_RATE 80 - -/* Utilities */ -#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) -#define PFKEY_EXTLEN(msg) \ - PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len) -#define PFKEY_ADDR_PREFIX(ext) \ - (((struct sadb_address *)(ext))->sadb_address_prefixlen) -#define PFKEY_ADDR_PROTO(ext) \ - (((struct sadb_address *)(ext))->sadb_address_proto) -#define PFKEY_ADDR_SADDR(ext) \ - ((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address))) - -/* in 64bits */ -#define PFKEY_UNUNIT64(a) ((a) << 3) -#define PFKEY_UNIT64(a) ((a) >> 3) - -#endif /* __PFKEY_V2_H */ - -#endif /* _NET_PFKEYV2_H_ */ diff --git a/sys/netinet/in.h b/sys/netinet/in.h index dc5479c190..f8c1abe095 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -346,8 +346,6 @@ struct sockaddr_in { #define IP_RSVP_VIF_OFF 18 /* unset RSVP per-vif socket */ #define IP_PORTRANGE 19 /* int; range to choose for unspec port */ #define IP_RECVIF 20 /* bool; receive reception if w/dgram */ -/* for IPSEC */ -#define IP_IPSEC_POLICY 21 /* int; set/get security policy */ #define IP_FW_TBL_CREATE 40 /* create ipfw table */ #define IP_FW_TBL_DESTROY 41 /* destroy ipfw table */ @@ -457,7 +455,7 @@ struct ip_mreq { { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ - { "ipsec", CTLTYPE_NODE }, \ + { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 50c42560dd..a6aa6d47fe 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -63,7 +63,6 @@ * $FreeBSD: src/sys/netinet/in_pcb.c,v 1.59.2.27 2004/01/02 04:06:42 ambrisko Exp $ */ -#include "opt_ipsec.h" #include "opt_inet6.h" #include @@ -101,22 +100,6 @@ #include #endif /* INET6 */ -#ifdef IPSEC -#include -#include -#include -#endif - -#ifdef FAST_IPSEC -#if defined(IPSEC) || defined(IPSEC_ESP) -#error "Bad idea: don't compile with both IPSEC and FAST_IPSEC!" -#endif - -#include -#include -#define IPSEC -#endif /* FAST_IPSEC */ - #define INP_LOCALGROUP_SIZMIN 8 #define INP_LOCALGROUP_SIZMAX 256 @@ -247,11 +230,6 @@ in_baddynamic(u_int16_t port, u_int16_t proto) case IPPROTO_TCP: return (DP_ISSET(baddynamicports.tcp, port)); case IPPROTO_UDP: -#ifdef IPSEC - /* Cannot preset this as it is a sysctl */ - if (port == udpencap_port) - return (1); -#endif return (DP_ISSET(baddynamicports.udp, port)); default: return (0); @@ -299,9 +277,6 @@ int in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo) { struct inpcb *inp; -#ifdef IPSEC - int error; -#endif inp = kmalloc(pcbinfo->ipi_size, M_PCB, M_WAITOK|M_ZERO|M_NULLOK); if (inp == NULL) @@ -310,13 +285,6 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo) inp->inp_gencnt = ++pcbinfo->ipi_gencnt; inp->inp_pcbinfo = pcbinfo; inp->inp_socket = so; -#ifdef IPSEC - error = ipsec_init_policy(so, &inp->inp_sp); - if (error != 0) { - kfree(inp, M_PCB); - return (error); - } -#endif #ifdef INET6 if (INP_CHECK_SOCKAF(so, AF_INET6)) { if (ip6_auto_flowlabel) @@ -1063,9 +1031,6 @@ in_pcbdetach(struct inpcb *inp) struct socket *so = inp->inp_socket; struct inpcbinfo *ipi = inp->inp_pcbinfo; -#ifdef IPSEC - ipsec4_delete_pcbpolicy(inp); -#endif /*IPSEC*/ inp->inp_gencnt = ++ipi->ipi_gencnt; KKASSERT((so->so_state & SS_ASSERTINPROG) == 0); in_pcbremlists(inp); diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 83d522eeff..85566812a8 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -80,8 +80,6 @@ #endif #define in6pcb inpcb /* for KAME src sync over BSD*'s */ -#define in6p_sp inp_sp /* for KAME src sync over BSD*'s */ -struct inpcbpolicy; /* * Common structure pcb for internet protocol implementation. @@ -200,7 +198,7 @@ struct inpcb { uint16_t inp_hashval; /* valid iff INP_HASH */ uint16_t inp_pad; /* explicit padding */ - struct inpcbpolicy *inp_sp; /* for IPSEC */ + void *inp_unused1; /* was: for IPSEC */ u_char inp_af; /* AF_INET or AF_INET6 */ u_char inp_ip_ttl; /* time to live proto */ u_char inp_ip_p; /* protocol proto */ diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 54e8815059..8f2372ed18 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -32,7 +32,6 @@ #include "opt_ipdivert.h" #include "opt_mrouting.h" -#include "opt_ipsec.h" #include "opt_inet6.h" #include "opt_carp.h" @@ -71,19 +70,6 @@ * TCP/IP protocol family: IP, ICMP, UDP, TCP. */ -#ifdef IPSEC -#include -#include -#ifdef IPSEC_ESP -#include -#endif -#include -#endif /* IPSEC */ - -#ifdef FAST_IPSEC -#include -#endif /* FAST_IPSEC */ - #include /* for cpu0_soport */ #ifdef CARP @@ -197,96 +183,6 @@ struct protosw inetsw[] = { .pr_usrreqs = &rip_usrreqs }, -#ifdef IPSEC - { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_AH, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = ah4_input, - .pr_output = NULL, - .pr_ctlinput = NULL, - .pr_ctloutput = NULL, - - .pr_ctlport = NULL, - .pr_usrreqs = &nousrreqs - }, -#ifdef IPSEC_ESP - { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_ESP, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = esp4_input, - .pr_output = NULL, - .pr_ctlinput = NULL, - .pr_ctloutput = NULL, - - .pr_ctlport = NULL, - .pr_usrreqs = &nousrreqs - }, -#endif - { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_IPCOMP, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = ipcomp4_input, - .pr_output = 0, - .pr_ctlinput = NULL, - .pr_ctloutput = NULL, - - .pr_ctlport = NULL, - .pr_usrreqs = &nousrreqs - }, -#endif /* IPSEC */ -#ifdef FAST_IPSEC - { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_AH, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = ipsec4_common_input, - .pr_output = NULL, - .pr_ctlinput = NULL, - .pr_ctloutput = NULL, - - .pr_ctlport = NULL, - .pr_usrreqs = &nousrreqs - }, - { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_ESP, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = ipsec4_common_input, - .pr_output = NULL, - .pr_ctlinput = NULL, - .pr_ctloutput = NULL, - - .pr_ctlport = NULL, - .pr_usrreqs = &nousrreqs - }, - { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_IPCOMP, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = ipsec4_common_input, - .pr_output = NULL, - .pr_ctlinput = NULL, - .pr_ctloutput = NULL, - - .pr_ctlport = NULL, - .pr_usrreqs = &nousrreqs - }, -#endif /* FAST_IPSEC */ { .pr_type = SOCK_RAW, .pr_domain = &inetdomain, @@ -463,18 +359,6 @@ SYSCTL_NODE(_net_inet, IPPROTO_ICMP, icmp, CTLFLAG_RW, 0, "ICMP"); SYSCTL_NODE(_net_inet, IPPROTO_UDP, udp, CTLFLAG_RW, 0, "UDP"); SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp, CTLFLAG_RW, 0, "TCP"); SYSCTL_NODE(_net_inet, IPPROTO_IGMP, igmp, CTLFLAG_RW, 0, "IGMP"); -#ifdef FAST_IPSEC -/* XXX no protocol # to use, pick something "reserved" */ -SYSCTL_NODE(_net_inet, 253, ipsec, CTLFLAG_RW, 0, "IPSEC"); -SYSCTL_NODE(_net_inet, IPPROTO_AH, ah, CTLFLAG_RW, 0, "AH"); -SYSCTL_NODE(_net_inet, IPPROTO_ESP, esp, CTLFLAG_RW, 0, "ESP"); -SYSCTL_NODE(_net_inet, IPPROTO_IPCOMP, ipcomp, CTLFLAG_RW, 0, "IPCOMP"); -SYSCTL_NODE(_net_inet, IPPROTO_IPIP, ipip, CTLFLAG_RW, 0, "IPIP"); -#else -#ifdef IPSEC -SYSCTL_NODE(_net_inet, IPPROTO_AH, ipsec, CTLFLAG_RW, 0, "IPSEC"); -#endif /* IPSEC */ -#endif /* !FAST_IPSEC */ SYSCTL_NODE(_net_inet, IPPROTO_RAW, raw, CTLFLAG_RW, 0, "RAW"); #ifdef IPDIVERT SYSCTL_NODE(_net_inet, IPPROTO_DIVERT, divert, CTLFLAG_RW, 0, "DIVERT"); diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index 273f1720fe..9b77b928f2 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -33,7 +33,6 @@ #include "opt_inet.h" #include "opt_ipdivert.h" -#include "opt_ipsec.h" #ifndef INET #error "IPDIVERT requires INET." diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 9d7920d5c7..28024feeb6 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -30,8 +30,6 @@ * $FreeBSD: src/sys/netinet/ip_icmp.c,v 1.39.2.19 2003/01/24 05:11:34 sam Exp $ */ -#include "opt_ipsec.h" - #include #include #include @@ -60,17 +58,6 @@ #include #include -#ifdef IPSEC -#include -#include -#endif - -#ifdef FAST_IPSEC -#include -#include -#define IPSEC -#endif - /* * ICMP routines: error generation, receive packet processing, and * routines to turnaround packets back to the originator, and @@ -508,13 +495,7 @@ icmp_redirect_done_handler(netmsg_t nmsg) struct netmsg_ctlinput *msg = (struct netmsg_ctlinput *)nmsg; struct mbuf *m = msg->m; int hlen = msg->hlen; -#ifdef IPSEC - struct sockaddr_in icmpsrc = { sizeof(struct sockaddr_in), AF_INET }; - struct icmp *icp = mtodoff(m, struct icmp *, hlen);; - icmpsrc.sin_addr = icp->icmp_ip.ip_dst; - key_sa_routechange((struct sockaddr *)&icmpsrc); -#endif rip_input(&m, &hlen, msg->proto); } @@ -912,9 +893,6 @@ reflect: return IPPROTO_DONE; } /* Move on; run rip_input() directly */ -#ifdef IPSEC - key_sa_routechange((struct sockaddr *)&icmpsrc); -#endif break; /* diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 62ae5b0b8a..0862ee5c9c 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -69,7 +69,6 @@ #include "opt_ipdn.h" #include "opt_ipdivert.h" #include "opt_ipstealth.h" -#include "opt_ipsec.h" #include "opt_rss.h" #include @@ -120,16 +119,6 @@ #include #include -#ifdef IPSEC -#include -#include -#endif - -#ifdef FAST_IPSEC -#include -#include -#endif - int rsvp_on = 0; static int ip_rsvp_on; struct socket *ip_rsvpd; @@ -468,11 +457,6 @@ ip_input(struct mbuf *m) struct m_tag *mtag; struct sockaddr_in *next_hop = NULL; lwkt_port_t port; -#ifdef FAST_IPSEC - struct tdb_ident *tdbi; - struct secpolicy *sp; - int error; -#endif ASSERT_NETISR_NCPUS(mycpuid); M_ASSERTPKTHDR(m); @@ -597,13 +581,6 @@ ip_input(struct mbuf *m) m_adj(m, ip->ip_len - m->m_pkthdr.len); } } -#if defined(IPSEC) && !defined(IPSEC_FILTERGIF) - /* - * Bypass packet filtering for packets from a tunnel (gif). - */ - if (ipsec_gethist(m, NULL)) - goto pass; -#endif /* * IpHack's section. @@ -831,43 +808,6 @@ pass: ipstat.ips_cantforward++; m_freem(m); } else { -#ifdef IPSEC - /* - * Enforce inbound IPsec SPD. - */ - if (ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; - goto bad; - } -#endif -#ifdef FAST_IPSEC - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - crit_enter(); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)m_tag_data(mtag); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); - } else { - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } - if (sp == NULL) { /* NB: can happen if error */ - crit_exit(); - /*XXX error stat???*/ - DPRINTF(("ip_input: no SP for forwarding\n")); /*XXX*/ - goto bad; - } - - /* - * Check security policy against packet attributes. - */ - error = ipsec_in_reject(sp, m); - KEY_FREESP(&sp); - crit_exit(); - if (error) { - ipstat.ips_cantforward++; - goto bad; - } -#endif ip_forward(m, using_srcrt, next_hop); } return; @@ -915,58 +855,6 @@ ours: ip->ip_len -= hlen; } -#ifdef IPSEC - /* - * enforce IPsec policy checking if we are seeing last header. - * note that we do not visit this with protocols with pcb layer - * code - like udp/tcp/raw ip. - */ - if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) && - ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; - goto bad; - } -#endif -#ifdef FAST_IPSEC - /* - * enforce IPsec policy checking if we are seeing last header. - * note that we do not visit this with protocols with pcb layer - * code - like udp/tcp/raw ip. - */ - if (inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) { - /* - * Check if the packet has already had IPsec processing - * done. If so, then just pass it along. This tag gets - * set during AH, ESP, etc. input handling, before the - * packet is returned to the ip input queue for delivery. - */ - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - crit_enter(); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)m_tag_data(mtag); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); - } else { - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } - if (sp != NULL) { - /* - * Check security policy against packet attributes. - */ - error = ipsec_in_reject(sp, m); - KEY_FREESP(&sp); - } else { - /* XXX error stat??? */ - error = EINVAL; -DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/ - crit_exit(); - goto bad; - } - crit_exit(); - if (error) - goto bad; - } -#endif /* FAST_IPSEC */ /* * We must forward the packet to the correct protocol thread if @@ -2133,101 +2021,8 @@ ip_forward(struct mbuf *m, boolean_t using_srcrt, struct sockaddr_in *next_hop) case EMSGSIZE: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; -#ifdef IPSEC - /* - * If the packet is routed over IPsec tunnel, tell the - * originator the tunnel MTU. - * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz - * XXX quickhack!!! - */ - if (fwd_ro.ro_rt != NULL) { - struct secpolicy *sp = NULL; - int ipsecerror; - int ipsechdr; - struct route *ro; - - sp = ipsec4_getpolicybyaddr(mcopy, - IPSEC_DIR_OUTBOUND, - IP_FORWARDING, - &ipsecerror); - - if (sp == NULL) - destmtu = fwd_ro.ro_rt->rt_ifp->if_mtu; - else { - /* count IPsec header size */ - ipsechdr = ipsec4_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, - NULL); - - /* - * find the correct route for outer IPv4 - * header, compute tunnel MTU. - * - */ - if (sp->req != NULL && sp->req->sav != NULL && - sp->req->sav->sah != NULL) { - ro = &sp->req->sav->sah->sa_route; - if (ro->ro_rt != NULL && - ro->ro_rt->rt_ifp != NULL) { - destmtu = - ro->ro_rt->rt_ifp->if_mtu; - destmtu -= ipsechdr; - } - } - - key_freesp(sp); - } - } -#elif defined(FAST_IPSEC) - /* - * If the packet is routed over IPsec tunnel, tell the - * originator the tunnel MTU. - * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz - * XXX quickhack!!! - */ - if (fwd_ro.ro_rt != NULL) { - struct secpolicy *sp = NULL; - int ipsecerror; - int ipsechdr; - struct route *ro; - - sp = ipsec_getpolicybyaddr(mcopy, - IPSEC_DIR_OUTBOUND, - IP_FORWARDING, - &ipsecerror); - - if (sp == NULL) - destmtu = fwd_ro.ro_rt->rt_ifp->if_mtu; - else { - /* count IPsec header size */ - ipsechdr = ipsec4_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, - NULL); - - /* - * find the correct route for outer IPv4 - * header, compute tunnel MTU. - */ - - if (sp->req != NULL && - sp->req->sav != NULL && - sp->req->sav->sah != NULL) { - ro = &sp->req->sav->sah->sa_route; - if (ro->ro_rt != NULL && - ro->ro_rt->rt_ifp != NULL) { - destmtu = - ro->ro_rt->rt_ifp->if_mtu; - destmtu -= ipsechdr; - } - } - - KEY_FREESP(&sp); - } - } -#else /* !IPSEC && !FAST_IPSEC */ if (fwd_ro.ro_rt != NULL) destmtu = fwd_ro.ro_rt->rt_ifp->if_mtu; -#endif /*IPSEC*/ ipstat.ips_cantfrag++; break; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index c97538d52e..05723f5dd0 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -34,7 +34,6 @@ #include "opt_ipdn.h" #include "opt_ipdivert.h" -#include "opt_ipsec.h" #include "opt_mbuf_stress_test.h" #include "opt_mpls.h" @@ -72,22 +71,6 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options"); -#ifdef IPSEC -#include -#include -#ifdef IPSEC_DEBUG -#include -#else -#define KEYDEBUG(lev,arg) -#endif -#endif /*IPSEC*/ - -#ifdef FAST_IPSEC -#include -#include -#include -#endif /*FAST_IPSEC*/ - #include #include @@ -202,14 +185,6 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, struct in_addr pkt_dst; struct route iproute; struct m_tag *mtag; -#ifdef IPSEC - struct secpolicy *sp = NULL; - struct socket *so = inp ? inp->inp_socket : NULL; -#endif -#ifdef FAST_IPSEC - struct secpolicy *sp = NULL; - struct tdb_ident *tdbi; -#endif /* FAST_IPSEC */ struct sockaddr_in *next_hop = NULL; int src_was_INADDR_ANY = 0; /* as the name says... */ @@ -527,255 +502,6 @@ reroute: } sendit: -#ifdef IPSEC - /* get SP for this packet */ - if (so == NULL) - sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error); - else - sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error); - - if (sp == NULL) { - ipsecstat.out_inval++; - goto bad; - } - - error = 0; - - /* check policy */ - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - /* - * This packet is just discarded. - */ - ipsecstat.out_polvio++; - goto bad; - - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_NONE: - case IPSEC_POLICY_TCP: - /* no need to do IPsec. */ - goto skip_ipsec; - - case IPSEC_POLICY_IPSEC: - if (sp->req == NULL) { - /* acquire a policy */ - error = key_spdacquire(sp); - goto bad; - } - break; - - case IPSEC_POLICY_ENTRUST: - default: - kprintf("ip_output: Invalid policy found. %d\n", sp->policy); - } - { - struct ipsec_output_state state; - bzero(&state, sizeof state); - state.m = m; - if (flags & IP_ROUTETOIF) { - state.ro = &iproute; - bzero(&iproute, sizeof iproute); - } else - state.ro = ro; - state.dst = (struct sockaddr *)dst; - - ip->ip_sum = 0; - - /* - * XXX - * delayed checksums are not currently compatible with IPsec - */ - if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { - in_delayed_cksum(m); - m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; - } - - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); - - error = ipsec4_output(&state, sp, flags); - - m = state.m; - if (flags & IP_ROUTETOIF) { - /* - * if we have tunnel mode SA, we may need to ignore - * IP_ROUTETOIF. - */ - if (state.ro != &iproute || state.ro->ro_rt != NULL) { - flags &= ~IP_ROUTETOIF; - ro = state.ro; - } - } else - ro = state.ro; - dst = (struct sockaddr_in *)state.dst; - if (error) { - /* mbuf is already reclaimed in ipsec4_output. */ - m0 = NULL; - switch (error) { - case EHOSTUNREACH: - case ENETUNREACH: - case EMSGSIZE: - case ENOBUFS: - case ENOMEM: - break; - default: - kprintf("ip4_output (ipsec): error code %d\n", error); - /*fall through*/ - case ENOENT: - /* don't show these error codes to the user */ - error = 0; - break; - } - goto bad; - } - } - - /* be sure to update variables that are affected by ipsec4_output() */ - ip = mtod(m, struct ip *); -#ifdef _IP_VHL - hlen = IP_VHL_HL(ip->ip_vhl) << 2; -#else - hlen = ip->ip_hl << 2; -#endif - if (ro->ro_rt == NULL) { - if (!(flags & IP_ROUTETOIF)) { - kprintf("ip_output: " - "can't update route after IPsec processing\n"); - error = EHOSTUNREACH; /*XXX*/ - goto bad; - } - } else { - ia = ifatoia(ro->ro_rt->rt_ifa); - ifp = ro->ro_rt->rt_ifp; - } - - /* make it flipped, again. */ - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); -skip_ipsec: -#endif /*IPSEC*/ -#ifdef FAST_IPSEC - /* - * Check the security policy (SP) for the packet and, if - * required, do IPsec-related processing. There are two - * cases here; the first time a packet is sent through - * it will be untagged and handled by ipsec4_checkpolicy. - * If the packet is resubmitted to ip_output (e.g. after - * AH, ESP, etc. processing), there will be a tag to bypass - * the lookup and related policy checking. - */ - mtag = m_tag_find(m, PACKET_TAG_IPSEC_PENDING_TDB, NULL); - crit_enter(); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)m_tag_data(mtag); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND); - if (sp == NULL) - error = -EINVAL; /* force silent drop */ - m_tag_delete(m, mtag); - } else { - sp = ipsec4_checkpolicy(m, IPSEC_DIR_OUTBOUND, flags, - &error, inp); - } - /* - * There are four return cases: - * sp != NULL apply IPsec policy - * sp == NULL, error == 0 no IPsec handling needed - * sp == NULL, error == -EINVAL discard packet w/o error - * sp == NULL, error != 0 discard packet, report error - */ - if (sp != NULL) { - /* Loop detection, check if ipsec processing already done */ - KASSERT(sp->req != NULL, ("ip_output: no ipsec request")); - for (mtag = m_tag_first(m); mtag != NULL; - mtag = m_tag_next(m, mtag)) { - if (mtag->m_tag_cookie != MTAG_ABI_COMPAT) - continue; - if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE && - mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED) - continue; - /* - * Check if policy has an SA associated with it. - * This can happen when an SP has yet to acquire - * an SA; e.g. on first reference. If it occurs, - * then we let ipsec4_process_packet do its thing. - */ - if (sp->req->sav == NULL) - break; - tdbi = (struct tdb_ident *)m_tag_data(mtag); - if (tdbi->spi == sp->req->sav->spi && - tdbi->proto == sp->req->sav->sah->saidx.proto && - bcmp(&tdbi->dst, &sp->req->sav->sah->saidx.dst, - sizeof(union sockaddr_union)) == 0) { - /* - * No IPsec processing is needed, free - * reference to SP. - * - * NB: null pointer to avoid free at - * done: below. - */ - KEY_FREESP(&sp), sp = NULL; - crit_exit(); - goto spd_done; - } - } - - /* - * Do delayed checksums now because we send before - * this is done in the normal processing path. - */ - if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { - in_delayed_cksum(m); - m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; - } - - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); - - /* NB: callee frees mbuf */ - error = ipsec4_process_packet(m, sp->req, flags, 0); - /* - * Preserve KAME behaviour: ENOENT can be returned - * when an SA acquire is in progress. Don't propagate - * this to user-level; it confuses applications. - * - * XXX this will go away when the SADB is redone. - */ - if (error == ENOENT) - error = 0; - crit_exit(); - goto done; - } else { - crit_exit(); - - if (error != 0) { - /* - * Hack: -EINVAL is used to signal that a packet - * should be silently discarded. This is typically - * because we asked key management for an SA and - * it was delayed (e.g. kicked up to IKE). - */ - if (error == -EINVAL) - error = 0; - goto bad; - } else { - /* No IPsec processing for this packet. */ - } -#ifdef notyet - /* - * If deferred crypto processing is needed, check that - * the interface supports it. - */ - mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL); - if (mtag != NULL && !(ifp->if_capenable & IFCAP_IPSEC)) { - /* notify IPsec to do its own crypto */ - ipsp_skipcrypto_unmark((struct tdb_ident *)m_tag_data(mtag)); - error = EHOSTUNREACH; - goto bad; - } -#endif - } -spd_done: -#endif /* FAST_IPSEC */ /* We are already being fwd'd from a firewall. */ if (next_hop != NULL) @@ -951,11 +677,6 @@ pass: IFA_STAT_INC(&ia->ia_ifa, obytes, m->m_pkthdr.len); } -#ifdef IPSEC - /* clean ipsec history once it goes out of the node */ - ipsec_delaux(m); -#endif - #ifdef MBUF_STRESS_TEST if (mbuf_frag_size && m->m_pkthdr.len > mbuf_frag_size) { struct mbuf *m1, *m2; @@ -1013,10 +734,6 @@ pass: for (; m; m = m0) { m0 = m->m_nextpkt; m->m_nextpkt = NULL; -#ifdef IPSEC - /* clean ipsec history once it goes out of the node */ - ipsec_delaux(m); -#endif if (error == 0) { /* Record statistics for this interface address. */ if (ia != NULL) { @@ -1043,17 +760,6 @@ done: RTFREE(ro->ro_rt); ro->ro_rt = NULL; } -#ifdef IPSEC - if (sp != NULL) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ip_output call free SP:%p\n", sp)); - key_freesp(sp); - } -#endif -#ifdef FAST_IPSEC - if (sp != NULL) - KEY_FREESP(&sp); -#endif return (error); bad: m_freem(m); @@ -1510,28 +1216,6 @@ ip_ctloutput(netmsg_t msg) } break; -#if defined(IPSEC) || defined(FAST_IPSEC) - case IP_IPSEC_POLICY: - { - caddr_t req; - size_t len = 0; - int priv; - struct mbuf *m; - int optname; - - if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */ - break; - soopt_to_mbuf(sopt, m); - priv = (sopt->sopt_td != NULL && - priv_check(sopt->sopt_td, PRIV_ROOT) != 0) ? 0 : 1; - req = mtod(m, caddr_t); - len = m->m_len; - optname = sopt->sopt_name; - error = ipsec4_set_policy(inp, optname, req, len, priv); - m_freem(m); - break; - } -#endif /*IPSEC*/ default: error = ENOPROTOOPT; @@ -1616,26 +1300,6 @@ ip_ctloutput(netmsg_t msg) error = ip_getmoptions(sopt, inp->inp_moptions); break; -#if defined(IPSEC) || defined(FAST_IPSEC) - case IP_IPSEC_POLICY: - { - struct mbuf *m = NULL; - caddr_t req = NULL; - size_t len = 0; - - if (m != NULL) { - req = mtod(m, caddr_t); - len = m->m_len; - } - error = ipsec4_get_policy(so->so_pcb, req, len, &m); - if (error == 0) - error = soopt_from_mbuf(sopt, m); /* XXX */ - if (error == 0) - m_freem(m); - break; - } -#endif /*IPSEC*/ - default: error = ENOPROTOOPT; break; diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index ae0293fd26..0ebf69e3d1 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -31,7 +31,6 @@ */ #include "opt_inet6.h" -#include "opt_ipsec.h" #include "opt_carp.h" #include @@ -73,14 +72,6 @@ #include #include -#ifdef FAST_IPSEC -#include -#endif /*FAST_IPSEC*/ - -#ifdef IPSEC -#include -#endif /*IPSEC*/ - struct inpcbinfo ripcbinfo; struct inpcbportinfo ripcbportinfo; @@ -174,21 +165,6 @@ rip_input(struct mbuf **mp, int *offp, int proto) if (last) { struct mbuf *n = m_copypacket(m, M_NOWAIT); -#ifdef IPSEC - /* check AH/ESP integrity. */ - if (n && ipsec4_in_reject_so(n, last->inp_socket)) { - m_freem(n); - ipsecstat.in_polvio++; - /* do not inject data to pcb */ - } else -#endif /*IPSEC*/ -#ifdef FAST_IPSEC - /* check AH/ESP integrity. */ - if (ipsec4_in_reject(n, last)) { - m_freem(n); - /* do not inject data to pcb */ - } else -#endif /*FAST_IPSEC*/ if (n) { lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token); if (last->inp_flags & INP_CONTROLOPTS || @@ -210,23 +186,6 @@ rip_input(struct mbuf **mp, int *offp, int proto) } last = inp; } -#ifdef IPSEC - /* check AH/ESP integrity. */ - if (last && ipsec4_in_reject_so(m, last->inp_socket)) { - m_freem(m); - ipsecstat.in_polvio++; - ipstat.ips_delivered--; - /* do not inject data to pcb */ - } else -#endif /*IPSEC*/ -#ifdef FAST_IPSEC - /* check AH/ESP integrity. */ - if (last && ipsec4_in_reject(m, last)) { - m_freem(m); - ipstat.ips_delivered--; - /* do not inject data to pcb */ - } else -#endif /*FAST_IPSEC*/ /* Check the minimum TTL for socket. */ if (last && ip->ip_ttl < last->inp_ip_minttl) { m_freem(opts); diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 7deb938103..be34ebeef0 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -65,7 +65,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include "opt_tcpdebug.h" #include "opt_tcp_input.h" @@ -119,17 +118,6 @@ u_char tcp_saveipgen[40]; /* the size must be of max ip header, now IPv6 */ struct tcphdr tcp_savetcp; #endif -#ifdef FAST_IPSEC -#include -#include -#endif - -#ifdef IPSEC -#include -#include -#include -#endif - /* * Limit burst of new packets during SACK based fast recovery * or extended limited transmit. @@ -933,28 +921,6 @@ findpcb: goto dropwithreset; } -#ifdef IPSEC - if (isipv6) { - if (ipsec6_in_reject_so(m, inp->inp_socket)) { - ipsec6stat.in_polvio++; - goto drop; - } - } else { - if (ipsec4_in_reject_so(m, inp->inp_socket)) { - ipsecstat.in_polvio++; - goto drop; - } - } -#endif -#ifdef FAST_IPSEC - if (isipv6) { - if (ipsec6_in_reject(m, inp)) - goto drop; - } else { - if (ipsec4_in_reject(m, inp)) - goto drop; - } -#endif /* Check the minimum TTL for socket. */ #ifdef INET6 if ((isipv6 ? ip6->ip6_hlim : ip->ip_ttl) < inp->inp_ip_minttl) diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index d3021c2a07..5496dd1008 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -65,7 +65,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include "opt_tcpdebug.h" #include @@ -106,15 +105,6 @@ #include #endif -#ifdef IPSEC -#include -#endif /*IPSEC*/ - -#ifdef FAST_IPSEC -#include -#define IPSEC -#endif /*FAST_IPSEC*/ - #ifdef notyet extern struct mbuf *m_copypack(); #endif @@ -253,7 +243,6 @@ tcp_output(struct tcpcb *tp) * PUSH on the last segment that it creates from the large TCP * segment. */ -#if !defined(IPSEC) && !defined(FAST_IPSEC) if (tcp_do_tso #ifdef TCP_SIGNATURE && (tp->t_flags & TF_SIGNATURE) == 0 @@ -269,7 +258,6 @@ tcp_output(struct tcpcb *tp) } } } -#endif /* !IPSEC && !FAST_IPSEC */ again: m = NULL; @@ -821,9 +809,6 @@ send: ipoptlen = 0; } } -#ifdef IPSEC - ipoptlen += ipsec_hdrsiz_tcp(tp); -#endif if (use_tso) { /* TSO segment length must be multiple of segment size */ @@ -1440,9 +1425,6 @@ tcp_tso_getsize(struct tcpcb *tp, u_int *segsz, u_int *hlen0) ipoptlen = 0; } } -#ifdef IPSEC - ipoptlen += ipsec_hdrsiz_tcp(tp); -#endif hlen += ipoptlen; optlen = 0; diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index fa0c1e80b8..b199955af4 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -65,7 +65,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include "opt_tcpdebug.h" #include @@ -120,22 +119,6 @@ #endif #include -#ifdef IPSEC -#include -#include -#ifdef INET6 -#include -#endif -#endif - -#ifdef FAST_IPSEC -#include -#ifdef INET6 -#include -#endif -#define IPSEC -#endif - #include #include @@ -1899,47 +1882,6 @@ tcp_rtlookup6(struct in_conninfo *inc) } #endif -#ifdef IPSEC -/* compute ESP/AH header size for TCP, including outer IP header. */ -size_t -ipsec_hdrsiz_tcp(struct tcpcb *tp) -{ - struct inpcb *inp; - struct mbuf *m; - size_t hdrsiz; - struct ip *ip; - struct tcphdr *th; - - if ((tp == NULL) || ((inp = tp->t_inpcb) == NULL)) - return (0); - MGETHDR(m, M_NOWAIT, MT_DATA); - if (!m) - return (0); - -#ifdef INET6 - if (INP_ISIPV6(inp)) { - struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); - - th = (struct tcphdr *)(ip6 + 1); - m->m_pkthdr.len = m->m_len = - sizeof(struct ip6_hdr) + sizeof(struct tcphdr); - tcp_fillheaders(tp, ip6, th, FALSE); - hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp); - } else -#endif - { - ip = mtod(m, struct ip *); - th = (struct tcphdr *)(ip + 1); - m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr); - tcp_fillheaders(tp, ip, th, FALSE); - hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp); - } - - m_free(m); - return (hdrsiz); -} -#endif - /* * TCP BANDWIDTH DELAY PRODUCT WINDOW LIMITING * diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index ceedc1ecf1..52894ae231 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -73,7 +73,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include #include @@ -116,23 +115,6 @@ #include #include -#ifdef IPSEC -#include -#ifdef INET6 -#include -#endif -#include -#endif /*IPSEC*/ - -#ifdef FAST_IPSEC -#include -#ifdef INET6 -#include -#endif -#include -#define IPSEC -#endif /*FAST_IPSEC*/ - static int tcp_syncookies = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_RW, &tcp_syncookies, 0, @@ -785,11 +767,6 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) tcp_pcbport_insert(ltp, inp); -#ifdef IPSEC - /* copy old policy into new socket's */ - if (ipsec_copy_policy(linp->inp_sp, inp->inp_sp)) - kprintf("syncache_expand: could not copy policy\n"); -#endif if (isipv6) { struct in6_addr laddr6; /* diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index b0e3327cc6..aa475ba34a 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -63,7 +63,6 @@ * $FreeBSD: src/sys/netinet/tcp_usrreq.c,v 1.51.2.17 2002/10/11 11:46:44 ume Exp $ */ -#include "opt_ipsec.h" #include "opt_inet.h" #include "opt_inet6.h" #include "opt_tcpdebug.h" @@ -122,10 +121,6 @@ #include #endif -#ifdef IPSEC -#include -#endif /*IPSEC*/ - /* * TCP protocol interface to socket abstraction. */ diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 0695eb3493..41f2726827 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -63,7 +63,6 @@ * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.64.2.18 2003/01/24 05:11:34 sam Exp $ */ -#include "opt_ipsec.h" #include "opt_inet6.h" #include @@ -110,14 +109,6 @@ #include #include -#ifdef FAST_IPSEC -#include -#endif - -#ifdef IPSEC -#include -#endif - #define MSGF_UDP_SEND MSGF_PROTO1 #define INP_DIRECT_DETACH INP_FLAG_PROTO2 @@ -356,19 +347,6 @@ udp_mcast_input(struct udp_mcast_arg *arg) if (last != NULL) { struct mbuf *n; -#ifdef IPSEC - /* check AH/ESP integrity. */ - if (ipsec4_in_reject_so(m, last->inp_socket)) - ipsecstat.in_polvio++; - /* do not inject data to pcb */ - else -#endif /*IPSEC*/ -#ifdef FAST_IPSEC - /* check AH/ESP integrity. */ - if (ipsec4_in_reject(m, last)) - ; - else -#endif /*FAST_IPSEC*/ if ((n = m_copypacket(m, M_NOWAIT)) != NULL) udp_append(last, ip, n, arg->iphlen + sizeof(struct udphdr), @@ -599,18 +577,6 @@ done: udp_stat.udps_noportbcast++; goto bad; } -#ifdef IPSEC - /* check AH/ESP integrity. */ - if (ipsec4_in_reject_so(m, last->inp_socket)) { - ipsecstat.in_polvio++; - goto bad; - } -#endif /*IPSEC*/ -#ifdef FAST_IPSEC - /* check AH/ESP integrity. */ - if (ipsec4_in_reject(m, last)) - goto bad; -#endif /*FAST_IPSEC*/ udp_append(last, ip, m, iphlen + sizeof(struct udphdr), &udp_in); return(IPPROTO_DONE); @@ -647,16 +613,6 @@ done: return(IPPROTO_DONE); } KASSERT(INP_ISIPV4(inp), ("not inet inpcb")); -#ifdef IPSEC - if (ipsec4_in_reject_so(m, inp->inp_socket)) { - ipsecstat.in_polvio++; - goto bad; - } -#endif /*IPSEC*/ -#ifdef FAST_IPSEC - if (ipsec4_in_reject(m, inp)) - goto bad; -#endif /*FAST_IPSEC*/ /* * Check the minimum TTL for socket. */ diff --git a/sys/netinet6/ah.h b/sys/netinet6/ah.h deleted file mode 100644 index 09c65ba377..0000000000 --- a/sys/netinet6/ah.h +++ /dev/null @@ -1,102 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ah.h,v 1.3.2.3 2002/04/28 05:40:26 suz Exp $ */ -/* $DragonFly: src/sys/netinet6/ah.h,v 1.6 2006/05/20 02:42:12 dillon Exp $ */ -/* $KAME: ah.h,v 1.16 2001/09/04 08:43:19 itojun Exp $ */ - -/* - * 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. - */ - -/* - * RFC1826/2402 authentication header. - */ - -#ifndef _NETINET6_AH_H_ -#define _NETINET6_AH_H_ - -#ifndef _SYS_TYPES_H_ -#include -#endif - -#if defined(_KERNEL) && !defined(_LKM) -#include "opt_inet.h" -#endif - -struct ah { - u_int8_t ah_nxt; /* Next Header */ - u_int8_t ah_len; /* Length of data, in 32bit */ - u_int16_t ah_reserve; /* Reserved for future use */ - u_int32_t ah_spi; /* Security parameter index */ - /* variable size, 32bit bound*/ /* Authentication data */ -}; - -struct newah { - u_int8_t ah_nxt; /* Next Header */ - u_int8_t ah_len; /* Length of data + 1, in 32bit */ - u_int16_t ah_reserve; /* Reserved for future use */ - u_int32_t ah_spi; /* Security parameter index */ - u_int32_t ah_seq; /* Sequence number field */ - /* variable size, 32bit bound*/ /* Authentication data */ -}; - -#ifdef _KERNEL - -struct secasvar; -struct ipsecrequest; -struct mbuf; - -struct ah_algorithm_state { - struct secasvar *sav; - void* foo; /* per algorithm data - maybe */ -}; - -struct ah_algorithm { - int (*sumsiz) (struct secasvar *); - int (*mature) (struct secasvar *); - int keymin; /* in bits */ - int keymax; /* in bits */ - const char *name; - int (*init) (struct ah_algorithm_state *, struct secasvar *); - void (*update) (struct ah_algorithm_state *, caddr_t, size_t); - void (*result) (struct ah_algorithm_state *, caddr_t); -}; - -#define AH_MAXSUMSIZE 16 - -extern const struct ah_algorithm *ah_algorithm_lookup (int); - -/* cksum routines */ -extern int ah_hdrlen (struct secasvar *); - -extern size_t ah_hdrsiz (struct ipsecrequest *); -extern int ah4_input (struct mbuf **, int *, int); -extern int ah4_output (struct mbuf *, struct ipsecrequest *); -extern int ah4_calccksum (struct mbuf *, caddr_t, size_t, - const struct ah_algorithm *, struct secasvar *); -#endif /* _KERNEL */ - -#endif /* _NETINET6_AH_H_ */ diff --git a/sys/netinet6/ah6.h b/sys/netinet6/ah6.h deleted file mode 100644 index 5e5fdf8ac0..0000000000 --- a/sys/netinet6/ah6.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ah6.h,v 1.2.2.2 2001/07/03 11:01:49 ume Exp $ */ -/* $DragonFly: src/sys/netinet6/ah6.h,v 1.4 2006/05/20 02:42:12 dillon Exp $ */ -/* $KAME: ah.h,v 1.13 2000/10/18 21:28:00 itojun Exp $ */ - -/* - * 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. - */ - -/* - * RFC1826/2402 authentication header. - */ - -#ifndef _NETINET6_AH6_H_ -#define _NETINET6_AH6_H_ - -#ifdef _KERNEL - -#ifndef _SYS_TYPES_H_ -#include -#endif - -struct mbuf; -struct secasvar; -struct sockaddr; -struct ah_algorithm; -struct ipsecrequest; - -extern int ah6_input (struct mbuf **, int *, int); -extern int ah6_output (struct mbuf *, u_char *, struct mbuf *, - struct ipsecrequest *); -extern int ah6_calccksum (struct mbuf *, caddr_t, size_t, - const struct ah_algorithm *, struct secasvar *); - -extern void ah6_ctlinput (int, struct sockaddr *, void *); - -#endif - -#endif /*_NETINET6_AH6_H_*/ diff --git a/sys/netinet6/ah_core.c b/sys/netinet6/ah_core.c deleted file mode 100644 index 174e12a01c..0000000000 --- a/sys/netinet6/ah_core.c +++ /dev/null @@ -1,1537 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ah_core.c,v 1.2.2.5 2002/04/28 05:40:26 suz Exp $ */ -/* $KAME: ah_core.c,v 1.44 2001/03/12 11:24:39 itojun Exp $ */ - -/* - * 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. - */ - -/* - * RFC1826/2402 authentication header. - */ - -/* TODO: have shared routines for hmac-* algorithms */ - -#include "opt_inet.h" -#include "opt_inet6.h" -#include "opt_ipsec.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#ifdef INET6 -#include -#include -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#ifdef IPSEC_ESP -#include -#ifdef INET6 -#include -#endif -#endif -#include -#include -#include -#include -#include - -#include - -#define HMACSIZE 16 - -static int ah_sumsiz_1216 (struct secasvar *); -static int ah_sumsiz_zero (struct secasvar *); -static int ah_none_mature (struct secasvar *); -static int ah_none_init (struct ah_algorithm_state *, struct secasvar *); -static void ah_none_loop (struct ah_algorithm_state *, caddr_t, size_t); -static void ah_none_result (struct ah_algorithm_state *, caddr_t); -static int ah_keyed_md5_mature (struct secasvar *); -static int ah_keyed_md5_init (struct ah_algorithm_state *, - struct secasvar *); -static void ah_keyed_md5_loop (struct ah_algorithm_state *, caddr_t, - size_t); -static void ah_keyed_md5_result (struct ah_algorithm_state *, caddr_t); -static int ah_keyed_sha1_mature (struct secasvar *); -static int ah_keyed_sha1_init (struct ah_algorithm_state *, - struct secasvar *); -static void ah_keyed_sha1_loop (struct ah_algorithm_state *, caddr_t, - size_t); -static void ah_keyed_sha1_result (struct ah_algorithm_state *, caddr_t); -static int ah_hmac_md5_mature (struct secasvar *); -static int ah_hmac_md5_init (struct ah_algorithm_state *, - struct secasvar *); -static void ah_hmac_md5_loop (struct ah_algorithm_state *, caddr_t, - size_t); -static void ah_hmac_md5_result (struct ah_algorithm_state *, caddr_t); -static int ah_hmac_sha1_mature (struct secasvar *); -static int ah_hmac_sha1_init (struct ah_algorithm_state *, - struct secasvar *); -static void ah_hmac_sha1_loop (struct ah_algorithm_state *, caddr_t, - size_t); -static void ah_hmac_sha1_result (struct ah_algorithm_state *, caddr_t); -static int ah_hmac_sha2_256_mature (struct secasvar *); -static int ah_hmac_sha2_256_init (struct ah_algorithm_state *, - struct secasvar *); -static void ah_hmac_sha2_256_loop (struct ah_algorithm_state *, caddr_t, - size_t); -static void ah_hmac_sha2_256_result (struct ah_algorithm_state *, caddr_t); -static int ah_hmac_sha2_384_mature (struct secasvar *); -static int ah_hmac_sha2_384_init (struct ah_algorithm_state *, - struct secasvar *); -static void ah_hmac_sha2_384_loop (struct ah_algorithm_state *, caddr_t, - size_t); -static void ah_hmac_sha2_384_result (struct ah_algorithm_state *, caddr_t); -static int ah_hmac_sha2_512_mature (struct secasvar *); -static int ah_hmac_sha2_512_init (struct ah_algorithm_state *, - struct secasvar *); -static void ah_hmac_sha2_512_loop (struct ah_algorithm_state *, caddr_t, - size_t); -static void ah_hmac_sha2_512_result (struct ah_algorithm_state *, caddr_t); - -static void ah_update_mbuf (struct mbuf *, int, int, - const struct ah_algorithm *, struct ah_algorithm_state *); - -const struct ah_algorithm * -ah_algorithm_lookup(int idx) -{ - /* checksum algorithms */ - static struct ah_algorithm ah_algorithms[] = { - { ah_sumsiz_1216, ah_hmac_md5_mature, 128, 128, "hmac-md5", - ah_hmac_md5_init, ah_hmac_md5_loop, - ah_hmac_md5_result, }, - { ah_sumsiz_1216, ah_hmac_sha1_mature, 160, 160, "hmac-sha1", - ah_hmac_sha1_init, ah_hmac_sha1_loop, - ah_hmac_sha1_result, }, - { ah_sumsiz_1216, ah_keyed_md5_mature, 128, 128, "keyed-md5", - ah_keyed_md5_init, ah_keyed_md5_loop, - ah_keyed_md5_result, }, - { ah_sumsiz_1216, ah_keyed_sha1_mature, 160, 160, "keyed-sha1", - ah_keyed_sha1_init, ah_keyed_sha1_loop, - ah_keyed_sha1_result, }, - { ah_sumsiz_zero, ah_none_mature, 0, 2048, "none", - ah_none_init, ah_none_loop, ah_none_result, }, - { ah_sumsiz_1216, ah_hmac_sha2_256_mature, 256, 256, - "hmac-sha2-256", - ah_hmac_sha2_256_init, ah_hmac_sha2_256_loop, - ah_hmac_sha2_256_result, }, - { ah_sumsiz_1216, ah_hmac_sha2_384_mature, 384, 384, - "hmac-sha2-384", - ah_hmac_sha2_384_init, ah_hmac_sha2_384_loop, - ah_hmac_sha2_384_result, }, - { ah_sumsiz_1216, ah_hmac_sha2_512_mature, 512, 512, - "hmac-sha2-512", - ah_hmac_sha2_512_init, ah_hmac_sha2_512_loop, - ah_hmac_sha2_512_result, }, - }; - - switch (idx) { - case SADB_AALG_MD5HMAC: - return &ah_algorithms[0]; - case SADB_AALG_SHA1HMAC: - return &ah_algorithms[1]; - case SADB_X_AALG_MD5: - return &ah_algorithms[2]; - case SADB_X_AALG_SHA: - return &ah_algorithms[3]; - case SADB_X_AALG_NULL: - return &ah_algorithms[4]; - case SADB_X_AALG_SHA2_256: - return &ah_algorithms[5]; - case SADB_X_AALG_SHA2_384: - return &ah_algorithms[6]; - case SADB_X_AALG_SHA2_512: - return &ah_algorithms[7]; - default: - return NULL; - } -} - - -static int -ah_sumsiz_1216(struct secasvar *sav) -{ - if (!sav) - return -1; - if (sav->flags & SADB_X_EXT_OLD) - return 16; - else - return 12; -} - -static int -ah_sumsiz_zero(struct secasvar *sav) -{ - if (!sav) - return -1; - return 0; -} - -static int -ah_none_mature(struct secasvar *sav) -{ - if (sav->sah->saidx.proto == IPPROTO_AH) { - ipseclog((LOG_ERR, - "ah_none_mature: protocol and algorithm mismatch.\n")); - return 1; - } - return 0; -} - -static int -ah_none_init(struct ah_algorithm_state *state, struct secasvar *sav) -{ - state->foo = NULL; - return 0; -} - -static void -ah_none_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len) -{ -} - -static void -ah_none_result(struct ah_algorithm_state *state, caddr_t addr) -{ -} - -static int -ah_keyed_md5_mature(struct secasvar *sav) -{ - /* anything is okay */ - return 0; -} - -static int -ah_keyed_md5_init(struct ah_algorithm_state *state, struct secasvar *sav) -{ - size_t padlen; - size_t keybitlen; - u_int8_t buf[32]; - - if (!state) - panic("ah_keyed_md5_init: what?"); - - state->sav = sav; - state->foo = (void *)kmalloc(sizeof(MD5_CTX), M_TEMP, M_NOWAIT); - if (state->foo == NULL) - return ENOBUFS; - - MD5Init((MD5_CTX *)state->foo); - if (state->sav) { - MD5Update((MD5_CTX *)state->foo, - (u_int8_t *)_KEYBUF(state->sav->key_auth), - (u_int)_KEYLEN(state->sav->key_auth)); - - /* - * Pad after the key. - * We cannot simply use md5_pad() since the function - * won't update the total length. - */ - if (_KEYLEN(state->sav->key_auth) < 56) - padlen = 64 - 8 - _KEYLEN(state->sav->key_auth); - else - padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth); - keybitlen = _KEYLEN(state->sav->key_auth); - keybitlen *= 8; - - buf[0] = 0x80; - MD5Update((MD5_CTX *)state->foo, &buf[0], 1); - padlen--; - - bzero(buf, sizeof(buf)); - while (sizeof(buf) < padlen) { - MD5Update((MD5_CTX *)state->foo, &buf[0], sizeof(buf)); - padlen -= sizeof(buf); - } - if (padlen) { - MD5Update((MD5_CTX *)state->foo, &buf[0], padlen); - } - - buf[0] = (keybitlen >> 0) & 0xff; - buf[1] = (keybitlen >> 8) & 0xff; - buf[2] = (keybitlen >> 16) & 0xff; - buf[3] = (keybitlen >> 24) & 0xff; - MD5Update((MD5_CTX *)state->foo, buf, 8); - } - - return 0; -} - -static void -ah_keyed_md5_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len) -{ - if (!state) - panic("ah_keyed_md5_loop: what?"); - - MD5Update((MD5_CTX *)state->foo, addr, len); -} - -static void -ah_keyed_md5_result(struct ah_algorithm_state *state, caddr_t addr) -{ - u_char digest[16]; - - if (!state) - panic("ah_keyed_md5_result: what?"); - - if (state->sav) { - MD5Update((MD5_CTX *)state->foo, - (u_int8_t *)_KEYBUF(state->sav->key_auth), - (u_int)_KEYLEN(state->sav->key_auth)); - } - MD5Final(&digest[0], (MD5_CTX *)state->foo); - kfree(state->foo, M_TEMP); - bcopy(&digest[0], (void *)addr, sizeof(digest)); -} - -static int -ah_keyed_sha1_mature(struct secasvar *sav) -{ - const struct ah_algorithm *algo; - - if (!sav->key_auth) { - ipseclog((LOG_ERR, "ah_keyed_sha1_mature: no key is given.\n")); - return 1; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_ERR, "ah_keyed_sha1_mature: unsupported algorithm.\n")); - return 1; - } - - if (sav->key_auth->sadb_key_bits < algo->keymin - || algo->keymax < sav->key_auth->sadb_key_bits) { - ipseclog((LOG_ERR, - "ah_keyed_sha1_mature: invalid key length %d.\n", - sav->key_auth->sadb_key_bits)); - return 1; - } - - return 0; -} - -static int -ah_keyed_sha1_init(struct ah_algorithm_state *state, struct secasvar *sav) -{ - SHA1_CTX *ctxt; - size_t padlen; - size_t keybitlen; - u_int8_t buf[32]; - - if (!state) - panic("ah_keyed_sha1_init: what?"); - - state->sav = sav; - state->foo = (void *)kmalloc(sizeof(SHA1_CTX), M_TEMP, M_NOWAIT); - if (!state->foo) - return ENOBUFS; - - ctxt = (SHA1_CTX *)state->foo; - SHA1Init(ctxt); - - if (state->sav) { - SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth), - (u_int)_KEYLEN(state->sav->key_auth)); - - /* - * Pad after the key. - */ - if (_KEYLEN(state->sav->key_auth) < 56) - padlen = 64 - 8 - _KEYLEN(state->sav->key_auth); - else - padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth); - keybitlen = _KEYLEN(state->sav->key_auth); - keybitlen *= 8; - - buf[0] = 0x80; - SHA1Update(ctxt, &buf[0], 1); - padlen--; - - bzero(buf, sizeof(buf)); - while (sizeof(buf) < padlen) { - SHA1Update(ctxt, &buf[0], sizeof(buf)); - padlen -= sizeof(buf); - } - if (padlen) { - SHA1Update(ctxt, &buf[0], padlen); - } - - buf[0] = (keybitlen >> 0) & 0xff; - buf[1] = (keybitlen >> 8) & 0xff; - buf[2] = (keybitlen >> 16) & 0xff; - buf[3] = (keybitlen >> 24) & 0xff; - SHA1Update(ctxt, buf, 8); - } - - return 0; -} - -static void -ah_keyed_sha1_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len) -{ - SHA1_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_keyed_sha1_loop: what?"); - ctxt = (SHA1_CTX *)state->foo; - - SHA1Update(ctxt, addr, len); -} - -static void -ah_keyed_sha1_result(struct ah_algorithm_state *state, caddr_t addr) -{ - u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */ - SHA1_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_keyed_sha1_result: what?"); - ctxt = (SHA1_CTX *)state->foo; - - if (state->sav) { - SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth), - (u_int)_KEYLEN(state->sav->key_auth)); - } - SHA1Final((caddr_t)&digest[0], ctxt); - bcopy(&digest[0], (void *)addr, HMACSIZE); - - kfree(state->foo, M_TEMP); -} - -static int -ah_hmac_md5_mature(struct secasvar *sav) -{ - const struct ah_algorithm *algo; - - if (!sav->key_auth) { - ipseclog((LOG_ERR, "ah_hmac_md5_mature: no key is given.\n")); - return 1; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_ERR, "ah_hmac_md5_mature: unsupported algorithm.\n")); - return 1; - } - - if (sav->key_auth->sadb_key_bits < algo->keymin - || algo->keymax < sav->key_auth->sadb_key_bits) { - ipseclog((LOG_ERR, - "ah_hmac_md5_mature: invalid key length %d.\n", - sav->key_auth->sadb_key_bits)); - return 1; - } - - return 0; -} - -static int -ah_hmac_md5_init(struct ah_algorithm_state *state, struct secasvar *sav) -{ - u_char *ipad; - u_char *opad; - u_char tk[16]; - u_char *key; - size_t keylen; - size_t i; - MD5_CTX *ctxt; - - if (!state) - panic("ah_hmac_md5_init: what?"); - - state->sav = sav; - state->foo = (void *)kmalloc(64 + 64 + sizeof(MD5_CTX), M_TEMP, M_NOWAIT); - if (!state->foo) - return ENOBUFS; - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (MD5_CTX *)(opad + 64); - - /* compress the key if necessery */ - if (64 < _KEYLEN(state->sav->key_auth)) { - MD5Init(ctxt); - MD5Update(ctxt, _KEYBUF(state->sav->key_auth), - _KEYLEN(state->sav->key_auth)); - MD5Final(&tk[0], ctxt); - key = &tk[0]; - keylen = 16; - } else { - key = _KEYBUF(state->sav->key_auth); - keylen = _KEYLEN(state->sav->key_auth); - } - - bzero(ipad, 64); - bzero(opad, 64); - bcopy(key, ipad, keylen); - bcopy(key, opad, keylen); - for (i = 0; i < 64; i++) { - ipad[i] ^= 0x36; - opad[i] ^= 0x5c; - } - - MD5Init(ctxt); - MD5Update(ctxt, ipad, 64); - - return 0; -} - -static void -ah_hmac_md5_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len) -{ - MD5_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_md5_loop: what?"); - ctxt = (MD5_CTX *)(((caddr_t)state->foo) + 128); - MD5Update(ctxt, addr, len); -} - -static void -ah_hmac_md5_result(struct ah_algorithm_state *state, caddr_t addr) -{ - u_char digest[16]; - u_char *ipad; - u_char *opad; - MD5_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_md5_result: what?"); - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (MD5_CTX *)(opad + 64); - - MD5Final(&digest[0], ctxt); - - MD5Init(ctxt); - MD5Update(ctxt, opad, 64); - MD5Update(ctxt, &digest[0], sizeof(digest)); - MD5Final(&digest[0], ctxt); - - bcopy(&digest[0], (void *)addr, HMACSIZE); - - kfree(state->foo, M_TEMP); -} - -static int -ah_hmac_sha1_mature(struct secasvar *sav) -{ - const struct ah_algorithm *algo; - - if (!sav->key_auth) { - ipseclog((LOG_ERR, "ah_hmac_sha1_mature: no key is given.\n")); - return 1; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_ERR, "ah_hmac_sha1_mature: unsupported algorithm.\n")); - return 1; - } - - if (sav->key_auth->sadb_key_bits < algo->keymin - || algo->keymax < sav->key_auth->sadb_key_bits) { - ipseclog((LOG_ERR, - "ah_hmac_sha1_mature: invalid key length %d.\n", - sav->key_auth->sadb_key_bits)); - return 1; - } - - return 0; -} - -static int -ah_hmac_sha1_init(struct ah_algorithm_state *state, struct secasvar *sav) -{ - u_char *ipad; - u_char *opad; - SHA1_CTX *ctxt; - u_char tk[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */ - u_char *key; - size_t keylen; - size_t i; - - if (!state) - panic("ah_hmac_sha1_init: what?"); - - state->sav = sav; - state->foo = (void *)kmalloc(64 + 64 + sizeof(SHA1_CTX), - M_TEMP, M_NOWAIT); - if (!state->foo) - return ENOBUFS; - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (SHA1_CTX *)(opad + 64); - - /* compress the key if necessery */ - if (64 < _KEYLEN(state->sav->key_auth)) { - SHA1Init(ctxt); - SHA1Update(ctxt, _KEYBUF(state->sav->key_auth), - _KEYLEN(state->sav->key_auth)); - SHA1Final(&tk[0], ctxt); - key = &tk[0]; - keylen = SHA1_RESULTLEN; - } else { - key = _KEYBUF(state->sav->key_auth); - keylen = _KEYLEN(state->sav->key_auth); - } - - bzero(ipad, 64); - bzero(opad, 64); - bcopy(key, ipad, keylen); - bcopy(key, opad, keylen); - for (i = 0; i < 64; i++) { - ipad[i] ^= 0x36; - opad[i] ^= 0x5c; - } - - SHA1Init(ctxt); - SHA1Update(ctxt, ipad, 64); - - return 0; -} - -static void -ah_hmac_sha1_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len) -{ - SHA1_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_sha1_loop: what?"); - - ctxt = (SHA1_CTX *)(((u_char *)state->foo) + 128); - SHA1Update(ctxt, addr, len); -} - -static void -ah_hmac_sha1_result(struct ah_algorithm_state *state, caddr_t addr) -{ - u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */ - u_char *ipad; - u_char *opad; - SHA1_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_sha1_result: what?"); - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (SHA1_CTX *)(opad + 64); - - SHA1Final((caddr_t)&digest[0], ctxt); - - SHA1Init(ctxt); - SHA1Update(ctxt, opad, 64); - SHA1Update(ctxt, (caddr_t)&digest[0], sizeof(digest)); - SHA1Final((caddr_t)&digest[0], ctxt); - - bcopy(&digest[0], (void *)addr, HMACSIZE); - - kfree(state->foo, M_TEMP); -} - -static int -ah_hmac_sha2_256_mature(struct secasvar *sav) -{ - const struct ah_algorithm *algo; - - if (!sav->key_auth) { - ipseclog((LOG_ERR, - "ah_hmac_sha2_256_mature: no key is given.\n")); - return 1; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_ERR, - "ah_hmac_sha2_256_mature: unsupported algorithm.\n")); - return 1; - } - - if (sav->key_auth->sadb_key_bits < algo->keymin || - algo->keymax < sav->key_auth->sadb_key_bits) { - ipseclog((LOG_ERR, - "ah_hmac_sha2_256_mature: invalid key length %d.\n", - sav->key_auth->sadb_key_bits)); - return 1; - } - - return 0; -} - -static int -ah_hmac_sha2_256_init(struct ah_algorithm_state *state, struct secasvar *sav) -{ - u_char *ipad; - u_char *opad; - SHA256_CTX *ctxt; - u_char tk[SHA256_DIGEST_LENGTH]; - u_char *key; - size_t keylen; - size_t i; - - if (!state) - panic("ah_hmac_sha2_256_init: what?"); - - state->sav = sav; - state->foo = (void *)kmalloc(64 + 64 + sizeof(SHA256_CTX), - M_TEMP, M_NOWAIT); - if (!state->foo) - return ENOBUFS; - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (SHA256_CTX *)(opad + 64); - - /* compress the key if necessery */ - if (64 < _KEYLEN(state->sav->key_auth)) { - bzero(tk, sizeof(tk)); - bzero(ctxt, sizeof(*ctxt)); - SHA256_Init(ctxt); - SHA256_Update(ctxt, _KEYBUF(state->sav->key_auth), - _KEYLEN(state->sav->key_auth)); - SHA256_Final(&tk[0], ctxt); - key = &tk[0]; - keylen = sizeof(tk) < 64 ? sizeof(tk) : 64; - } else { - key = _KEYBUF(state->sav->key_auth); - keylen = _KEYLEN(state->sav->key_auth); - } - - bzero(ipad, 64); - bzero(opad, 64); - bcopy(key, ipad, keylen); - bcopy(key, opad, keylen); - for (i = 0; i < 64; i++) { - ipad[i] ^= 0x36; - opad[i] ^= 0x5c; - } - - bzero(ctxt, sizeof(*ctxt)); - SHA256_Init(ctxt); - SHA256_Update(ctxt, ipad, 64); - - return 0; -} - -static void -ah_hmac_sha2_256_loop(struct ah_algorithm_state *state, caddr_t addr, size_t - len) -{ - SHA256_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_sha2_256_loop: what?"); - - ctxt = (SHA256_CTX *)(((u_char *)state->foo) + 128); - SHA256_Update(ctxt, addr, len); -} - -static void -ah_hmac_sha2_256_result(struct ah_algorithm_state *state, caddr_t addr) -{ - u_char digest[SHA256_DIGEST_LENGTH]; - u_char *ipad; - u_char *opad; - SHA256_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_sha2_256_result: what?"); - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (SHA256_CTX *)(opad + 64); - - SHA256_Final((caddr_t)&digest[0], ctxt); - - bzero(ctxt, sizeof(*ctxt)); - SHA256_Init(ctxt); - SHA256_Update(ctxt, opad, 64); - SHA256_Update(ctxt, (caddr_t)&digest[0], sizeof(digest)); - SHA256_Final((caddr_t)&digest[0], ctxt); - - bcopy(&digest[0], (void *)addr, HMACSIZE); - - kfree(state->foo, M_TEMP); -} - -static int -ah_hmac_sha2_384_mature(struct secasvar *sav) -{ - const struct ah_algorithm *algo; - - if (!sav->key_auth) { - ipseclog((LOG_ERR, - "ah_hmac_sha2_384_mature: no key is given.\n")); - return 1; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_ERR, - "ah_hmac_sha2_384_mature: unsupported algorithm.\n")); - return 1; - } - - if (sav->key_auth->sadb_key_bits < algo->keymin || - algo->keymax < sav->key_auth->sadb_key_bits) { - ipseclog((LOG_ERR, - "ah_hmac_sha2_384_mature: invalid key length %d.\n", - sav->key_auth->sadb_key_bits)); - return 1; - } - - return 0; -} - -static int -ah_hmac_sha2_384_init(struct ah_algorithm_state *state, struct secasvar *sav) -{ - u_char *ipad; - u_char *opad; - SHA384_CTX *ctxt; - u_char tk[SHA384_DIGEST_LENGTH]; - u_char *key; - size_t keylen; - size_t i; - - if (!state) - panic("ah_hmac_sha2_384_init: what?"); - - state->sav = sav; - state->foo = (void *)kmalloc(64 + 64 + sizeof(SHA384_CTX), - M_TEMP, M_NOWAIT | M_ZERO); - if (!state->foo) - return ENOBUFS; - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (SHA384_CTX *)(opad + 64); - - /* compress the key if necessery */ - if (64 < _KEYLEN(state->sav->key_auth)) { - bzero(tk, sizeof(tk)); - bzero(ctxt, sizeof(*ctxt)); - SHA384_Init(ctxt); - SHA384_Update(ctxt, _KEYBUF(state->sav->key_auth), - _KEYLEN(state->sav->key_auth)); - SHA384_Final(&tk[0], ctxt); - key = &tk[0]; - keylen = sizeof(tk) < 64 ? sizeof(tk) : 64; - } else { - key = _KEYBUF(state->sav->key_auth); - keylen = _KEYLEN(state->sav->key_auth); - } - - bzero(ipad, 64); - bzero(opad, 64); - bcopy(key, ipad, keylen); - bcopy(key, opad, keylen); - for (i = 0; i < 64; i++) { - ipad[i] ^= 0x36; - opad[i] ^= 0x5c; - } - - bzero(ctxt, sizeof(*ctxt)); - SHA384_Init(ctxt); - SHA384_Update(ctxt, ipad, 64); - - return 0; -} - -static void -ah_hmac_sha2_384_loop(struct ah_algorithm_state *state, caddr_t addr, - size_t len) -{ - SHA384_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_sha2_384_loop: what?"); - - ctxt = (SHA384_CTX *)(((u_char *)state->foo) + 128); - SHA384_Update(ctxt, addr, len); -} - -static void -ah_hmac_sha2_384_result(struct ah_algorithm_state *state, caddr_t addr) -{ - u_char digest[SHA384_DIGEST_LENGTH]; - u_char *ipad; - u_char *opad; - SHA384_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_sha2_384_result: what?"); - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (SHA384_CTX *)(opad + 64); - - SHA384_Final((caddr_t)&digest[0], ctxt); - - bzero(ctxt, sizeof(*ctxt)); - SHA384_Init(ctxt); - SHA384_Update(ctxt, opad, 64); - SHA384_Update(ctxt, (caddr_t)&digest[0], sizeof(digest)); - SHA384_Final((caddr_t)&digest[0], ctxt); - - bcopy(&digest[0], (void *)addr, HMACSIZE); - - kfree(state->foo, M_TEMP); -} - -static int -ah_hmac_sha2_512_mature(struct secasvar *sav) -{ - const struct ah_algorithm *algo; - - if (!sav->key_auth) { - ipseclog((LOG_ERR, - "ah_hmac_sha2_512_mature: no key is given.\n")); - return 1; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_ERR, - "ah_hmac_sha2_512_mature: unsupported algorithm.\n")); - return 1; - } - - if (sav->key_auth->sadb_key_bits < algo->keymin || - algo->keymax < sav->key_auth->sadb_key_bits) { - ipseclog((LOG_ERR, - "ah_hmac_sha2_512_mature: invalid key length %d.\n", - sav->key_auth->sadb_key_bits)); - return 1; - } - - return 0; -} - -static int -ah_hmac_sha2_512_init(struct ah_algorithm_state *state, struct secasvar *sav) -{ - u_char *ipad; - u_char *opad; - SHA512_CTX *ctxt; - u_char tk[SHA512_DIGEST_LENGTH]; - u_char *key; - size_t keylen; - size_t i; - - if (!state) - panic("ah_hmac_sha2_512_init: what?"); - - state->sav = sav; - state->foo = (void *)kmalloc(64 + 64 + sizeof(SHA512_CTX), - M_TEMP, M_NOWAIT | M_ZERO); - if (!state->foo) - return ENOBUFS; - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (SHA512_CTX *)(opad + 64); - - /* compress the key if necessery */ - if (64 < _KEYLEN(state->sav->key_auth)) { - bzero(tk, sizeof(tk)); - bzero(ctxt, sizeof(*ctxt)); - SHA512_Init(ctxt); - SHA512_Update(ctxt, _KEYBUF(state->sav->key_auth), - _KEYLEN(state->sav->key_auth)); - SHA512_Final(&tk[0], ctxt); - key = &tk[0]; - keylen = sizeof(tk) < 64 ? sizeof(tk) : 64; - } else { - key = _KEYBUF(state->sav->key_auth); - keylen = _KEYLEN(state->sav->key_auth); - } - - bzero(ipad, 64); - bzero(opad, 64); - bcopy(key, ipad, keylen); - bcopy(key, opad, keylen); - for (i = 0; i < 64; i++) { - ipad[i] ^= 0x36; - opad[i] ^= 0x5c; - } - - bzero(ctxt, sizeof(*ctxt)); - SHA512_Init(ctxt); - SHA512_Update(ctxt, ipad, 64); - - return 0; -} - -static void -ah_hmac_sha2_512_loop(struct ah_algorithm_state *state, caddr_t addr, - size_t len) -{ - SHA512_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_sha2_512_loop: what?"); - - ctxt = (SHA512_CTX *)(((u_char *)state->foo) + 128); - SHA512_Update(ctxt, addr, len); -} - -static void -ah_hmac_sha2_512_result(struct ah_algorithm_state *state, caddr_t addr) -{ - u_char digest[SHA512_DIGEST_LENGTH]; - u_char *ipad; - u_char *opad; - SHA512_CTX *ctxt; - - if (!state || !state->foo) - panic("ah_hmac_sha2_512_result: what?"); - - ipad = (u_char *)state->foo; - opad = (u_char *)(ipad + 64); - ctxt = (SHA512_CTX *)(opad + 64); - - SHA512_Final((caddr_t)&digest[0], ctxt); - - bzero(ctxt, sizeof(*ctxt)); - SHA512_Init(ctxt); - SHA512_Update(ctxt, opad, 64); - SHA512_Update(ctxt, (caddr_t)&digest[0], sizeof(digest)); - SHA512_Final((caddr_t)&digest[0], ctxt); - - bcopy(&digest[0], (void *)addr, HMACSIZE); - - kfree(state->foo, M_TEMP); -} - -/*------------------------------------------------------------*/ - -/* - * go generate the checksum. - */ -static void -ah_update_mbuf(struct mbuf *m, int off, int len, - const struct ah_algorithm *algo, - struct ah_algorithm_state *algos) -{ - struct mbuf *n; - int tlen; - - /* easy case first */ - if (off + len <= m->m_len) { - (algo->update)(algos, mtod(m, caddr_t) + off, len); - return; - } - - for (n = m; n; n = n->m_next) { - if (off < n->m_len) - break; - - off -= n->m_len; - } - - if (!n) - panic("ah_update_mbuf: wrong offset specified"); - - for (/* nothing */; n && len > 0; n = n->m_next) { - if (n->m_len == 0) - continue; - if (n->m_len - off < len) - tlen = n->m_len - off; - else - tlen = len; - - (algo->update)(algos, mtod(n, caddr_t) + off, tlen); - - len -= tlen; - off = 0; - } -} - -#ifdef INET -/* - * Go generate the checksum. This function won't modify the mbuf chain - * except AH itself. - * - * NOTE: the function does not free mbuf on failure. - * Don't use m_copy(), it will try to share cluster mbuf by using refcnt. - */ -int -ah4_calccksum(struct mbuf *m, caddr_t ahdat, size_t len, - const struct ah_algorithm *algo, struct secasvar *sav) -{ - int off; - int hdrtype; - size_t advancewidth; - struct ah_algorithm_state algos; - u_char sumbuf[AH_MAXSUMSIZE]; - int error = 0; - int ahseen; - struct mbuf *n = NULL; - - if ((m->m_flags & M_PKTHDR) == 0) - return EINVAL; - - ahseen = 0; - hdrtype = -1; /* dummy, it is called IPPROTO_IP */ - - off = 0; - - error = (algo->init)(&algos, sav); - if (error) - return error; - - advancewidth = 0; /* safety */ - -again: - /* gory. */ - switch (hdrtype) { - case -1: /* first one only */ - { - /* - * copy ip hdr, modify to fit the AH checksum rule, - * then take a checksum. - */ - struct ip iphdr; - size_t hlen; - - m_copydata(m, off, sizeof(iphdr), (caddr_t)&iphdr); -#ifdef _IP_VHL - hlen = IP_VHL_HL(iphdr.ip_vhl) << 2; -#else - hlen = iphdr.ip_hl << 2; -#endif - iphdr.ip_ttl = 0; - iphdr.ip_sum = htons(0); - if (ip4_ah_cleartos) - iphdr.ip_tos = 0; - iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask); - (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip)); - - if (hlen != sizeof(struct ip)) { - u_char *p; - int i, l, skip; - - if (hlen > MCLBYTES) { - error = EMSGSIZE; - goto fail; - } - n = m_getb(hlen, M_NOWAIT, MT_DATA, 0); - if (n == NULL) { - error = ENOBUFS; - goto fail; - } - m_copydata(m, off, hlen, mtod(n, caddr_t)); - - /* - * IP options processing. - * See RFC2402 appendix A. - */ - p = mtod(n, u_char *); - i = sizeof(struct ip); - while (i < hlen) { - if (i + IPOPT_OPTVAL >= hlen) { - ipseclog((LOG_ERR, "ah4_calccksum: " - "invalid IP option\n")); - error = EINVAL; - goto fail; - } - if (p[i + IPOPT_OPTVAL] == IPOPT_EOL || - p[i + IPOPT_OPTVAL] == IPOPT_NOP || - i + IPOPT_OLEN < hlen) - ; - else { - ipseclog((LOG_ERR, - "ah4_calccksum: invalid IP option " - "(type=%02x)\n", - p[i + IPOPT_OPTVAL])); - error = EINVAL; - goto fail; - } - - skip = 1; - switch (p[i + IPOPT_OPTVAL]) { - case IPOPT_EOL: - case IPOPT_NOP: - l = 1; - skip = 0; - break; - case IPOPT_SECURITY: /* 0x82 */ - case 0x85: /* Extended security */ - case 0x86: /* Commercial security */ - case 0x94: /* Router alert */ - case 0x95: /* RFC1770 */ - l = p[i + IPOPT_OLEN]; - if (l < 2) - goto invalopt; - skip = 0; - break; - default: - l = p[i + IPOPT_OLEN]; - if (l < 2) - goto invalopt; - skip = 1; - break; - } - if (l < 1 || hlen - i < l) { - invalopt: - ipseclog((LOG_ERR, - "ah4_calccksum: invalid IP option " - "(type=%02x len=%02x)\n", - p[i + IPOPT_OPTVAL], - p[i + IPOPT_OLEN])); - error = EINVAL; - goto fail; - } - if (skip) - bzero(p + i, l); - if (p[i + IPOPT_OPTVAL] == IPOPT_EOL) - break; - i += l; - } - p = mtod(n, u_char *) + sizeof(struct ip); - (algo->update)(&algos, p, hlen - sizeof(struct ip)); - - m_free(n); - n = NULL; - } - - hdrtype = (iphdr.ip_p) & 0xff; - advancewidth = hlen; - break; - } - - case IPPROTO_AH: - { - struct ah ah; - int siz; - int hdrsiz; - int totlen; - - m_copydata(m, off, sizeof(ah), (caddr_t)&ah); - hdrsiz = (sav->flags & SADB_X_EXT_OLD) - ? sizeof(struct ah) - : sizeof(struct newah); - siz = (*algo->sumsiz)(sav); - totlen = (ah.ah_len + 2) << 2; - - /* - * special treatment is necessary for the first one, not others - */ - if (!ahseen) { - if (totlen > m->m_pkthdr.len - off || - totlen > MCLBYTES) { - error = EMSGSIZE; - goto fail; - } - n = m_getb(totlen, M_NOWAIT, MT_DATA, 0); - if (n == NULL) { - error = ENOBUFS; - goto fail; - } - m_copydata(m, off, totlen, mtod(n, caddr_t)); - n->m_len = totlen; - bzero(mtod(n, caddr_t) + hdrsiz, siz); - (algo->update)(&algos, mtod(n, caddr_t), n->m_len); - m_free(n); - n = NULL; - } else - ah_update_mbuf(m, off, totlen, algo, &algos); - ahseen++; - - hdrtype = ah.ah_nxt; - advancewidth = totlen; - break; - } - - default: - ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo, &algos); - advancewidth = m->m_pkthdr.len - off; - break; - } - - off += advancewidth; - if (off < m->m_pkthdr.len) - goto again; - - if (len < (*algo->sumsiz)(sav)) { - error = EINVAL; - goto fail; - } - - (algo->result)(&algos, &sumbuf[0]); - bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav)); - - if (n) - m_free(n); - return error; - -fail: - if (n) - m_free(n); - return error; -} -#endif - -#ifdef INET6 -/* - * Go generate the checksum. This function won't modify the mbuf chain - * except AH itself. - * - * NOTE: the function does not free mbuf on failure. - * Don't use m_copy(), it will try to share cluster mbuf by using refcnt. - */ -int -ah6_calccksum(struct mbuf *m, caddr_t ahdat, size_t len, - const struct ah_algorithm *algo, struct secasvar *sav) -{ - int newoff, off; - int proto, nxt; - struct mbuf *n = NULL; - int error; - int ahseen; - struct ah_algorithm_state algos; - u_char sumbuf[AH_MAXSUMSIZE]; - - if ((m->m_flags & M_PKTHDR) == 0) - return EINVAL; - - error = (algo->init)(&algos, sav); - if (error) - return error; - - off = 0; - proto = IPPROTO_IPV6; - nxt = -1; - ahseen = 0; - -again: - newoff = ip6_nexthdr(m, off, proto, &nxt); - if (newoff < 0) - newoff = m->m_pkthdr.len; - else if (newoff <= off) { - error = EINVAL; - goto fail; - } - - switch (proto) { - case IPPROTO_IPV6: - /* - * special treatment is necessary for the first one, not others - */ - if (off == 0) { - struct ip6_hdr ip6copy; - - if (newoff - off != sizeof(struct ip6_hdr)) { - error = EINVAL; - goto fail; - } - - m_copydata(m, off, newoff - off, (caddr_t)&ip6copy); - /* RFC2402 */ - ip6copy.ip6_flow = 0; - ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK; - ip6copy.ip6_vfc |= IPV6_VERSION; - ip6copy.ip6_hlim = 0; - in6_clearscope(&ip6copy.ip6_src); /* XXX */ - in6_clearscope(&ip6copy.ip6_dst); /* XXX */ - (algo->update)(&algos, (caddr_t)&ip6copy, - sizeof(struct ip6_hdr)); - } else { - newoff = m->m_pkthdr.len; - ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo, - &algos); - } - break; - - case IPPROTO_AH: - { - int siz; - int hdrsiz; - - hdrsiz = (sav->flags & SADB_X_EXT_OLD) - ? sizeof(struct ah) - : sizeof(struct newah); - siz = (*algo->sumsiz)(sav); - - /* - * special treatment is necessary for the first one, not others - */ - if (!ahseen) { - if (newoff - off > MCLBYTES) { - error = EMSGSIZE; - goto fail; - } - n = m_getb(newoff - off, M_NOWAIT, MT_DATA, 0); - if (n == NULL) { - error = ENOBUFS; - goto fail; - } - m_copydata(m, off, newoff - off, mtod(n, caddr_t)); - n->m_len = newoff - off; - bzero(mtod(n, caddr_t) + hdrsiz, siz); - (algo->update)(&algos, mtod(n, caddr_t), n->m_len); - m_free(n); - n = NULL; - } else - ah_update_mbuf(m, off, newoff - off, algo, &algos); - ahseen++; - break; - } - - case IPPROTO_HOPOPTS: - case IPPROTO_DSTOPTS: - { - struct ip6_ext *ip6e; - int hdrlen, optlen; - u_int8_t *p, *optend, *optp; - - if (newoff - off > MCLBYTES) { - error = EMSGSIZE; - goto fail; - } - n = m_getb(newoff - off, M_NOWAIT, MT_DATA, 0); - if (n == NULL) { - error = ENOBUFS; - goto fail; - } - m_copydata(m, off, newoff - off, mtod(n, caddr_t)); - n->m_len = newoff - off; - - ip6e = mtod(n, struct ip6_ext *); - hdrlen = (ip6e->ip6e_len + 1) << 3; - if (newoff - off < hdrlen) { - error = EINVAL; - m_free(n); - n = NULL; - goto fail; - } - p = mtod(n, u_int8_t *); - optend = p + hdrlen; - - /* - * ICV calculation for the options header including all - * options. This part is a little tricky since there are - * two type of options; mutable and immutable. We try to - * null-out mutable ones here. - */ - optp = p + 2; - while (optp < optend) { - if (optp[0] == IP6OPT_PAD1) - optlen = 1; - else { - if (optp + 2 > optend) { - error = EINVAL; - m_free(n); - n = NULL; - goto fail; - } - optlen = optp[1] + 2; - - if (optp[0] & IP6OPT_MUTABLE) - bzero(optp + 2, optlen - 2); - } - - optp += optlen; - } - - (algo->update)(&algos, mtod(n, caddr_t), n->m_len); - m_free(n); - n = NULL; - break; - } - - case IPPROTO_ROUTING: - /* - * For an input packet, we can just calculate `as is'. - * For an output packet, we assume ip6_output have already - * made packet how it will be received at the final - * destination. - */ - /* FALLTHROUGH */ - - default: - ah_update_mbuf(m, off, newoff - off, algo, &algos); - break; - } - - if (newoff < m->m_pkthdr.len) { - proto = nxt; - off = newoff; - goto again; - } - - if (len < (*algo->sumsiz)(sav)) { - error = EINVAL; - goto fail; - } - - (algo->result)(&algos, &sumbuf[0]); - bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav)); - - /* just in case */ - if (n) - m_free(n); - return 0; -fail: - /* just in case */ - if (n) - m_free(n); - return error; -} -#endif diff --git a/sys/netinet6/ah_input.c b/sys/netinet6/ah_input.c deleted file mode 100644 index 2797b77e96..0000000000 --- a/sys/netinet6/ah_input.c +++ /dev/null @@ -1,1037 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ah_input.c,v 1.1.2.6 2002/04/28 05:40:26 suz Exp $ */ -/* $KAME: ah_input.c,v 1.67 2002/01/07 11:39:56 kjc Exp $ */ - -/* - * 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. - */ - -/* - * RFC1826/2402 authentication header. - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#ifdef INET6 -#include -#endif - -#ifdef INET6 -#include -#include -#include -#include -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#include -#include -#ifdef IPSEC_DEBUG -#include -#else -#define KEYDEBUG(lev,arg) -#endif - -#include - -#define IPLEN_FLIPPED - -#ifdef INET -extern struct protosw inetsw[]; - -int -ah4_input(struct mbuf **mp, int *offp, int proto) -{ - int off; - struct mbuf *m; - struct ip *ip; - struct ah *ah; - u_int32_t spi; - const struct ah_algorithm *algo; - size_t siz; - size_t siz1; - u_char *cksum; - struct secasvar *sav = NULL; - u_int16_t nxt; - size_t hlen; - size_t stripsiz = 0; - - off = *offp; - m = *mp; - *mp = NULL; - -#ifndef PULLDOWN_TEST - if (m->m_len < off + sizeof(struct newah)) { - m = m_pullup(m, off + sizeof(struct newah)); - if (!m) { - ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;" - "dropping the packet for simplicity\n")); - ipsecstat.in_inval++; - goto fail; - } - } - - ip = mtod(m, struct ip *); - ah = (struct ah *)(((caddr_t)ip) + off); -#else - ip = mtod(m, struct ip *); - IP6_EXTHDR_GET(ah, struct ah *, m, off, sizeof(struct newah)); - if (ah == NULL) { - ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;" - "dropping the packet for simplicity\n")); - ipsecstat.in_inval++; - goto fail; - } -#endif - nxt = ah->ah_nxt; -#ifdef _IP_VHL - hlen = IP_VHL_HL(ip->ip_vhl) << 2; -#else - hlen = ip->ip_hl << 2; -#endif - - /* find the sassoc. */ - spi = ah->ah_spi; - - if ((sav = key_allocsa(AF_INET, - (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst, - IPPROTO_AH, spi)) == NULL) { - ipseclog((LOG_WARNING, - "IPv4 AH input: no key association found for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsecstat.in_nosa++; - goto fail; - } - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ah4_input called to allocate SA:%p\n", sav)); - if (sav->state != SADB_SASTATE_MATURE - && sav->state != SADB_SASTATE_DYING) { - ipseclog((LOG_DEBUG, - "IPv4 AH input: non-mature/dying SA found for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsecstat.in_badspi++; - goto fail; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_DEBUG, "IPv4 AH input: " - "unsupported authentication algorithm for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsecstat.in_badspi++; - goto fail; - } - - siz = (*algo->sumsiz)(sav); - siz1 = ((siz + 3) & ~(4 - 1)); - - /* - * sanity checks for header, 1. - */ - { - int sizoff; - - sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4; - - /* - * Here, we do not do "siz1 == siz". This is because the way - * RFC240[34] section 2 is written. They do not require truncation - * to 96 bits. - * For example, Microsoft IPsec stack attaches 160 bits of - * authentication data for both hmac-md5 and hmac-sha1. For hmac-sha1, - * 32 bits of padding is attached. - * - * There are two downsides to this specification. - * They have no real harm, however, they leave us fuzzy feeling. - * - if we attach more than 96 bits of authentication data onto AH, - * we will never notice about possible modification by rogue - * intermediate nodes. - * Since extra bits in AH checksum is never used, this constitutes - * no real issue, however, it is wacky. - * - even if the peer attaches big authentication data, we will never - * notice the difference, since longer authentication data will just - * work. - * - * We may need some clarification in the spec. - */ - if (siz1 < siz) { - ipseclog((LOG_NOTICE, "sum length too short in IPv4 AH input " - "(%lu, should be at least %lu): %s\n", - (u_long)siz1, (u_long)siz, - ipsec4_logpacketstr(ip, spi))); - ipsecstat.in_inval++; - goto fail; - } - if ((ah->ah_len << 2) - sizoff != siz1) { - ipseclog((LOG_NOTICE, "sum length mismatch in IPv4 AH input " - "(%d should be %lu): %s\n", - (ah->ah_len << 2) - sizoff, (u_long)siz1, - ipsec4_logpacketstr(ip, spi))); - ipsecstat.in_inval++; - goto fail; - } - -#ifndef PULLDOWN_TEST - if (m->m_len < off + sizeof(struct ah) + sizoff + siz1) { - m = m_pullup(m, off + sizeof(struct ah) + sizoff + siz1); - if (!m) { - ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n")); - ipsecstat.in_inval++; - goto fail; - } - - ip = mtod(m, struct ip *); - ah = (struct ah *)(((caddr_t)ip) + off); - } -#else - IP6_EXTHDR_GET(ah, struct ah *, m, off, - sizeof(struct ah) + sizoff + siz1); - if (ah == NULL) { - ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n")); - ipsecstat.in_inval++; - goto fail; - } -#endif - } - - /* - * check for sequence number. - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav)) - ; /* okey */ - else { - ipsecstat.in_ahreplay++; - ipseclog((LOG_WARNING, - "replay packet in IPv4 AH input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - goto fail; - } - } - - /* - * alright, it seems sane. now we are going to check the - * cryptographic checksum. - */ - cksum = kmalloc(siz1, M_TEMP, M_NOWAIT); - if (!cksum) { - ipseclog((LOG_DEBUG, "IPv4 AH input: " - "couldn't alloc temporary region for cksum\n")); - ipsecstat.in_inval++; - goto fail; - } - - /* - * some of IP header fields are flipped to the host endian. - * convert them back to network endian. VERY stupid. - */ - ip->ip_len = htons(ip->ip_len + hlen); - ip->ip_off = htons(ip->ip_off); - if (ah4_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) { - kfree(cksum, M_TEMP); - ipsecstat.in_inval++; - goto fail; - } - ipsecstat.in_ahhist[sav->alg_auth]++; - /* - * flip them back. - */ - ip->ip_len = ntohs(ip->ip_len) - hlen; - ip->ip_off = ntohs(ip->ip_off); - - { - caddr_t sumpos = NULL; - - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1826 */ - sumpos = (caddr_t)(ah + 1); - } else { - /* RFC 2402 */ - sumpos = (caddr_t)(((struct newah *)ah) + 1); - } - - if (bcmp(sumpos, cksum, siz) != 0) { - ipseclog((LOG_WARNING, - "checksum mismatch in IPv4 AH input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - kfree(cksum, M_TEMP); - ipsecstat.in_ahauthfail++; - goto fail; - } - } - - kfree(cksum, M_TEMP); - - m->m_flags |= M_AUTHIPHDR; - m->m_flags |= M_AUTHIPDGM; - -#if 0 - /* - * looks okey, but we need more sanity check. - * XXX should elaborate. - */ - if (ah->ah_nxt == IPPROTO_IPIP || ah->ah_nxt == IPPROTO_IP) { - struct ip *nip; - size_t sizoff; - - sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4; - - if (m->m_len < off + sizeof(struct ah) + sizoff + siz1 + hlen) { - m = m_pullup(m, off + sizeof(struct ah) - + sizoff + siz1 + hlen); - if (!m) { - ipseclog((LOG_DEBUG, - "IPv4 AH input: can't pullup\n")); - ipsecstat.in_inval++; - goto fail; - } - } - - nip = (struct ip *)((u_char *)(ah + 1) + sizoff + siz1); - if (nip->ip_src.s_addr != ip->ip_src.s_addr - || nip->ip_dst.s_addr != ip->ip_dst.s_addr) { - m->m_flags &= ~M_AUTHIPHDR; - m->m_flags &= ~M_AUTHIPDGM; - } - } -#ifdef INET6 - else if (ah->ah_nxt == IPPROTO_IPV6) { - m->m_flags &= ~M_AUTHIPHDR; - m->m_flags &= ~M_AUTHIPDGM; - } -#endif /* INET6 */ -#endif /* 0 */ - - if (m->m_flags & M_AUTHIPHDR - && m->m_flags & M_AUTHIPDGM) { -#if 0 - ipseclog((LOG_DEBUG, - "IPv4 AH input: authentication succeess\n")); -#endif - ipsecstat.in_ahauthsucc++; - } else { - ipseclog((LOG_WARNING, - "authentication failed in IPv4 AH input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_ahauthfail++; - goto fail; - } - - /* - * update sequence number. - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) { - ipsecstat.in_ahreplay++; - goto fail; - } - } - - /* was it transmitted over the IPsec tunnel SA? */ - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1826 */ - stripsiz = sizeof(struct ah) + siz1; - } else { - /* RFC 2402 */ - stripsiz = sizeof(struct newah) + siz1; - } - if (ipsec4_tunnel_validate(m, off + stripsiz, nxt, sav)) { - /* - * strip off all the headers that precedes AH. - * IP xx AH IP' payload -> IP' payload - * - * XXX more sanity checks - * XXX relationship with gif? - */ - u_int8_t tos; - - tos = ip->ip_tos; - m_adj(m, off + stripsiz); - if (m->m_len < sizeof(*ip)) { - m = m_pullup(m, sizeof(*ip)); - if (!m) { - ipsecstat.in_inval++; - goto fail; - } - } - ip = mtod(m, struct ip *); - /* ECN consideration. */ - ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos); - if (!key_checktunnelsanity(sav, AF_INET, - (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) { - ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch " - "in IPv4 AH input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_inval++; - goto fail; - } - -#if 1 - /* - * Should the inner packet be considered authentic? - * My current answer is: NO. - * - * host1 -- gw1 === gw2 -- host2 - * In this case, gw2 can trust the authenticity of the - * outer packet, but NOT inner. Packet may be altered - * between host1 and gw1. - * - * host1 -- gw1 === host2 - * This case falls into the same scenario as above. - * - * host1 === host2 - * This case is the only case when we may be able to leave - * M_AUTHIPHDR and M_AUTHIPDGM set. - * However, if host1 is wrongly configured, and allows - * attacker to inject some packet with src=host1 and - * dst=host2, you are in risk. - */ - m->m_flags &= ~M_AUTHIPHDR; - m->m_flags &= ~M_AUTHIPDGM; -#endif - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 || - ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) { - ipsecstat.in_nomem++; - goto fail; - } - - if (netisr_queue(NETISR_IP, m)) { - ipsecstat.in_inval++; - m = NULL; - goto fail; - } - - nxt = IPPROTO_DONE; - } else { - /* - * strip off AH. - */ - - ip = mtod(m, struct ip *); -#ifndef PULLDOWN_TEST - /* - * We do deep-copy since KAME requires that - * the packet is placed in a single external mbuf. - */ - bcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off); - m->m_data += stripsiz; - m->m_len -= stripsiz; - m->m_pkthdr.len -= stripsiz; -#else - /* - * even in m_pulldown case, we need to strip off AH so that - * we can compute checksum for multiple AH correctly. - */ - if (m->m_len >= stripsiz + off) { - bcopy((caddr_t)ip, ((caddr_t)ip) + stripsiz, off); - m->m_data += stripsiz; - m->m_len -= stripsiz; - m->m_pkthdr.len -= stripsiz; - } else { - /* - * this comes with no copy if the boundary is on - * cluster - */ - struct mbuf *n; - - n = m_split(m, off, M_NOWAIT); - if (n == NULL) { - /* m is retained by m_split */ - goto fail; - } - m_adj(n, stripsiz); - /* m_cat does not update m_pkthdr.len */ - m->m_pkthdr.len += n->m_pkthdr.len; - m_cat(m, n); - } -#endif - - if (m->m_len < sizeof(*ip)) { - m = m_pullup(m, sizeof(*ip)); - if (m == NULL) { - ipsecstat.in_inval++; - goto fail; - } - } - ip = mtod(m, struct ip *); -#ifdef IPLEN_FLIPPED - ip->ip_len = ip->ip_len - stripsiz; -#else - ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz); -#endif - ip->ip_p = nxt; - /* forget about IP hdr checksum, the check has already been passed */ - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) { - ipsecstat.in_nomem++; - goto fail; - } - - if (nxt != IPPROTO_DONE) { - if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) && - ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; - goto fail; - } - if (!ip_lengthcheck(&m, 0)) { - /* freed in ip_lengthcheck() */ - goto fail; - } - *mp = m; - *offp = off; - (*inetsw[ip_protox[nxt]].pr_input)(mp, offp, nxt); - } else { - m_freem(m); - } - m = NULL; - } - - if (sav) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ah4_input call free SA:%p\n", sav)); - key_freesav(sav); - } - ipsecstat.in_success++; - return(IPPROTO_DONE); - -fail: - if (sav) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ah4_input call free SA:%p\n", sav)); - key_freesav(sav); - } - if (m) - m_freem(m); - return(IPPROTO_DONE); -} -#endif /* INET */ - -#ifdef INET6 -int -ah6_input(struct mbuf **mp, int *offp, int proto) -{ - struct mbuf *m = *mp; - int off = *offp; - struct ip6_hdr *ip6; - struct ah *ah; - u_int32_t spi; - const struct ah_algorithm *algo; - size_t siz; - size_t siz1; - u_char *cksum; - struct secasvar *sav = NULL; - u_int16_t nxt; - size_t stripsiz = 0; - -#ifndef PULLDOWN_TEST - IP6_EXTHDR_CHECK(m, off, sizeof(struct ah), IPPROTO_DONE); - ah = (struct ah *)(mtod(m, caddr_t) + off); -#else - IP6_EXTHDR_GET(ah, struct ah *, m, off, sizeof(struct newah)); - if (ah == NULL) { - ipseclog((LOG_DEBUG, "IPv6 AH input: can't pullup\n")); - ipsec6stat.in_inval++; - return IPPROTO_DONE; - } -#endif - ip6 = mtod(m, struct ip6_hdr *); - nxt = ah->ah_nxt; - - /* find the sassoc. */ - spi = ah->ah_spi; - - if (ntohs(ip6->ip6_plen) == 0) { - ipseclog((LOG_ERR, "IPv6 AH input: " - "AH with IPv6 jumbogram is not supported.\n")); - ipsec6stat.in_inval++; - goto fail; - } - - if ((sav = key_allocsa(AF_INET6, - (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst, - IPPROTO_AH, spi)) == NULL) { - ipseclog((LOG_WARNING, - "IPv6 AH input: no key association found for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsec6stat.in_nosa++; - goto fail; - } - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ah6_input called to allocate SA:%p\n", sav)); - if (sav->state != SADB_SASTATE_MATURE - && sav->state != SADB_SASTATE_DYING) { - ipseclog((LOG_DEBUG, - "IPv6 AH input: non-mature/dying SA found for spi %u; ", - (u_int32_t)ntohl(spi))); - ipsec6stat.in_badspi++; - goto fail; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_DEBUG, "IPv6 AH input: " - "unsupported authentication algorithm for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsec6stat.in_badspi++; - goto fail; - } - - siz = (*algo->sumsiz)(sav); - siz1 = ((siz + 3) & ~(4 - 1)); - - /* - * sanity checks for header, 1. - */ - { - int sizoff; - - sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4; - - /* - * Here, we do not do "siz1 == siz". See ah4_input() for complete - * description. - */ - if (siz1 < siz) { - ipseclog((LOG_NOTICE, "sum length too short in IPv6 AH input " - "(%lu, should be at least %lu): %s\n", - (u_long)siz1, (u_long)siz, - ipsec6_logpacketstr(ip6, spi))); - ipsec6stat.in_inval++; - goto fail; - } - if ((ah->ah_len << 2) - sizoff != siz1) { - ipseclog((LOG_NOTICE, "sum length mismatch in IPv6 AH input " - "(%d should be %lu): %s\n", - (ah->ah_len << 2) - sizoff, (u_long)siz1, - ipsec6_logpacketstr(ip6, spi))); - ipsec6stat.in_inval++; - goto fail; - } -#ifndef PULLDOWN_TEST - IP6_EXTHDR_CHECK(m, off, sizeof(struct ah) + sizoff + siz1, IPPROTO_DONE); -#else - IP6_EXTHDR_GET(ah, struct ah *, m, off, - sizeof(struct ah) + sizoff + siz1); - if (ah == NULL) { - ipseclog((LOG_NOTICE, "couldn't pullup gather IPv6 AH checksum part")); - ipsec6stat.in_inval++; - m = NULL; - goto fail; - } -#endif - } - - /* - * check for sequence number. - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav)) - ; /* okey */ - else { - ipsec6stat.in_ahreplay++; - ipseclog((LOG_WARNING, - "replay packet in IPv6 AH input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), - ipsec_logsastr(sav))); - goto fail; - } - } - - /* - * alright, it seems sane. now we are going to check the - * cryptographic checksum. - */ - cksum = kmalloc(siz1, M_TEMP, M_NOWAIT); - if (!cksum) { - ipseclog((LOG_DEBUG, "IPv6 AH input: " - "couldn't alloc temporary region for cksum\n")); - ipsec6stat.in_inval++; - goto fail; - } - - if (ah6_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) { - kfree(cksum, M_TEMP); - ipsec6stat.in_inval++; - goto fail; - } - ipsec6stat.in_ahhist[sav->alg_auth]++; - - { - caddr_t sumpos = NULL; - - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1826 */ - sumpos = (caddr_t)(ah + 1); - } else { - /* RFC 2402 */ - sumpos = (caddr_t)(((struct newah *)ah) + 1); - } - - if (bcmp(sumpos, cksum, siz) != 0) { - ipseclog((LOG_WARNING, - "checksum mismatch in IPv6 AH input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - kfree(cksum, M_TEMP); - ipsec6stat.in_ahauthfail++; - goto fail; - } - } - - kfree(cksum, M_TEMP); - - m->m_flags |= M_AUTHIPHDR; - m->m_flags |= M_AUTHIPDGM; - -#if 0 - /* - * looks okey, but we need more sanity check. - * XXX should elaborate. - */ - if (ah->ah_nxt == IPPROTO_IPV6) { - struct ip6_hdr *nip6; - size_t sizoff; - - sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4; - - IP6_EXTHDR_CHECK(m, off, sizeof(struct ah) + sizoff + siz1 - + sizeof(struct ip6_hdr), IPPROTO_DONE); - - nip6 = (struct ip6_hdr *)((u_char *)(ah + 1) + sizoff + siz1); - if (!IN6_ARE_ADDR_EQUAL(&nip6->ip6_src, &ip6->ip6_src) - || !IN6_ARE_ADDR_EQUAL(&nip6->ip6_dst, &ip6->ip6_dst)) { - m->m_flags &= ~M_AUTHIPHDR; - m->m_flags &= ~M_AUTHIPDGM; - } - } else if (ah->ah_nxt == IPPROTO_IPIP) { - m->m_flags &= ~M_AUTHIPHDR; - m->m_flags &= ~M_AUTHIPDGM; - } else if (ah->ah_nxt == IPPROTO_IP) { - m->m_flags &= ~M_AUTHIPHDR; - m->m_flags &= ~M_AUTHIPDGM; - } -#endif - - if (m->m_flags & M_AUTHIPHDR - && m->m_flags & M_AUTHIPDGM) { -#if 0 - ipseclog((LOG_DEBUG, - "IPv6 AH input: authentication succeess\n")); -#endif - ipsec6stat.in_ahauthsucc++; - } else { - ipseclog((LOG_WARNING, - "authentication failed in IPv6 AH input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_ahauthfail++; - goto fail; - } - - /* - * update sequence number. - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) { - ipsec6stat.in_ahreplay++; - goto fail; - } - } - - /* was it transmitted over the IPsec tunnel SA? */ - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1826 */ - stripsiz = sizeof(struct ah) + siz1; - } else { - /* RFC 2402 */ - stripsiz = sizeof(struct newah) + siz1; - } - if (ipsec6_tunnel_validate(m, off + stripsiz, nxt, sav)) { - /* - * strip off all the headers that precedes AH. - * IP6 xx AH IP6' payload -> IP6' payload - * - * XXX more sanity checks - * XXX relationship with gif? - */ - u_int32_t flowinfo; /* net endian */ - - flowinfo = ip6->ip6_flow; - m_adj(m, off + stripsiz); - if (m->m_len < sizeof(*ip6)) { - /* - * m_pullup is prohibited in KAME IPv6 input processing - * but there's no other way! - */ - m = m_pullup(m, sizeof(*ip6)); - if (!m) { - ipsec6stat.in_inval++; - goto fail; - } - } - ip6 = mtod(m, struct ip6_hdr *); - /* ECN consideration. */ - ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); - if (!key_checktunnelsanity(sav, AF_INET6, - (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) { - ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch " - "in IPv6 AH input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), - ipsec_logsastr(sav))); - ipsec6stat.in_inval++; - goto fail; - } - -#if 1 - /* - * should the inner packet be considered authentic? - * see comment in ah4_input(). - */ - m->m_flags &= ~M_AUTHIPHDR; - m->m_flags &= ~M_AUTHIPDGM; -#endif - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 || - ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) { - ipsec6stat.in_nomem++; - goto fail; - } - - if (netisr_queue(NETISR_IPV6, m)) { - ipsec6stat.in_inval++; - m = NULL; - goto fail; - } - - nxt = IPPROTO_DONE; - } else { - /* - * strip off AH. - */ - char *prvnxtp; - - /* - * Copy the value of the next header field of AH to the - * next header field of the previous header. - * This is necessary because AH will be stripped off below. - */ - prvnxtp = ip6_get_prevhdr(m, off); /* XXX */ - *prvnxtp = nxt; - - ip6 = mtod(m, struct ip6_hdr *); -#ifndef PULLDOWN_TEST - /* - * We do deep-copy since KAME requires that - * the packet is placed in a single mbuf. - */ - bcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off); - m->m_data += stripsiz; - m->m_len -= stripsiz; - m->m_pkthdr.len -= stripsiz; -#else - /* - * even in m_pulldown case, we need to strip off AH so that - * we can compute checksum for multiple AH correctly. - */ - if (m->m_len >= stripsiz + off) { - bcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off); - m->m_data += stripsiz; - m->m_len -= stripsiz; - m->m_pkthdr.len -= stripsiz; - } else { - /* - * this comes with no copy if the boundary is on - * cluster - */ - struct mbuf *n; - - n = m_split(m, off, M_NOWAIT); - if (n == NULL) { - /* m is retained by m_split */ - goto fail; - } - m_adj(n, stripsiz); - /* m_cat does not update m_pkthdr.len */ - m->m_pkthdr.len += n->m_pkthdr.len; - m_cat(m, n); - } -#endif - ip6 = mtod(m, struct ip6_hdr *); - /* XXX jumbogram */ - ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz); - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) { - ipsec6stat.in_nomem++; - goto fail; - } - } - - *offp = off; - *mp = m; - - if (sav) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ah6_input call free SA:%p\n", sav)); - key_freesav(sav); - } - ipsec6stat.in_success++; - return nxt; - -fail: - if (sav) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ah6_input call free SA:%p\n", sav)); - key_freesav(sav); - } - if (m) - m_freem(m); - return IPPROTO_DONE; -} - -void -ah6_ctlinput(int cmd, struct sockaddr *sa, void *d) -{ - const struct newah *ahp; - struct newah ah; - struct secasvar *sav; - struct ip6_hdr *ip6; - struct mbuf *m; - struct ip6ctlparam *ip6cp = NULL; - int off; - struct sockaddr_in6 *sa6_src, *sa6_dst; - - if (sa->sa_family != AF_INET6 || - sa->sa_len != sizeof(struct sockaddr_in6)) - return; - if ((unsigned)cmd >= PRC_NCMDS) - return; - - /* if the parameter is from icmp6, decode it. */ - if (d != NULL) { - ip6cp = (struct ip6ctlparam *)d; - m = ip6cp->ip6c_m; - ip6 = ip6cp->ip6c_ip6; - off = ip6cp->ip6c_off; - } else { - m = NULL; - ip6 = NULL; - off = 0; /* fix warning */ - } - - if (ip6) { - /* - * XXX: We assume that when ip6 is non NULL, - * M and OFF are valid. - */ - - /* check if we can safely examine src and dst ports */ - if (m->m_pkthdr.len < off + sizeof(ah)) - return; - - if (m->m_len < off + sizeof(ah)) { - /* - * this should be rare case, - * so we compromise on this copy... - */ - m_copydata(m, off, sizeof(ah), (caddr_t)&ah); - ahp = &ah; - } else - ahp = (struct newah *)(mtod(m, caddr_t) + off); - - if (cmd == PRC_MSGSIZE) { - int valid = 0; - - /* - * Check to see if we have a valid SA corresponding to - * the address in the ICMP message payload. - */ - sa6_src = ip6cp->ip6c_src; - sa6_dst = (struct sockaddr_in6 *)sa; - sav = key_allocsa(AF_INET6, - (caddr_t)&sa6_src->sin6_addr, - (caddr_t)&sa6_dst->sin6_addr, - IPPROTO_AH, ahp->ah_spi); - if (sav) { - if (sav->state == SADB_SASTATE_MATURE || - sav->state == SADB_SASTATE_DYING) - valid++; - key_freesav(sav); - } - - /* XXX Further validation? */ - - /* - * Depending on the value of "valid" and routing table - * size (mtudisc_{hi,lo}wat), we will: - * - recalcurate the new MTU and create the - * corresponding routing entry, or - * - ignore the MTU change notification. - */ - icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); - } - - /* we normally notify single pcb here */ - } else { - /* we normally notify any pcb here */ - } -} -#endif /* INET6 */ diff --git a/sys/netinet6/ah_output.c b/sys/netinet6/ah_output.c deleted file mode 100644 index f7b4cd00b1..0000000000 --- a/sys/netinet6/ah_output.c +++ /dev/null @@ -1,574 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ah_output.c,v 1.1.2.5 2003/05/06 06:46:58 suz Exp $ */ -/* $KAME: ah_output.c,v 1.31 2001/07/26 06:53:15 jinmei Exp $ */ - -/* - * 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. - */ - -/* - * RFC1826/2402 authentication header. - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -#ifdef INET6 -#include -#include -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#include -#include - -#include - -#ifdef INET -static struct in_addr *ah4_finaldst (struct mbuf *); -#endif - -/* - * compute AH header size. - * transport mode only. for tunnel mode, we should implement - * virtual interface, and control MTU/MSS by the interface MTU. - */ -size_t -ah_hdrsiz(struct ipsecrequest *isr) -{ - const struct ah_algorithm *algo; - size_t hdrsiz; - - /* sanity check */ - if (isr == NULL) - panic("ah_hdrsiz: NULL was passed."); - - if (isr->saidx.proto != IPPROTO_AH) - panic("unsupported mode passed to ah_hdrsiz"); - - if (isr->sav == NULL) - goto estimate; - if (isr->sav->state != SADB_SASTATE_MATURE - && isr->sav->state != SADB_SASTATE_DYING) - goto estimate; - - /* we need transport mode AH. */ - algo = ah_algorithm_lookup(isr->sav->alg_auth); - if (!algo) - goto estimate; - - /* - * XXX - * right now we don't calcurate the padding size. simply - * treat the padding size as constant, for simplicity. - * - * XXX variable size padding support - */ - hdrsiz = (((*algo->sumsiz)(isr->sav) + 3) & ~(4 - 1)); - if (isr->sav->flags & SADB_X_EXT_OLD) - hdrsiz += sizeof(struct ah); - else - hdrsiz += sizeof(struct newah); - - return hdrsiz; - -estimate: - /* ASSUMING: - * sizeof(struct newah) > sizeof(struct ah). - * 16 = (16 + 3) & ~(4 - 1). - */ - return sizeof(struct newah) + 16; -} - -#ifdef INET -/* - * Modify the packet so that it includes the authentication data. - * The mbuf passed must start with IPv4 header. - * - * assumes that the first mbuf contains IPv4 header + option only. - * the function does not modify m. - */ -int -ah4_output(struct mbuf *m, struct ipsecrequest *isr) -{ - struct secasvar *sav = isr->sav; - const struct ah_algorithm *algo; - u_int32_t spi; - u_char *ahdrpos; - u_char *ahsumpos = NULL; - size_t hlen = 0; /* IP header+option in bytes */ - size_t plen = 0; /* AH payload size in bytes */ - size_t ahlen = 0; /* plen + sizeof(ah) */ - struct ip *ip; - struct in_addr dst; - struct in_addr *finaldst; - int error; - - /* sanity checks */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) { - struct ip *ip; - - ip = mtod(m, struct ip *); - ipseclog((LOG_DEBUG, "ah4_output: internal error: " - "sav->replay is null: %x->%x, SPI=%u\n", - (u_int32_t)ntohl(ip->ip_src.s_addr), - (u_int32_t)ntohl(ip->ip_dst.s_addr), - (u_int32_t)ntohl(sav->spi))); - ipsecstat.out_inval++; - m_freem(m); - return EINVAL; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_ERR, "ah4_output: unsupported algorithm: " - "SPI=%u\n", (u_int32_t)ntohl(sav->spi))); - ipsecstat.out_inval++; - m_freem(m); - return EINVAL; - } - spi = sav->spi; - - /* - * determine the size to grow. - */ - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1826 */ - plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */ - ahlen = plen + sizeof(struct ah); - } else { - /* RFC 2402 */ - plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */ - ahlen = plen + sizeof(struct newah); - } - - /* - * grow the mbuf to accomodate AH. - */ - ip = mtod(m, struct ip *); -#ifdef _IP_VHL - hlen = IP_VHL_HL(ip->ip_vhl) << 2; -#else - hlen = ip->ip_hl << 2; -#endif - - if (m->m_len != hlen) - panic("ah4_output: assumption failed (first mbuf length)"); - if (M_LEADINGSPACE(m->m_next) < ahlen) { - struct mbuf *n; - MGET(n, M_NOWAIT, MT_DATA); - if (!n) { - ipseclog((LOG_DEBUG, "ENOBUFS in ah4_output %d\n", - __LINE__)); - m_freem(m); - return ENOBUFS; - } - n->m_len = ahlen; - n->m_next = m->m_next; - m->m_next = n; - m->m_pkthdr.len += ahlen; - ahdrpos = mtod(n, u_char *); - } else { - m->m_next->m_len += ahlen; - m->m_next->m_data -= ahlen; - m->m_pkthdr.len += ahlen; - ahdrpos = mtod(m->m_next, u_char *); - } - - ip = mtod(m, struct ip *); /* just to be sure */ - - /* - * initialize AH. - */ - if (sav->flags & SADB_X_EXT_OLD) { - struct ah *ahdr; - - ahdr = (struct ah *)ahdrpos; - ahsumpos = (u_char *)(ahdr + 1); - ahdr->ah_len = plen >> 2; - ahdr->ah_nxt = ip->ip_p; - ahdr->ah_reserve = htons(0); - ahdr->ah_spi = spi; - bzero(ahdr + 1, plen); - } else { - struct newah *ahdr; - - ahdr = (struct newah *)ahdrpos; - ahsumpos = (u_char *)(ahdr + 1); - ahdr->ah_len = (plen >> 2) + 1; /* plus one for seq# */ - ahdr->ah_nxt = ip->ip_p; - ahdr->ah_reserve = htons(0); - ahdr->ah_spi = spi; - if (sav->replay->count == ~0) { - if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) { - /* XXX Is it noisy ? */ - ipseclog((LOG_WARNING, - "replay counter overflowed. %s\n", - ipsec_logsastr(sav))); - ipsecstat.out_inval++; - m_freem(m); - return EINVAL; - } - } - sav->replay->count++; - /* - * XXX sequence number must not be cycled, if the SA is - * installed by IKE daemon. - */ - ahdr->ah_seq = htonl(sav->replay->count & 0xffffffff); - bzero(ahdr + 1, plen); - } - - /* - * modify IPv4 header. - */ - ip->ip_p = IPPROTO_AH; - if (ahlen < (IP_MAXPACKET - ntohs(ip->ip_len))) - ip->ip_len = htons(ntohs(ip->ip_len) + ahlen); - else { - ipseclog((LOG_ERR, "IPv4 AH output: size exceeds limit\n")); - ipsecstat.out_inval++; - m_freem(m); - return EMSGSIZE; - } - - /* - * If there is source routing option, update destination field in - * the IPv4 header to the final destination. - * Note that we do not need to update source routing option itself - * (as done in IPv4 AH processing -- see ip6_output()), since - * source routing option is not part of the ICV computation. - */ - finaldst = ah4_finaldst(m); - if (finaldst) { - dst.s_addr = ip->ip_dst.s_addr; - ip->ip_dst.s_addr = finaldst->s_addr; - } else { - dst.s_addr = 0; /* fix compiler warning */ - } - - /* - * calcurate the checksum, based on security association - * and the algorithm specified. - */ - error = ah4_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav); - if (error) { - ipseclog((LOG_ERR, - "error after ah4_calccksum, called from ah4_output")); - m_freem(m); - m = NULL; - ipsecstat.out_inval++; - return error; - } - - if (finaldst) { - ip = mtod(m, struct ip *); /* just to make sure */ - ip->ip_dst.s_addr = dst.s_addr; - } - ipsecstat.out_success++; - ipsecstat.out_ahhist[sav->alg_auth]++; - key_sa_recordxfer(sav, m); - - return 0; -} -#endif - -/* Calculate AH length */ -int -ah_hdrlen(struct secasvar *sav) -{ - const struct ah_algorithm *algo; - int plen, ahlen; - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) - return 0; - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1826 */ - plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */ - ahlen = plen + sizeof(struct ah); - } else { - /* RFC 2402 */ - plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */ - ahlen = plen + sizeof(struct newah); - } - - return (ahlen); -} - -#ifdef INET6 -/* - * Fill in the Authentication Header and calculate checksum. - */ -int -ah6_output(struct mbuf *m, u_char *nexthdrp, struct mbuf *md, - struct ipsecrequest *isr) -{ - struct mbuf *mprev; - struct mbuf *mah; - struct secasvar *sav = isr->sav; - const struct ah_algorithm *algo; - u_int32_t spi; - u_char *ahsumpos = NULL; - size_t plen; /* AH payload size in bytes */ - int error = 0; - int ahlen; - struct ip6_hdr *ip6; - - if (m->m_len < sizeof(struct ip6_hdr)) { - ipseclog((LOG_DEBUG, "ah6_output: first mbuf too short\n")); - m_freem(m); - return EINVAL; - } - - ahlen = ah_hdrlen(sav); - if (ahlen == 0) - return 0; - - for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next) - ; - if (!mprev || mprev->m_next != md) { - ipseclog((LOG_DEBUG, "ah6_output: md is not in chain\n")); - m_freem(m); - return EINVAL; - } - - mah = m_getb(ahlen, M_NOWAIT, MT_DATA, 0); - if (mah == NULL) { - m_freem(m); - return ENOBUFS; - } - mah->m_len = ahlen; - mah->m_next = md; - mprev->m_next = mah; - m->m_pkthdr.len += ahlen; - - /* fix plen */ - if (m->m_pkthdr.len - sizeof(struct ip6_hdr) > IPV6_MAXPACKET) { - ipseclog((LOG_ERR, - "ah6_output: AH with IPv6 jumbogram is not supported\n")); - m_freem(m); - return EINVAL; - } - ip6 = mtod(m, struct ip6_hdr *); - ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); - - if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) { - ipseclog((LOG_DEBUG, "ah6_output: internal error: " - "sav->replay is null: SPI=%u\n", - (u_int32_t)ntohl(sav->spi))); - ipsec6stat.out_inval++; - m_freem(m); - return EINVAL; - } - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_ERR, "ah6_output: unsupported algorithm: " - "SPI=%u\n", (u_int32_t)ntohl(sav->spi))); - ipsec6stat.out_inval++; - m_freem(m); - return EINVAL; - } - spi = sav->spi; - - /* - * initialize AH. - */ - if (sav->flags & SADB_X_EXT_OLD) { - struct ah *ahdr = mtod(mah, struct ah *); - - plen = mah->m_len - sizeof(struct ah); - ahsumpos = (u_char *)(ahdr + 1); - ahdr->ah_nxt = *nexthdrp; - *nexthdrp = IPPROTO_AH; - ahdr->ah_len = plen >> 2; - ahdr->ah_reserve = htons(0); - ahdr->ah_spi = spi; - bzero(ahdr + 1, plen); - } else { - struct newah *ahdr = mtod(mah, struct newah *); - - plen = mah->m_len - sizeof(struct newah); - ahsumpos = (u_char *)(ahdr + 1); - ahdr->ah_nxt = *nexthdrp; - *nexthdrp = IPPROTO_AH; - ahdr->ah_len = (plen >> 2) + 1; /* plus one for seq# */ - ahdr->ah_reserve = htons(0); - ahdr->ah_spi = spi; - if (sav->replay->count == ~0) { - if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) { - /* XXX Is it noisy ? */ - ipseclog((LOG_WARNING, - "replay counter overflowed. %s\n", - ipsec_logsastr(sav))); - ipsec6stat.out_inval++; - m_freem(m); - return EINVAL; - } - } - sav->replay->count++; - /* - * XXX sequence number must not be cycled, if the SA is - * installed by IKE daemon. - */ - ahdr->ah_seq = htonl(sav->replay->count); - bzero(ahdr + 1, plen); - } - - /* - * calcurate the checksum, based on security association - * and the algorithm specified. - */ - error = ah6_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav); - if (error) { - ipsec6stat.out_inval++; - m_freem(m); - } else { - ipsec6stat.out_success++; - key_sa_recordxfer(sav, m); - } - ipsec6stat.out_ahhist[sav->alg_auth]++; - - return (error); -} -#endif - -#ifdef INET -/* - * Find the final destination if there is loose/strict source routing option. - * Returns NULL if there's no source routing options. - * Returns NULL on errors too. - * Note that this function will return a pointer INTO the given parameter, - * struct mbuf *m. - * The mbuf must be pulled up toward, at least, ip option part. - */ -static struct in_addr * -ah4_finaldst(struct mbuf *m) -{ - struct ip *ip; - int optlen; - u_char *q; - int i; - int hlen; - - if (!m) - panic("ah4_finaldst: m == NULL"); - ip = mtod(m, struct ip *); - hlen = (ip->ip_hl << 2); - - if (m->m_len < hlen) { - ipseclog((LOG_DEBUG, - "ah4_finaldst: parameter mbuf wrong (not pulled up)\n")); - return NULL; - } - - if (hlen == sizeof(struct ip)) - return NULL; - - optlen = hlen - sizeof(struct ip); - if (optlen < 0) { - ipseclog((LOG_DEBUG, "ah4_finaldst: wrong optlen %d\n", - optlen)); - return NULL; - } - - q = (u_char *)(ip + 1); - i = 0; - while (i < optlen) { - if (i + IPOPT_OPTVAL >= optlen) - return NULL; - if (q[i + IPOPT_OPTVAL] == IPOPT_EOL || - q[i + IPOPT_OPTVAL] == IPOPT_NOP || - i + IPOPT_OLEN < optlen) - ; - else - return NULL; - - switch (q[i + IPOPT_OPTVAL]) { - case IPOPT_EOL: - i = optlen; /* bye */ - break; - case IPOPT_NOP: - i++; - break; - case IPOPT_LSRR: - case IPOPT_SSRR: - if (q[i + IPOPT_OLEN] < 2 + sizeof(struct in_addr) || - optlen - i < q[i + IPOPT_OLEN]) { - ipseclog((LOG_ERR, - "ip_finaldst: invalid IP option " - "(code=%02x len=%02x)\n", - q[i + IPOPT_OPTVAL], q[i + IPOPT_OLEN])); - return NULL; - } - i += q[i + IPOPT_OLEN] - sizeof(struct in_addr); - return (struct in_addr *)(q + i); - default: - if (q[i + IPOPT_OLEN] < 2 || - optlen - i < q[i + IPOPT_OLEN]) { - ipseclog((LOG_ERR, - "ip_finaldst: invalid IP option " - "(code=%02x len=%02x)\n", - q[i + IPOPT_OPTVAL], q[i + IPOPT_OLEN])); - return NULL; - } - i += q[i + IPOPT_OLEN]; - break; - } - } - return NULL; -} -#endif diff --git a/sys/netinet6/esp.h b/sys/netinet6/esp.h deleted file mode 100644 index 5ea5e1e863..0000000000 --- a/sys/netinet6/esp.h +++ /dev/null @@ -1,112 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/esp.h,v 1.8 2005/01/07 02:30:34 imp Exp $ */ -/* $KAME: esp.h,v 1.19 2001/09/04 08:43:19 itojun Exp $ */ - -/*- - * 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. - */ - -/* - * RFC1827/2406 Encapsulated Security Payload. - */ - -#ifndef _NETINET6_ESP_H_ -#define _NETINET6_ESP_H_ - -#ifndef _SYS_TYPES_H_ -#include -#endif - -#if defined(_KERNEL) && !defined(_LKM) -#include "opt_inet.h" -#endif - -struct esp { - u_int32_t esp_spi; /* ESP */ - /* variable size, 32bit bound */ /* Initialization Vector */ - /* variable size */ /* Payload data */ - /* variable size */ /* padding */ - /* 8bit */ /* pad size */ - /* 8bit */ /* next header */ - /* variable size, 32bit bound */ /* Authentication data (new IPsec) */ -}; - -struct newesp { - u_int32_t esp_spi; /* ESP */ - u_int32_t esp_seq; /* Sequence number */ - /* variable size */ /* (IV and) Payload data */ - /* variable size */ /* padding */ - /* 8bit */ /* pad size */ - /* 8bit */ /* next header */ - /* variable size, 32bit bound *//* Authentication data */ -}; - -struct esptail { - u_int8_t esp_padlen; /* pad length */ - u_int8_t esp_nxt; /* Next header */ - /* variable size, 32bit bound *//* Authentication data (new IPsec)*/ -}; - -#ifdef _KERNEL - -struct secasvar; - -struct esp_algorithm { - size_t padbound; /* pad boundary, in byte */ - int ivlenval; /* iv length, in byte */ - int (*mature) (struct secasvar *); - int keymin; /* in bits */ - int keymax; /* in bits */ - size_t (*schedlen) (const struct esp_algorithm *); - const char *name; - int (*ivlen) (const struct esp_algorithm *, struct secasvar *); - int (*decrypt) (struct mbuf *, size_t, - struct secasvar *, const struct esp_algorithm *, int); - int (*encrypt) (struct mbuf *, size_t, size_t, - struct secasvar *, const struct esp_algorithm *, int); - /* not supposed to be called directly */ - int (*schedule) (const struct esp_algorithm *, struct secasvar *); - int (*blockdecrypt) (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); - int (*blockencrypt) (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); -}; - -extern const struct esp_algorithm *esp_algorithm_lookup (int); -extern int esp_max_ivlen (void); - -/* crypt routines */ -extern int esp4_output (struct mbuf *, struct ipsecrequest *); -extern int esp4_input(struct mbuf **, int *, int); -extern size_t esp_hdrsiz (struct ipsecrequest *); - -extern int esp_schedule (const struct esp_algorithm *, struct secasvar *); -extern int esp_auth (struct mbuf *, size_t, size_t, - struct secasvar *, u_char *); -#endif /* _KERNEL */ - -#endif /* _NETINET6_ESP_H_ */ diff --git a/sys/netinet6/esp6.h b/sys/netinet6/esp6.h deleted file mode 100644 index 76c1e6c763..0000000000 --- a/sys/netinet6/esp6.h +++ /dev/null @@ -1,60 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/esp6.h,v 1.2.2.2 2001/07/03 11:01:49 ume Exp $ */ -/* $DragonFly: src/sys/netinet6/esp6.h,v 1.4 2006/05/20 02:42:12 dillon Exp $ */ -/* $KAME: esp.h,v 1.16 2000/10/18 21:28:00 itojun Exp $ */ - -/* - * 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. - */ - -/* - * RFC1827/2406 Encapsulated Security Payload. - */ - -#ifndef _NETINET6_ESP6_H_ -#define _NETINET6_ESP6_H_ - -#ifdef _KERNEL - -#ifndef _SYS_TYPES_H_ -#include -#endif - -struct mbuf; -struct ipsecrequest; -struct sockaddr; -union netmsg; - -extern int esp6_output (struct mbuf *, u_char *, struct mbuf *, - struct ipsecrequest *); -extern int esp6_input (struct mbuf **, int *, int); - -extern void esp6_ctlinput (union netmsg *); - -#endif /*_KERNEL*/ - -#endif /*_NETINET6_ESP6_H_*/ diff --git a/sys/netinet6/esp_aesctr.c b/sys/netinet6/esp_aesctr.c deleted file mode 100644 index ddeda1764b..0000000000 --- a/sys/netinet6/esp_aesctr.c +++ /dev/null @@ -1,447 +0,0 @@ -/* $KAME: esp_aesctr.c,v 1.2 2003/07/20 00:29:37 itojun Exp $ */ - -/*- - * Copyright (C) 1995, 1996, 1997, 1998 and 2003 WIDE Project. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -#include - -#include - -#define AES_BLOCKSIZE 16 - -#define NONCESIZE 4 -union cblock { - struct { - u_int8_t nonce[4]; - u_int8_t iv[8]; - u_int32_t ctr; - } __packed v; - u_int8_t cblock[16]; -}; - -typedef struct { - u_int32_t r_ek[(RIJNDAEL_MAXNR+1)*4]; - int r_nr; /* key-length-dependent number of rounds */ -} aesctr_ctx; - -int -esp_aesctr_mature(struct secasvar *sav) -{ - int keylen; - const struct esp_algorithm *algo; - - algo = esp_algorithm_lookup(sav->alg_enc); - if (!algo) { - ipseclog((LOG_ERR, - "esp_aeesctr_mature: unsupported algorithm %d\n", - sav->alg_enc)); - return 1; - } - - keylen = sav->key_enc->sadb_key_bits; - if (keylen < algo->keymin || algo->keymax < keylen) { - ipseclog((LOG_ERR, - "esp_aesctr_mature %s: invalid key length %d.\n", - algo->name, sav->key_enc->sadb_key_bits)); - return 1; - } - - /* rijndael key + nonce */ - if (!(keylen == 128 + 32 || keylen == 192 + 32 || keylen == 256 + 32)) { - ipseclog((LOG_ERR, - "esp_aesctr_mature %s: invalid key length %d.\n", - algo->name, keylen)); - return 1; - } - - return 0; -} - -size_t -esp_aesctr_schedlen(const struct esp_algorithm *algo) -{ - - return sizeof(aesctr_ctx); -} - -int -esp_aesctr_schedule(const struct esp_algorithm *algo, struct secasvar *sav) -{ - aesctr_ctx *ctx; - int keylen; - - /* SA key = AES key + nonce */ - keylen = _KEYLEN(sav->key_enc) * 8 - NONCESIZE * 8; - - ctx = (aesctr_ctx *)sav->sched; - if ((ctx->r_nr = rijndaelKeySetupEnc(ctx->r_ek, - (char *)_KEYBUF(sav->key_enc), keylen)) == 0) - return -1; - return 0; -} - -int -esp_aesctr_decrypt(struct mbuf *m, size_t off, struct secasvar *sav, - const struct esp_algorithm *algo, int ivlen) -{ - struct mbuf *s; - struct mbuf *d, *d0 = NULL, *dp; - int soff, doff; /* offset from the head of chain, to head of this mbuf */ - int sn, dn; /* offset from the head of the mbuf, to meat */ - size_t ivoff, bodyoff; - union cblock cblock; - u_int8_t keystream[AES_BLOCKSIZE], *nonce; - u_int32_t ctr; - u_int8_t sbuf[AES_BLOCKSIZE], *sp, *dst; - struct mbuf *scut; - int scutoff; - int i; - int blocklen; - aesctr_ctx *ctx; - - if (ivlen != sav->ivlen) { - ipseclog((LOG_ERR, "esp_aesctr_decrypt %s: " - "unsupported ivlen %d\n", algo->name, ivlen)); - goto fail; - } - - /* assumes blocklen == padbound */ - blocklen = algo->padbound; - - ivoff = off + sizeof(struct newesp); - bodyoff = off + sizeof(struct newesp) + ivlen; - - /* setup counter block */ - nonce = _KEYBUF(sav->key_enc) + _KEYLEN(sav->key_enc) - NONCESIZE; - bcopy(nonce, cblock.v.nonce, NONCESIZE); - m_copydata(m, ivoff, ivlen, cblock.v.iv); - ctr = 1; - - if (m->m_pkthdr.len < bodyoff) { - ipseclog((LOG_ERR, "esp_aesctr_decrypt %s: bad len %d/%lu\n", - algo->name, m->m_pkthdr.len, (unsigned long)bodyoff)); - goto fail; - } - if ((m->m_pkthdr.len - bodyoff) % blocklen) { - ipseclog((LOG_ERR, "esp_aesctr_decrypt %s: " - "payload length must be multiple of %d\n", - algo->name, blocklen)); - goto fail; - } - - s = m; - d = d0 = dp = NULL; - soff = doff = sn = dn = 0; - sp = NULL; - - /* skip bodyoff */ - while (soff < bodyoff) { - if (soff + s->m_len > bodyoff) { - sn = bodyoff - soff; - break; - } - - soff += s->m_len; - s = s->m_next; - } - scut = s; - scutoff = sn; - - /* skip over empty mbuf */ - while (s && s->m_len == 0) - s = s->m_next; - - while (soff < m->m_pkthdr.len) { - /* source */ - if (sn + blocklen <= s->m_len) { - /* body is continuous */ - sp = mtod(s, u_int8_t *) + sn; - } else { - /* body is non-continuous */ - m_copydata(s, sn, blocklen, (caddr_t)sbuf); - sp = sbuf; - } - - /* destination */ - if (!d || dn + blocklen > d->m_len) { - if (d) - dp = d; - MGET(d, M_NOWAIT, MT_DATA); - i = m->m_pkthdr.len - (soff + sn); - if (d && i > MLEN) { - MCLGET(d, M_NOWAIT); - if ((d->m_flags & M_EXT) == 0) { - m_free(d); - d = NULL; - } - } - if (!d) { - goto nomem; - } - if (!d0) - d0 = d; - if (dp) - dp->m_next = d; - d->m_len = 0; - d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen; - if (d->m_len > i) - d->m_len = i; - dn = 0; - } - - /* put counter into counter block */ - cblock.v.ctr = htonl(ctr); - - /* setup keystream */ - ctx = (aesctr_ctx *)sav->sched; - rijndaelEncrypt(ctx->r_ek, ctx->r_nr, cblock.cblock, keystream); - - bcopy(sp, mtod(d, u_int8_t *) + dn, blocklen); - dst = mtod(d, u_int8_t *) + dn; - for (i = 0; i < blocklen; i++) - dst[i] ^= keystream[i]; - - ctr++; - - sn += blocklen; - dn += blocklen; - - /* find the next source block */ - while (s && sn >= s->m_len) { - sn -= s->m_len; - soff += s->m_len; - s = s->m_next; - } - - /* skip over empty mbuf */ - while (s && s->m_len == 0) - s = s->m_next; - } - - m_freem(scut->m_next); - scut->m_len = scutoff; - scut->m_next = d0; - - /* just in case */ - bzero(&cblock, sizeof(cblock)); - bzero(keystream, sizeof(keystream)); - - return 0; - -fail: - m_freem(m); - if (d0) - m_freem(d0); - return EINVAL; - -nomem: - m_freem(m); - if (d0) - m_freem(d0); - return ENOBUFS; -} - -int -esp_aesctr_encrypt(struct mbuf *m, size_t off, size_t plen, struct secasvar *sav, - const struct esp_algorithm *algo, int ivlen) -{ - struct mbuf *s; - struct mbuf *d, *d0, *dp; - int soff, doff; /* offset from the head of chain, to head of this mbuf */ - int sn, dn; /* offset from the head of the mbuf, to meat */ - size_t ivoff, bodyoff; - union cblock cblock; - u_int8_t keystream[AES_BLOCKSIZE], *nonce; - u_int32_t ctr; - u_int8_t sbuf[AES_BLOCKSIZE], *sp, *dst; - struct mbuf *scut; - int scutoff; - int i; - int blocklen; - aesctr_ctx *ctx; - - if (ivlen != sav->ivlen) { - ipseclog((LOG_ERR, "esp_aesctr_encrypt %s: " - "unsupported ivlen %d\n", algo->name, ivlen)); - m_freem(m); - return EINVAL; - } - - /* assumes blocklen == padbound */ - blocklen = algo->padbound; - - ivoff = off + sizeof(struct newesp); - bodyoff = off + sizeof(struct newesp) + ivlen; - - /* put iv into the packet. */ - /* maybe it is better to overwrite dest, not source */ - m_copyback(m, ivoff, ivlen, sav->iv); - - /* setup counter block */ - nonce = _KEYBUF(sav->key_enc) + _KEYLEN(sav->key_enc) - NONCESIZE; - bcopy(nonce, cblock.v.nonce, NONCESIZE); - m_copydata(m, ivoff, ivlen, cblock.v.iv); - ctr = 1; - - if (m->m_pkthdr.len < bodyoff) { - ipseclog((LOG_ERR, "esp_aesctr_encrypt %s: bad len %d/%lu\n", - algo->name, m->m_pkthdr.len, (unsigned long)bodyoff)); - m_freem(m); - return EINVAL; - } - if ((m->m_pkthdr.len - bodyoff) % blocklen) { - ipseclog((LOG_ERR, "esp_aesctr_encrypt %s: " - "payload length must be multiple of %lu\n", - algo->name, (unsigned long)algo->padbound)); - m_freem(m); - return EINVAL; - } - - s = m; - d = d0 = dp = NULL; - soff = doff = sn = dn = 0; - sp = NULL; - - /* skip bodyoff */ - while (soff < bodyoff) { - if (soff + s->m_len > bodyoff) { - sn = bodyoff - soff; - break; - } - - soff += s->m_len; - s = s->m_next; - } - scut = s; - scutoff = sn; - - /* skip over empty mbuf */ - while (s && s->m_len == 0) - s = s->m_next; - - while (soff < m->m_pkthdr.len) { - /* source */ - if (sn + blocklen <= s->m_len) { - /* body is continuous */ - sp = mtod(s, u_int8_t *) + sn; - } else { - /* body is non-continuous */ - m_copydata(s, sn, blocklen, (caddr_t)sbuf); - sp = sbuf; - } - - /* destination */ - if (!d || dn + blocklen > d->m_len) { - if (d) - dp = d; - MGET(d, M_NOWAIT, MT_DATA); - i = m->m_pkthdr.len - (soff + sn); - if (d && i > MLEN) { - MCLGET(d, M_NOWAIT); - if ((d->m_flags & M_EXT) == 0) { - m_free(d); - d = NULL; - } - } - if (!d) { - m_freem(m); - if (d0) - m_freem(d0); - return ENOBUFS; - } - if (!d0) - d0 = d; - if (dp) - dp->m_next = d; - d->m_len = 0; - d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen; - if (d->m_len > i) - d->m_len = i; - dn = 0; - } - - /* put counter into counter block */ - cblock.v.ctr = htonl(ctr); - - /* setup keystream */ - ctx = (aesctr_ctx *)sav->sched; - rijndaelEncrypt(ctx->r_ek, ctx->r_nr, cblock.cblock, keystream); - - bcopy(sp, mtod(d, u_int8_t *) + dn, blocklen); - dst = mtod(d, u_int8_t *) + dn; - for (i = 0; i < blocklen; i++) - dst[i] ^= keystream[i]; - - ctr++; - - sn += blocklen; - dn += blocklen; - - /* find the next source block */ - while (s && sn >= s->m_len) { - sn -= s->m_len; - soff += s->m_len; - s = s->m_next; - } - - /* skip over empty mbuf */ - while (s && s->m_len == 0) - s = s->m_next; - } - - m_freem(scut->m_next); - scut->m_len = scutoff; - scut->m_next = d0; - - /* just in case */ - bzero(&cblock, sizeof(cblock)); - bzero(keystream, sizeof(keystream)); - - key_sa_stir_iv(sav); - - return 0; -} diff --git a/sys/netinet6/esp_camellia.c b/sys/netinet6/esp_camellia.c deleted file mode 100644 index dcd834f1ec..0000000000 --- a/sys/netinet6/esp_camellia.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Copyright (c) 2006 - * NTT (Nippon Telegraph and Telephone Corporation) . 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 as - * the first lines of this file unmodified. - * 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. - * - * THIS SOFTWARE IS PROVIDED BY NTT ``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 NTT BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include - -size_t -esp_camellia_schedlen(const struct esp_algorithm *algo) -{ - - return sizeof(camellia_ctx); -} - -int -esp_camellia_schedule(const struct esp_algorithm *algo, struct secasvar *sav) -{ - camellia_ctx *ctx; - - ctx = (camellia_ctx *)sav->sched; - camellia_set_key(ctx, - (u_char *)_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc) * 8); - return 0; -} - -int -esp_camellia_blockdecrypt(const struct esp_algorithm *algo, struct secasvar *sav, - u_int8_t *s, u_int8_t *d) -{ - camellia_ctx *ctx; - - ctx = (camellia_ctx *)sav->sched; - camellia_decrypt(ctx, s, d); - return 0; -} - -int -esp_camellia_blockencrypt(const struct esp_algorithm *algo, struct secasvar *sav, - u_int8_t *s, u_int8_t *d) -{ - camellia_ctx *ctx; - - ctx = (camellia_ctx *)sav->sched; - camellia_encrypt(ctx, s, d); - return 0; -} diff --git a/sys/netinet6/esp_core.c b/sys/netinet6/esp_core.c deleted file mode 100644 index ee127ceba3..0000000000 --- a/sys/netinet6/esp_core.c +++ /dev/null @@ -1,1057 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/esp_core.c,v 1.23.2.1 2007/12/07 08:45:28 gnn Exp $ */ -/* $KAME: esp_core.c,v 1.50 2000/11/02 12:27:38 itojun Exp $ */ - -/*- - * 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. - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#ifdef INET6 -#include -#include -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#define cast128_key cast_key -#define cast128_setkey(key, rawkey, keybytes) \ - cast_setkey((key), (rawkey), (keybytes)) -#define cast128_encrypt(key, inblock, outblock) \ - cast_encrypt((key), (inblock), (outblock)) -#define cast128_decrypt(key, inblock, outblock) \ - cast_decrypt((key), (inblock), (outblock)) - -#include - -static int esp_null_mature (struct secasvar *); -static int esp_null_decrypt (struct mbuf *, size_t, - struct secasvar *, const struct esp_algorithm *, int); -static int esp_null_encrypt (struct mbuf *, size_t, size_t, - struct secasvar *, const struct esp_algorithm *, int); -static int esp_descbc_mature (struct secasvar *); -static int esp_descbc_ivlen (const struct esp_algorithm *, - struct secasvar *); -static int esp_des_schedule (const struct esp_algorithm *, - struct secasvar *); -static size_t esp_des_schedlen (const struct esp_algorithm *); -static int esp_des_blockdecrypt (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); -static int esp_des_blockencrypt (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); -static int esp_cbc_mature (struct secasvar *); -static int esp_blowfish_schedule (const struct esp_algorithm *, - struct secasvar *); -static size_t esp_blowfish_schedlen (const struct esp_algorithm *); -static int esp_blowfish_blockdecrypt (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); -static int esp_blowfish_blockencrypt (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); -static int esp_cast128_schedule (const struct esp_algorithm *, - struct secasvar *); -static size_t esp_cast128_schedlen (const struct esp_algorithm *); -static int esp_cast128_blockdecrypt (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); -static int esp_cast128_blockencrypt (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); -static int esp_3des_schedule (const struct esp_algorithm *, - struct secasvar *); -static size_t esp_3des_schedlen (const struct esp_algorithm *); -static int esp_3des_blockdecrypt (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); -static int esp_3des_blockencrypt (const struct esp_algorithm *, - struct secasvar *, u_int8_t *, u_int8_t *); -static int esp_common_ivlen (const struct esp_algorithm *, - struct secasvar *); -static int esp_cbc_decrypt (struct mbuf *, size_t, - struct secasvar *, const struct esp_algorithm *, int); -static int esp_cbc_encrypt (struct mbuf *, size_t, size_t, - struct secasvar *, const struct esp_algorithm *, int); - -#define MAXIVLEN 16 - -static const struct esp_algorithm esp_algorithms[] = { - { 8, -1, esp_descbc_mature, 64, 64, esp_des_schedlen, - "des-cbc", - esp_descbc_ivlen, esp_cbc_decrypt, - esp_cbc_encrypt, esp_des_schedule, - esp_des_blockdecrypt, esp_des_blockencrypt, }, - { 8, 8, esp_cbc_mature, 192, 192, esp_3des_schedlen, - "3des-cbc", - esp_common_ivlen, esp_cbc_decrypt, - esp_cbc_encrypt, esp_3des_schedule, - esp_3des_blockdecrypt, esp_3des_blockencrypt, }, - { 1, 0, esp_null_mature, 0, 2048, NULL, "null", - esp_common_ivlen, esp_null_decrypt, - esp_null_encrypt, NULL, }, - { 8, 8, esp_cbc_mature, 40, 448, esp_blowfish_schedlen, "blowfish-cbc", - esp_common_ivlen, esp_cbc_decrypt, - esp_cbc_encrypt, esp_blowfish_schedule, - esp_blowfish_blockdecrypt, esp_blowfish_blockencrypt, }, - { 8, 8, esp_cbc_mature, 40, 128, esp_cast128_schedlen, - "cast128-cbc", - esp_common_ivlen, esp_cbc_decrypt, - esp_cbc_encrypt, esp_cast128_schedule, - esp_cast128_blockdecrypt, esp_cast128_blockencrypt, }, - { 16, 16, esp_cbc_mature, 128, 256, esp_rijndael_schedlen, - "rijndael-cbc", - esp_common_ivlen, esp_cbc_decrypt, - esp_cbc_encrypt, esp_rijndael_schedule, - esp_rijndael_blockdecrypt, esp_rijndael_blockencrypt }, - { 16, 8, esp_aesctr_mature, 160, 288, esp_aesctr_schedlen, "aes-ctr", - esp_common_ivlen, esp_aesctr_decrypt, - esp_aesctr_encrypt, esp_aesctr_schedule }, - { 16, 16, esp_cbc_mature, 128, 256, esp_camellia_schedlen, - "camellia-cbc", - esp_common_ivlen, esp_cbc_decrypt, - esp_cbc_encrypt, esp_camellia_schedule, - esp_camellia_blockdecrypt, esp_camellia_blockencrypt }, -}; - -const struct esp_algorithm * -esp_algorithm_lookup(int idx) -{ - - switch (idx) { - case SADB_EALG_DESCBC: - return &esp_algorithms[0]; - case SADB_EALG_3DESCBC: - return &esp_algorithms[1]; - case SADB_EALG_NULL: - return &esp_algorithms[2]; - case SADB_X_EALG_BLOWFISHCBC: - return &esp_algorithms[3]; - case SADB_X_EALG_CAST128CBC: - return &esp_algorithms[4]; - case SADB_X_EALG_RIJNDAELCBC: - return &esp_algorithms[5]; - case SADB_X_EALG_AESCTR: - return &esp_algorithms[6]; - case SADB_X_EALG_CAMELLIACBC: - return &esp_algorithms[7]; - default: - return NULL; - } -} - -int -esp_max_ivlen(void) -{ - int idx; - int ivlen; - - ivlen = 0; - for (idx = 0; idx < NELEM(esp_algorithms); - idx++) { - if (esp_algorithms[idx].ivlenval > ivlen) - ivlen = esp_algorithms[idx].ivlenval; - } - return ivlen; -} - -int -esp_schedule(const struct esp_algorithm *algo, struct secasvar *sav) -{ - int error; - - /* check for key length */ - if (_KEYBITS(sav->key_enc) < algo->keymin || - _KEYBITS(sav->key_enc) > algo->keymax) { - ipseclog((LOG_ERR, - "esp_schedule %s: unsupported key length %d: " - "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc), - algo->keymin, algo->keymax)); - return EINVAL; - } - - /* already allocated */ - if (sav->sched && sav->schedlen != 0) - return 0; - /* no schedule necessary */ - if (!algo->schedule || !algo->schedlen) - return 0; - - sav->schedlen = (*algo->schedlen)(algo); - sav->sched = kmalloc(sav->schedlen, M_SECA, M_NOWAIT); - if (!sav->sched) { - sav->schedlen = 0; - return ENOBUFS; - } - - error = (*algo->schedule)(algo, sav); - if (error) { - ipseclog((LOG_ERR, "esp_schedule %s: error %d\n", - algo->name, error)); - bzero(sav->sched, sav->schedlen); - kfree(sav->sched, M_SECA); - sav->sched = NULL; - sav->schedlen = 0; - } - return error; -} - -static int -esp_null_mature(struct secasvar *sav) -{ - - /* anything is okay */ - return 0; -} - -static int -esp_null_decrypt(struct mbuf *m, - size_t off, /* offset to ESP header */ - struct secasvar *sav, const struct esp_algorithm *algo, - int ivlen) -{ - - return 0; /* do nothing */ -} - -static int -esp_null_encrypt(struct mbuf *m, - size_t off, /* offset to ESP header */ - size_t plen, struct secasvar *sav, - const struct esp_algorithm *algo, int ivlen) -{ - - return 0; /* do nothing */ -} - -static int -esp_descbc_mature(struct secasvar *sav) -{ - const struct esp_algorithm *algo; - - if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) { - ipseclog((LOG_ERR, "esp_cbc_mature: " - "algorithm incompatible with 4 octets IV length\n")); - return 1; - } - - if (!sav->key_enc) { - ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n")); - return 1; - } - - algo = esp_algorithm_lookup(sav->alg_enc); - if (!algo) { - ipseclog((LOG_ERR, - "esp_descbc_mature: unsupported algorithm.\n")); - return 1; - } - - if (_KEYBITS(sav->key_enc) < algo->keymin || - _KEYBITS(sav->key_enc) > algo->keymax) { - ipseclog((LOG_ERR, - "esp_descbc_mature: invalid key length %d.\n", - _KEYBITS(sav->key_enc))); - return 1; - } - - /* weak key check */ - if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) { - ipseclog((LOG_ERR, - "esp_descbc_mature: weak key was passed.\n")); - return 1; - } - - return 0; -} - -static int -esp_descbc_ivlen(const struct esp_algorithm *algo, struct secasvar *sav) -{ - - if (!sav) - return 8; - if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) - return 4; - if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV)) - return 4; - return 8; -} - -static size_t -esp_des_schedlen(const struct esp_algorithm *algo) -{ - - return sizeof(des_key_schedule); -} - -static int -esp_des_schedule(const struct esp_algorithm *algo, struct secasvar *sav) -{ - - if (des_key_sched((des_cblock *)_KEYBUF(sav->key_enc), - *(des_key_schedule *)sav->sched)) - return EINVAL; - else - return 0; -} - -static int -esp_des_blockdecrypt(const struct esp_algorithm *algo, struct secasvar *sav, - u_int8_t *s, u_int8_t *d) -{ - - /* assumption: d has a good alignment */ - bcopy(s, d, sizeof(DES_LONG) * 2); - des_ecb_encrypt((des_cblock *)d, (des_cblock *)d, - *(des_key_schedule *)sav->sched, DES_DECRYPT); - return 0; -} - -static int -esp_des_blockencrypt(const struct esp_algorithm *algo, struct secasvar *sav, - u_int8_t *s, u_int8_t *d) -{ - - /* assumption: d has a good alignment */ - bcopy(s, d, sizeof(DES_LONG) * 2); - des_ecb_encrypt((des_cblock *)d, (des_cblock *)d, - *(des_key_schedule *)sav->sched, DES_ENCRYPT); - return 0; -} - -static int -esp_cbc_mature(struct secasvar *sav) -{ - int keylen; - const struct esp_algorithm *algo; - - if (sav->flags & SADB_X_EXT_OLD) { - ipseclog((LOG_ERR, - "esp_cbc_mature: algorithm incompatible with esp-old\n")); - return 1; - } - if (sav->flags & SADB_X_EXT_DERIV) { - ipseclog((LOG_ERR, - "esp_cbc_mature: algorithm incompatible with derived\n")); - return 1; - } - - if (!sav->key_enc) { - ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n")); - return 1; - } - - algo = esp_algorithm_lookup(sav->alg_enc); - if (!algo) { - ipseclog((LOG_ERR, - "esp_cbc_mature: unsupported algorithm %d\n", - sav->alg_enc)); - return 1; - } - - keylen = sav->key_enc->sadb_key_bits; - if (keylen < algo->keymin || algo->keymax < keylen) { - ipseclog((LOG_ERR, - "esp_cbc_mature %s: invalid key length %d.\n", - algo->name, sav->key_enc->sadb_key_bits)); - return 1; - } - switch (sav->alg_enc) { - case SADB_EALG_3DESCBC: - /* weak key check */ - if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) || - des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) || - des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) { - ipseclog((LOG_ERR, - "esp_cbc_mature %s: weak key was passed.\n", - algo->name)); - return 1; - } - break; - case SADB_X_EALG_BLOWFISHCBC: - case SADB_X_EALG_CAST128CBC: - break; - case SADB_X_EALG_RIJNDAELCBC: - case SADB_X_EALG_CAMELLIACBC: - /* allows specific key sizes only */ - if (!(keylen == 128 || keylen == 192 || keylen == 256)) { - ipseclog((LOG_ERR, - "esp_cbc_mature %s: invalid key length %d.\n", - algo->name, keylen)); - return 1; - } - break; - } - - return 0; -} - -static size_t -esp_blowfish_schedlen(const struct esp_algorithm *algo) -{ - - return sizeof(BF_KEY); -} - -static int -esp_blowfish_schedule(const struct esp_algorithm *algo, struct secasvar *sav) -{ - - BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc), - _KEYBUF(sav->key_enc)); - return 0; -} - -static int -esp_blowfish_blockdecrypt(const struct esp_algorithm *algo, - struct secasvar *sav, u_int8_t *s, u_int8_t *d) -{ - - BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 0); - return 0; -} - -static int -esp_blowfish_blockencrypt(const struct esp_algorithm *algo, - struct secasvar *sav, u_int8_t *s, u_int8_t *d) -{ - - BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 1); - return 0; -} - -static size_t -esp_cast128_schedlen(const struct esp_algorithm *algo) -{ - - return sizeof(cast128_key); -} - -static int -esp_cast128_schedule(const struct esp_algorithm *algo, struct secasvar *sav) -{ - - cast128_setkey((cast128_key *)sav->sched, _KEYBUF(sav->key_enc), - _KEYLEN(sav->key_enc)); - return 0; -} - -static int -esp_cast128_blockdecrypt(const struct esp_algorithm *algo, - struct secasvar *sav, u_int8_t *s, u_int8_t *d) -{ - - cast128_decrypt((cast128_key *)sav->sched, s, d); - return 0; -} - -static int -esp_cast128_blockencrypt(const struct esp_algorithm *algo, struct secasvar *sav, - u_int8_t *s, u_int8_t *d) -{ - - cast128_encrypt((cast128_key *)sav->sched, s, d); - return 0; -} - -static size_t -esp_3des_schedlen(const struct esp_algorithm *algo) -{ - - return sizeof(des_key_schedule) * 3; -} - -static int -esp_3des_schedule(const struct esp_algorithm *algo, struct secasvar *sav) -{ - int error; - des_key_schedule *p; - int i; - u_int8_t *k; - - p = (des_key_schedule *)sav->sched; - k = _KEYBUF(sav->key_enc); - for (i = 0; i < 3; i++) { - error = des_key_sched((des_cblock *)(k + 8 * i), p[i]); - if (error) - return EINVAL; - } - return 0; -} - -static int -esp_3des_blockdecrypt(const struct esp_algorithm *algo, struct secasvar *sav, - u_int8_t *s, u_int8_t *d) -{ - des_key_schedule *p; - - /* assumption: d has a good alignment */ - p = (des_key_schedule *)sav->sched; - bcopy(s, d, sizeof(DES_LONG) * 2); - des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d, - p[0], p[1], p[2], DES_DECRYPT); - return 0; -} - -static int -esp_3des_blockencrypt(const struct esp_algorithm *algo, struct secasvar *sav, - u_int8_t *s, u_int8_t *d) -{ - des_key_schedule *p; - - /* assumption: d has a good alignment */ - p = (des_key_schedule *)sav->sched; - bcopy(s, d, sizeof(DES_LONG) * 2); - des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d, - p[0], p[1], p[2], DES_ENCRYPT); - return 0; -} - -static int -esp_common_ivlen(const struct esp_algorithm *algo, struct secasvar *sav) -{ - - if (!algo) - panic("esp_common_ivlen: unknown algorithm"); - return algo->ivlenval; -} - -static int -esp_cbc_decrypt(struct mbuf *m, size_t off, struct secasvar *sav, - const struct esp_algorithm *algo, int ivlen) -{ - struct mbuf *s; - struct mbuf *d, *d0, *dp; - int soff, doff; /* offset from the head of chain, to head of this mbuf */ - int sn, dn; /* offset from the head of the mbuf, to meat */ - size_t ivoff, bodyoff; - u_int8_t iv[MAXIVLEN], *ivp; - u_int8_t sbuf[MAXIVLEN], *sp; - u_int8_t *p, *q; - struct mbuf *scut; - int scutoff; - int i; - int blocklen; - - if (ivlen != sav->ivlen || ivlen > sizeof(iv)) { - ipseclog((LOG_ERR, "esp_cbc_decrypt %s: " - "unsupported ivlen %d\n", algo->name, ivlen)); - m_freem(m); - return EINVAL; - } - - /* assumes blocklen == padbound */ - blocklen = algo->padbound; - -#ifdef DIAGNOSTIC - if (blocklen > sizeof(iv)) { - ipseclog((LOG_ERR, "esp_cbc_decrypt %s: " - "unsupported blocklen %d\n", algo->name, blocklen)); - m_freem(m); - return EINVAL; - } -#endif - - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1827 */ - ivoff = off + sizeof(struct esp); - bodyoff = off + sizeof(struct esp) + ivlen; - } else { - /* RFC 2406 */ - if (sav->flags & SADB_X_EXT_DERIV) { - /* - * draft-ietf-ipsec-ciph-des-derived-00.txt - * uses sequence number field as IV field. - */ - ivoff = off + sizeof(struct esp); - bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t); - ivlen = sizeof(u_int32_t); - } else { - ivoff = off + sizeof(struct newesp); - bodyoff = off + sizeof(struct newesp) + ivlen; - } - } - - /* grab iv */ - m_copydata(m, ivoff, ivlen, (caddr_t)iv); - - /* extend iv */ - if (ivlen == blocklen) - ; - else if (ivlen == 4 && blocklen == 8) { - bcopy(&iv[0], &iv[4], 4); - iv[4] ^= 0xff; - iv[5] ^= 0xff; - iv[6] ^= 0xff; - iv[7] ^= 0xff; - } else { - ipseclog((LOG_ERR, "esp_cbc_encrypt %s: " - "unsupported ivlen/blocklen: %d %d\n", - algo->name, ivlen, blocklen)); - m_freem(m); - return EINVAL; - } - - if (m->m_pkthdr.len < bodyoff) { - ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n", - algo->name, m->m_pkthdr.len, (unsigned long)bodyoff)); - m_freem(m); - return EINVAL; - } - if ((m->m_pkthdr.len - bodyoff) % blocklen) { - ipseclog((LOG_ERR, "esp_cbc_decrypt %s: " - "payload length must be multiple of %d\n", - algo->name, blocklen)); - m_freem(m); - return EINVAL; - } - - s = m; - d = d0 = dp = NULL; - soff = doff = sn = dn = 0; - ivp = sp = NULL; - - /* skip bodyoff */ - while (soff < bodyoff) { - if (soff + s->m_len >= bodyoff) { - sn = bodyoff - soff; - break; - } - - soff += s->m_len; - s = s->m_next; - } - scut = s; - scutoff = sn; - - /* skip over empty mbuf */ - while (s && s->m_len == 0) - s = s->m_next; - - while (soff < m->m_pkthdr.len) { - /* source */ - if (sn + blocklen <= s->m_len) { - /* body is continuous */ - sp = mtod(s, u_int8_t *) + sn; - } else { - /* body is non-continuous */ - m_copydata(s, sn, blocklen, sbuf); - sp = sbuf; - } - - /* destination */ - if (!d || dn + blocklen > d->m_len) { - if (d) - dp = d; - i = m->m_pkthdr.len - (soff + sn); - d = m_getb(i, M_NOWAIT, MT_DATA, 0); - if (!d) { - m_freem(m); - if (d0) - m_freem(d0); - return ENOBUFS; - } - if (!d0) - d0 = d; - if (dp) - dp->m_next = d; - d->m_len = 0; - d->m_len = rounddown(M_TRAILINGSPACE(d), blocklen); - if (d->m_len > i) - d->m_len = i; - dn = 0; - } - - /* decrypt */ - (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn); - - /* xor */ - p = ivp ? ivp : iv; - q = mtod(d, u_int8_t *) + dn; - for (i = 0; i < blocklen; i++) - q[i] ^= p[i]; - - /* next iv */ - if (sp == sbuf) { - bcopy(sbuf, iv, blocklen); - ivp = NULL; - } else - ivp = sp; - - sn += blocklen; - dn += blocklen; - - /* find the next source block */ - while (s && sn >= s->m_len) { - sn -= s->m_len; - soff += s->m_len; - s = s->m_next; - } - - /* skip over empty mbuf */ - while (s && s->m_len == 0) - s = s->m_next; - } - - m_freem(scut->m_next); - scut->m_len = scutoff; - scut->m_next = d0; - - /* just in case */ - bzero(iv, sizeof(iv)); - bzero(sbuf, sizeof(sbuf)); - - return 0; -} - -static int -esp_cbc_encrypt(struct mbuf *m, size_t off, size_t plen, struct secasvar *sav, - const struct esp_algorithm *algo, int ivlen) -{ - struct mbuf *s; - struct mbuf *d, *d0, *dp; - int soff, doff; /* offset from the head of chain, to head of this mbuf */ - int sn, dn; /* offset from the head of the mbuf, to meat */ - size_t ivoff, bodyoff; - u_int8_t iv[MAXIVLEN], *ivp; - u_int8_t sbuf[MAXIVLEN], *sp; - u_int8_t *p, *q; - struct mbuf *scut; - int scutoff; - int i; - int blocklen; - int derived; - - if (ivlen != sav->ivlen || ivlen > sizeof(iv)) { - ipseclog((LOG_ERR, "esp_cbc_encrypt %s: " - "unsupported ivlen %d\n", algo->name, ivlen)); - m_freem(m); - return EINVAL; - } - - /* assumes blocklen == padbound */ - blocklen = algo->padbound; - -#ifdef DIAGNOSTIC - if (blocklen > sizeof(iv)) { - ipseclog((LOG_ERR, "esp_cbc_encrypt %s: " - "unsupported blocklen %d\n", algo->name, blocklen)); - m_freem(m); - return EINVAL; - } -#endif - - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1827 */ - ivoff = off + sizeof(struct esp); - bodyoff = off + sizeof(struct esp) + ivlen; - derived = 0; - } else { - /* RFC 2406 */ - if (sav->flags & SADB_X_EXT_DERIV) { - /* - * draft-ietf-ipsec-ciph-des-derived-00.txt - * uses sequence number field as IV field. - */ - ivoff = off + sizeof(struct esp); - bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t); - ivlen = sizeof(u_int32_t); - derived = 1; - } else { - ivoff = off + sizeof(struct newesp); - bodyoff = off + sizeof(struct newesp) + ivlen; - derived = 0; - } - } - - /* put iv into the packet. if we are in derived mode, use seqno. */ - if (derived) - m_copydata(m, ivoff, ivlen, (caddr_t)iv); - else { - bcopy(sav->iv, iv, ivlen); - /* maybe it is better to overwrite dest, not source */ - m_copyback(m, ivoff, ivlen, (caddr_t)iv); - } - - /* extend iv */ - if (ivlen == blocklen) - ; - else if (ivlen == 4 && blocklen == 8) { - bcopy(&iv[0], &iv[4], 4); - iv[4] ^= 0xff; - iv[5] ^= 0xff; - iv[6] ^= 0xff; - iv[7] ^= 0xff; - } else { - ipseclog((LOG_ERR, "esp_cbc_encrypt %s: " - "unsupported ivlen/blocklen: %d %d\n", - algo->name, ivlen, blocklen)); - m_freem(m); - return EINVAL; - } - - if (m->m_pkthdr.len < bodyoff) { - ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n", - algo->name, m->m_pkthdr.len, (unsigned long)bodyoff)); - m_freem(m); - return EINVAL; - } - if ((m->m_pkthdr.len - bodyoff) % blocklen) { - ipseclog((LOG_ERR, "esp_cbc_encrypt %s: " - "payload length must be multiple of %lu\n", - algo->name, (unsigned long)algo->padbound)); - m_freem(m); - return EINVAL; - } - - s = m; - d = d0 = dp = NULL; - soff = doff = sn = dn = 0; - ivp = sp = NULL; - - /* skip bodyoff */ - while (soff < bodyoff) { - if (soff + s->m_len >= bodyoff) { - sn = bodyoff - soff; - break; - } - - soff += s->m_len; - s = s->m_next; - } - scut = s; - scutoff = sn; - - /* skip over empty mbuf */ - while (s && s->m_len == 0) - s = s->m_next; - - while (soff < m->m_pkthdr.len) { - /* source */ - if (sn + blocklen <= s->m_len) { - /* body is continuous */ - sp = mtod(s, u_int8_t *) + sn; - } else { - /* body is non-continuous */ - m_copydata(s, sn, blocklen, (caddr_t)sbuf); - sp = sbuf; - } - - /* destination */ - if (!d || dn + blocklen > d->m_len) { - if (d) - dp = d; - i = m->m_pkthdr.len - (soff + sn); - d = m_getb(i, M_NOWAIT, MT_DATA, 0); - if (!d) { - m_freem(m); - if (d0) - m_freem(d0); - return ENOBUFS; - } - if (!d0) - d0 = d; - if (dp) - dp->m_next = d; - d->m_len = 0; - d->m_len = rounddown(M_TRAILINGSPACE(d), blocklen); - if (d->m_len > i) - d->m_len = i; - dn = 0; - } - - /* xor */ - p = ivp ? ivp : iv; - q = sp; - for (i = 0; i < blocklen; i++) - q[i] ^= p[i]; - - /* encrypt */ - (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn); - - /* next iv */ - ivp = mtod(d, u_int8_t *) + dn; - - sn += blocklen; - dn += blocklen; - - /* find the next source block */ - while (s && sn >= s->m_len) { - sn -= s->m_len; - soff += s->m_len; - s = s->m_next; - } - - /* skip over empty mbuf */ - while (s && s->m_len == 0) - s = s->m_next; - } - - m_freem(scut->m_next); - scut->m_len = scutoff; - scut->m_next = d0; - - /* just in case */ - bzero(iv, sizeof(iv)); - bzero(sbuf, sizeof(sbuf)); - - key_sa_stir_iv(sav); - - return 0; -} - -/*------------------------------------------------------------*/ - -/* does not free m0 on error */ -int -esp_auth(struct mbuf *m0, - size_t skip, /* offset to ESP header */ - size_t length, /* payload length */ - struct secasvar *sav, u_char *sum) -{ - struct mbuf *m; - size_t off; - struct ah_algorithm_state s; - u_char sumbuf[AH_MAXSUMSIZE]; - const struct ah_algorithm *algo; - size_t siz; - int error; - - /* sanity checks */ - if (m0->m_pkthdr.len < skip) { - ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n")); - return EINVAL; - } - if (m0->m_pkthdr.len < skip + length) { - ipseclog((LOG_DEBUG, - "esp_auth: mbuf length < skip + length\n")); - return EINVAL; - } - /* - * length of esp part (excluding authentication data) must be 4n, - * since nexthdr must be at offset 4n+3. - */ - if (length % 4) { - ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n")); - return EINVAL; - } - if (!sav) { - ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n")); - return EINVAL; - } - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_ERR, - "esp_auth: bad ESP auth algorithm passed: %d\n", - sav->alg_auth)); - return EINVAL; - } - - m = m0; - off = 0; - - siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1)); - if (sizeof(sumbuf) < siz) { - ipseclog((LOG_DEBUG, - "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n", - (u_long)siz)); - return EINVAL; - } - - /* skip the header */ - while (skip) { - if (!m) - panic("mbuf chain?"); - if (m->m_len <= skip) { - skip -= m->m_len; - m = m->m_next; - off = 0; - } else { - off = skip; - skip = 0; - } - } - - error = (*algo->init)(&s, sav); - if (error) - return error; - - while (0 < length) { - if (!m) - panic("mbuf chain?"); - - if (m->m_len - off < length) { - (*algo->update)(&s, mtod(m, u_char *) + off, - m->m_len - off); - length -= m->m_len - off; - m = m->m_next; - off = 0; - } else { - (*algo->update)(&s, mtod(m, u_char *) + off, length); - break; - } - } - (*algo->result)(&s, sumbuf); - bcopy(sumbuf, sum, siz); /* XXX */ - - return 0; -} diff --git a/sys/netinet6/esp_input.c b/sys/netinet6/esp_input.c deleted file mode 100644 index 4a620e4d1f..0000000000 --- a/sys/netinet6/esp_input.c +++ /dev/null @@ -1,978 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/esp_input.c,v 1.1.2.8 2003/01/23 21:06:47 sam Exp $ */ -/* $KAME: esp_input.c,v 1.62 2002/01/07 11:39:57 kjc Exp $ */ - -/* - * 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. - */ - -/* - * RFC1827/2406 Encapsulated Security Payload. - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#ifdef INET6 -#include -#endif - -#ifdef INET6 -#include -#include -#include -#include -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#include -#include -#include - -#include - -#include - -#define IPLEN_FLIPPED - -#define ESPMAXLEN \ - (sizeof(struct esp) < sizeof(struct newesp) \ - ? sizeof(struct newesp) : sizeof(struct esp)) - -#ifdef INET -extern struct protosw inetsw[]; - -int -esp4_input(struct mbuf **mp, int *offp, int proto) -{ - int off; - struct ip *ip; - struct esp *esp; - struct esptail esptail; - struct mbuf *m; - u_int32_t spi; - struct secasvar *sav = NULL; - size_t taillen; - u_int16_t nxt; - const struct esp_algorithm *algo; - int ivlen; - size_t esplen; - - off = *offp; - m = *mp; - *mp = NULL; - - /* sanity check for alignment. */ - if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) { - ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem " - "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len)); - ipsecstat.in_inval++; - goto bad; - } - - if (m->m_len < off + ESPMAXLEN) { - m = m_pullup(m, off + ESPMAXLEN); - if (!m) { - ipseclog((LOG_DEBUG, - "IPv4 ESP input: can't pullup in esp4_input\n")); - ipsecstat.in_inval++; - goto bad; - } - } - - ip = mtod(m, struct ip *); - esp = (struct esp *)(((u_int8_t *)ip) + off); - - /* find the sassoc. */ - spi = esp->esp_spi; - - if ((sav = key_allocsa(AF_INET, - (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst, - IPPROTO_ESP, spi)) == NULL) { - ipseclog((LOG_WARNING, - "IPv4 ESP input: no key association found for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsecstat.in_nosa++; - goto bad; - } - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP esp4_input called to allocate SA:%p\n", sav)); - if (sav->state != SADB_SASTATE_MATURE - && sav->state != SADB_SASTATE_DYING) { - ipseclog((LOG_DEBUG, - "IPv4 ESP input: non-mature/dying SA found for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsecstat.in_badspi++; - goto bad; - } - algo = esp_algorithm_lookup(sav->alg_enc); - if (!algo) { - ipseclog((LOG_DEBUG, "IPv4 ESP input: " - "unsupported encryption algorithm for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsecstat.in_badspi++; - goto bad; - } - - /* check if we have proper ivlen information */ - ivlen = sav->ivlen; - if (ivlen < 0) { - ipseclog((LOG_ERR, "improper ivlen in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_inval++; - goto bad; - } - - if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay - && (sav->alg_auth && sav->key_auth))) - goto noreplaycheck; - - if (sav->alg_auth == SADB_X_AALG_NULL || - sav->alg_auth == SADB_AALG_NONE) - goto noreplaycheck; - - /* - * check for sequence number. - */ - if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) - ; /* okey */ - else { - ipsecstat.in_espreplay++; - ipseclog((LOG_WARNING, - "replay packet in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - goto bad; - } - - /* check ICV */ - { - u_char sum0[AH_MAXSUMSIZE]; - u_char sum[AH_MAXSUMSIZE]; - const struct ah_algorithm *sumalgo; - size_t siz; - - sumalgo = ah_algorithm_lookup(sav->alg_auth); - if (!sumalgo) - goto noreplaycheck; - siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1)); - if (m->m_pkthdr.len < off + ESPMAXLEN + siz) { - ipsecstat.in_inval++; - goto bad; - } - if (AH_MAXSUMSIZE < siz) { - ipseclog((LOG_DEBUG, - "internal error: AH_MAXSUMSIZE must be larger than %lu\n", - (u_long)siz)); - ipsecstat.in_inval++; - goto bad; - } - - m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]); - - if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) { - ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_espauthfail++; - goto bad; - } - - if (bcmp(sum0, sum, siz) != 0) { - ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_espauthfail++; - goto bad; - } - - /* strip off the authentication data */ - m_adj(m, -siz); - ip = mtod(m, struct ip *); -#ifdef IPLEN_FLIPPED - ip->ip_len = ip->ip_len - siz; -#else - ip->ip_len = htons(ntohs(ip->ip_len) - siz); -#endif - m->m_flags |= M_AUTHIPDGM; - ipsecstat.in_espauthsucc++; - } - - /* - * update sequence number. - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) { - ipsecstat.in_espreplay++; - goto bad; - } - } - -noreplaycheck: - - /* process main esp header. */ - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1827 */ - esplen = sizeof(struct esp); - } else { - /* RFC 2406 */ - if (sav->flags & SADB_X_EXT_DERIV) - esplen = sizeof(struct esp); - else - esplen = sizeof(struct newesp); - } - - if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) { - ipseclog((LOG_WARNING, - "IPv4 ESP input: packet too short\n")); - ipsecstat.in_inval++; - goto bad; - } - - if (m->m_len < off + esplen + ivlen) { - m = m_pullup(m, off + esplen + ivlen); - if (!m) { - ipseclog((LOG_DEBUG, - "IPv4 ESP input: can't pullup in esp4_input\n")); - ipsecstat.in_inval++; - goto bad; - } - } - - /* - * pre-compute and cache intermediate key - */ - if (esp_schedule(algo, sav) != 0) { - ipsecstat.in_inval++; - goto bad; - } - - /* - * decrypt the packet. - */ - if (!algo->decrypt) - panic("internal error: no decrypt function"); - if ((*algo->decrypt)(m, off, sav, algo, ivlen)) { - /* m is already freed */ - m = NULL; - ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n", - ipsec_logsastr(sav))); - ipsecstat.in_inval++; - goto bad; - } - ipsecstat.in_esphist[sav->alg_enc]++; - - m->m_flags |= M_DECRYPTED; - - /* - * find the trailer of the ESP. - */ - m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail), - (caddr_t)&esptail); - nxt = esptail.esp_nxt; - taillen = esptail.esp_padlen + sizeof(esptail); - - if (m->m_pkthdr.len < taillen || - m->m_pkthdr.len - taillen < off + esplen + ivlen + sizeof(esptail)) { - ipseclog((LOG_WARNING, - "bad pad length in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_inval++; - goto bad; - } - - /* strip off the trailing pad area. */ - m_adj(m, -taillen); - -#ifdef IPLEN_FLIPPED - ip->ip_len = ip->ip_len - taillen; -#else - ip->ip_len = htons(ntohs(ip->ip_len) - taillen); -#endif - - /* was it transmitted over the IPsec tunnel SA? */ - if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) { - /* - * strip off all the headers that precedes ESP header. - * IP4 xx ESP IP4' payload -> IP4' payload - * - * XXX more sanity checks - * XXX relationship with gif? - */ - u_int8_t tos; - - tos = ip->ip_tos; - m_adj(m, off + esplen + ivlen); - if (m->m_len < sizeof(*ip)) { - m = m_pullup(m, sizeof(*ip)); - if (!m) { - ipsecstat.in_inval++; - goto bad; - } - } - ip = mtod(m, struct ip *); - /* ECN consideration. */ - ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos); - if (!key_checktunnelsanity(sav, AF_INET, - (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) { - ipseclog((LOG_ERR, "ipsec tunnel address mismatch " - "in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - ipsecstat.in_inval++; - goto bad; - } - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || - ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) { - ipsecstat.in_nomem++; - goto bad; - } - - if (netisr_queue(NETISR_IP, m)) { - ipsecstat.in_inval++; - m = NULL; - goto bad; - } - - nxt = IPPROTO_DONE; - } else { - /* - * strip off ESP header and IV. - * even in m_pulldown case, we need to strip off ESP so that - * we can always compute checksum for AH correctly. - */ - size_t stripsiz; - - stripsiz = esplen + ivlen; - - ip = mtod(m, struct ip *); - bcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off); - m->m_data += stripsiz; - m->m_len -= stripsiz; - m->m_pkthdr.len -= stripsiz; - - ip = mtod(m, struct ip *); -#ifdef IPLEN_FLIPPED - ip->ip_len = ip->ip_len - stripsiz; -#else - ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz); -#endif - ip->ip_p = nxt; - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) { - ipsecstat.in_nomem++; - goto bad; - } - - if (nxt != IPPROTO_DONE) { - if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) && - ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; - goto bad; - } - if (!ip_lengthcheck(&m, 0)) { - /* freed in ip_lengthcheck() */ - goto bad; - } - *mp = m; - *offp = off; - (*inetsw[ip_protox[nxt]].pr_input)(mp, offp, nxt); - } else { - m_freem(m); - } - m = NULL; - } - - if (sav) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP esp4_input call free SA:%p\n", sav)); - key_freesav(sav); - } - ipsecstat.in_success++; - return(IPPROTO_DONE); - -bad: - if (sav) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP esp4_input call free SA:%p\n", sav)); - key_freesav(sav); - } - if (m) - m_freem(m); - return(IPPROTO_DONE); -} -#endif /* INET */ - -#ifdef INET6 -int -esp6_input(struct mbuf **mp, int *offp, int proto) -{ - struct mbuf *m = *mp; - int off = *offp; - struct ip6_hdr *ip6; - struct esp *esp; - struct esptail esptail; - u_int32_t spi; - struct secasvar *sav = NULL; - size_t taillen; - u_int16_t nxt; - const struct esp_algorithm *algo; - int ivlen; - size_t esplen; - - /* sanity check for alignment. */ - if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) { - ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem " - "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len)); - ipsec6stat.in_inval++; - goto bad; - } - -#ifndef PULLDOWN_TEST - IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, IPPROTO_DONE); - esp = (struct esp *)(mtod(m, caddr_t) + off); -#else - IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN); - if (esp == NULL) { - ipsec6stat.in_inval++; - return IPPROTO_DONE; - } -#endif - ip6 = mtod(m, struct ip6_hdr *); - - if (ntohs(ip6->ip6_plen) == 0) { - ipseclog((LOG_ERR, "IPv6 ESP input: " - "ESP with IPv6 jumbogram is not supported.\n")); - ipsec6stat.in_inval++; - goto bad; - } - - /* find the sassoc. */ - spi = esp->esp_spi; - - if ((sav = key_allocsa(AF_INET6, - (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst, - IPPROTO_ESP, spi)) == NULL) { - ipseclog((LOG_WARNING, - "IPv6 ESP input: no key association found for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsec6stat.in_nosa++; - goto bad; - } - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP esp6_input called to allocate SA:%p\n", sav)); - if (sav->state != SADB_SASTATE_MATURE - && sav->state != SADB_SASTATE_DYING) { - ipseclog((LOG_DEBUG, - "IPv6 ESP input: non-mature/dying SA found for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsec6stat.in_badspi++; - goto bad; - } - algo = esp_algorithm_lookup(sav->alg_enc); - if (!algo) { - ipseclog((LOG_DEBUG, "IPv6 ESP input: " - "unsupported encryption algorithm for spi %u\n", - (u_int32_t)ntohl(spi))); - ipsec6stat.in_badspi++; - goto bad; - } - - /* check if we have proper ivlen information */ - ivlen = sav->ivlen; - if (ivlen < 0) { - ipseclog((LOG_ERR, "improper ivlen in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_badspi++; - goto bad; - } - - if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay - && (sav->alg_auth && sav->key_auth))) - goto noreplaycheck; - - if (sav->alg_auth == SADB_X_AALG_NULL || - sav->alg_auth == SADB_AALG_NONE) - goto noreplaycheck; - - /* - * check for sequence number. - */ - if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) - ; /* okey */ - else { - ipsec6stat.in_espreplay++; - ipseclog((LOG_WARNING, - "replay packet in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - goto bad; - } - - /* check ICV */ - { - u_char sum0[AH_MAXSUMSIZE]; - u_char sum[AH_MAXSUMSIZE]; - const struct ah_algorithm *sumalgo; - size_t siz; - - sumalgo = ah_algorithm_lookup(sav->alg_auth); - if (!sumalgo) - goto noreplaycheck; - siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1)); - if (m->m_pkthdr.len < off + ESPMAXLEN + siz) { - ipsec6stat.in_inval++; - goto bad; - } - if (AH_MAXSUMSIZE < siz) { - ipseclog((LOG_DEBUG, - "internal error: AH_MAXSUMSIZE must be larger than %lu\n", - (u_long)siz)); - ipsec6stat.in_inval++; - goto bad; - } - - m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]); - - if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) { - ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_espauthfail++; - goto bad; - } - - if (bcmp(sum0, sum, siz) != 0) { - ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_espauthfail++; - goto bad; - } - - /* strip off the authentication data */ - m_adj(m, -siz); - ip6 = mtod(m, struct ip6_hdr *); - ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz); - - m->m_flags |= M_AUTHIPDGM; - ipsec6stat.in_espauthsucc++; - } - - /* - * update sequence number. - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) { - ipsec6stat.in_espreplay++; - goto bad; - } - } - -noreplaycheck: - - /* process main esp header. */ - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1827 */ - esplen = sizeof(struct esp); - } else { - /* RFC 2406 */ - if (sav->flags & SADB_X_EXT_DERIV) - esplen = sizeof(struct esp); - else - esplen = sizeof(struct newesp); - } - - if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) { - ipseclog((LOG_WARNING, - "IPv6 ESP input: packet too short\n")); - ipsec6stat.in_inval++; - goto bad; - } - -#ifndef PULLDOWN_TEST - IP6_EXTHDR_CHECK(m, off, esplen + ivlen, IPPROTO_DONE); /* XXX */ -#else - IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen); - if (esp == NULL) { - ipsec6stat.in_inval++; - m = NULL; - goto bad; - } -#endif - ip6 = mtod(m, struct ip6_hdr *); /* set it again just in case */ - - /* - * pre-compute and cache intermediate key - */ - if (esp_schedule(algo, sav) != 0) { - ipsec6stat.in_inval++; - goto bad; - } - - /* - * decrypt the packet. - */ - if (!algo->decrypt) - panic("internal error: no decrypt function"); - if ((*algo->decrypt)(m, off, sav, algo, ivlen)) { - /* m is already freed */ - m = NULL; - ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n", - ipsec_logsastr(sav))); - ipsec6stat.in_inval++; - goto bad; - } - ipsec6stat.in_esphist[sav->alg_enc]++; - - m->m_flags |= M_DECRYPTED; - - /* - * find the trailer of the ESP. - */ - m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail), - (caddr_t)&esptail); - nxt = esptail.esp_nxt; - taillen = esptail.esp_padlen + sizeof(esptail); - - if (m->m_pkthdr.len < taillen - || m->m_pkthdr.len - taillen < sizeof(struct ip6_hdr)) { /* ? */ - ipseclog((LOG_WARNING, - "bad pad length in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - ipsec6stat.in_inval++; - goto bad; - } - - /* strip off the trailing pad area. */ - m_adj(m, -taillen); - - ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen); - - /* was it transmitted over the IPsec tunnel SA? */ - if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) { - /* - * strip off all the headers that precedes ESP header. - * IP6 xx ESP IP6' payload -> IP6' payload - * - * XXX more sanity checks - * XXX relationship with gif? - */ - u_int32_t flowinfo; /* net endian */ - flowinfo = ip6->ip6_flow; - m_adj(m, off + esplen + ivlen); - if (m->m_len < sizeof(*ip6)) { -#ifndef PULLDOWN_TEST - /* - * m_pullup is prohibited in KAME IPv6 input processing - * but there's no other way! - */ -#else - /* okay to pullup in m_pulldown style */ -#endif - m = m_pullup(m, sizeof(*ip6)); - if (!m) { - ipsec6stat.in_inval++; - goto bad; - } - } - ip6 = mtod(m, struct ip6_hdr *); - /* ECN consideration. */ - ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); - if (!key_checktunnelsanity(sav, AF_INET6, - (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) { - ipseclog((LOG_ERR, "ipsec tunnel address mismatch " - "in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), - ipsec_logsastr(sav))); - ipsec6stat.in_inval++; - goto bad; - } - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || - ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) { - ipsec6stat.in_nomem++; - goto bad; - } - - if (netisr_queue(NETISR_IPV6, m)) { - ipsec6stat.in_inval++; - m = NULL; - goto bad; - } - - nxt = IPPROTO_DONE; - } else { - /* - * strip off ESP header and IV. - * even in m_pulldown case, we need to strip off ESP so that - * we can always compute checksum for AH correctly. - */ - size_t stripsiz; - char *prvnxtp; - - /* - * Set the next header field of the previous header correctly. - */ - prvnxtp = ip6_get_prevhdr(m, off); /* XXX */ - *prvnxtp = nxt; - - stripsiz = esplen + ivlen; - - ip6 = mtod(m, struct ip6_hdr *); - if (m->m_len >= stripsiz + off) { - bcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off); - m->m_data += stripsiz; - m->m_len -= stripsiz; - m->m_pkthdr.len -= stripsiz; - } else { - /* - * this comes with no copy if the boundary is on - * cluster - */ - struct mbuf *n; - - n = m_split(m, off, M_NOWAIT); - if (n == NULL) { - /* m is retained by m_split */ - goto bad; - } - m_adj(n, stripsiz); - /* m_cat does not update m_pkthdr.len */ - m->m_pkthdr.len += n->m_pkthdr.len; - m_cat(m, n); - } - -#ifndef PULLDOWN_TEST - /* - * KAME requires that the packet to be contiguous on the - * mbuf. We need to make that sure. - * this kind of code should be avoided. - * XXX other conditions to avoid running this part? - */ - if (m->m_len != m->m_pkthdr.len) { - struct mbuf *n = NULL; - int maxlen; - - n = m_getb(m->m_pkthdr.len, M_NOWAIT, MT_HEADER, - M_PKTHDR); - if (!n) { - kprintf("esp6_input: mbuf allocation failed\n"); - goto bad; - } - M_MOVE_PKTHDR(n, m); - - maxlen = (n->m_flags & M_EXT) ? MCLBYTES : MHLEN; - if (n->m_pkthdr.len <= maxlen) { - m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t)); - n->m_len = n->m_pkthdr.len; - n->m_next = NULL; - m_freem(m); - } else { - m_copydata(m, 0, maxlen, mtod(n, caddr_t)); - n->m_len = maxlen; - n->m_next = m; - m_adj(m, maxlen); - } - m = n; - } -#endif - - ip6 = mtod(m, struct ip6_hdr *); - ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz); - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) { - ipsec6stat.in_nomem++; - goto bad; - } - } - - *offp = off; - *mp = m; - - if (sav) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP esp6_input call free SA:%p\n", sav)); - key_freesav(sav); - } - ipsec6stat.in_success++; - return nxt; - -bad: - if (sav) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP esp6_input call free SA:%p\n", sav)); - key_freesav(sav); - } - if (m) - m_freem(m); - return IPPROTO_DONE; -} - -void -esp6_ctlinput(netmsg_t msg) -{ - int cmd = msg->ctlinput.nm_cmd; - struct sockaddr *sa = msg->ctlinput.nm_arg; - void *d = msg->ctlinput.nm_extra; - const struct newesp *espp; - struct newesp esp; - struct ip6ctlparam *ip6cp = NULL, ip6cp1; - struct secasvar *sav; - struct ip6_hdr *ip6; - struct mbuf *m; - int off; - struct sockaddr_in6 *sa6_src, *sa6_dst; - - if (sa->sa_family != AF_INET6 || - sa->sa_len != sizeof(struct sockaddr_in6)) - goto out; - if ((unsigned)cmd >= PRC_NCMDS) - goto out; - - /* if the parameter is from icmp6, decode it. */ - if (d != NULL) { - ip6cp = (struct ip6ctlparam *)d; - m = ip6cp->ip6c_m; - ip6 = ip6cp->ip6c_ip6; - off = ip6cp->ip6c_off; - } else { - m = NULL; - ip6 = NULL; - off = 0; /* fix warning */ - } - - if (ip6) { - /* - * Notify the error to all possible sockets via pfctlinput2. - * Since the upper layer information (such as protocol type, - * source and destination ports) is embedded in the encrypted - * data and might have been cut, we can't directly call - * an upper layer ctlinput function. However, the pcbnotify - * function will consider source and destination addresses - * as well as the flow info value, and may be able to find - * some PCB that should be notified. - * Although kpfctlinput2 will call esp6_ctlinput(), there is - * no possibility of an infinite loop of function calls, - * because we don't pass the inner IPv6 header. - */ - bzero(&ip6cp1, sizeof(ip6cp1)); - ip6cp1.ip6c_src = ip6cp->ip6c_src; - kpfctlinput2(cmd, sa, (void *)&ip6cp1); - - /* - * Then go to special cases that need ESP header information. - * XXX: We assume that when ip6 is non NULL, - * M and OFF are valid. - */ - - /* check if we can safely examine src and dst ports */ - if (m->m_pkthdr.len < off + sizeof(esp)) - goto out; - - if (m->m_len < off + sizeof(esp)) { - /* - * this should be rare case, - * so we compromise on this copy... - */ - m_copydata(m, off, sizeof(esp), (caddr_t)&esp); - espp = &esp; - } else - espp = (struct newesp*)(mtod(m, caddr_t) + off); - - if (cmd == PRC_MSGSIZE) { - int valid = 0; - - /* - * Check to see if we have a valid SA corresponding to - * the address in the ICMP message payload. - */ - sa6_src = ip6cp->ip6c_src; - sa6_dst = (struct sockaddr_in6 *)sa; - sav = key_allocsa(AF_INET6, - (caddr_t)&sa6_src->sin6_addr, - (caddr_t)&sa6_dst->sin6_addr, - IPPROTO_ESP, espp->esp_spi); - if (sav) { - if (sav->state == SADB_SASTATE_MATURE || - sav->state == SADB_SASTATE_DYING) - valid++; - key_freesav(sav); - } - - /* XXX Further validation? */ - - /* - * Depending on the value of "valid" and routing table - * size (mtudisc_{hi,lo}wat), we will: - * - recalcurate the new MTU and create the - * corresponding routing entry, or - * - ignore the MTU change notification. - */ - icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); - } - } else { - /* we normally notify any pcb here */ - } -out: - lwkt_replymsg(&msg->ctlinput.base.lmsg, 0); -} -#endif /* INET6 */ diff --git a/sys/netinet6/esp_output.c b/sys/netinet6/esp_output.c deleted file mode 100644 index 9c4731377a..0000000000 --- a/sys/netinet6/esp_output.c +++ /dev/null @@ -1,699 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/esp_output.c,v 1.1.2.4 2003/05/06 06:46:58 suz Exp $ */ -/* $KAME: esp_output.c,v 1.44 2001/07/26 06:53:15 jinmei Exp $ */ - -/* - * 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. - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -/* - * RFC1827/2406 Encapsulated Security Payload. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#ifdef INET6 -#include -#include -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#include -#include - -#include - -static int esp_output (struct mbuf *, u_char *, struct mbuf *, - struct ipsecrequest *, int); - -/* - * compute ESP header size. - */ -size_t -esp_hdrsiz(struct ipsecrequest *isr) -{ - struct secasvar *sav; - const struct esp_algorithm *algo; - const struct ah_algorithm *aalgo; - size_t ivlen; - size_t authlen; - size_t hdrsiz; - - /* sanity check */ - if (isr == NULL) - panic("esp_hdrsiz: NULL was passed."); - - sav = isr->sav; - - if (isr->saidx.proto != IPPROTO_ESP) - panic("unsupported mode passed to esp_hdrsiz"); - - if (sav == NULL) - goto estimate; - if (sav->state != SADB_SASTATE_MATURE && - sav->state != SADB_SASTATE_DYING) - goto estimate; - - /* we need transport mode ESP. */ - algo = esp_algorithm_lookup(sav->alg_enc); - if (!algo) - goto estimate; - ivlen = sav->ivlen; - if (ivlen < 0) - goto estimate; - - /* - * XXX - * right now we don't calcurate the padding size. simply - * treat the padding size as constant, for simplicity. - * - * XXX variable size padding support - */ - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1827 */ - hdrsiz = sizeof(struct esp) + ivlen + 9; - } else { - /* RFC 2406 */ - aalgo = ah_algorithm_lookup(sav->alg_auth); - if (aalgo && sav->replay && sav->key_auth) - authlen = (aalgo->sumsiz)(sav); - else - authlen = 0; - hdrsiz = sizeof(struct newesp) + ivlen + 9 + authlen; - } - - return hdrsiz; - -estimate: - /* - * ASSUMING: - * sizeof(struct newesp) > sizeof(struct esp). - * esp_max_ivlen() = max ivlen for CBC mode - * 9 = (maximum padding length without random padding length) - * + (Pad Length field) + (Next Header field). - * 16 = maximum ICV we support. - */ - return sizeof(struct newesp) + esp_max_ivlen() + 9 + 16; -} - -/* - * Modify the packet so that the payload is encrypted. - * The mbuf (m) must start with IPv4 or IPv6 header. - * On failure, free the given mbuf and return NULL. - * - * on invocation: - * m nexthdrp md - * v v v - * IP ......... payload - * during the encryption: - * m nexthdrp mprev md - * v v v v - * IP ............... esp iv payload pad padlen nxthdr - * <--><-><------><---------------> - * esplen plen extendsiz - * ivlen - * <-----> esphlen - * <-> hlen - * <-----------------> espoff - */ -static int -esp_output(struct mbuf *m, u_char *nexthdrp, struct mbuf *md, - struct ipsecrequest *isr, int af) -{ - struct mbuf *n; - struct mbuf *mprev; - struct esp *esp; - struct esptail *esptail; - struct secasvar *sav = isr->sav; - const struct esp_algorithm *algo; - u_int32_t spi; - u_int8_t nxt = 0; - size_t plen; /* payload length to be encrypted */ - size_t espoff; - int ivlen; - int afnumber; - size_t extendsiz; - int error = 0; - struct ipsecstat *stat; - - switch (af) { -#ifdef INET - case AF_INET: - afnumber = 4; - stat = &ipsecstat; - break; -#endif -#ifdef INET6 - case AF_INET6: - afnumber = 6; - stat = &ipsec6stat; - break; -#endif - default: - ipseclog((LOG_ERR, "esp_output: unsupported af %d\n", af)); - return 0; /* no change at all */ - } - - /* some sanity check */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) { - switch (af) { -#ifdef INET - case AF_INET: - { - struct ip *ip; - - ip = mtod(m, struct ip *); - ipseclog((LOG_DEBUG, "esp4_output: internal error: " - "sav->replay is null: %x->%x, SPI=%u\n", - (u_int32_t)ntohl(ip->ip_src.s_addr), - (u_int32_t)ntohl(ip->ip_dst.s_addr), - (u_int32_t)ntohl(sav->spi))); - ipsecstat.out_inval++; - break; - } -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - ipseclog((LOG_DEBUG, "esp6_output: internal error: " - "sav->replay is null: SPI=%u\n", - (u_int32_t)ntohl(sav->spi))); - ipsec6stat.out_inval++; - break; -#endif /* INET6 */ - default: - panic("esp_output: should not reach here"); - } - m_freem(m); - return EINVAL; - } - - algo = esp_algorithm_lookup(sav->alg_enc); - if (!algo) { - ipseclog((LOG_ERR, "esp_output: unsupported algorithm: " - "SPI=%u\n", (u_int32_t)ntohl(sav->spi))); - m_freem(m); - return EINVAL; - } - spi = sav->spi; - ivlen = sav->ivlen; - /* should be okey */ - if (ivlen < 0) { - panic("invalid ivlen"); - } - - { - /* - * insert ESP header. - * XXX inserts ESP header right after IPv4 header. should - * chase the header chain. - * XXX sequential number - */ -#ifdef INET - struct ip *ip = NULL; -#endif - size_t esplen; /* sizeof(struct esp/newesp) */ - size_t esphlen; /* sizeof(struct esp/newesp) + ivlen */ - - if (sav->flags & SADB_X_EXT_OLD) { - /* RFC 1827 */ - esplen = sizeof(struct esp); - } else { - /* RFC 2406 */ - if (sav->flags & SADB_X_EXT_DERIV) - esplen = sizeof(struct esp); - else - esplen = sizeof(struct newesp); - } - esphlen = esplen + ivlen; - - for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next) - ; - if (mprev == NULL || mprev->m_next != md) { - ipseclog((LOG_DEBUG, "esp%d_output: md is not in chain\n", - afnumber)); - m_freem(m); - return EINVAL; - } - - plen = 0; - for (n = md; n; n = n->m_next) - plen += n->m_len; - - switch (af) { -#ifdef INET - case AF_INET: - ip = mtod(m, struct ip *); - break; -#endif -#ifdef INET6 - case AF_INET6: - break; -#endif - } - - /* make the packet over-writable */ - mprev->m_next = NULL; - if ((md = ipsec_copypkt(md)) == NULL) { - m_freem(m); - error = ENOBUFS; - goto fail; - } - mprev->m_next = md; - - espoff = m->m_pkthdr.len - plen; - - /* - * grow the mbuf to accomodate ESP header. - * before: IP ... payload - * after: IP ... ESP IV payload - */ - if (M_LEADINGSPACE(md) < esphlen || (md->m_flags & M_EXT)) { - MGET(n, M_NOWAIT, MT_DATA); - if (!n) { - m_freem(m); - error = ENOBUFS; - goto fail; - } - n->m_len = esphlen; - mprev->m_next = n; - n->m_next = md; - m->m_pkthdr.len += esphlen; - esp = mtod(n, struct esp *); - } else { - md->m_len += esphlen; - md->m_data -= esphlen; - m->m_pkthdr.len += esphlen; - esp = mtod(md, struct esp *); - } - - nxt = *nexthdrp; - *nexthdrp = IPPROTO_ESP; - switch (af) { -#ifdef INET - case AF_INET: - if (esphlen < (IP_MAXPACKET - ntohs(ip->ip_len))) - ip->ip_len = htons(ntohs(ip->ip_len) + esphlen); - else { - ipseclog((LOG_ERR, - "IPv4 ESP output: size exceeds limit\n")); - ipsecstat.out_inval++; - m_freem(m); - error = EMSGSIZE; - goto fail; - } - break; -#endif -#ifdef INET6 - case AF_INET6: - /* total packet length will be computed in ip6_output() */ - break; -#endif - } - } - - /* initialize esp header. */ - esp->esp_spi = spi; - if ((sav->flags & SADB_X_EXT_OLD) == 0) { - struct newesp *nesp; - nesp = (struct newesp *)esp; - if (sav->replay->count == ~0) { - if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) { - /* XXX Is it noisy ? */ - ipseclog((LOG_WARNING, - "replay counter overflowed. %s\n", - ipsec_logsastr(sav))); - stat->out_inval++; - m_freem(m); - return EINVAL; - } - } - sav->replay->count++; - /* - * XXX sequence number must not be cycled, if the SA is - * installed by IKE daemon. - */ - nesp->esp_seq = htonl(sav->replay->count & 0xffffffff); - } - - { - /* - * find the last mbuf. make some room for ESP trailer. - */ -#ifdef INET - struct ip *ip = NULL; -#endif - size_t padbound; - u_char *extend; - int i; - int randpadmax; - - if (algo->padbound) - padbound = algo->padbound; - else - padbound = 4; - /* ESP packet, including nxthdr field, must be length of 4n */ - if (padbound < 4) - padbound = 4; - - extendsiz = padbound - (plen % padbound); - if (extendsiz == 1) - extendsiz = padbound + 1; - - /* random padding */ - switch (af) { -#ifdef INET - case AF_INET: - randpadmax = ip4_esp_randpad; - break; -#endif -#ifdef INET6 - case AF_INET6: - randpadmax = ip6_esp_randpad; - break; -#endif - default: - randpadmax = -1; - break; - } - if (randpadmax < 0 || plen + extendsiz >= randpadmax) - ; - else { - int n; - - /* round */ - randpadmax = (randpadmax / padbound) * padbound; - n = (randpadmax - plen + extendsiz) / padbound; - - if (n > 0) - n = (krandom() % n) * padbound; - else - n = 0; - - /* - * make sure we do not pad too much. - * MLEN limitation comes from the trailer attachment - * code below. - * 256 limitation comes from sequential padding. - * also, the 1-octet length field in ESP trailer imposes - * limitation (but is less strict than sequential padding - * as length field do not count the last 2 octets). - */ - if (extendsiz + n <= MLEN && extendsiz + n < 256) - extendsiz += n; - } - -#ifdef DIAGNOSTIC - if (extendsiz > MLEN || extendsiz >= 256) - panic("extendsiz too big in esp_output"); -#endif - - n = m; - while (n->m_next) - n = n->m_next; - - /* - * if M_EXT, the external mbuf data may be shared among - * two consequtive TCP packets, and it may be unsafe to use the - * trailing space. - */ - if (!(n->m_flags & M_EXT) && extendsiz < M_TRAILINGSPACE(n)) { - extend = mtod(n, u_char *) + n->m_len; - n->m_len += extendsiz; - m->m_pkthdr.len += extendsiz; - } else { - struct mbuf *nn; - - MGET(nn, M_NOWAIT, MT_DATA); - if (!nn) { - ipseclog((LOG_DEBUG, "esp%d_output: can't alloc mbuf", - afnumber)); - m_freem(m); - error = ENOBUFS; - goto fail; - } - extend = mtod(nn, u_char *); - nn->m_len = extendsiz; - nn->m_next = NULL; - n->m_next = nn; - n = nn; - m->m_pkthdr.len += extendsiz; - } - switch (sav->flags & SADB_X_EXT_PMASK) { - case SADB_X_EXT_PRAND: - key_randomfill(extend, extendsiz); - break; - case SADB_X_EXT_PZERO: - bzero(extend, extendsiz); - break; - case SADB_X_EXT_PSEQ: - for (i = 0; i < extendsiz; i++) - extend[i] = (i + 1) & 0xff; - break; - } - - /* initialize esp trailer. */ - esptail = (struct esptail *) - (mtod(n, u_int8_t *) + n->m_len - sizeof(struct esptail)); - esptail->esp_nxt = nxt; - esptail->esp_padlen = extendsiz - 2; - - /* modify IP header (for ESP header part only) */ - switch (af) { -#ifdef INET - case AF_INET: - ip = mtod(m, struct ip *); - if (extendsiz < (IP_MAXPACKET - ntohs(ip->ip_len))) - ip->ip_len = htons(ntohs(ip->ip_len) + extendsiz); - else { - ipseclog((LOG_ERR, - "IPv4 ESP output: size exceeds limit\n")); - ipsecstat.out_inval++; - m_freem(m); - error = EMSGSIZE; - goto fail; - } - break; -#endif -#ifdef INET6 - case AF_INET6: - /* total packet length will be computed in ip6_output() */ - break; -#endif - } - } - - /* - * pre-compute and cache intermediate key - */ - error = esp_schedule(algo, sav); - if (error) { - m_freem(m); - stat->out_inval++; - goto fail; - } - - /* - * encrypt the packet, based on security association - * and the algorithm specified. - */ - if (!algo->encrypt) - panic("internal error: no encrypt function"); - if ((*algo->encrypt)(m, espoff, plen + extendsiz, sav, algo, ivlen)) { - /* m is already freed */ - ipseclog((LOG_ERR, "packet encryption failure\n")); - stat->out_inval++; - error = EINVAL; - goto fail; - } - - /* - * calculate ICV if required. - */ - if (!sav->replay) - goto noantireplay; - if (!sav->key_auth) - goto noantireplay; - if (sav->alg_auth == SADB_AALG_NONE) - goto noantireplay; - - { - const struct ah_algorithm *aalgo; - u_char authbuf[AH_MAXSUMSIZE]; - struct mbuf *n; - u_char *p; - size_t siz; -#ifdef INET - struct ip *ip; -#endif - - aalgo = ah_algorithm_lookup(sav->alg_auth); - if (!aalgo) - goto noantireplay; - siz = ((aalgo->sumsiz)(sav) + 3) & ~(4 - 1); - if (AH_MAXSUMSIZE < siz) - panic("assertion failed for AH_MAXSUMSIZE"); - - if (esp_auth(m, espoff, m->m_pkthdr.len - espoff, sav, authbuf)) { - ipseclog((LOG_ERR, "ESP checksum generation failure\n")); - m_freem(m); - error = EINVAL; - stat->out_inval++; - goto fail; - } - - n = m; - while (n->m_next) - n = n->m_next; - - if (!(n->m_flags & M_EXT) && siz < M_TRAILINGSPACE(n)) { /* XXX */ - n->m_len += siz; - m->m_pkthdr.len += siz; - p = mtod(n, u_char *) + n->m_len - siz; - } else { - struct mbuf *nn; - - MGET(nn, M_NOWAIT, MT_DATA); - if (!nn) { - ipseclog((LOG_DEBUG, "can't alloc mbuf in esp%d_output", - afnumber)); - m_freem(m); - error = ENOBUFS; - goto fail; - } - nn->m_len = siz; - nn->m_next = NULL; - n->m_next = nn; - n = nn; - m->m_pkthdr.len += siz; - p = mtod(nn, u_char *); - } - bcopy(authbuf, p, siz); - - /* modify IP header (for ESP header part only) */ - switch (af) { -#ifdef INET - case AF_INET: - ip = mtod(m, struct ip *); - if (siz < (IP_MAXPACKET - ntohs(ip->ip_len))) - ip->ip_len = htons(ntohs(ip->ip_len) + siz); - else { - ipseclog((LOG_ERR, - "IPv4 ESP output: size exceeds limit\n")); - ipsecstat.out_inval++; - m_freem(m); - error = EMSGSIZE; - goto fail; - } - break; -#endif -#ifdef INET6 - case AF_INET6: - /* total packet length will be computed in ip6_output() */ - break; -#endif - } - } - -noantireplay: - if (!m) { - ipseclog((LOG_ERR, - "NULL mbuf after encryption in esp%d_output", afnumber)); - } else - stat->out_success++; - stat->out_esphist[sav->alg_enc]++; - key_sa_recordxfer(sav, m); - return 0; - -fail: -#if 1 - return error; -#else - panic("something bad in esp_output"); -#endif -} - -#ifdef INET -int -esp4_output(struct mbuf *m, struct ipsecrequest *isr) -{ - struct ip *ip; - if (m->m_len < sizeof(struct ip)) { - ipseclog((LOG_DEBUG, "esp4_output: first mbuf too short\n")); - m_freem(m); - return 0; - } - ip = mtod(m, struct ip *); - /* XXX assumes that m->m_next points to payload */ - return esp_output(m, &ip->ip_p, m->m_next, isr, AF_INET); -} -#endif /* INET */ - -#ifdef INET6 -int -esp6_output(struct mbuf *m, u_char *nexthdrp, struct mbuf *md, - struct ipsecrequest *isr) -{ - if (m->m_len < sizeof(struct ip6_hdr)) { - ipseclog((LOG_DEBUG, "esp6_output: first mbuf too short\n")); - m_freem(m); - return 0; - } - return esp_output(m, nexthdrp, md, isr, AF_INET6); -} -#endif /* INET6 */ diff --git a/sys/netinet6/esp_rijndael.c b/sys/netinet6/esp_rijndael.c deleted file mode 100644 index aa5ea3a9fc..0000000000 --- a/sys/netinet6/esp_rijndael.c +++ /dev/null @@ -1,109 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/esp_rijndael.c,v 1.1.2.2 2003/01/11 19:10:59 ume Exp $ */ -/* $DragonFly: src/sys/netinet6/esp_rijndael.c,v 1.3 2004/05/20 18:30:36 cpressey Exp $ */ -/* $KAME: esp_rijndael.c,v 1.4 2001/03/02 05:53:05 itojun Exp $ */ - -/* - * 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. - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include - -#include - -/* as rijndael uses assymetric scheduled keys, we need to do it twice. */ -size_t -esp_rijndael_schedlen(const struct esp_algorithm *algo) -{ - - return sizeof(keyInstance) * 2; -} - -int -esp_rijndael_schedule(const struct esp_algorithm *algo, struct secasvar *sav) -{ - keyInstance *k; - - k = (keyInstance *)sav->sched; - if (rijndael_makeKey(&k[0], DIR_DECRYPT, _KEYLEN(sav->key_enc) * 8, - _KEYBUF(sav->key_enc)) < 0) - return -1; - if (rijndael_makeKey(&k[1], DIR_ENCRYPT, _KEYLEN(sav->key_enc) * 8, - _KEYBUF(sav->key_enc)) < 0) - return -1; - return 0; -} - -int -esp_rijndael_blockdecrypt(const struct esp_algorithm *algo, - struct secasvar *sav, u_int8_t *s, u_int8_t *d) -{ - cipherInstance c; - keyInstance *p; - - /* does not take advantage of CBC mode support */ - bzero(&c, sizeof(c)); - if (rijndael_cipherInit(&c, MODE_ECB, NULL) < 0) - return -1; - p = (keyInstance *)sav->sched; - if (rijndael_blockDecrypt(&c, &p[0], s, algo->padbound * 8, d) < 0) - return -1; - return 0; -} - -int -esp_rijndael_blockencrypt(const struct esp_algorithm *algo, - struct secasvar *sav, u_int8_t *s, u_int8_t *d) -{ - cipherInstance c; - keyInstance *p; - - /* does not take advantage of CBC mode support */ - bzero(&c, sizeof(c)); - if (rijndael_cipherInit(&c, MODE_ECB, NULL) < 0) - return -1; - p = (keyInstance *)sav->sched; - if (rijndael_blockEncrypt(&c, &p[1], s, algo->padbound * 8, d) < 0) - return -1; - return 0; -} diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 4b2eb0b0aa..e5840f7766 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -63,7 +63,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include #include @@ -100,17 +99,6 @@ #include #include -#ifdef IPSEC -#include -#include -#endif - -#ifdef FAST_IPSEC -#include -#include -#define IPSEC -#endif - #include #ifdef HAVE_NRL_INPCB @@ -126,7 +114,6 @@ #define in6p_outputopts inp_outputopts6 #define in6p_ip6 inp_ipv6 #define in6p_flowinfo inp_flowinfo -#define in6p_sp inp_sp #define in6p_next inp_next #define in6p_prev inp_prev /* function names */ @@ -2348,9 +2335,6 @@ icmp6_redirect_input(struct mbuf *m, int off) sdst.sin6_len = sizeof(struct sockaddr_in6); bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); kpfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst); -#ifdef IPSEC - key_sa_routechange((struct sockaddr *)&sdst); -#endif } freeit: diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index 546d67f68c..2a4862924e 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -426,10 +426,6 @@ struct route_in6 { #define IPV6_BINDV6ONLY IPV6_V6ONLY #endif -#if 1 /* IPSEC */ -#define IPV6_IPSEC_POLICY 28 /* struct; get/set security policy */ -#endif - #if 1 /* IPV6FIREWALL */ #define IPV6_FW_ADD 30 /* add a firewall rule to chain */ #define IPV6_FW_DEL 31 /* delete a firewall rule from chain */ diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 4a3d317edf..f036d761f5 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -64,7 +64,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include #include @@ -101,25 +100,6 @@ #include #include -#ifdef IPSEC -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#include -#endif /* IPSEC */ - -#ifdef FAST_IPSEC -#include -#include -#include -#define IPSEC -#endif /* FAST_IPSEC */ - struct in6_addr zeroin6_addr; int @@ -417,10 +397,6 @@ in6_pcbdetach(struct inpcb *inp) struct socket *so = inp->inp_socket; struct inpcbinfo *ipi = inp->inp_pcbinfo; -#ifdef IPSEC - if (inp->in6p_sp != NULL) - ipsec6_delete_pcbpolicy(inp); -#endif /* IPSEC */ inp->inp_gencnt = ++ipi->ipi_gencnt; in_pcbremlists(inp); so->so_pcb = NULL; diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index f9bf11013e..abacca52b7 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -63,7 +63,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include "opt_carp.h" #include @@ -101,36 +100,6 @@ #include #include -#ifdef IPSEC -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#ifdef IPSEC_ESP -#include -#ifdef INET6 -#include -#endif -#endif -#include -#ifdef INET6 -#include -#endif -#endif /* IPSEC */ - -#ifdef FAST_IPSEC -#include -#define IPSEC -#define IPSEC_ESP -#define ah6_input ipsec6_common_input -#define esp6_input ipsec6_common_input -#define ipcomp6_input ipsec6_common_input -#endif /* FAST_IPSEC */ - #include #include @@ -262,49 +231,6 @@ struct protosw inet6sw[] = { .pr_usrreqs = &nousrreqs }, -#ifdef IPSEC - { - .pr_type = SOCK_RAW, - .pr_domain = &inet6domain, - .pr_protocol = IPPROTO_AH, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = ah6_input, - .pr_output = NULL, - .pr_ctlinput = NULL, - .pr_ctloutput = NULL, - - .pr_usrreqs = &nousrreqs - }, -#ifdef IPSEC_ESP - { - .pr_type = SOCK_RAW, - .pr_domain = &inet6domain, - .pr_protocol = IPPROTO_ESP, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = esp6_input, - .pr_output = NULL, - .pr_ctlinput = esp6_ctlinput, - .pr_ctloutput = NULL, - - .pr_usrreqs = &nousrreqs - }, -#endif - { - .pr_type = SOCK_RAW, - .pr_domain = &inet6domain, - .pr_protocol = IPPROTO_IPCOMP, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = ipcomp6_input, - .pr_output = NULL, - .pr_ctlinput = NULL, - .pr_ctloutput = NULL, - - .pr_usrreqs = &nousrreqs - }, -#endif /* IPSEC */ #ifdef INET { .pr_type = SOCK_RAW, @@ -479,9 +405,6 @@ SYSCTL_NODE(_net_inet6, IPPROTO_IPV6, ip6, CTLFLAG_RW, 0, "IP6"); SYSCTL_NODE(_net_inet6, IPPROTO_ICMPV6, icmp6, CTLFLAG_RW, 0, "ICMP6"); SYSCTL_NODE(_net_inet6, IPPROTO_UDP, udp6, CTLFLAG_RW, 0, "UDP6"); SYSCTL_NODE(_net_inet6, IPPROTO_TCP, tcp6, CTLFLAG_RW, 0, "TCP6"); -#ifdef IPSEC -SYSCTL_NODE(_net_inet6, IPPROTO_ESP, ipsec6, CTLFLAG_RW, 0, "IPSEC6"); -#endif /* IPSEC */ /* net.inet6.ip6 */ static int diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index 4d54c25fa2..a514e0f30b 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -1,5 +1,4 @@ /* $FreeBSD: src/sys/netinet6/ip6_forward.c,v 1.4.2.7 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netinet6/ip6_forward.c,v 1.13 2006/12/22 23:57:53 swildner Exp $ */ /* $KAME: ip6_forward.c,v 1.69 2001/05/17 03:48:30 itojun Exp $ */ /* @@ -34,7 +33,6 @@ #include "opt_ip6fw.h" #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include #include @@ -65,21 +63,6 @@ #include -#ifdef IPSEC -#include -#ifdef INET6 -#include -#endif -#include -#endif /* IPSEC */ - -#ifdef FAST_IPSEC -#include -#include -#include -#define IPSEC -#endif /* FAST_IPSEC */ - #include #include @@ -109,26 +92,6 @@ ip6_forward(struct mbuf *m, int srcrt) struct mbuf *mcopy = NULL; struct ifnet *origifp; /* maybe unnecessary */ u_int32_t srczone, dstzone; -#ifdef IPSEC - struct secpolicy *sp = NULL; -#endif - -#ifdef IPSEC - /* - * Check AH/ESP integrity. - */ - /* - * Don't increment ip6s_cantforward because this is the check - * before forwarding packet actually. - */ - if (ipsec6_in_reject(m, NULL)) { -#if !defined(FAST_IPSEC) - ipsec6stat.in_polvio++; -#endif - m_freem(m); - return; - } -#endif /* IPSEC */ /* * Do not forward packets to multicast destination (should be handled @@ -168,136 +131,9 @@ ip6_forward(struct mbuf *m, int srcrt) * size of IPv6 + ICMPv6 headers) bytes of the packet in case * we need to generate an ICMP6 message to the src. * Thanks to M_EXT, in most cases copy will not occur. - * - * It is important to save it before IPsec processing as IPsec - * processing may modify the mbuf. */ mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN)); -#ifdef IPSEC - /* get a security policy for this packet */ - sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING, - &error); - if (sp == NULL) { - ipsec6stat.out_inval++; - ip6stat.ip6s_cantforward++; - if (mcopy) { -#if 0 - /* XXX: what icmp ? */ -#else - m_freem(mcopy); -#endif - } - m_freem(m); - return; - } - - error = 0; - - /* check policy */ - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - /* - * This packet is just discarded. - */ - ipsec6stat.out_polvio++; - ip6stat.ip6s_cantforward++; - key_freesp(sp); - if (mcopy) { -#if 0 - /* XXX: what icmp ? */ -#else - m_freem(mcopy); -#endif - } - m_freem(m); - return; - - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_NONE: - /* no need to do IPsec. */ - key_freesp(sp); - goto skip_ipsec; - - case IPSEC_POLICY_IPSEC: - if (sp->req == NULL) { - /* XXX should be panic ? */ - kprintf("ip6_forward: No IPsec request specified.\n"); - ip6stat.ip6s_cantforward++; - key_freesp(sp); - if (mcopy) { -#if 0 - /* XXX: what icmp ? */ -#else - m_freem(mcopy); -#endif - } - m_freem(m); - return; - } - /* do IPsec */ - break; - - case IPSEC_POLICY_ENTRUST: - default: - /* should be panic ?? */ - kprintf("ip6_forward: Invalid policy found. %d\n", sp->policy); - key_freesp(sp); - goto skip_ipsec; - } - - { - struct ipsec_output_state state; - - /* - * All the extension headers will become inaccessible - * (since they can be encrypted). - * Don't panic, we need no more updates to extension headers - * on inner IPv6 packet (since they are now encapsulated). - * - * IPv6 [ESP|AH] IPv6 [extension headers] payload - */ - bzero(&state, sizeof(state)); - state.m = m; - state.ro = NULL; /* update at ipsec6_output_tunnel() */ - state.dst = NULL; /* update at ipsec6_output_tunnel() */ - - error = ipsec6_output_tunnel(&state, sp, 0); - - m = state.m; - key_freesp(sp); - - if (error) { - /* mbuf is already reclaimed in ipsec6_output_tunnel. */ - switch (error) { - case EHOSTUNREACH: - case ENETUNREACH: - case EMSGSIZE: - case ENOBUFS: - case ENOMEM: - break; - default: - kprintf("ip6_output (ipsec): error code %d\n", error); - /* FALLTHROUGH */ - case ENOENT: - /* don't show these error codes to the user */ - break; - } - ip6stat.ip6s_cantforward++; - if (mcopy) { -#if 0 - /* XXX: what icmp ? */ -#else - m_freem(mcopy); -#endif - } - m_freem(m); - return; - } - } -skip_ipsec: -#endif /* IPSEC */ - dst = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst; if (!srcrt) { /* ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst */ @@ -383,37 +219,8 @@ skip_ipsec: in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig); if (mcopy) { u_long mtu; -#ifdef IPSEC - struct secpolicy *sp; - int ipsecerror; - size_t ipsechdrsiz; -#endif mtu = IN6_LINKMTU(rt->rt_ifp); -#ifdef IPSEC - /* - * When we do IPsec tunnel ingress, we need to play - * with if_mtu value (decrement IPsec header size - * from mtu value). The code is much simpler than v4 - * case, as we have the outgoing interface for - * encapsulated packet as "rt->rt_ifp". - */ - sp = ipsec6_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, - IP_FORWARDING, &ipsecerror); - if (sp) { - ipsechdrsiz = ipsec6_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, NULL); - if (ipsechdrsiz < mtu) - mtu -= ipsechdrsiz; - } - - /* - * if mtu becomes less than minimum MTU, - * tell minimum MTU (and I'll need to fragment it). - */ - if (mtu < IPV6_MMTU) - mtu = IPV6_MMTU; -#endif icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu); } m_freem(m); diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 95a3fd0fb6..b98a6c30fa 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -64,7 +64,6 @@ #include "opt_ip6fw.h" #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include #include @@ -108,19 +107,6 @@ #include #include -#ifdef IPSEC -#include -#ifdef INET6 -#include -#endif -#endif - -#ifdef FAST_IPSEC -#include -#include -#define IPSEC -#endif /* FAST_IPSEC */ - #include #include @@ -227,17 +213,6 @@ ip6_input(netmsg_t msg) struct in6_addr odst; int srcrt = 0; -#ifdef IPSEC - /* - * should the inner packet be considered authentic? - * see comment in ah4_input(). - */ - if (m) { - m->m_flags &= ~M_AUTHIPHDR; - m->m_flags &= ~M_AUTHIPDGM; - } -#endif - /* * make sure we don't have onion peering information into m_aux. */ @@ -758,17 +733,6 @@ hbhcheck: } sw6 = &inet6sw[ip6_protox[nxt]]; -#ifdef IPSEC - /* - * enforce IPsec policy checking if we are seeing last header. - * note that we do not visit this with protocols with pcb layer - * code - like udp/tcp/raw ip. - */ - if ((sw6->pr_flags & PR_LASTHDR) && ipsec6_in_reject(m, NULL)) { - ipsec6stat.in_polvio++; - goto bad; - } -#endif /* * If this is a terminal header forward to the port, otherwise * process synchronously for more headers. diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 83e725e73f..62eff5632c 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -64,7 +64,6 @@ #include "opt_ip6fw.h" #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include #include @@ -95,20 +94,6 @@ #include #include -#ifdef IPSEC -#include -#ifdef INET6 -#include -#endif -#include -#endif /* IPSEC */ - -#ifdef FAST_IPSEC -#include -#include -#include -#endif - #include #include @@ -174,20 +159,6 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro, struct in6_addr finaldst; struct route_in6 *ro_pmtu = NULL; boolean_t hdrsplit = FALSE; - boolean_t needipsec = FALSE; -#ifdef IPSEC - boolean_t needipsectun = FALSE; - struct secpolicy *sp = NULL; - struct socket *so = inp ? inp->inp_socket : NULL; - - ip6 = mtod(m, struct ip6_hdr *); -#endif -#ifdef FAST_IPSEC - boolean_t needipsectun = FALSE; - struct secpolicy *sp = NULL; - - ip6 = mtod(m, struct ip6_hdr *); -#endif bzero(&exthdrs, sizeof exthdrs); @@ -202,91 +173,6 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro, goto freehdrs; } -#ifdef IPSEC - /* get a security policy for this packet */ - if (so == NULL) - sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error); - else - sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error); - - if (sp == NULL) { - ipsec6stat.out_inval++; - goto freehdrs; - } - - error = 0; - - /* check policy */ - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - /* - * This packet is just discarded. - */ - ipsec6stat.out_polvio++; - goto freehdrs; - - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_NONE: - /* no need to do IPsec. */ - needipsec = FALSE; - break; - - case IPSEC_POLICY_IPSEC: - if (sp->req == NULL) { - error = key_spdacquire(sp); /* acquire a policy */ - goto freehdrs; - } - needipsec = TRUE; - break; - - case IPSEC_POLICY_ENTRUST: - default: - kprintf("ip6_output: Invalid policy found. %d\n", sp->policy); - } -#endif /* IPSEC */ -#ifdef FAST_IPSEC - /* get a security policy for this packet */ - if (inp == NULL) - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error); - else - sp = ipsec_getpolicybysock(m, IPSEC_DIR_OUTBOUND, inp, &error); - - if (sp == NULL) { - newipsecstat.ips_out_inval++; - goto freehdrs; - } - - error = 0; - - /* check policy */ - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - /* - * This packet is just discarded. - */ - newipsecstat.ips_out_polvio++; - goto freehdrs; - - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_NONE: - /* no need to do IPsec. */ - needipsec = FALSE; - break; - - case IPSEC_POLICY_IPSEC: - if (sp->req == NULL) { - error = key_spdacquire(sp); /* acquire a policy */ - goto freehdrs; - } - needipsec = TRUE; - break; - - case IPSEC_POLICY_ENTRUST: - default: - kprintf("ip6_output: Invalid policy found. %d\n", sp->policy); - } -#endif /* FAST_IPSEC */ - /* * Calculate the total length of the extension header chain. * Keep the length of the unfragmentable part for fragmentation. @@ -301,10 +187,10 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro, optlen += m_lengthm(exthdrs.ip6e_dest2, NULL); /* - * If we need IPsec, or there is at least one extension header, + * If there is at least one extension header, * separate IP6 header from the payload. */ - if ((needipsec || optlen) && !hdrsplit) { + if (optlen && !hdrsplit) { exthdrs.ip6e_ip6 = ip6_splithdr(m); if (exthdrs.ip6e_ip6 == NULL) { error = ENOBUFS; @@ -355,8 +241,7 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro, mprev = m; /* - * we treat dest2 specially. this makes IPsec processing - * much easier. the goal here is to make mprev point the + * we treat dest2 specially. the goal here is to make mprev point the * mbuf prior to dest2. * * result: IPv6 dest2 payload @@ -397,58 +282,6 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro, MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, nexthdrp, IPPROTO_DSTOPTS); MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp, IPPROTO_ROUTING); -#if defined(IPSEC) || defined(FAST_IPSEC) - if (needipsec) { - struct ipsec_output_state state; - int segleft_org = 0; - struct ip6_rthdr *rh = NULL; - - /* - * pointers after IPsec headers are not valid any more. - * other pointers need a great care too. - * (IPsec routines should not mangle mbufs prior to AH/ESP) - */ - exthdrs.ip6e_dest2 = NULL; - - if (exthdrs.ip6e_rthdr) { - rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *); - segleft_org = rh->ip6r_segleft; - rh->ip6r_segleft = 0; - } - - bzero(&state, sizeof state); - state.m = m; - error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags, - &needipsectun); - m = state.m; - if (error) { - /* mbuf is already reclaimed in ipsec6_output_trans. */ - m = NULL; - switch (error) { - case EHOSTUNREACH: - case ENETUNREACH: - case EMSGSIZE: - case ENOBUFS: - case ENOMEM: - break; - default: - kprintf("ip6_output (ipsec): error code %d\n", - error); - /* FALLTHROUGH */ - case ENOENT: - /* don't show these error codes to the user */ - error = 0; - break; - } - goto bad; - } - if (exthdrs.ip6e_rthdr) { - /* ah6_output doesn't modify mbuf chain */ - rh->ip6r_segleft = segleft_org; - } - } -#endif - /* * If there is a routing header, replace the destination address field * with the first hop of the routing header. @@ -509,57 +342,6 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro, dst->sin6_len = sizeof(struct sockaddr_in6); dst->sin6_addr = ip6->ip6_dst; } -#if defined(IPSEC) || defined(FAST_IPSEC) - if (needipsec && needipsectun) { - struct ipsec_output_state state; - - /* - * All the extension headers will become inaccessible - * (since they can be encrypted). - * Don't panic, we need no more updates to extension headers - * on inner IPv6 packet (since they are now encapsulated). - * - * IPv6 [ESP|AH] IPv6 [extension headers] payload - */ - bzero(&exthdrs, sizeof(exthdrs)); - exthdrs.ip6e_ip6 = m; - - bzero(&state, sizeof(state)); - state.m = m; - state.ro = (struct route *)ro; - state.dst = (struct sockaddr *)dst; - - error = ipsec6_output_tunnel(&state, sp, flags); - - m = state.m; - ro = (struct route_in6 *)state.ro; - dst = (struct sockaddr_in6 *)state.dst; - if (error) { - /* mbuf is already reclaimed in ipsec6_output_tunnel. */ - m0 = m = NULL; - m = NULL; - switch (error) { - case EHOSTUNREACH: - case ENETUNREACH: - case EMSGSIZE: - case ENOBUFS: - case ENOMEM: - break; - default: - kprintf("ip6_output (ipsec): error code %d\n", error); - /* FALLTHROUGH */ - case ENOENT: - /* don't show these error codes to the user */ - error = 0; - break; - } - goto bad; - } - - exthdrs.ip6e_ip6 = m; - } -#endif - if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { /* Unicast */ @@ -946,10 +728,6 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro, IFA_STAT_INC(&ia6->ia_ifa, opackets, 1); IFA_STAT_INC(&ia6->ia_ifa, obytes, m->m_pkthdr.len); } -#ifdef IPSEC - /* clean ipsec history once it goes out of the node */ - ipsec_delaux(m); -#endif error = nd6_output(ifp, origifp, m, dst, ro->ro_rt); goto done; } @@ -1080,10 +858,6 @@ sendorfree: IFA_STAT_INC(&ia->ia_ifa, obytes, m->m_pkthdr.len); } -#ifdef IPSEC - /* clean ipsec history once it goes out of the node */ - ipsec_delaux(m); -#endif error = nd6_output(ifp, origifp, m, dst, ro->ro_rt); } else m_freem(m); @@ -1099,15 +873,6 @@ done: RTFREE(ro_pmtu->ro_rt); } -#ifdef IPSEC - if (sp != NULL) - key_freesp(sp); -#endif -#ifdef FAST_IPSEC - if (sp != NULL) - KEY_FREESP(&sp); -#endif - return (error); freehdrs: @@ -1749,27 +1514,6 @@ do { \ } break; -#if defined(IPSEC) || defined(FAST_IPSEC) - case IPV6_IPSEC_POLICY: - { - caddr_t req = NULL; - size_t len = 0; - struct mbuf *m; - - if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */ - break; - soopt_to_mbuf(sopt, m); /* XXX */ - if (m) { - req = mtod(m, caddr_t); - len = m->m_len; - } - error = ipsec6_set_policy(in6p, optname, req, - len, privileged); - m_freem(m); - } - break; -#endif /* KAME IPSEC */ - case IPV6_FW_ADD: case IPV6_FW_DEL: case IPV6_FW_FLUSH: @@ -1996,31 +1740,6 @@ do { \ } break; -#if defined(IPSEC) || defined(FAST_IPSEC) - case IPV6_IPSEC_POLICY: - { - caddr_t req = NULL; - size_t len = 0; - struct mbuf *m = NULL; - struct mbuf **mp = &m; - - error = soopt_getm(sopt, &m); /* XXX */ - if (error != 0) - break; - soopt_to_mbuf(sopt, m); /* XXX */ - if (m) { - req = mtod(m, caddr_t); - len = m->m_len; - } - error = ipsec6_get_policy(in6p, req, len, mp); - if (error == 0) - error = soopt_from_mbuf(sopt, m);/*XXX*/ - if (error == 0 && m != NULL) - m_freem(m); - break; - } -#endif /* KAME IPSEC */ - case IPV6_FW_GET: { struct mbuf *m; diff --git a/sys/netinet6/ipcomp.h b/sys/netinet6/ipcomp.h deleted file mode 100644 index aef645841f..0000000000 --- a/sys/netinet6/ipcomp.h +++ /dev/null @@ -1,79 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ipcomp.h,v 1.1.2.3 2002/04/28 05:40:27 suz Exp $ */ -/* $DragonFly: src/sys/netinet6/ipcomp.h,v 1.6 2006/05/20 02:42:12 dillon Exp $ */ -/* $KAME: ipcomp.h,v 1.11 2001/09/04 08:43:19 itojun Exp $ */ - -/* - * Copyright (C) 1999 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. - */ - -/* - * RFC2393 IP payload compression protocol (IPComp). - */ - -#ifndef _NETINET6_IPCOMP_H_ -#define _NETINET6_IPCOMP_H_ - -#ifndef _SYS_TYPES_H_ -#include -#endif - -#if defined(_KERNEL) && !defined(_LKM) -#include "opt_inet.h" -#endif - -struct ipcomp { - u_int8_t comp_nxt; /* Next Header */ - u_int8_t comp_flags; /* reserved, must be zero */ - u_int16_t comp_cpi; /* Compression parameter index */ -}; - -/* well-known algorithm number (in CPI), from RFC2409 */ -#define IPCOMP_OUI 1 /* vendor specific */ -#define IPCOMP_DEFLATE 2 /* RFC2394 */ -#define IPCOMP_LZS 3 /* RFC2395 */ -#define IPCOMP_MAX 4 - -#define IPCOMP_CPI_NEGOTIATE_MIN 256 - -#ifdef _KERNEL - -struct mbuf; -struct ipsecrequest; - -struct ipcomp_algorithm { - int (*compress) (struct mbuf *, struct mbuf *, size_t *); - int (*decompress) (struct mbuf *, struct mbuf *, size_t *); - size_t minplen; /* minimum required length for compression */ -}; - -extern const struct ipcomp_algorithm *ipcomp_algorithm_lookup (int); -extern int ipcomp4_input (struct mbuf **, int *, int); -extern int ipcomp4_output (struct mbuf *, struct ipsecrequest *); -#endif /* KERNEL */ - -#endif /* _NETINET6_IPCOMP_H_ */ diff --git a/sys/netinet6/ipcomp6.h b/sys/netinet6/ipcomp6.h deleted file mode 100644 index 2b4b1b522d..0000000000 --- a/sys/netinet6/ipcomp6.h +++ /dev/null @@ -1,56 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ipcomp6.h,v 1.1.2.2 2001/07/03 11:01:54 ume Exp $ */ -/* $DragonFly: src/sys/netinet6/ipcomp6.h,v 1.4 2006/05/20 02:42:12 dillon Exp $ */ -/* $KAME: ipcomp.h,v 1.8 2000/09/26 07:55:14 itojun Exp $ */ - -/* - * Copyright (C) 1999 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. - */ - -/* - * RFC2393 IP payload compression protocol (IPComp). - */ - -#ifndef _NETINET6_IPCOMP6_H_ -#define _NETINET6_IPCOMP6_H_ - -#ifdef _KERNEL - -#ifndef _SYS_TYPES_H_ -#include -#endif - -struct mbuf; -struct ipsecrequest; - -extern int ipcomp6_input (struct mbuf **, int *, int); -extern int ipcomp6_output (struct mbuf *, u_char *, struct mbuf *, - struct ipsecrequest *); - -#endif /*KERNEL*/ - -#endif /*_NETINET6_IPCOMP6_H_*/ diff --git a/sys/netinet6/ipcomp_core.c b/sys/netinet6/ipcomp_core.c deleted file mode 100644 index a6f80ddbe8..0000000000 --- a/sys/netinet6/ipcomp_core.c +++ /dev/null @@ -1,342 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ipcomp_core.c,v 1.1.2.5 2003/01/11 19:10:59 ume Exp $ */ -/* $KAME: ipcomp_core.c,v 1.25 2001/07/26 06:53:17 jinmei Exp $ */ - -/* - * Copyright (C) 1999 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. - */ - -/* - * RFC2393 IP payload compression protocol (IPComp). - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif - -#include - -#include - -static void *deflate_alloc (void *, u_int, u_int); -static void deflate_free (void *, void *); -static int deflate_common (struct mbuf *, struct mbuf *, size_t *, int); -static int deflate_compress (struct mbuf *, struct mbuf *, size_t *); -static int deflate_decompress (struct mbuf *, struct mbuf *, size_t *); - -/* - * We need to use default window size (2^15 = 32Kbytes as of writing) for - * inbound case. Otherwise we get interop problem. - * Use negative value to avoid Adler32 checksum. This is an undocumented - * feature in zlib (see ipsec wg mailing list archive in January 2000). - */ -static int deflate_policy = Z_DEFAULT_COMPRESSION; -static int deflate_window_out = -12; -static const int deflate_window_in = -1 * MAX_WBITS; /* don't change it */ -static int deflate_memlevel = MAX_MEM_LEVEL; - -static const struct ipcomp_algorithm ipcomp_algorithms[] = { - { deflate_compress, deflate_decompress, 90 }, -}; - -const struct ipcomp_algorithm * -ipcomp_algorithm_lookup(int idx) -{ - - if (idx == SADB_X_CALG_DEFLATE) - return &ipcomp_algorithms[0]; - return NULL; -} - -static void * -deflate_alloc(void *aux, u_int items, u_int siz) -{ - void *ptr; - ptr = kmalloc(items * siz, M_TEMP, M_NOWAIT); - return ptr; -} - -static void -deflate_free(void *aux, void *ptr) -{ - kfree(ptr, M_TEMP); -} - -static int -deflate_common(struct mbuf *m, struct mbuf *md, size_t *lenp, - int mode) /* 0: compress 1: decompress */ -{ - struct mbuf *mprev; - struct mbuf *p; - struct mbuf *n = NULL, *n0 = NULL, **np; - z_stream zs; - int error = 0; - int zerror; - size_t offset; - -#define MOREBLOCK() \ -do { \ - /* keep the reply buffer into our chain */ \ - if (n) { \ - n->m_len = zs.total_out - offset; \ - offset = zs.total_out; \ - *np = n; \ - np = &n->m_next; \ - n = NULL; \ - } \ - \ - /* get a fresh reply buffer */ \ - n = m_getcl(M_NOWAIT, MT_DATA, 0); \ - if (!n) { \ - error = ENOBUFS; \ - goto fail; \ - } \ - n->m_len = 0; \ - n->m_len = M_TRAILINGSPACE(n); \ - n->m_next = NULL; \ - /* \ - * if this is the first reply buffer, reserve \ - * region for ipcomp header. \ - */ \ - if (*np == NULL) { \ - n->m_len -= sizeof(struct ipcomp); \ - n->m_data += sizeof(struct ipcomp); \ - } \ - \ - zs.next_out = mtod(n, u_int8_t *); \ - zs.avail_out = n->m_len; \ -} while (0) - - for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next) - ; - if (!mprev) - panic("md is not in m in deflate_common"); - - bzero(&zs, sizeof(zs)); - zs.zalloc = deflate_alloc; - zs.zfree = deflate_free; - - zerror = mode ? inflateInit2(&zs, deflate_window_in) - : deflateInit2(&zs, deflate_policy, Z_DEFLATED, - deflate_window_out, deflate_memlevel, - Z_DEFAULT_STRATEGY); - if (zerror != Z_OK) { - error = ENOBUFS; - goto fail; - } - - n0 = n = NULL; - np = &n0; - offset = 0; - zerror = 0; - p = md; - while (p && p->m_len == 0) { - p = p->m_next; - } - - /* input stream and output stream are available */ - while (p && zs.avail_in == 0) { - /* get input buffer */ - if (p && zs.avail_in == 0) { - zs.next_in = mtod(p, u_int8_t *); - zs.avail_in = p->m_len; - p = p->m_next; - while (p && p->m_len == 0) { - p = p->m_next; - } - } - - /* get output buffer */ - if (zs.next_out == NULL || zs.avail_out == 0) { - MOREBLOCK(); - } - - zerror = mode ? inflate(&zs, Z_NO_FLUSH) - : deflate(&zs, Z_NO_FLUSH); - - if (zerror == Z_STREAM_END) - ; /* once more. */ - else if (zerror == Z_OK) { - /* inflate: Z_OK can indicate the end of decode */ - if (mode && !p && zs.avail_out != 0) - goto terminate; - else { - ; /* once more. */ - } - } else { - if (zs.msg) { - ipseclog((LOG_ERR, "ipcomp_%scompress: " - "%sflate(Z_NO_FLUSH): %s\n", - mode ? "de" : "", mode ? "in" : "de", - zs.msg)); - } else { - ipseclog((LOG_ERR, "ipcomp_%scompress: " - "%sflate(Z_NO_FLUSH): unknown error (%d)\n", - mode ? "de" : "", mode ? "in" : "de", - zerror)); - } - mode ? inflateEnd(&zs) : deflateEnd(&zs); - error = EINVAL; - goto fail; - } - } - - if (zerror == Z_STREAM_END) - goto terminate; - - /* termination */ - while (1) { - /* get output buffer */ - if (zs.next_out == NULL || zs.avail_out == 0) { - MOREBLOCK(); - } - - zerror = mode ? inflate(&zs, Z_SYNC_FLUSH) - : deflate(&zs, Z_FINISH); - - if (zerror == Z_STREAM_END) - break; - else if (zerror == Z_OK) { - if (mode && zs.avail_out != 0) - goto terminate; - else { - ; /* once more. */ - } - } else { - if (zs.msg) { - ipseclog((LOG_ERR, "ipcomp_%scompress: " - "%sflate(Z_FINISH): %s\n", - mode ? "de" : "", mode ? "in" : "de", - zs.msg)); - } else { - ipseclog((LOG_ERR, "ipcomp_%scompress: " - "%sflate(Z_FINISH): unknown error (%d)\n", - mode ? "de" : "", mode ? "in" : "de", - zerror)); - } - mode ? inflateEnd(&zs) : deflateEnd(&zs); - error = EINVAL; - goto fail; - } - } - -terminate: - zerror = mode ? inflateEnd(&zs) : deflateEnd(&zs); - if (zerror != Z_OK) { - if (zs.msg) { - ipseclog((LOG_ERR, "ipcomp_%scompress: " - "%sflateEnd: %s\n", - mode ? "de" : "", mode ? "in" : "de", - zs.msg)); - } else { - ipseclog((LOG_ERR, "ipcomp_%scompress: " - "%sflateEnd: unknown error (%d)\n", - mode ? "de" : "", mode ? "in" : "de", - zerror)); - } - error = EINVAL; - goto fail; - } - /* keep the final reply buffer into our chain */ - if (n) { - n->m_len = zs.total_out - offset; - offset = zs.total_out; - *np = n; - np = &n->m_next; - n = NULL; - } - - /* switch the mbuf to the new one */ - mprev->m_next = n0; - m_freem(md); - *lenp = zs.total_out; - - return 0; - -fail: - if (m) - m_freem(m); - if (n) - m_freem(n); - if (n0) - m_freem(n0); - return error; -#undef MOREBLOCK -} - -static int -deflate_compress(struct mbuf *m, struct mbuf *md, size_t *lenp) -{ - if (!m) - panic("m == NULL in deflate_compress"); - if (!md) - panic("md == NULL in deflate_compress"); - if (!lenp) - panic("lenp == NULL in deflate_compress"); - - return deflate_common(m, md, lenp, 0); -} - -static int -deflate_decompress(struct mbuf *m, struct mbuf *md, size_t *lenp) -{ - if (!m) - panic("m == NULL in deflate_decompress"); - if (!md) - panic("md == NULL in deflate_decompress"); - if (!lenp) - panic("lenp == NULL in deflate_decompress"); - - return deflate_common(m, md, lenp, 1); -} diff --git a/sys/netinet6/ipcomp_input.c b/sys/netinet6/ipcomp_input.c deleted file mode 100644 index ecbc149bff..0000000000 --- a/sys/netinet6/ipcomp_input.c +++ /dev/null @@ -1,345 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ipcomp_input.c,v 1.1.2.3 2002/04/28 05:40:27 suz Exp $ */ -/* $KAME: ipcomp_input.c,v 1.25 2001/03/01 09:12:09 itojun Exp $ */ - -/* - * Copyright (C) 1999 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. - */ - -/* - * RFC2393 IP payload compression protocol (IPComp). - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef INET6 -#include -#include -#endif -#include -#ifdef INET6 -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#include - -#include - -#include - -#define IPLEN_FLIPPED - -#ifdef INET -extern struct protosw inetsw[]; - -int -ipcomp4_input(struct mbuf **mp, int *offp, int proto) -{ - int off; - struct mbuf *md; - struct mbuf *m; - struct ip *ip; - struct ipcomp *ipcomp; - const struct ipcomp_algorithm *algo; - u_int16_t cpi; /* host order */ - u_int16_t nxt; - int error; - size_t newlen, olen; - struct secasvar *sav = NULL; - - off = *offp; - m = *mp; - *mp = NULL; - - if (m->m_pkthdr.len < off + sizeof(struct ipcomp)) { - ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed " - "(packet too short)\n")); - ipsecstat.in_inval++; - goto fail; - } - - md = m_pulldown(m, off, sizeof(*ipcomp), NULL); - if (!md) { - m = NULL; /* already freed */ - ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed " - "(pulldown failure)\n")); - ipsecstat.in_inval++; - goto fail; - } - ipcomp = mtod(md, struct ipcomp *); - ip = mtod(m, struct ip *); - nxt = ipcomp->comp_nxt; - - cpi = ntohs(ipcomp->comp_cpi); - - if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) { - sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, - (caddr_t)&ip->ip_dst, IPPROTO_IPCOMP, htonl(cpi)); - if (sav != NULL - && (sav->state == SADB_SASTATE_MATURE - || sav->state == SADB_SASTATE_DYING)) { - cpi = sav->alg_enc; /* XXX */ - /* other parameters to look at? */ - } - } - algo = ipcomp_algorithm_lookup(cpi); - if (!algo) { - ipseclog((LOG_WARNING, "IPv4 IPComp input: unknown cpi %u\n", - cpi)); - ipsecstat.in_nosa++; - goto fail; - } - - /* chop ipcomp header */ - ipcomp = NULL; - md->m_data += sizeof(struct ipcomp); - md->m_len -= sizeof(struct ipcomp); - m->m_pkthdr.len -= sizeof(struct ipcomp); -#ifdef IPLEN_FLIPPED - ip->ip_len -= sizeof(struct ipcomp); -#else - ip->ip_len = htons(ntohs(ip->ip_len) - sizeof(struct ipcomp)); -#endif - - olen = m->m_pkthdr.len; - newlen = m->m_pkthdr.len - off; - error = (*algo->decompress)(m, m->m_next, &newlen); - if (error != 0) { - if (error == EINVAL) - ipsecstat.in_inval++; - else if (error == ENOBUFS) - ipsecstat.in_nomem++; - m = NULL; - goto fail; - } - ipsecstat.in_comphist[cpi]++; - - /* - * returning decompressed packet onto icmp is meaningless. - * mark it decrypted to prevent icmp from attaching original packet. - */ - m->m_flags |= M_DECRYPTED; - - m->m_pkthdr.len = off + newlen; - ip = mtod(m, struct ip *); - { - size_t len; -#ifdef IPLEN_FLIPPED - len = ip->ip_len; -#else - len = ntohs(ip->ip_len); -#endif - /* - * be careful about underflow. also, do not assign exact value - * as ip_len is manipulated differently on *BSDs. - */ - len += m->m_pkthdr.len; - len -= olen; - if (len & ~0xffff) { - /* packet too big after decompress */ - ipsecstat.in_inval++; - goto fail; - } -#ifdef IPLEN_FLIPPED - ip->ip_len = len & 0xffff; -#else - ip->ip_len = htons(len & 0xffff); -#endif - ip->ip_p = nxt; - } - - if (sav) { - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) { - ipsecstat.in_nomem++; - goto fail; - } - key_freesav(sav); - sav = NULL; - } - - if (nxt != IPPROTO_DONE) { - if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) && - ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; - goto fail; - } - *mp = m; - *offp = off; - (*inetsw[ip_protox[nxt]].pr_input)(mp, offp, nxt); - } else { - m_freem(m); - } - m = NULL; - - ipsecstat.in_success++; - return(IPPROTO_DONE); - -fail: - if (sav) - key_freesav(sav); - if (m) - m_freem(m); - return(IPPROTO_DONE); -} -#endif /* INET */ - -#ifdef INET6 -int -ipcomp6_input(struct mbuf **mp, int *offp, int proto) -{ - struct mbuf *m, *md; - int off; - struct ip6_hdr *ip6; - struct ipcomp *ipcomp; - const struct ipcomp_algorithm *algo; - u_int16_t cpi; /* host order */ - u_int16_t nxt; - int error; - size_t newlen; - struct secasvar *sav = NULL; - char *prvnxtp; - - m = *mp; - off = *offp; - - md = m_pulldown(m, off, sizeof(*ipcomp), NULL); - if (!md) { - m = NULL; /* already freed */ - ipseclog((LOG_DEBUG, "IPv6 IPComp input: assumption failed " - "(pulldown failure)\n")); - ipsec6stat.in_inval++; - goto fail; - } - ipcomp = mtod(md, struct ipcomp *); - ip6 = mtod(m, struct ip6_hdr *); - nxt = ipcomp->comp_nxt; - - cpi = ntohs(ipcomp->comp_cpi); - - if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) { - sav = key_allocsa(AF_INET6, (caddr_t)&ip6->ip6_src, - (caddr_t)&ip6->ip6_dst, IPPROTO_IPCOMP, htonl(cpi)); - if (sav != NULL - && (sav->state == SADB_SASTATE_MATURE - || sav->state == SADB_SASTATE_DYING)) { - cpi = sav->alg_enc; /* XXX */ - /* other parameters to look at? */ - } - } - algo = ipcomp_algorithm_lookup(cpi); - if (!algo) { - ipseclog((LOG_WARNING, "IPv6 IPComp input: unknown cpi %u; " - "dropping the packet for simplicity\n", cpi)); - ipsec6stat.in_nosa++; - goto fail; - } - - /* chop ipcomp header */ - ipcomp = NULL; - md->m_data += sizeof(struct ipcomp); - md->m_len -= sizeof(struct ipcomp); - m->m_pkthdr.len -= sizeof(struct ipcomp); - - newlen = m->m_pkthdr.len - off; - error = (*algo->decompress)(m, md, &newlen); - if (error != 0) { - if (error == EINVAL) - ipsec6stat.in_inval++; - else if (error == ENOBUFS) - ipsec6stat.in_nomem++; - m = NULL; - goto fail; - } - ipsec6stat.in_comphist[cpi]++; - m->m_pkthdr.len = off + newlen; - - /* - * returning decompressed packet onto icmp is meaningless. - * mark it decrypted to prevent icmp from attaching original packet. - */ - m->m_flags |= M_DECRYPTED; - - /* update next header field */ - prvnxtp = ip6_get_prevhdr(m, off); - *prvnxtp = nxt; - - /* - * no need to adjust payload length, as all the IPv6 protocols - * look at m->m_pkthdr.len - */ - - if (sav) { - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) { - ipsec6stat.in_nomem++; - goto fail; - } - key_freesav(sav); - sav = NULL; - } - *offp = off; - *mp = m; - ipsec6stat.in_success++; - return nxt; - -fail: - if (m) - m_freem(m); - if (sav) - key_freesav(sav); - return IPPROTO_DONE; -} -#endif /* INET6 */ diff --git a/sys/netinet6/ipcomp_output.c b/sys/netinet6/ipcomp_output.c deleted file mode 100644 index 44d29d4e3e..0000000000 --- a/sys/netinet6/ipcomp_output.c +++ /dev/null @@ -1,363 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ipcomp_output.c,v 1.1.2.4 2003/04/29 08:33:50 suz Exp $ */ -/* $KAME: ipcomp_output.c,v 1.25 2002/06/09 14:44:00 itojun Exp $ */ - -/* - * Copyright (C) 1999 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. - */ - -/* - * RFC2393 IP payload compression protocol (IPComp). - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef INET6 -#include -#include -#endif -#include -#ifdef INET6 -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#include - -#include - -#include - -static int ipcomp_output (struct mbuf *, u_char *, struct mbuf *, - struct ipsecrequest *, int); - -/* - * Modify the packet so that the payload is compressed. - * The mbuf (m) must start with IPv4 or IPv6 header. - * On failure, free the given mbuf and return non-zero. - * - * on invocation: - * m nexthdrp md - * v v v - * IP ......... payload - * during the encryption: - * m nexthdrp mprev md - * v v v v - * IP ............... ipcomp payload - * <-----><-----> - * complen plen - * <-> hlen - * <-----------------> compoff - */ -static int -ipcomp_output(struct mbuf *m, u_char *nexthdrp, struct mbuf *md, - struct ipsecrequest *isr, int af) -{ - struct mbuf *n; - struct mbuf *md0; - struct mbuf *mcopy; - struct mbuf *mprev; - struct ipcomp *ipcomp; - struct secasvar *sav = isr->sav; - const struct ipcomp_algorithm *algo; - u_int16_t cpi; /* host order */ - size_t plen0, plen; /* payload length to be compressed */ - size_t compoff; - int afnumber; - int error = 0; - struct ipsecstat *stat; - - switch (af) { -#ifdef INET - case AF_INET: - afnumber = 4; - stat = &ipsecstat; - break; -#endif -#ifdef INET6 - case AF_INET6: - afnumber = 6; - stat = &ipsec6stat; - break; -#endif - default: - ipseclog((LOG_ERR, "ipcomp_output: unsupported af %d\n", af)); - return 0; /* no change at all */ - } - - /* grab parameters */ - algo = ipcomp_algorithm_lookup(sav->alg_enc); - if ((ntohl(sav->spi) & ~0xffff) != 0 || !algo) { - stat->out_inval++; - m_freem(m); - return EINVAL; - } - if ((sav->flags & SADB_X_EXT_RAWCPI) == 0) - cpi = sav->alg_enc; - else - cpi = ntohl(sav->spi) & 0xffff; - - /* compute original payload length */ - plen = 0; - for (n = md; n; n = n->m_next) - plen += n->m_len; - - /* if the payload is short enough, we don't need to compress */ - if (plen < algo->minplen) - return 0; - - /* - * retain the original packet for two purposes: - * (1) we need to backout our changes when compression is not necessary. - * (2) byte lifetime computation should use the original packet. - * see RFC2401 page 23. - * compromise two m_copym(). we will be going through every byte of - * the payload during compression process anyways. - */ - mcopy = m_copym(m, 0, M_COPYALL, M_NOWAIT); - if (mcopy == NULL) { - error = ENOBUFS; - return 0; - } - md0 = m_copym(md, 0, M_COPYALL, M_NOWAIT); - if (md0 == NULL) { - m_freem(mcopy); - error = ENOBUFS; - return 0; - } - plen0 = plen; - - /* make the packet over-writable */ - for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next) - ; - if (mprev == NULL || mprev->m_next != md) { - ipseclog((LOG_DEBUG, "ipcomp%d_output: md is not in chain\n", - afnumber)); - stat->out_inval++; - m_freem(m); - m_freem(md0); - m_freem(mcopy); - return EINVAL; - } - mprev->m_next = NULL; - if ((md = ipsec_copypkt(md)) == NULL) { - m_freem(m); - m_freem(md0); - m_freem(mcopy); - error = ENOBUFS; - goto fail; - } - mprev->m_next = md; - - /* compress data part */ - if ((*algo->compress)(m, md, &plen) || mprev->m_next == NULL) { - ipseclog((LOG_ERR, "packet compression failure\n")); - m = NULL; - m_freem(md0); - m_freem(mcopy); - stat->out_inval++; - error = EINVAL; - goto fail; - } - stat->out_comphist[sav->alg_enc]++; - md = mprev->m_next; - - /* - * if the packet became bigger, meaningless to use IPComp. - * we've only wasted our cpu time. - */ - if (plen0 < plen) { - m_freem(md); - m_freem(mcopy); - mprev->m_next = md0; - return 0; - } - - /* - * no need to backout change beyond here. - */ - m_freem(md0); - md0 = NULL; - - m->m_pkthdr.len -= plen0; - m->m_pkthdr.len += plen; - - { - /* - * insert IPComp header. - */ -#ifdef INET - struct ip *ip = NULL; -#endif - size_t complen = sizeof(struct ipcomp); - - switch (af) { -#ifdef INET - case AF_INET: - ip = mtod(m, struct ip *); - break; -#endif -#ifdef INET6 - case AF_INET6: - break; -#endif - } - - compoff = m->m_pkthdr.len - plen; - - /* - * grow the mbuf to accomodate ipcomp header. - * before: IP ... payload - * after: IP ... ipcomp payload - */ - if (M_LEADINGSPACE(md) < complen) { - MGET(n, M_NOWAIT, MT_DATA); - if (!n) { - m_freem(m); - error = ENOBUFS; - goto fail; - } - n->m_len = complen; - mprev->m_next = n; - n->m_next = md; - m->m_pkthdr.len += complen; - ipcomp = mtod(n, struct ipcomp *); - } else { - md->m_len += complen; - md->m_data -= complen; - m->m_pkthdr.len += complen; - ipcomp = mtod(md, struct ipcomp *); - } - - bzero(ipcomp, sizeof(*ipcomp)); - ipcomp->comp_nxt = *nexthdrp; - *nexthdrp = IPPROTO_IPCOMP; - ipcomp->comp_cpi = htons(cpi); - switch (af) { -#ifdef INET - case AF_INET: - if (compoff + complen + plen < IP_MAXPACKET) - ip->ip_len = htons(compoff + complen + plen); - else { - ipseclog((LOG_ERR, - "IPv4 ESP output: size exceeds limit\n")); - ipsecstat.out_inval++; - m_freem(m); - error = EMSGSIZE; - goto fail; - } - break; -#endif -#ifdef INET6 - case AF_INET6: - /* total packet length will be computed in ip6_output() */ - break; -#endif - } - } - - if (!m) { - ipseclog((LOG_DEBUG, - "NULL mbuf after compression in ipcomp%d_output", - afnumber)); - stat->out_inval++; - } - stat->out_success++; - - /* compute byte lifetime against original packet */ - key_sa_recordxfer(sav, mcopy); - m_freem(mcopy); - - return 0; - -fail: -#if 1 - return error; -#else - panic("something bad in ipcomp_output"); -#endif -} - -#ifdef INET -int -ipcomp4_output(struct mbuf *m, struct ipsecrequest *isr) -{ - struct ip *ip; - if (m->m_len < sizeof(struct ip)) { - ipseclog((LOG_DEBUG, "ipcomp4_output: first mbuf too short\n")); - ipsecstat.out_inval++; - m_freem(m); - return 0; - } - ip = mtod(m, struct ip *); - /* XXX assumes that m->m_next points to payload */ - return ipcomp_output(m, &ip->ip_p, m->m_next, isr, AF_INET); -} -#endif /* INET */ - -#ifdef INET6 -int -ipcomp6_output(struct mbuf *m, u_char *nexthdrp, struct mbuf *md, - struct ipsecrequest *isr) -{ - if (m->m_len < sizeof(struct ip6_hdr)) { - ipseclog((LOG_DEBUG, "ipcomp6_output: first mbuf too short\n")); - ipsec6stat.out_inval++; - m_freem(m); - return 0; - } - return ipcomp_output(m, nexthdrp, md, isr, AF_INET6); -} -#endif /* INET6 */ diff --git a/sys/netinet6/ipsec.c b/sys/netinet6/ipsec.c deleted file mode 100644 index f9aa5c47f3..0000000000 --- a/sys/netinet6/ipsec.c +++ /dev/null @@ -1,3474 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ipsec.c,v 1.3.2.12 2003/05/06 06:46:58 suz Exp $ */ -/* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef INET6 -#include -#endif -#include - -#include -#ifdef INET6 -#include -#endif -#ifdef INET6 -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#ifdef IPSEC_ESP -#include -#ifdef INET6 -#include -#endif -#endif -#include -#ifdef INET6 -#include -#endif -#include -#include -#include - -#include - -#ifdef IPSEC_DEBUG -int ipsec_debug = 1; -#else -int ipsec_debug = 0; -#endif - -struct ipsecstat ipsecstat; -int ip4_ah_cleartos = 1; -int ip4_ah_offsetmask = 0; /* maybe IP_DF? */ -int ip4_ipsec_dfbit = 0; /* DF bit on encap. 0: clear 1: set 2: copy */ -int ip4_esp_trans_deflev = IPSEC_LEVEL_USE; -int ip4_esp_net_deflev = IPSEC_LEVEL_USE; -int ip4_ah_trans_deflev = IPSEC_LEVEL_USE; -int ip4_ah_net_deflev = IPSEC_LEVEL_USE; -struct secpolicy ip4_def_policy; -int ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ -int ip4_esp_randpad = -1; - -#ifdef SYSCTL_DECL -SYSCTL_DECL(_net_inet_ipsec); -#ifdef INET6 -SYSCTL_DECL(_net_inet6_ipsec6); -#endif -#endif - -/* net.inet.ipsec */ -SYSCTL_STRUCT(_net_inet_ipsec, IPSECCTL_STATS, - stats, CTLFLAG_RD, &ipsecstat, ipsecstat, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, - def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, - CTLFLAG_RW, &ip4_esp_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, - CTLFLAG_RW, &ip4_esp_net_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, - CTLFLAG_RW, &ip4_ah_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, - CTLFLAG_RW, &ip4_ah_net_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS, - ah_cleartos, CTLFLAG_RW, &ip4_ah_cleartos, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, - ah_offsetmask, CTLFLAG_RW, &ip4_ah_offsetmask, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT, - dfbit, CTLFLAG_RW, &ip4_ipsec_dfbit, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN, - ecn, CTLFLAG_RW, &ip4_ipsec_ecn, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG, - debug, CTLFLAG_RW, &ipsec_debug, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD, - esp_randpad, CTLFLAG_RW, &ip4_esp_randpad, 0, ""); - -#ifdef INET6 -struct ipsecstat ipsec6stat; -int ip6_esp_trans_deflev = IPSEC_LEVEL_USE; -int ip6_esp_net_deflev = IPSEC_LEVEL_USE; -int ip6_ah_trans_deflev = IPSEC_LEVEL_USE; -int ip6_ah_net_deflev = IPSEC_LEVEL_USE; -struct secpolicy ip6_def_policy; -int ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ -int ip6_esp_randpad = -1; - -/* net.inet6.ipsec6 */ -SYSCTL_STRUCT(_net_inet6_ipsec6, IPSECCTL_STATS, - stats, CTLFLAG_RD, &ipsec6stat, ipsecstat, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, - def_policy, CTLFLAG_RW, &ip6_def_policy.policy, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, - CTLFLAG_RW, &ip6_esp_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, - CTLFLAG_RW, &ip6_esp_net_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, - CTLFLAG_RW, &ip6_ah_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, - CTLFLAG_RW, &ip6_ah_net_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN, - ecn, CTLFLAG_RW, &ip6_ipsec_ecn, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG, - debug, CTLFLAG_RW, &ipsec_debug, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, - esp_randpad, CTLFLAG_RW, &ip6_esp_randpad, 0, ""); -#endif /* INET6 */ - -static int ipsec_setspidx_mbuf - (struct secpolicyindex *, u_int, u_int, struct mbuf *, int); -static int ipsec4_setspidx_inpcb (struct mbuf *, struct inpcb *); -#ifdef INET6 -static int ipsec6_setspidx_in6pcb (struct mbuf *, struct in6pcb *); -#endif -static int ipsec_setspidx (struct mbuf *, struct secpolicyindex *, int); -static void ipsec4_get_ulp (struct mbuf *, struct secpolicyindex *, int); -static int ipsec4_setspidx_ipaddr (struct mbuf *, struct secpolicyindex *); -#ifdef INET6 -static void ipsec6_get_ulp (struct mbuf *, struct secpolicyindex *, int); -static int ipsec6_setspidx_ipaddr (struct mbuf *, struct secpolicyindex *); -#endif -static struct inpcbpolicy *ipsec_newpcbpolicy (void); -static void ipsec_delpcbpolicy (struct inpcbpolicy *); -static struct secpolicy *ipsec_deepcopy_policy (struct secpolicy *); -static int ipsec_set_policy (struct secpolicy **, int, caddr_t, size_t, int); -static int ipsec_get_policy (struct secpolicy *, struct mbuf **); -static void vshiftl (unsigned char *, int, int); -static int ipsec_in_reject (struct secpolicy *, struct mbuf *); -static size_t ipsec_hdrsiz (struct secpolicy *); -#ifdef INET -static struct mbuf *ipsec4_splithdr (struct mbuf *); -#endif -#ifdef INET6 -static struct mbuf *ipsec6_splithdr (struct mbuf *); -#endif -#ifdef INET -static int ipsec4_encapsulate (struct mbuf *, struct secasvar *); -#endif -#ifdef INET6 -static int ipsec6_encapsulate (struct mbuf *, struct secasvar *); -#endif - -/* - * For OUTBOUND packet having a socket. Searching SPD for packet, - * and return a pointer to SP. - * OUT: NULL: no apropreate SP found, the following value is set to error. - * 0 : bypass - * EACCES : discard packet. - * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. - * others: a pointer to SP - * - * NOTE: IPv6 mapped adddress concern is implemented here. - */ -struct secpolicy * -ipsec4_getpolicybysock(struct mbuf *m, u_int dir, struct socket *so, int *error) -{ - struct inpcbpolicy *pcbsp = NULL; - struct secpolicy *currsp = NULL; /* policy on socket */ - struct secpolicy *kernsp = NULL; /* policy on kernel */ - - /* sanity check */ - if (m == NULL || so == NULL || error == NULL) - panic("ipsec4_getpolicybysock: NULL pointer was passed."); - - switch (so->so_proto->pr_domain->dom_family) { - case AF_INET: - /* set spidx in pcb */ - *error = ipsec4_setspidx_inpcb(m, so->so_pcb); - break; -#ifdef INET6 - case AF_INET6: - /* set spidx in pcb */ - *error = ipsec6_setspidx_in6pcb(m, so->so_pcb); - break; -#endif - default: - panic("ipsec4_getpolicybysock: unsupported address family"); - } - if (*error) - return NULL; - switch (so->so_proto->pr_domain->dom_family) { - case AF_INET: - pcbsp = sotoinpcb(so)->inp_sp; - break; -#ifdef INET6 - case AF_INET6: - pcbsp = sotoin6pcb(so)->in6p_sp; - break; -#endif - } - - /* sanity check */ - if (pcbsp == NULL) - panic("ipsec4_getpolicybysock: pcbsp is NULL."); - - switch (dir) { - case IPSEC_DIR_INBOUND: - currsp = pcbsp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - currsp = pcbsp->sp_out; - break; - default: - panic("ipsec4_getpolicybysock: illegal direction."); - } - - /* sanity check */ - if (currsp == NULL) - panic("ipsec4_getpolicybysock: currsp is NULL."); - - lwkt_gettoken(&key_token); - - /* when privilieged socket */ - if (pcbsp->priv) { - switch (currsp->policy) { - case IPSEC_POLICY_BYPASS: - currsp->refcnt++; - *error = 0; - lwkt_reltoken(&key_token); - return currsp; - - case IPSEC_POLICY_ENTRUST: - /* look for a policy in SPD */ - kernsp = key_allocsp(&currsp->spidx, dir); - - /* SP found */ - if (kernsp != NULL) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec4_getpolicybysock called " - "to allocate SP:%p\n", kernsp)); - *error = 0; - lwkt_reltoken(&key_token); - return kernsp; - } - - /* no SP found */ - if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD - && ip4_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, - "fixed system default policy: %d->%d\n", - ip4_def_policy.policy, IPSEC_POLICY_NONE)); - ip4_def_policy.policy = IPSEC_POLICY_NONE; - } - ip4_def_policy.refcnt++; - *error = 0; - lwkt_reltoken(&key_token); - return &ip4_def_policy; - - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; - *error = 0; - lwkt_reltoken(&key_token); - return currsp; - - default: - ipseclog((LOG_ERR, "ipsec4_getpolicybysock: " - "Invalid policy for PCB %d\n", currsp->policy)); - *error = EINVAL; - lwkt_reltoken(&key_token); - return NULL; - } - /* NOTREACHED */ - } - - /* when non-privilieged socket */ - /* look for a policy in SPD */ - kernsp = key_allocsp(&currsp->spidx, dir); - - /* SP found */ - if (kernsp != NULL) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec4_getpolicybysock called " - "to allocate SP:%p\n", kernsp)); - *error = 0; - lwkt_reltoken(&key_token); - return kernsp; - } - - /* no SP found */ - switch (currsp->policy) { - case IPSEC_POLICY_BYPASS: - ipseclog((LOG_ERR, "ipsec4_getpolicybysock: " - "Illegal policy for non-priviliged defined %d\n", - currsp->policy)); - *error = EINVAL; - lwkt_reltoken(&key_token); - return NULL; - - case IPSEC_POLICY_ENTRUST: - if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD - && ip4_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, - "fixed system default policy: %d->%d\n", - ip4_def_policy.policy, IPSEC_POLICY_NONE)); - ip4_def_policy.policy = IPSEC_POLICY_NONE; - } - ip4_def_policy.refcnt++; - *error = 0; - lwkt_reltoken(&key_token); - return &ip4_def_policy; - - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; - *error = 0; - lwkt_reltoken(&key_token); - return currsp; - - default: - ipseclog((LOG_ERR, "ipsec4_getpolicybysock: " - "Invalid policy for PCB %d\n", currsp->policy)); - *error = EINVAL; - lwkt_reltoken(&key_token); - return NULL; - } - /* NOTREACHED */ -} - -/* - * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet, - * and return a pointer to SP. - * OUT: positive: a pointer to the entry for security policy leaf matched. - * NULL: no apropreate SP found, the following value is set to error. - * 0 : bypass - * EACCES : discard packet. - * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. - */ -struct secpolicy * -ipsec4_getpolicybyaddr(struct mbuf *m, u_int dir, int flag, int *error) -{ - struct secpolicy *sp = NULL; - struct secpolicyindex spidx; - - /* sanity check */ - if (m == NULL || error == NULL) - panic("ipsec4_getpolicybyaddr: NULL pointer was passed."); - - bzero(&spidx, sizeof(spidx)); - - /* make an index to look for a policy */ - *error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET, m, - (flag & IP_FORWARDING) ? 0 : 1); - - if (*error != 0) - return NULL; - - lwkt_gettoken(&key_token); - sp = key_allocsp(&spidx, dir); - - /* SP found */ - if (sp != NULL) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec4_getpolicybyaddr called " - "to allocate SP:%p\n", sp)); - *error = 0; - lwkt_reltoken(&key_token); - return sp; - } - - /* no SP found */ - if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD && - ip4_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, "fixed system default policy:%d->%d\n", - ip4_def_policy.policy, IPSEC_POLICY_NONE)); - ip4_def_policy.policy = IPSEC_POLICY_NONE; - } - ip4_def_policy.refcnt++; - *error = 0; - lwkt_reltoken(&key_token); - return &ip4_def_policy; -} - -#ifdef INET6 -/* - * For OUTBOUND packet having a socket. Searching SPD for packet, - * and return a pointer to SP. - * OUT: NULL: no apropreate SP found, the following value is set to error. - * 0 : bypass - * EACCES : discard packet. - * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. - * others: a pointer to SP - */ -struct secpolicy * -ipsec6_getpolicybysock(struct mbuf *m, u_int dir, struct socket *so, int *error) -{ - struct inpcbpolicy *pcbsp = NULL; - struct secpolicy *currsp = NULL; /* policy on socket */ - struct secpolicy *kernsp = NULL; /* policy on kernel */ - - /* sanity check */ - if (m == NULL || so == NULL || error == NULL) - panic("ipsec6_getpolicybysock: NULL pointer was passed."); - -#ifdef DIAGNOSTIC - if (so->so_proto->pr_domain->dom_family != AF_INET6) - panic("ipsec6_getpolicybysock: socket domain != inet6"); -#endif - - lwkt_gettoken(&key_token); - - /* set spidx in pcb */ - ipsec6_setspidx_in6pcb(m, so->so_pcb); - pcbsp = sotoin6pcb(so)->in6p_sp; - - /* sanity check */ - if (pcbsp == NULL) - panic("ipsec6_getpolicybysock: pcbsp is NULL."); - - switch (dir) { - case IPSEC_DIR_INBOUND: - currsp = pcbsp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - currsp = pcbsp->sp_out; - break; - default: - panic("ipsec6_getpolicybysock: illegal direction."); - } - - /* sanity check */ - if (currsp == NULL) - panic("ipsec6_getpolicybysock: currsp is NULL."); - - /* when privilieged socket */ - if (pcbsp->priv) { - switch (currsp->policy) { - case IPSEC_POLICY_BYPASS: - currsp->refcnt++; - *error = 0; - break; - case IPSEC_POLICY_ENTRUST: - /* look for a policy in SPD */ - kernsp = key_allocsp(&currsp->spidx, dir); - - /* SP found */ - if (kernsp != NULL) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec6_getpolicybysock called " - "to allocate SP:%p\n", kernsp)); - *error = 0; - currsp = kernsp; - break; - } - - /* no SP found */ - if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD - && ip6_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, - "fixed system default policy: %d->%d\n", - ip6_def_policy.policy, IPSEC_POLICY_NONE)); - ip6_def_policy.policy = IPSEC_POLICY_NONE; - } - currsp = &ip6_def_policy; - currsp->refcnt++; - *error = 0; - break; - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; - *error = 0; - break; - default: - ipseclog((LOG_ERR, "ipsec6_getpolicybysock: " - "Invalid policy for PCB %d\n", currsp->policy)); - *error = EINVAL; - lwkt_reltoken(&key_token); - currsp = NULL; - break; - } - lwkt_reltoken(&key_token); - return currsp; - /* NOTREACHED */ - } - - /* when non-privilieged socket */ - /* look for a policy in SPD */ - kernsp = key_allocsp(&currsp->spidx, dir); - - /* SP found */ - if (kernsp != NULL) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec6_getpolicybysock called " - "to allocate SP:%p\n", kernsp)); - *error = 0; - lwkt_reltoken(&key_token); - return kernsp; - } - - /* no SP found */ - switch (currsp->policy) { - case IPSEC_POLICY_BYPASS: - ipseclog((LOG_ERR, "ipsec6_getpolicybysock: " - "Illegal policy for non-priviliged defined %d\n", - currsp->policy)); - *error = EINVAL; - currsp = NULL; - break; - case IPSEC_POLICY_ENTRUST: - if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD - && ip6_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, - "fixed system default policy: %d->%d\n", - ip6_def_policy.policy, IPSEC_POLICY_NONE)); - ip6_def_policy.policy = IPSEC_POLICY_NONE; - } - currsp = &ip6_def_policy; - currsp->refcnt++; - *error = 0; - break; - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; - *error = 0; - break; - default: - ipseclog((LOG_ERR, - "ipsec6_policybysock: Invalid policy for PCB %d\n", - currsp->policy)); - *error = EINVAL; - currsp = NULL; - break; - } - lwkt_reltoken(&key_token); - return currsp; -} - -/* - * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet, - * and return a pointer to SP. - * `flag' means that packet is to be forwarded whether or not. - * flag = 1: forwad - * OUT: positive: a pointer to the entry for security policy leaf matched. - * NULL: no apropreate SP found, the following value is set to error. - * 0 : bypass - * EACCES : discard packet. - * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. - */ -#ifndef IP_FORWARDING -#define IP_FORWARDING 1 -#endif - -struct secpolicy * -ipsec6_getpolicybyaddr(struct mbuf *m, u_int dir, int flag, int *error) -{ - struct secpolicy *sp = NULL; - struct secpolicyindex spidx; - - /* sanity check */ - if (m == NULL || error == NULL) - panic("ipsec6_getpolicybyaddr: NULL pointer was passed."); - bzero(&spidx, sizeof(spidx)); - - lwkt_gettoken(&key_token); - - /* make an index to look for a policy */ - *error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET6, m, - (flag & IP_FORWARDING) ? 0 : 1); - if (*error != 0) { - lwkt_reltoken(&key_token); - return NULL; - } - - sp = key_allocsp(&spidx, dir); - - /* SP found */ - if (sp != NULL) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec6_getpolicybyaddr called " - "to allocate SP:%p\n", sp)); - *error = 0; - lwkt_reltoken(&key_token); - return sp; - } - - /* no SP found */ - if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD - && ip6_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", - ip6_def_policy.policy, IPSEC_POLICY_NONE)); - ip6_def_policy.policy = IPSEC_POLICY_NONE; - } - sp = &ip6_def_policy; - sp->refcnt++; - *error = 0; - lwkt_reltoken(&key_token); - - return sp; -} -#endif /* INET6 */ - -/* - * set IP address into spidx from mbuf. - * When Forwarding packet and ICMP echo reply, this function is used. - * - * IN: get the followings from mbuf. - * protocol family, src, dst, next protocol - * OUT: - * 0: success. - * other: failure, and set errno. - */ -static int -ipsec_setspidx_mbuf(struct secpolicyindex *spidx, u_int dir, u_int family, - struct mbuf *m, int needport) -{ - int error; - - /* sanity check */ - if (spidx == NULL || m == NULL) - panic("ipsec_setspidx_mbuf: NULL pointer was passed."); - - bzero(spidx, sizeof(*spidx)); - - error = ipsec_setspidx(m, spidx, needport); - if (error) - goto bad; - spidx->dir = dir; - - return 0; - -bad: - /* XXX initialize */ - bzero(spidx, sizeof(*spidx)); - return EINVAL; -} - -static int -ipsec4_setspidx_inpcb(struct mbuf *m, struct inpcb *pcb) -{ - struct secpolicyindex *spidx; - int error; - - /* sanity check */ - if (pcb == NULL) - panic("ipsec4_setspidx_inpcb: no PCB found."); - if (pcb->inp_sp == NULL) - panic("ipsec4_setspidx_inpcb: no inp_sp found."); - if (pcb->inp_sp->sp_out == NULL || pcb->inp_sp->sp_in == NULL) - panic("ipsec4_setspidx_inpcb: no sp_in/out found."); - - bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx)); - bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx)); - - spidx = &pcb->inp_sp->sp_in->spidx; - error = ipsec_setspidx(m, spidx, 1); - if (error) - goto bad; - spidx->dir = IPSEC_DIR_INBOUND; - - spidx = &pcb->inp_sp->sp_out->spidx; - error = ipsec_setspidx(m, spidx, 1); - if (error) - goto bad; - spidx->dir = IPSEC_DIR_OUTBOUND; - - return 0; - -bad: - bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx)); - bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx)); - return error; -} - -#ifdef INET6 -static int -ipsec6_setspidx_in6pcb(struct mbuf *m, struct in6pcb *pcb) -{ - struct secpolicyindex *spidx; - int error; - - /* sanity check */ - if (pcb == NULL) - panic("ipsec6_setspidx_in6pcb: no PCB found."); - if (pcb->in6p_sp == NULL) - panic("ipsec6_setspidx_in6pcb: no in6p_sp found."); - if (pcb->in6p_sp->sp_out == NULL || pcb->in6p_sp->sp_in == NULL) - panic("ipsec6_setspidx_in6pcb: no sp_in/out found."); - - bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx)); - bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx)); - - spidx = &pcb->in6p_sp->sp_in->spidx; - error = ipsec_setspidx(m, spidx, 1); - if (error) - goto bad; - spidx->dir = IPSEC_DIR_INBOUND; - - spidx = &pcb->in6p_sp->sp_out->spidx; - error = ipsec_setspidx(m, spidx, 1); - if (error) - goto bad; - spidx->dir = IPSEC_DIR_OUTBOUND; - - return 0; - -bad: - bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx)); - bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx)); - return error; -} -#endif - -/* - * configure security policy index (src/dst/proto/sport/dport) - * by looking at the content of mbuf. - * the caller is responsible for error recovery (like clearing up spidx). - */ -static int -ipsec_setspidx(struct mbuf *m, struct secpolicyindex *spidx, int needport) -{ - struct ip *ip = NULL; - struct ip ipbuf; - u_int v; - struct mbuf *n; - int len; - int error; - - if (m == NULL) - panic("ipsec_setspidx: m == 0 passed."); - - /* - * validate m->m_pkthdr.len. we see incorrect length if we - * mistakenly call this function with inconsistent mbuf chain - * (like 4.4BSD tcp/udp processing). XXX should we panic here? - */ - len = 0; - for (n = m; n; n = n->m_next) - len += n->m_len; - if (m->m_pkthdr.len != len) { - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_setspidx: " - "total of m_len(%d) != pkthdr.len(%d), " - "ignored.\n", - len, m->m_pkthdr.len)); - return EINVAL; - } - - if (m->m_pkthdr.len < sizeof(struct ip)) { - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_setspidx: " - "pkthdr.len(%d) < sizeof(struct ip), ignored.\n", - m->m_pkthdr.len)); - return EINVAL; - } - - if (m->m_len >= sizeof(*ip)) - ip = mtod(m, struct ip *); - else { - m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf); - ip = &ipbuf; - } -#ifdef _IP_VHL - v = _IP_VHL_V(ip->ip_vhl); -#else - v = ip->ip_v; -#endif - switch (v) { - case 4: - error = ipsec4_setspidx_ipaddr(m, spidx); - if (error) - return error; - ipsec4_get_ulp(m, spidx, needport); - return 0; -#ifdef INET6 - case 6: - if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) { - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_setspidx: " - "pkthdr.len(%d) < sizeof(struct ip6_hdr), " - "ignored.\n", m->m_pkthdr.len)); - return EINVAL; - } - error = ipsec6_setspidx_ipaddr(m, spidx); - if (error) - return error; - ipsec6_get_ulp(m, spidx, needport); - return 0; -#endif - default: - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_setspidx: " - "unknown IP version %u, ignored.\n", v)); - return EINVAL; - } -} - -static void -ipsec4_get_ulp(struct mbuf *m, struct secpolicyindex *spidx, int needport) -{ - struct ip ip; - struct ip6_ext ip6e; - u_int8_t nxt; - int off; - struct tcphdr th; - struct udphdr uh; - - /* sanity check */ - if (m == NULL) - panic("ipsec4_get_ulp: NULL pointer was passed."); - if (m->m_pkthdr.len < sizeof(ip)) - panic("ipsec4_get_ulp: too short"); - - /* set default */ - spidx->ul_proto = IPSEC_ULPROTO_ANY; - ((struct sockaddr_in *)&spidx->src)->sin_port = IPSEC_PORT_ANY; - ((struct sockaddr_in *)&spidx->dst)->sin_port = IPSEC_PORT_ANY; - - m_copydata(m, 0, sizeof(ip), (caddr_t)&ip); - /* ip_input() flips it into host endian XXX need more checking */ - if (ip.ip_off & (IP_MF | IP_OFFMASK)) - return; - - nxt = ip.ip_p; -#ifdef _IP_VHL - off = _IP_VHL_HL(ip->ip_vhl) << 2; -#else - off = ip.ip_hl << 2; -#endif - while (off < m->m_pkthdr.len) { - switch (nxt) { - case IPPROTO_TCP: - spidx->ul_proto = nxt; - if (!needport) - return; - if (off + sizeof(struct tcphdr) > m->m_pkthdr.len) - return; - m_copydata(m, off, sizeof(th), (caddr_t)&th); - ((struct sockaddr_in *)&spidx->src)->sin_port = - th.th_sport; - ((struct sockaddr_in *)&spidx->dst)->sin_port = - th.th_dport; - return; - case IPPROTO_UDP: - spidx->ul_proto = nxt; - if (!needport) - return; - if (off + sizeof(struct udphdr) > m->m_pkthdr.len) - return; - m_copydata(m, off, sizeof(uh), (caddr_t)&uh); - ((struct sockaddr_in *)&spidx->src)->sin_port = - uh.uh_sport; - ((struct sockaddr_in *)&spidx->dst)->sin_port = - uh.uh_dport; - return; - case IPPROTO_AH: - if (off + sizeof(ip6e) > m->m_pkthdr.len) - return; - m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e); - off += (ip6e.ip6e_len + 2) << 2; - nxt = ip6e.ip6e_nxt; - break; - case IPPROTO_ICMP: - default: - /* XXX intermediate headers??? */ - spidx->ul_proto = nxt; - return; - } - } -} - -/* assumes that m is sane */ -static int -ipsec4_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx) -{ - struct ip *ip = NULL; - struct ip ipbuf; - struct sockaddr_in *sin; - - if (m->m_len >= sizeof(*ip)) - ip = mtod(m, struct ip *); - else { - m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf); - ip = &ipbuf; - } - - sin = (struct sockaddr_in *)&spidx->src; - bzero(sin, sizeof(*sin)); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(struct sockaddr_in); - bcopy(&ip->ip_src, &sin->sin_addr, sizeof(ip->ip_src)); - spidx->prefs = sizeof(struct in_addr) << 3; - - sin = (struct sockaddr_in *)&spidx->dst; - bzero(sin, sizeof(*sin)); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(struct sockaddr_in); - bcopy(&ip->ip_dst, &sin->sin_addr, sizeof(ip->ip_dst)); - spidx->prefd = sizeof(struct in_addr) << 3; - return 0; -} - -#ifdef INET6 -static void -ipsec6_get_ulp(struct mbuf *m, struct secpolicyindex *spidx, int needport) -{ - int off, nxt; - struct tcphdr th; - struct udphdr uh; - - /* sanity check */ - if (m == NULL) - panic("ipsec6_get_ulp: NULL pointer was passed."); - - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec6_get_ulp:\n"); kdebug_mbuf(m)); - - /* set default */ - spidx->ul_proto = IPSEC_ULPROTO_ANY; - ((struct sockaddr_in6 *)&spidx->src)->sin6_port = IPSEC_PORT_ANY; - ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = IPSEC_PORT_ANY; - - 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); - ((struct sockaddr_in6 *)&spidx->src)->sin6_port = th.th_sport; - ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = th.th_dport; - 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); - ((struct sockaddr_in6 *)&spidx->src)->sin6_port = uh.uh_sport; - ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = uh.uh_dport; - break; - case IPPROTO_ICMPV6: - default: - /* XXX intermediate headers??? */ - spidx->ul_proto = nxt; - break; - } -} - -/* assumes that m is sane */ -static int -ipsec6_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx) -{ - struct ip6_hdr *ip6 = NULL; - struct ip6_hdr ip6buf; - struct sockaddr_in6 *sin6; - - if (m->m_len >= sizeof(*ip6)) - ip6 = mtod(m, struct ip6_hdr *); - else { - m_copydata(m, 0, sizeof(ip6buf), (caddr_t)&ip6buf); - ip6 = &ip6buf; - } - - sin6 = (struct sockaddr_in6 *)&spidx->src; - bzero(sin6, sizeof(*sin6)); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(struct sockaddr_in6); - bcopy(&ip6->ip6_src, &sin6->sin6_addr, sizeof(ip6->ip6_src)); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]); - } - spidx->prefs = sizeof(struct in6_addr) << 3; - - sin6 = (struct sockaddr_in6 *)&spidx->dst; - bzero(sin6, sizeof(*sin6)); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(struct sockaddr_in6); - bcopy(&ip6->ip6_dst, &sin6->sin6_addr, sizeof(ip6->ip6_dst)); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]); - } - spidx->prefd = sizeof(struct in6_addr) << 3; - - return 0; -} -#endif - -static struct inpcbpolicy * -ipsec_newpcbpolicy(void) -{ - struct inpcbpolicy *p; - - p = (struct inpcbpolicy *)kmalloc(sizeof(*p), M_SECA, M_NOWAIT); - return p; -} - -static void -ipsec_delpcbpolicy(struct inpcbpolicy *p) -{ - kfree(p, M_SECA); -} - -/* initialize policy in PCB */ -int -ipsec_init_policy(struct socket *so, struct inpcbpolicy **pcb_sp) -{ - struct inpcbpolicy *new; - - /* sanity check. */ - if (so == NULL || pcb_sp == NULL) - panic("ipsec_init_policy: NULL pointer was passed."); - - lwkt_gettoken(&key_token); - - new = ipsec_newpcbpolicy(); - if (new == NULL) { - ipseclog((LOG_DEBUG, "ipsec_init_policy: No more memory.\n")); - lwkt_reltoken(&key_token); - return ENOBUFS; - } - bzero(new, sizeof(*new)); - - if (so->so_cred != NULL && so->so_cred->cr_uid == 0) - new->priv = 1; - else - new->priv = 0; - - if ((new->sp_in = key_newsp()) == NULL) { - ipsec_delpcbpolicy(new); - lwkt_reltoken(&key_token); - return ENOBUFS; - } - new->sp_in->state = IPSEC_SPSTATE_ALIVE; - new->sp_in->policy = IPSEC_POLICY_ENTRUST; - - if ((new->sp_out = key_newsp()) == NULL) { - key_freesp(new->sp_in); - ipsec_delpcbpolicy(new); - lwkt_reltoken(&key_token); - return ENOBUFS; - } - new->sp_out->state = IPSEC_SPSTATE_ALIVE; - new->sp_out->policy = IPSEC_POLICY_ENTRUST; - - *pcb_sp = new; - lwkt_reltoken(&key_token); - - return 0; -} - -/* copy old ipsec policy into new */ -int -ipsec_copy_policy(struct inpcbpolicy *old, struct inpcbpolicy *new) -{ - struct secpolicy *sp; - - lwkt_gettoken(&key_token); - sp = ipsec_deepcopy_policy(old->sp_in); - if (sp) { - key_freesp(new->sp_in); - new->sp_in = sp; - } else { - lwkt_reltoken(&key_token); - return ENOBUFS; - } - - sp = ipsec_deepcopy_policy(old->sp_out); - if (sp) { - key_freesp(new->sp_out); - new->sp_out = sp; - } else { - lwkt_reltoken(&key_token); - return ENOBUFS; - } - - new->priv = old->priv; - lwkt_reltoken(&key_token); - - return 0; -} - -/* deep-copy a policy in PCB */ -static struct secpolicy * -ipsec_deepcopy_policy(struct secpolicy *src) -{ - struct ipsecrequest *newchain = NULL; - struct ipsecrequest *p; - struct ipsecrequest **q; - struct ipsecrequest *r; - struct secpolicy *dst; - - lwkt_gettoken(&key_token); - dst = key_newsp(); - if (src == NULL || dst == NULL) { - lwkt_reltoken(&key_token); - return NULL; - } - - /* - * deep-copy IPsec request chain. This is required since struct - * ipsecrequest is not reference counted. - */ - q = &newchain; - for (p = src->req; p; p = p->next) { - *q = (struct ipsecrequest *)kmalloc(sizeof(struct ipsecrequest), - M_SECA, M_NOWAIT | M_ZERO); - if (*q == NULL) - goto fail; - (*q)->next = NULL; - - (*q)->saidx.proto = p->saidx.proto; - (*q)->saidx.mode = p->saidx.mode; - (*q)->level = p->level; - (*q)->saidx.reqid = p->saidx.reqid; - - bcopy(&p->saidx.src, &(*q)->saidx.src, sizeof((*q)->saidx.src)); - bcopy(&p->saidx.dst, &(*q)->saidx.dst, sizeof((*q)->saidx.dst)); - - (*q)->sav = NULL; - (*q)->sp = dst; - - q = &((*q)->next); - } - - dst->req = newchain; - dst->state = src->state; - dst->policy = src->policy; - /* do not touch the refcnt fields */ - lwkt_reltoken(&key_token); - - return dst; - -fail: - lwkt_reltoken(&key_token); - for (p = newchain; p; p = r) { - r = p->next; - kfree(p, M_SECA); - p = NULL; - } - return NULL; -} - -/* set policy and ipsec request if present. */ -static int -ipsec_set_policy(struct secpolicy **pcb_sp, int optname, caddr_t request, - size_t len, int priv) -{ - struct sadb_x_policy *xpl; - struct secpolicy *newsp = NULL; - int error; - - /* sanity check. */ - if (pcb_sp == NULL || *pcb_sp == NULL || request == NULL) - return EINVAL; - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_set_policy: passed policy\n"); - kdebug_sadb_x_policy((struct sadb_ext *)xpl)); - - /* check policy type */ - /* ipsec_set_policy() accepts IPSEC, ENTRUST and BYPASS. */ - if (xpl->sadb_x_policy_type == IPSEC_POLICY_DISCARD || - xpl->sadb_x_policy_type == IPSEC_POLICY_NONE) - return EINVAL; - - /* check privileged socket */ - if (priv == 0 && xpl->sadb_x_policy_type == IPSEC_POLICY_BYPASS) - return EACCES; - - /* allocation new SP entry */ - if ((newsp = key_msg2sp(xpl, len, &error)) == NULL) - return error; - - newsp->state = IPSEC_SPSTATE_ALIVE; - - /* clear old SP and set new SP */ - key_freesp(*pcb_sp); - *pcb_sp = newsp; - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_set_policy: new policy\n"); - kdebug_secpolicy(newsp)); - - return 0; -} - -static int -ipsec_get_policy(struct secpolicy *pcb_sp, struct mbuf **mp) -{ - - /* sanity check. */ - if (pcb_sp == NULL || mp == NULL) - return EINVAL; - - *mp = key_sp2msg(pcb_sp); - if (!*mp) { - ipseclog((LOG_DEBUG, "ipsec_get_policy: No more memory.\n")); - return ENOBUFS; - } - - KKASSERT((*mp)->m_type == MT_DATA); - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_get_policy:\n"); - kdebug_mbuf(*mp)); - - return 0; -} - -int -ipsec4_set_policy(struct inpcb *inp, int optname, caddr_t request, size_t len, - int priv) -{ - struct sadb_x_policy *xpl; - struct secpolicy **pcb_sp; - int error; - - /* sanity check. */ - if (inp == NULL || request == NULL) - return EINVAL; - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - lwkt_gettoken(&key_token); - /* select direction */ - switch (xpl->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - pcb_sp = &inp->inp_sp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - pcb_sp = &inp->inp_sp->sp_out; - break; - default: - ipseclog((LOG_ERR, "ipsec4_set_policy: invalid direction=%u\n", - xpl->sadb_x_policy_dir)); - lwkt_reltoken(&key_token); - return EINVAL; - } - error = ipsec_set_policy(pcb_sp, optname, request, len, priv); - lwkt_reltoken(&key_token); - return error; -} - -int -ipsec4_get_policy(struct inpcb *inp, caddr_t request, size_t len, - struct mbuf **mp) -{ - struct sadb_x_policy *xpl; - struct secpolicy *pcb_sp; - int error; - - /* sanity check. */ - if (inp == NULL || request == NULL || mp == NULL) - return EINVAL; - if (inp->inp_sp == NULL) - panic("policy in PCB is NULL"); - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - lwkt_gettoken(&key_token); - - /* select direction */ - switch (xpl->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - pcb_sp = inp->inp_sp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - pcb_sp = inp->inp_sp->sp_out; - break; - default: - ipseclog((LOG_ERR, "ipsec4_get_policy: invalid direction=%u\n", - xpl->sadb_x_policy_dir)); - lwkt_reltoken(&key_token); - return EINVAL; - } - error = ipsec_get_policy(pcb_sp, mp); - lwkt_reltoken(&key_token); - return error; -} - -/* delete policy in PCB */ -int -ipsec4_delete_pcbpolicy(struct inpcb *inp) -{ - struct inpcbpolicy *isp; - - /* sanity check. */ - if (inp == NULL) - panic("ipsec4_delete_pcbpolicy: NULL pointer was passed."); - - lwkt_gettoken(&key_token); - - if ((isp = inp->inp_sp) == NULL) { - lwkt_reltoken(&key_token); - return 0; - } - - if (isp->sp_in != NULL) { - key_freesp(isp->sp_in); - isp->sp_in = NULL; - } - - if (isp->sp_out != NULL) { - key_freesp(isp->sp_out); - isp->sp_out = NULL; - } - KKASSERT(inp->inp_sp == isp); - inp->inp_sp = NULL; - ipsec_delpcbpolicy(isp); - lwkt_reltoken(&key_token); - - return 0; -} - -#ifdef INET6 -int -ipsec6_set_policy(struct in6pcb *in6p, int optname, caddr_t request, size_t len, - int priv) -{ - struct sadb_x_policy *xpl; - struct secpolicy **pcb_sp; - int error; - - /* sanity check. */ - if (in6p == NULL || request == NULL) - return EINVAL; - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - lwkt_gettoken(&key_token); - - /* select direction */ - switch (xpl->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - pcb_sp = &in6p->in6p_sp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - pcb_sp = &in6p->in6p_sp->sp_out; - break; - default: - ipseclog((LOG_ERR, "ipsec6_set_policy: invalid direction=%u\n", - xpl->sadb_x_policy_dir)); - lwkt_reltoken(&key_token); - return EINVAL; - } - - error = ipsec_set_policy(pcb_sp, optname, request, len, priv); - lwkt_reltoken(&key_token); - return error; -} - -int -ipsec6_get_policy(struct in6pcb *in6p, caddr_t request, size_t len, - struct mbuf **mp) -{ - struct sadb_x_policy *xpl; - struct secpolicy *pcb_sp; - int error; - - /* sanity check. */ - if (in6p == NULL || request == NULL || mp == NULL) - return EINVAL; - if (in6p->in6p_sp == NULL) - panic("policy in PCB is NULL"); - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - lwkt_gettoken(&key_token); - - /* select direction */ - switch (xpl->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - pcb_sp = in6p->in6p_sp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - pcb_sp = in6p->in6p_sp->sp_out; - break; - default: - ipseclog((LOG_ERR, "ipsec6_get_policy: invalid direction=%u\n", - xpl->sadb_x_policy_dir)); - lwkt_reltoken(&key_token); - return EINVAL; - } - - error = ipsec_get_policy(pcb_sp, mp); - lwkt_reltoken(&key_token); - return error; -} - -int -ipsec6_delete_pcbpolicy(struct in6pcb *in6p) -{ - struct inpcbpolicy *isp; - - /* sanity check. */ - if (in6p == NULL) - panic("ipsec6_delete_pcbpolicy: NULL pointer was passed."); - - lwkt_gettoken(&key_token); - - if ((isp = in6p->in6p_sp) == NULL) { - lwkt_reltoken(&key_token); - return 0; - } - - if (isp->sp_in != NULL) { - key_freesp(isp->sp_in); - isp->sp_in = NULL; - } - - if (isp->sp_out != NULL) { - key_freesp(isp->sp_out); - isp->sp_out = NULL; - } - KKASSERT(in6p->in6p_sp == isp); - in6p->in6p_sp = NULL; - ipsec_delpcbpolicy(isp); - lwkt_reltoken(&key_token); - - return 0; -} -#endif - -/* - * return current level. - * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned. - */ -u_int -ipsec_get_reqlevel(struct ipsecrequest *isr) -{ - u_int level = 0; - u_int esp_trans_deflev, esp_net_deflev, ah_trans_deflev, ah_net_deflev; - - /* sanity check */ - if (isr == NULL || isr->sp == NULL) - panic("ipsec_get_reqlevel: NULL pointer is passed."); - if (((struct sockaddr *)&isr->sp->spidx.src)->sa_family - != ((struct sockaddr *)&isr->sp->spidx.dst)->sa_family) - panic("ipsec_get_reqlevel: family mismatched."); - -/* XXX note that we have ipseclog() expanded here - code sync issue */ -#define IPSEC_CHECK_DEFAULT(lev) \ - (((lev) != IPSEC_LEVEL_USE && (lev) != IPSEC_LEVEL_REQUIRE \ - && (lev) != IPSEC_LEVEL_UNIQUE) \ - ? (ipsec_debug \ - ? log(LOG_INFO, "fixed system default level " #lev ":%d->%d\n",\ - (lev), IPSEC_LEVEL_REQUIRE) \ - : 0), \ - (lev) = IPSEC_LEVEL_REQUIRE, \ - (lev) \ - : (lev)) - - /* set default level */ - switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) { -#ifdef INET - case AF_INET: - esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev); - esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev); - ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev); - ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev); - break; -#endif -#ifdef INET6 - case AF_INET6: - esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev); - esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev); - ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev); - ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev); - break; -#endif /* INET6 */ - default: - panic("key_get_reqlevel: Unknown family. %d", - ((struct sockaddr *)&isr->sp->spidx.src)->sa_family); - } - -#undef IPSEC_CHECK_DEFAULT - - /* set level */ - 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; - case IPPROTO_IPCOMP: - /* - * we don't really care, as IPcomp document says that - * we shouldn't compress small packets - */ - level = IPSEC_LEVEL_USE; - break; - default: - panic("ipsec_get_reqlevel: " - "Illegal protocol defined %u", - 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: - panic("ipsec_get_reqlevel: Illegal IPsec level %u", - isr->level); - } - - return level; -} - -/* - * Check AH/ESP integrity. - * OUT: - * 0: valid - * 1: invalid - */ -static int -ipsec_in_reject(struct secpolicy *sp, struct mbuf *m) -{ - struct ipsecrequest *isr; - u_int level; - int need_auth, need_conf, need_icv; - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec_in_reject: using SP\n"); - kdebug_secpolicy(sp)); - - /* check policy */ - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - return 1; - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_NONE: - return 0; - - case IPSEC_POLICY_IPSEC: - break; - - case IPSEC_POLICY_ENTRUST: - default: - panic("ipsec_hdrsiz: Invalid policy found. %d", sp->policy); - } - - need_auth = 0; - need_conf = 0; - need_icv = 0; - - /* XXX should compare policy against ipsec header history */ - - for (isr = sp->req; isr != NULL; isr = isr->next) { - /* get current level */ - level = ipsec_get_reqlevel(isr); - - switch (isr->saidx.proto) { - case IPPROTO_ESP: - if (level == IPSEC_LEVEL_REQUIRE) { - need_conf++; - - if (isr->sav != NULL - && isr->sav->flags == SADB_X_EXT_NONE - && isr->sav->alg_auth != SADB_AALG_NONE) - need_icv++; - } - break; - case IPPROTO_AH: - if (level == IPSEC_LEVEL_REQUIRE) { - need_auth++; - need_icv++; - } - break; - case IPPROTO_IPCOMP: - /* - * we don't really care, as IPcomp document says that - * we shouldn't compress small packets, IPComp policy - * should always be treated as being in "use" level. - */ - break; - } - } - - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_in_reject: auth:%d conf:%d icv:%d m_flags:%x\n", - need_auth, need_conf, need_icv, m->m_flags)); - - if ((need_conf && !(m->m_flags & M_DECRYPTED)) - || (!need_auth && need_icv && !(m->m_flags & M_AUTHIPDGM)) - || (need_auth && !(m->m_flags & M_AUTHIPHDR))) - return 1; - - return 0; -} - -/* - * Check AH/ESP integrity. - * This function is called from tcp_input(), udp_input(), - * and {ah,esp}4_input for tunnel mode - */ -int -ipsec4_in_reject_so(struct mbuf *m, struct socket *so) -{ - struct secpolicy *sp = NULL; - int error; - int result; - - /* sanity check */ - if (m == NULL) - return 0; /* XXX should be panic ? */ - - /* get SP for this packet. - * When we are called from ip_forward(), we call - * ipsec4_getpolicybyaddr() with IP_FORWARDING flag. - */ - lwkt_gettoken(&key_token); - if (so == NULL) { - sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } else { - sp = ipsec4_getpolicybysock(m, IPSEC_DIR_INBOUND, so, &error); - } - - /* XXX should be panic ? -> No, there may be error. */ - if (sp == NULL) { - lwkt_reltoken(&key_token); - return 0; - } - - result = ipsec_in_reject(sp, m); - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec4_in_reject_so call free SP:%p\n", sp)); - key_freesp(sp); - lwkt_reltoken(&key_token); - - return result; -} - -int -ipsec4_in_reject(struct mbuf *m, struct inpcb *inp) -{ - if (inp == NULL) - return ipsec4_in_reject_so(m, NULL); - if (inp->inp_socket) - return ipsec4_in_reject_so(m, inp->inp_socket); - else - panic("ipsec4_in_reject: invalid inpcb/socket"); -} - -#ifdef INET6 -/* - * Check AH/ESP integrity. - * This function is called from tcp6_input(), udp6_input(), - * and {ah,esp}6_input for tunnel mode - */ -int -ipsec6_in_reject_so(struct mbuf *m, struct socket *so) -{ - struct secpolicy *sp = NULL; - int error; - int result; - - /* sanity check */ - if (m == NULL) - return 0; /* XXX should be panic ? */ - - /* get SP for this packet. - * When we are called from ip_forward(), we call - * ipsec6_getpolicybyaddr() with IP_FORWARDING flag. - */ - lwkt_gettoken(&key_token); - if (so == NULL) { - sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } else { - sp = ipsec6_getpolicybysock(m, IPSEC_DIR_INBOUND, so, &error); - } - - if (sp == NULL) { - lwkt_reltoken(&key_token); - return 0; /* XXX should be panic ? */ - } - - result = ipsec_in_reject(sp, m); - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec6_in_reject_so call free SP:%p\n", sp)); - key_freesp(sp); - lwkt_reltoken(&key_token); - - return result; -} - -int -ipsec6_in_reject(struct mbuf *m, struct in6pcb *in6p) -{ - if (in6p == NULL) - return ipsec6_in_reject_so(m, NULL); - if (in6p->in6p_socket) - return ipsec6_in_reject_so(m, in6p->in6p_socket); - else - panic("ipsec6_in_reject: invalid in6p/socket"); -} -#endif - -/* - * compute the byte size to be occupied by IPsec header. - * in case it is tunneled, it includes the size of outer IP header. - * NOTE: SP passed is free in this function. - */ -static size_t -ipsec_hdrsiz(struct secpolicy *sp) -{ - struct ipsecrequest *isr; - size_t siz, clen; - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec_hdrsiz: using SP\n"); - kdebug_secpolicy(sp)); - - /* check policy */ - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_NONE: - return 0; - - case IPSEC_POLICY_IPSEC: - break; - - case IPSEC_POLICY_ENTRUST: - default: - panic("ipsec_hdrsiz: Invalid policy found. %d", sp->policy); - } - - siz = 0; - - for (isr = sp->req; isr != NULL; isr = isr->next) { - - clen = 0; - - switch (isr->saidx.proto) { - case IPPROTO_ESP: -#ifdef IPSEC_ESP - clen = esp_hdrsiz(isr); -#else - clen = 0; /* XXX */ -#endif - break; - case IPPROTO_AH: - clen = ah_hdrsiz(isr); - break; - case IPPROTO_IPCOMP: - clen = sizeof(struct ipcomp); - break; - } - - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { - switch (((struct sockaddr *)&isr->saidx.dst)->sa_family) { - case AF_INET: - clen += sizeof(struct ip); - break; -#ifdef INET6 - case AF_INET6: - clen += sizeof(struct ip6_hdr); - break; -#endif - default: - ipseclog((LOG_ERR, "ipsec_hdrsiz: " - "unknown AF %d in IPsec tunnel SA\n", - ((struct sockaddr *)&isr->saidx.dst)->sa_family)); - break; - } - } - siz += clen; - } - - return siz; -} - -/* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */ -size_t -ipsec4_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp) -{ - struct secpolicy *sp = NULL; - int error; - size_t size; - - /* sanity check */ - if (m == NULL) - return 0; /* XXX should be panic ? */ - if (inp != NULL && inp->inp_socket == NULL) - panic("ipsec4_hdrsize: why is socket NULL but there is PCB."); - - /* get SP for this packet. - * When we are called from ip_forward(), we call - * ipsec4_getpolicybyaddr() with IP_FORWARDING flag. - */ - lwkt_gettoken(&key_token); - if (inp == NULL) - sp = ipsec4_getpolicybyaddr(m, dir, IP_FORWARDING, &error); - else - sp = ipsec4_getpolicybysock(m, dir, inp->inp_socket, &error); - - if (sp == NULL) { - lwkt_reltoken(&key_token); - return 0; /* XXX should be panic ? */ - } - - size = ipsec_hdrsiz(sp); - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec4_hdrsiz call free SP:%p\n", sp)); - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec4_hdrsiz: size:%lu.\n", (unsigned long)size)); - key_freesp(sp); - lwkt_reltoken(&key_token); - - return size; -} - -#ifdef INET6 -/* This function is called from ipsec6_hdrsize_tcp(), - * and maybe from ip6_forward.() - */ -size_t -ipsec6_hdrsiz(struct mbuf *m, u_int dir, struct in6pcb *in6p) -{ - struct secpolicy *sp = NULL; - int error; - size_t size; - - /* sanity check */ - if (m == NULL) - return 0; /* XXX shoud be panic ? */ - if (in6p != NULL && in6p->in6p_socket == NULL) - panic("ipsec6_hdrsize: why is socket NULL but there is PCB."); - - /* get SP for this packet */ - /* XXX Is it right to call with IP_FORWARDING. */ - lwkt_gettoken(&key_token); - if (in6p == NULL) - sp = ipsec6_getpolicybyaddr(m, dir, IP_FORWARDING, &error); - else - sp = ipsec6_getpolicybysock(m, dir, in6p->in6p_socket, &error); - - if (sp == NULL) { - lwkt_reltoken(&key_token); - return 0; - } - size = ipsec_hdrsiz(sp); - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec6_hdrsiz call free SP:%p\n", sp)); - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec6_hdrsiz: size:%lu.\n", (unsigned long)size)); - key_freesp(sp); - lwkt_reltoken(&key_token); - - return size; -} -#endif /* INET6 */ - -#ifdef INET -/* - * encapsulate for ipsec tunnel. - * ip->ip_src must be fixed later on. - */ -static int -ipsec4_encapsulate(struct mbuf *m, struct secasvar *sav) -{ - struct ip *oip; - struct ip *ip; - size_t hlen; - size_t plen; - - /* can't tunnel between different AFs */ - if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family - != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family - || ((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET) { - m_freem(m); - return EINVAL; - } -#if 0 - /* XXX if the dst is myself, perform nothing. */ - if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) { - m_freem(m); - return EINVAL; - } -#endif - - if (m->m_len < sizeof(*ip)) - panic("ipsec4_encapsulate: assumption failed (first mbuf length)"); - - ip = mtod(m, struct ip *); -#ifdef _IP_VHL - hlen = _IP_VHL_HL(ip->ip_vhl) << 2; -#else - hlen = ip->ip_hl << 2; -#endif - - if (m->m_len != hlen) - panic("ipsec4_encapsulate: assumption failed (first mbuf length)"); - - /* generate header checksum */ - ip->ip_sum = 0; -#ifdef _IP_VHL - if (ip->ip_vhl == IP_VHL_BORING) - ip->ip_sum = in_cksum_hdr(ip); - else - ip->ip_sum = in_cksum(m, hlen); -#else - ip->ip_sum = in_cksum(m, hlen); -#endif - - plen = m->m_pkthdr.len; - - /* - * grow the mbuf to accomodate the new IPv4 header. - * NOTE: IPv4 options will never be copied. - */ - if (M_LEADINGSPACE(m->m_next) < hlen) { - struct mbuf *n; - MGET(n, M_NOWAIT, MT_DATA); - if (!n) { - m_freem(m); - return ENOBUFS; - } - n->m_len = hlen; - n->m_next = m->m_next; - m->m_next = n; - m->m_pkthdr.len += hlen; - oip = mtod(n, struct ip *); - } else { - m->m_next->m_len += hlen; - m->m_next->m_data -= hlen; - m->m_pkthdr.len += hlen; - oip = mtod(m->m_next, struct ip *); - } - ip = mtod(m, struct ip *); - bcopy((caddr_t)ip, (caddr_t)oip, hlen); - m->m_len = sizeof(struct ip); - m->m_pkthdr.len -= (hlen - sizeof(struct ip)); - - /* construct new IPv4 header. see RFC 2401 5.1.2.1 */ - /* ECN consideration. */ - ip_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos); -#ifdef _IP_VHL - ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2); -#else - ip->ip_hl = sizeof(struct ip) >> 2; -#endif - ip->ip_off &= htons(~IP_OFFMASK); - ip->ip_off &= htons(~IP_MF); - switch (ip4_ipsec_dfbit) { - case 0: /* clear DF bit */ - ip->ip_off &= htons(~IP_DF); - break; - case 1: /* set DF bit */ - ip->ip_off |= htons(IP_DF); - break; - default: /* copy DF bit */ - break; - } - ip->ip_p = IPPROTO_IPIP; - if (plen + sizeof(struct ip) < IP_MAXPACKET) - ip->ip_len = htons(plen + sizeof(struct ip)); - else { - ipseclog((LOG_ERR, "IPv4 ipsec: size exceeds limit: " - "leave ip_len as is (invalid packet)\n")); - } -#ifdef RANDOM_IP_ID - ip->ip_id = ip_randomid(); -#else - ip->ip_id = htons(ip_id++); -#endif - bcopy(&((struct sockaddr_in *)&sav->sah->saidx.src)->sin_addr, - &ip->ip_src, sizeof(ip->ip_src)); - bcopy(&((struct sockaddr_in *)&sav->sah->saidx.dst)->sin_addr, - &ip->ip_dst, sizeof(ip->ip_dst)); - ip->ip_ttl = IPDEFTTL; - - /* XXX Should ip_src be updated later ? */ - - return 0; -} -#endif /* INET */ - -#ifdef INET6 -static int -ipsec6_encapsulate(struct mbuf *m, struct secasvar *sav) -{ - struct ip6_hdr *oip6; - struct ip6_hdr *ip6; - size_t plen; - - /* can't tunnel between different AFs */ - if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family - != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family - || ((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET6) { - m_freem(m); - return EINVAL; - } -#if 0 - /* XXX if the dst is myself, perform nothing. */ - if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) { - m_freem(m); - return EINVAL; - } -#endif - - plen = m->m_pkthdr.len; - - /* - * grow the mbuf to accomodate the new IPv6 header. - */ - if (m->m_len != sizeof(struct ip6_hdr)) - panic("ipsec6_encapsulate: assumption failed (first mbuf length)"); - if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) { - struct mbuf *n; - MGET(n, M_NOWAIT, MT_DATA); - if (!n) { - m_freem(m); - return ENOBUFS; - } - n->m_len = sizeof(struct ip6_hdr); - n->m_next = m->m_next; - m->m_next = n; - m->m_pkthdr.len += sizeof(struct ip6_hdr); - oip6 = mtod(n, struct ip6_hdr *); - } else { - m->m_next->m_len += sizeof(struct ip6_hdr); - m->m_next->m_data -= sizeof(struct ip6_hdr); - m->m_pkthdr.len += sizeof(struct ip6_hdr); - oip6 = mtod(m->m_next, struct ip6_hdr *); - } - ip6 = mtod(m, struct ip6_hdr *); - bcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr)); - - /* XXX: Fake scoped addresses */ - in6_clearscope(&oip6->ip6_src); - in6_clearscope(&oip6->ip6_dst); - - /* construct new IPv6 header. see RFC 2401 5.1.2.2 */ - /* ECN consideration. */ - ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow); - if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr)) - ip6->ip6_plen = htons(plen); - else { - /* ip6->ip6_plen will be updated in ip6_output() */ - } - ip6->ip6_nxt = IPPROTO_IPV6; - bcopy(&((struct sockaddr_in6 *)&sav->sah->saidx.src)->sin6_addr, - &ip6->ip6_src, sizeof(ip6->ip6_src)); - bcopy(&((struct sockaddr_in6 *)&sav->sah->saidx.dst)->sin6_addr, - &ip6->ip6_dst, sizeof(ip6->ip6_dst)); - ip6->ip6_hlim = IPV6_DEFHLIM; - - /* XXX Should ip6_src be updated later ? */ - - return 0; -} -#endif /* INET6 */ - -/* - * 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. - * - * based on RFC 2401. - * - * XXX need to update for 64bit sequence number - 2401bis - */ -int -ipsec_chkreplay(u_int32_t seq, struct secasvar *sav) -{ - const struct secreplay *replay; - u_int32_t diff; - int fr; - u_int32_t wsizeb; /* constant: bits of window size */ - int frlast; /* constant: last frame */ - - /* sanity check */ - if (sav == NULL) - panic("ipsec_chkreplay: NULL pointer was passed."); - - replay = sav->replay; - - if (replay->wsize == 0) - return 1; /* no need to check replay. */ - - /* constant */ - frlast = replay->wsize - 1; - wsizeb = replay->wsize << 3; - - /* sequence number of 0 is invalid */ - if (seq == 0) - return 0; - - /* first time is always okay */ - if (replay->count == 0) - return 1; - - if (seq > replay->lastseq) { - /* larger sequences are okay */ - return 1; - } else { - /* seq is equal or less than lastseq. */ - diff = replay->lastseq - seq; - - /* over range to check, i.e. too old or wrapped */ - if (diff >= wsizeb) - return 0; - - fr = frlast - diff / 8; - - /* this packet already seen ? */ - if (replay->bitmap[fr] & (1 << (diff % 8))) - return 0; - - /* out of order but good */ - return 1; - } -} - -/* - * check replay counter whether to update or not. - * OUT: 0: OK - * 1: NG - * XXX need to update for 64bit sequence number - 2401bis - */ -int -ipsec_updatereplay(u_int32_t seq, struct secasvar *sav) -{ - struct secreplay *replay; - u_int32_t diff; - int fr; - u_int32_t wsizeb; /* constant: bits of window size */ - int frlast; /* constant: last frame */ - - /* sanity check */ - if (sav == NULL) - panic("ipsec_chkreplay: NULL pointer was passed."); - - replay = sav->replay; - - if (replay->wsize == 0) - goto ok; /* no need to check replay. */ - - /* constant */ - frlast = replay->wsize - 1; - wsizeb = replay->wsize << 3; - - /* sequence number of 0 is invalid */ - if (seq == 0) - return 1; - - /* first time */ - if (replay->count == 0) { - replay->lastseq = seq; - bzero(replay->bitmap, replay->wsize); - replay->bitmap[frlast] = 1; - goto ok; - } - - if (seq > replay->lastseq) { - /* seq is larger than lastseq. */ - diff = seq - replay->lastseq; - - /* new larger sequence number */ - if (diff < wsizeb) { - /* In window */ - /* set bit for this packet */ - vshiftl(replay->bitmap, diff, replay->wsize); - replay->bitmap[frlast] |= 1; - } else { - /* this packet has a "way larger" */ - bzero(replay->bitmap, replay->wsize); - replay->bitmap[frlast] = 1; - } - replay->lastseq = seq; - - /* larger is good */ - } else { - /* seq is equal or less than lastseq. */ - diff = replay->lastseq - seq; - - /* over range to check, i.e. too old or wrapped */ - if (diff >= wsizeb) - return 1; - - fr = frlast - diff / 8; - - /* this packet already seen ? */ - if (replay->bitmap[fr] & (1 << (diff % 8))) - return 1; - - /* mark as seen */ - replay->bitmap[fr] |= (1 << (diff % 8)); - - /* out of order but good */ - } - -ok: - if (replay->count == ~0) { - - /* set overflow flag */ - replay->overflow++; - - /* don't increment, no more packets accepted */ - if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) - return 1; - - ipseclog((LOG_WARNING, "replay counter made %d cycle. %s\n", - replay->overflow, ipsec_logsastr(sav))); - } - - replay->count++; - - return 0; -} - -/* - * shift variable length buffer to left. - * IN: bitmap: pointer to the buffer - * nbit: the number of to shift. - * wsize: buffer size (bytes). - */ -static void -vshiftl(unsigned char *bitmap, int nbit, int wsize) -{ - int s, j, i; - unsigned char over; - - for (j = 0; j < nbit; j += 8) { - s = (nbit - j < 8) ? (nbit - j): 8; - bitmap[0] <<= s; - for (i = 1; i < wsize; i++) { - over = (bitmap[i] >> (8 - s)); - bitmap[i] <<= s; - bitmap[i-1] |= over; - } - } - - return; -} - -const char * -ipsec4_logpacketstr(struct ip *ip, u_int32_t spi) -{ - static char buf[256]; - char *p; - u_int8_t *s, *d; - - s = (u_int8_t *)(&ip->ip_src); - d = (u_int8_t *)(&ip->ip_dst); - - p = buf; - ksnprintf(buf, sizeof(buf), "packet(SPI=%u ", (u_int32_t)ntohl(spi)); - while (p && *p) - p++; - ksnprintf(p, sizeof(buf) - (p - buf), "src=%u.%u.%u.%u", - s[0], s[1], s[2], s[3]); - while (p && *p) - p++; - ksnprintf(p, sizeof(buf) - (p - buf), " dst=%u.%u.%u.%u", - d[0], d[1], d[2], d[3]); - while (p && *p) - p++; - ksnprintf(p, sizeof(buf) - (p - buf), ")"); - - return buf; -} - -#ifdef INET6 -const char * -ipsec6_logpacketstr(struct ip6_hdr *ip6, u_int32_t spi) -{ - static char buf[256]; - char *p; - - p = buf; - ksnprintf(buf, sizeof(buf), "packet(SPI=%u ", (u_int32_t)ntohl(spi)); - while (p && *p) - p++; - ksnprintf(p, sizeof(buf) - (p - buf), "src=%s", - ip6_sprintf(&ip6->ip6_src)); - while (p && *p) - p++; - ksnprintf(p, sizeof(buf) - (p - buf), " dst=%s", - ip6_sprintf(&ip6->ip6_dst)); - while (p && *p) - p++; - ksnprintf(p, sizeof(buf) - (p - buf), ")"); - - return buf; -} -#endif /* INET6 */ - -const char * -ipsec_logsastr(struct secasvar *sav) -{ - static char buf[256]; - char *p; - struct secasindex *saidx = &sav->sah->saidx; - - /* validity check */ - if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family - != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family) - panic("ipsec_logsastr: family mismatched."); - - p = buf; - ksnprintf(buf, sizeof(buf), "SA(SPI=%u ", (u_int32_t)ntohl(sav->spi)); - while (p && *p) - p++; - if (((struct sockaddr *)&saidx->src)->sa_family == AF_INET) { - u_int8_t *s, *d; - s = (u_int8_t *)&((struct sockaddr_in *)&saidx->src)->sin_addr; - d = (u_int8_t *)&((struct sockaddr_in *)&saidx->dst)->sin_addr; - ksnprintf(p, sizeof(buf) - (p - buf), - "src=%d.%d.%d.%d dst=%d.%d.%d.%d", - s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]); - } -#ifdef INET6 - else if (((struct sockaddr *)&saidx->src)->sa_family == AF_INET6) { - ksnprintf(p, sizeof(buf) - (p - buf), - "src=%s", - ip6_sprintf(&((struct sockaddr_in6 *)&saidx->src)->sin6_addr)); - while (p && *p) - p++; - ksnprintf(p, sizeof(buf) - (p - buf), - " dst=%s", - ip6_sprintf(&((struct sockaddr_in6 *)&saidx->dst)->sin6_addr)); - } -#endif - while (p && *p) - p++; - ksnprintf(p, sizeof(buf) - (p - buf), ")"); - - return buf; -} - -void -ipsec_dumpmbuf(struct mbuf *m) -{ - int totlen; - int i; - u_char *p; - - totlen = 0; - kprintf("---\n"); - while (m) { - p = mtod(m, u_char *); - for (i = 0; i < m->m_len; i++) { - kprintf("%02x ", p[i]); - totlen++; - if (totlen % 16 == 0) - kprintf("\n"); - } - m = m->m_next; - } - if (totlen % 16 != 0) - kprintf("\n"); - kprintf("---\n"); -} - -#ifdef INET -/* - * IPsec output logic for IPv4. - */ -int -ipsec4_output(struct ipsec_output_state *state, struct secpolicy *sp, int flags) -{ - struct ip *ip = NULL; - struct ipsecrequest *isr = NULL; - struct secasindex saidx; - int error; - struct sockaddr_in *dst4; - struct sockaddr_in *sin; - - if (!state) - panic("state == NULL in ipsec4_output"); - if (!state->m) - panic("state->m == NULL in ipsec4_output"); - if (!state->ro) - panic("state->ro == NULL in ipsec4_output"); - if (!state->dst) - panic("state->dst == NULL in ipsec4_output"); - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec4_output: applyed SP\n"); - kdebug_secpolicy(sp)); - - for (isr = sp->req; isr != NULL; isr = isr->next) { - -#if 0 /* give up to check restriction of transport mode */ - /* XXX but should be checked somewhere */ - /* - * some of the IPsec operation must be performed only in - * originating case. - */ - if (isr->saidx.mode == IPSEC_MODE_TRANSPORT - && (flags & IP_FORWARDING)) - continue; -#endif - - /* make SA index for search proper SA */ - ip = mtod(state->m, struct ip *); - bcopy(&isr->saidx, &saidx, sizeof(saidx)); - saidx.mode = isr->saidx.mode; - saidx.reqid = isr->saidx.reqid; - sin = (struct sockaddr_in *)&saidx.src; - if (sin->sin_len == 0) { - sin->sin_len = sizeof(*sin); - sin->sin_family = AF_INET; - sin->sin_port = IPSEC_PORT_ANY; - bcopy(&ip->ip_src, &sin->sin_addr, - sizeof(sin->sin_addr)); - } - sin = (struct sockaddr_in *)&saidx.dst; - if (sin->sin_len == 0) { - sin->sin_len = sizeof(*sin); - sin->sin_family = AF_INET; - sin->sin_port = IPSEC_PORT_ANY; - bcopy(&ip->ip_dst, &sin->sin_addr, - sizeof(sin->sin_addr)); - } - - if ((error = key_checkrequest(isr, &saidx)) != 0) { - /* - * IPsec processing is required, but no SA found. - * I assume that key_acquire() had been called - * to get/establish the SA. Here I discard - * this packet because it is responsibility for - * upper layer to retransmit the packet. - */ - ipsecstat.out_nosa++; - goto bad; - } - - /* validity check */ - if (isr->sav == NULL) { - switch (ipsec_get_reqlevel(isr)) { - case IPSEC_LEVEL_USE: - continue; - case IPSEC_LEVEL_REQUIRE: - /* must be not reached here. */ - panic("ipsec4_output: no SA found, but required."); - } - } - - /* - * If there is no valid SA, we give up to process any - * more. In such a case, the SA's status is changed - * from DYING to DEAD after allocating. If a packet - * send to the receiver by dead SA, the receiver can - * not decode a packet because SA has been dead. - */ - if (isr->sav->state != SADB_SASTATE_MATURE - && isr->sav->state != SADB_SASTATE_DYING) { - ipsecstat.out_nosa++; - error = EINVAL; - goto bad; - } - - /* - * There may be the case that SA status will be changed when - * we are refering to one. So calling crit_enter(). - */ - crit_enter(); - - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { - /* - * build IPsec tunnel. - */ - /* XXX should be processed with other familiy */ - if (((struct sockaddr *)&isr->sav->sah->saidx.src)->sa_family != AF_INET) { - ipseclog((LOG_ERR, "ipsec4_output: " - "family mismatched between inner and outer spi=%u\n", - (u_int32_t)ntohl(isr->sav->spi))); - crit_exit(); - error = EAFNOSUPPORT; - goto bad; - } - - state->m = ipsec4_splithdr(state->m); - if (!state->m) { - crit_exit(); - error = ENOMEM; - goto bad; - } - error = ipsec4_encapsulate(state->m, isr->sav); - crit_exit(); - if (error) { - state->m = NULL; - goto bad; - } - ip = mtod(state->m, struct ip *); - - state->ro = &isr->sav->sah->sa_route; - state->dst = (struct sockaddr *)&state->ro->ro_dst; - dst4 = (struct sockaddr_in *)state->dst; - if (state->ro->ro_rt - && ((state->ro->ro_rt->rt_flags & RTF_UP) == 0 - || dst4->sin_addr.s_addr != ip->ip_dst.s_addr)) { - RTFREE(state->ro->ro_rt); - state->ro->ro_rt = NULL; - } - if (state->ro->ro_rt == NULL) { - dst4->sin_family = AF_INET; - dst4->sin_len = sizeof(*dst4); - dst4->sin_addr = ip->ip_dst; - rtalloc(state->ro); - } - if (state->ro->ro_rt == NULL) { - ipstat.ips_noroute++; - error = EHOSTUNREACH; - goto bad; - } - - /* adjust state->dst if tunnel endpoint is offlink */ - if (state->ro->ro_rt->rt_flags & RTF_GATEWAY) { - state->dst = (struct sockaddr *)state->ro->ro_rt->rt_gateway; - dst4 = (struct sockaddr_in *)state->dst; - } - } else - crit_exit(); - - state->m = ipsec4_splithdr(state->m); - if (!state->m) { - error = ENOMEM; - goto bad; - } - switch (isr->saidx.proto) { - case IPPROTO_ESP: -#ifdef IPSEC_ESP - if ((error = esp4_output(state->m, isr)) != 0) { - state->m = NULL; - goto bad; - } - break; -#else - m_freem(state->m); - state->m = NULL; - error = EINVAL; - goto bad; -#endif - case IPPROTO_AH: - if ((error = ah4_output(state->m, isr)) != 0) { - state->m = NULL; - goto bad; - } - break; - case IPPROTO_IPCOMP: - if ((error = ipcomp4_output(state->m, isr)) != 0) { - state->m = NULL; - goto bad; - } - break; - default: - ipseclog((LOG_ERR, - "ipsec4_output: unknown ipsec protocol %d\n", - isr->saidx.proto)); - m_freem(state->m); - state->m = NULL; - error = EINVAL; - goto bad; - } - - if (state->m == NULL) { - error = ENOMEM; - goto bad; - } - ip = mtod(state->m, struct ip *); - } - - return 0; - -bad: - m_freem(state->m); - state->m = NULL; - return error; -} -#endif - -#ifdef INET6 -/* - * IPsec output logic for IPv6, transport mode. - */ -int -ipsec6_output_trans(struct ipsec_output_state *state, u_char *nexthdrp, - struct mbuf *mprev, struct secpolicy *sp, int flags, - boolean_t *tun) -{ - struct ip6_hdr *ip6; - struct ipsecrequest *isr = NULL; - struct secasindex saidx; - int error = 0; - int plen; - struct sockaddr_in6 *sin6; - - if (!state) - panic("state == NULL in ipsec6_output_trans"); - if (!state->m) - panic("state->m == NULL in ipsec6_output_trans"); - if (!nexthdrp) - panic("nexthdrp == NULL in ipsec6_output_trans"); - if (!mprev) - panic("mprev == NULL in ipsec6_output_trans"); - if (!sp) - panic("sp == NULL in ipsec6_output_trans"); - if (!tun) - panic("tun == NULL in ipsec6_output_trans"); - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec6_output_trans: applyed SP\n"); - kdebug_secpolicy(sp)); - - lwkt_gettoken(&key_token); - - *tun = 0; - for (isr = sp->req; isr; isr = isr->next) { - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { - /* the rest will be handled by ipsec6_output_tunnel() */ - break; - } - - /* make SA index for search proper SA */ - ip6 = mtod(state->m, struct ip6_hdr *); - bcopy(&isr->saidx, &saidx, sizeof(saidx)); - saidx.mode = isr->saidx.mode; - saidx.reqid = isr->saidx.reqid; - sin6 = (struct sockaddr_in6 *)&saidx.src; - if (sin6->sin6_len == 0) { - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = IPSEC_PORT_ANY; - bcopy(&ip6->ip6_src, &sin6->sin6_addr, - sizeof(ip6->ip6_src)); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { - /* fix scope id for comparing SPD */ - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]); - } - } - sin6 = (struct sockaddr_in6 *)&saidx.dst; - if (sin6->sin6_len == 0) { - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = IPSEC_PORT_ANY; - bcopy(&ip6->ip6_dst, &sin6->sin6_addr, - sizeof(ip6->ip6_dst)); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { - /* fix scope id for comparing SPD */ - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]); - } - } - - if (key_checkrequest(isr, &saidx) == ENOENT) { - /* - * IPsec processing is required, but no SA found. - * I assume that key_acquire() had been called - * to get/establish the SA. Here I discard - * this packet because it is responsibility for - * upper layer to retransmit the packet. - */ - ipsec6stat.out_nosa++; - error = ENOENT; - - /* - * Notify the fact that the packet is discarded - * to ourselves. I believe this is better than - * just silently discarding. (jinmei@kame.net) - * XXX: should we restrict the error to TCP packets? - * XXX: should we directly notify sockets via - * kpfctlinputs? - */ - icmp6_error(state->m, ICMP6_DST_UNREACH, - ICMP6_DST_UNREACH_ADMIN, 0); - state->m = NULL; /* icmp6_error freed the mbuf */ - goto bad; - } - - /* validity check */ - if (isr->sav == NULL) { - switch (ipsec_get_reqlevel(isr)) { - case IPSEC_LEVEL_USE: - continue; - case IPSEC_LEVEL_REQUIRE: - /* must be not reached here. */ - panic("ipsec6_output_trans: no SA found, but required."); - } - } - - /* - * If there is no valid SA, we give up to process. - * see same place at ipsec4_output(). - */ - if (isr->sav->state != SADB_SASTATE_MATURE - && isr->sav->state != SADB_SASTATE_DYING) { - ipsec6stat.out_nosa++; - error = EINVAL; - goto bad; - } - - switch (isr->saidx.proto) { - case IPPROTO_ESP: -#ifdef IPSEC_ESP - error = esp6_output(state->m, nexthdrp, mprev->m_next, isr); -#else - m_freem(state->m); - error = EINVAL; -#endif - break; - case IPPROTO_AH: - error = ah6_output(state->m, nexthdrp, mprev->m_next, isr); - break; - case IPPROTO_IPCOMP: - error = ipcomp6_output(state->m, nexthdrp, mprev->m_next, isr); - break; - default: - ipseclog((LOG_ERR, "ipsec6_output_trans: " - "unknown ipsec protocol %d\n", isr->saidx.proto)); - m_freem(state->m); - ipsec6stat.out_inval++; - error = EINVAL; - break; - } - if (error) { - state->m = NULL; - goto bad; - } - plen = state->m->m_pkthdr.len - sizeof(struct ip6_hdr); - if (plen > IPV6_MAXPACKET) { - ipseclog((LOG_ERR, "ipsec6_output_trans: " - "IPsec with IPv6 jumbogram is not supported\n")); - ipsec6stat.out_inval++; - error = EINVAL; /* XXX */ - goto bad; - } - ip6 = mtod(state->m, struct ip6_hdr *); - ip6->ip6_plen = htons(plen); - } - - /* if we have more to go, we need a tunnel mode processing */ - if (isr != NULL) - *tun = TRUE; - lwkt_reltoken(&key_token); - return 0; - -bad: - lwkt_reltoken(&key_token); - m_freem(state->m); - state->m = NULL; - return error; -} - -/* - * IPsec output logic for IPv6, tunnel mode. - */ -int -ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, - int flags) -{ - struct ip6_hdr *ip6; - struct ipsecrequest *isr = NULL; - struct secasindex saidx; - int error = 0; - int plen; - struct sockaddr_in6* dst6; - - if (!state) - panic("state == NULL in ipsec6_output_tunnel"); - if (!state->m) - panic("state->m == NULL in ipsec6_output_tunnel"); - if (!sp) - panic("sp == NULL in ipsec6_output_tunnel"); - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec6_output_tunnel: applyed SP\n"); - kdebug_secpolicy(sp)); - - /* - * transport mode ipsec (before the 1st tunnel mode) is already - * processed by ipsec6_output_trans(). - */ - lwkt_gettoken(&key_token); - for (isr = sp->req; isr; isr = isr->next) { - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) - break; - } - - for (/* already initialized */; isr; isr = isr->next) { - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { - /* When tunnel mode, SA peers must be specified. */ - bcopy(&isr->saidx, &saidx, sizeof(saidx)); - } else { - /* make SA index to look for a proper SA */ - struct sockaddr_in6 *sin6; - - bzero(&saidx, sizeof(saidx)); - saidx.proto = isr->saidx.proto; - saidx.mode = isr->saidx.mode; - saidx.reqid = isr->saidx.reqid; - - ip6 = mtod(state->m, struct ip6_hdr *); - sin6 = (struct sockaddr_in6 *)&saidx.src; - if (sin6->sin6_len == 0) { - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = IPSEC_PORT_ANY; - bcopy(&ip6->ip6_src, &sin6->sin6_addr, - sizeof(ip6->ip6_src)); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { - /* fix scope id for comparing SPD */ - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]); - } - } - sin6 = (struct sockaddr_in6 *)&saidx.dst; - if (sin6->sin6_len == 0) { - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = IPSEC_PORT_ANY; - bcopy(&ip6->ip6_dst, &sin6->sin6_addr, - sizeof(ip6->ip6_dst)); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { - /* fix scope id for comparing SPD */ - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]); - } - } - } - - if (key_checkrequest(isr, &saidx) == ENOENT) { - /* - * IPsec processing is required, but no SA found. - * I assume that key_acquire() had been called - * to get/establish the SA. Here I discard - * this packet because it is responsibility for - * upper layer to retransmit the packet. - */ - ipsec6stat.out_nosa++; - error = ENOENT; - goto bad; - } - - /* validity check */ - if (isr->sav == NULL) { - switch (ipsec_get_reqlevel(isr)) { - case IPSEC_LEVEL_USE: - continue; - case IPSEC_LEVEL_REQUIRE: - /* must be not reached here. */ - panic("ipsec6_output_tunnel: no SA found, but required."); - } - } - - /* - * If there is no valid SA, we give up to process. - * see same place at ipsec4_output(). - */ - if (isr->sav->state != SADB_SASTATE_MATURE - && isr->sav->state != SADB_SASTATE_DYING) { - ipsec6stat.out_nosa++; - error = EINVAL; - goto bad; - } - - /* - * There may be the case that SA status will be changed when - * we are refering to one. So calling crit_enter(). - */ - crit_enter(); - - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { - /* - * build IPsec tunnel. - */ - /* XXX should be processed with other familiy */ - if (((struct sockaddr *)&isr->sav->sah->saidx.src)->sa_family != AF_INET6) { - ipseclog((LOG_ERR, "ipsec6_output_tunnel: " - "family mismatched between inner and outer, spi=%u\n", - (u_int32_t)ntohl(isr->sav->spi))); - crit_exit(); - ipsec6stat.out_inval++; - error = EAFNOSUPPORT; - goto bad; - } - - state->m = ipsec6_splithdr(state->m); - if (!state->m) { - crit_exit(); - ipsec6stat.out_nomem++; - error = ENOMEM; - goto bad; - } - error = ipsec6_encapsulate(state->m, isr->sav); - crit_exit(); - if (error) { - state->m = NULL; - goto bad; - } - ip6 = mtod(state->m, struct ip6_hdr *); - - state->ro = &isr->sav->sah->sa_route; - state->dst = (struct sockaddr *)&state->ro->ro_dst; - dst6 = (struct sockaddr_in6 *)state->dst; - if (state->ro->ro_rt && - ((state->ro->ro_rt->rt_flags & RTF_UP) == 0 || - !IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ip6->ip6_dst))) { - RTFREE(state->ro->ro_rt); - state->ro->ro_rt = NULL; - } - if (state->ro->ro_rt == NULL) { - bzero(dst6, sizeof(*dst6)); - dst6->sin6_family = AF_INET6; - dst6->sin6_len = sizeof(*dst6); - dst6->sin6_addr = ip6->ip6_dst; - rtalloc(state->ro); - } - if (state->ro->ro_rt == NULL) { - ip6stat.ip6s_noroute++; - ipsec6stat.out_noroute++; - error = EHOSTUNREACH; - goto bad; - } - - /* adjust state->dst if tunnel endpoint is offlink */ - if (state->ro->ro_rt->rt_flags & RTF_GATEWAY) { - state->dst = (struct sockaddr *)state->ro->ro_rt->rt_gateway; - dst6 = (struct sockaddr_in6 *)state->dst; - } - } else - crit_exit(); - - state->m = ipsec6_splithdr(state->m); - if (!state->m) { - ipsec6stat.out_nomem++; - error = ENOMEM; - goto bad; - } - ip6 = mtod(state->m, struct ip6_hdr *); - switch (isr->saidx.proto) { - case IPPROTO_ESP: -#ifdef IPSEC_ESP - error = esp6_output(state->m, &ip6->ip6_nxt, - state->m->m_next, isr); -#else - m_freem(state->m); - error = EINVAL; -#endif - break; - case IPPROTO_AH: - error = ah6_output(state->m, &ip6->ip6_nxt, - state->m->m_next, isr); - break; - case IPPROTO_IPCOMP: - /* XXX code should be here */ - /* FALLTHROUGH */ - default: - ipseclog((LOG_ERR, "ipsec6_output_tunnel: " - "unknown ipsec protocol %d\n", isr->saidx.proto)); - m_freem(state->m); - ipsec6stat.out_inval++; - error = EINVAL; - break; - } - if (error) { - state->m = NULL; - goto bad; - } - plen = state->m->m_pkthdr.len - sizeof(struct ip6_hdr); - if (plen > IPV6_MAXPACKET) { - ipseclog((LOG_ERR, "ipsec6_output_tunnel: " - "IPsec with IPv6 jumbogram is not supported\n")); - ipsec6stat.out_inval++; - error = EINVAL; /* XXX */ - goto bad; - } - ip6 = mtod(state->m, struct ip6_hdr *); - ip6->ip6_plen = htons(plen); - } - lwkt_reltoken(&key_token); - - return 0; - -bad: - lwkt_reltoken(&key_token); - m_freem(state->m); - state->m = NULL; - return error; -} -#endif /* INET6 */ - -#ifdef INET -/* - * Chop IP header and option off from the payload. - */ -static struct mbuf * -ipsec4_splithdr(struct mbuf *m) -{ - struct mbuf *mh; - struct ip *ip; - int hlen; - - if (m->m_len < sizeof(struct ip)) - panic("ipsec4_splithdr: first mbuf too short"); - ip = mtod(m, struct ip *); -#ifdef _IP_VHL - hlen = _IP_VHL_HL(ip->ip_vhl) << 2; -#else - hlen = ip->ip_hl << 2; -#endif - if (m->m_len > hlen) { - MGETHDR(mh, M_NOWAIT, MT_HEADER); - if (!mh) { - m_freem(m); - return NULL; - } - M_MOVE_PKTHDR(mh, m); - MH_ALIGN(mh, hlen); - m->m_len -= hlen; - m->m_data += hlen; - mh->m_next = m; - m = mh; - m->m_len = hlen; - bcopy((caddr_t)ip, mtod(m, caddr_t), hlen); - } else if (m->m_len < hlen) { - m = m_pullup(m, hlen); - if (!m) - return NULL; - } - return m; -} -#endif - -#ifdef INET6 -static struct mbuf * -ipsec6_splithdr(struct mbuf *m) -{ - struct mbuf *mh; - struct ip6_hdr *ip6; - int hlen; - - if (m->m_len < sizeof(struct ip6_hdr)) - panic("ipsec6_splithdr: first mbuf too short"); - ip6 = mtod(m, struct ip6_hdr *); - hlen = sizeof(struct ip6_hdr); - if (m->m_len > hlen) { - MGETHDR(mh, M_NOWAIT, MT_HEADER); - if (!mh) { - m_freem(m); - return NULL; - } - M_MOVE_PKTHDR(mh, m); - MH_ALIGN(mh, hlen); - m->m_len -= hlen; - m->m_data += hlen; - mh->m_next = m; - m = mh; - m->m_len = hlen; - bcopy((caddr_t)ip6, mtod(m, caddr_t), hlen); - } else if (m->m_len < hlen) { - m = m_pullup(m, hlen); - if (!m) - return NULL; - } - return m; -} -#endif - -/* validate inbound IPsec tunnel packet. */ -int -ipsec4_tunnel_validate(struct mbuf *m, /* no pullup permitted, m->m_len >= ip */ - int off, u_int nxt0, struct secasvar *sav) -{ - u_int8_t nxt = nxt0 & 0xff; - struct sockaddr_in *sin; - struct sockaddr_in osrc, odst, isrc, idst; - int hlen; - struct secpolicy *sp; - struct ip *oip; - -#ifdef DIAGNOSTIC - if (m->m_len < sizeof(struct ip)) - panic("too short mbuf on ipsec4_tunnel_validate"); -#endif - if (nxt != IPPROTO_IPV4) - return 0; - if (m->m_pkthdr.len < off + sizeof(struct ip)) - return 0; - /* do not decapsulate if the SA is for transport mode only */ - if (sav->sah->saidx.mode == IPSEC_MODE_TRANSPORT) - return 0; - - oip = mtod(m, struct ip *); -#ifdef _IP_VHL - hlen = _IP_VHL_HL(oip->ip_vhl) << 2; -#else - hlen = oip->ip_hl << 2; -#endif - if (hlen != sizeof(struct ip)) - return 0; - - /* AF_INET6 should be supported, but at this moment we don't. */ - sin = (struct sockaddr_in *)&sav->sah->saidx.dst; - if (sin->sin_family != AF_INET) - return 0; - if (bcmp(&oip->ip_dst, &sin->sin_addr, sizeof(oip->ip_dst)) != 0) - return 0; - - /* XXX slow */ - bzero(&osrc, sizeof(osrc)); - bzero(&odst, sizeof(odst)); - bzero(&isrc, sizeof(isrc)); - bzero(&idst, sizeof(idst)); - osrc.sin_family = odst.sin_family = isrc.sin_family = idst.sin_family = - AF_INET; - osrc.sin_len = odst.sin_len = isrc.sin_len = idst.sin_len = - sizeof(struct sockaddr_in); - osrc.sin_addr = oip->ip_src; - odst.sin_addr = oip->ip_dst; - m_copydata(m, off + offsetof(struct ip, ip_src), sizeof(isrc.sin_addr), - (caddr_t)&isrc.sin_addr); - m_copydata(m, off + offsetof(struct ip, ip_dst), sizeof(idst.sin_addr), - (caddr_t)&idst.sin_addr); - - /* - * RFC2401 5.2.1 (b): (assume that we are using tunnel mode) - * - if the inner destination is multicast address, there can be - * multiple permissible inner source address. implementation - * may want to skip verification of inner source address against - * SPD selector. - * - if the inner protocol is ICMP, the packet may be an error report - * from routers on the other side of the VPN cloud (R in the - * following diagram). in this case, we cannot verify inner source - * address against SPD selector. - * me -- gw === gw -- R -- you - * - * we consider the first bullet to be users responsibility on SPD entry - * configuration (if you need to encrypt multicast traffic, set - * the source range of SPD selector to 0.0.0.0/0, or have explicit - * address ranges for possible senders). - * the second bullet is not taken care of (yet). - * - * therefore, we do not do anything special about inner source. - */ - - lwkt_gettoken(&key_token); - sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst, - (struct sockaddr *)&isrc, (struct sockaddr *)&idst); - if (sp) { - key_freesp(sp); - lwkt_reltoken(&key_token); - return 1; - } else{ - lwkt_reltoken(&key_token); - return 0; - } -} - -#ifdef INET6 -/* validate inbound IPsec tunnel packet. */ -int -ipsec6_tunnel_validate(struct mbuf *m, /* no pullup permitted, m->m_len >= ip */ - int off, u_int nxt0, struct secasvar *sav) -{ - u_int8_t nxt = nxt0 & 0xff; - struct sockaddr_in6 *sin6; - struct sockaddr_in6 osrc, odst, isrc, idst; - struct secpolicy *sp; - struct ip6_hdr *oip6; - -#ifdef DIAGNOSTIC - if (m->m_len < sizeof(struct ip6_hdr)) - panic("too short mbuf on ipsec6_tunnel_validate"); -#endif - if (nxt != IPPROTO_IPV6) - return 0; - if (m->m_pkthdr.len < off + sizeof(struct ip6_hdr)) - return 0; - /* do not decapsulate if the SA is for transport mode only */ - if (sav->sah->saidx.mode == IPSEC_MODE_TRANSPORT) - return 0; - - oip6 = mtod(m, struct ip6_hdr *); - /* AF_INET should be supported, but at this moment we don't. */ - sin6 = (struct sockaddr_in6 *)&sav->sah->saidx.dst; - if (sin6->sin6_family != AF_INET6) - return 0; - if (!IN6_ARE_ADDR_EQUAL(&oip6->ip6_dst, &sin6->sin6_addr)) - return 0; - - /* XXX slow */ - bzero(&osrc, sizeof(osrc)); - bzero(&odst, sizeof(odst)); - bzero(&isrc, sizeof(isrc)); - bzero(&idst, sizeof(idst)); - osrc.sin6_family = odst.sin6_family = isrc.sin6_family = - idst.sin6_family = AF_INET6; - osrc.sin6_len = odst.sin6_len = isrc.sin6_len = idst.sin6_len = - sizeof(struct sockaddr_in6); - osrc.sin6_addr = oip6->ip6_src; - odst.sin6_addr = oip6->ip6_dst; - m_copydata(m, off + offsetof(struct ip6_hdr, ip6_src), - sizeof(isrc.sin6_addr), (caddr_t)&isrc.sin6_addr); - m_copydata(m, off + offsetof(struct ip6_hdr, ip6_dst), - sizeof(idst.sin6_addr), (caddr_t)&idst.sin6_addr); - - /* - * regarding to inner source address validation, see a long comment - * in ipsec4_tunnel_validate. - */ - - lwkt_gettoken(&key_token); - sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst, - (struct sockaddr *)&isrc, (struct sockaddr *)&idst); - /* - * when there is no suitable inbound policy for the packet of the ipsec - * tunnel mode, the kernel never decapsulate the tunneled packet - * as the ipsec tunnel mode even when the system wide policy is "none". - * then the kernel leaves the generic tunnel module to process this - * packet. if there is no rule of the generic tunnel, the packet - * is rejected and the statistics will be counted up. - */ - if (sp) { - key_freesp(sp); - lwkt_reltoken(&key_token); - return 1; - } else { - lwkt_reltoken(&key_token); - return 0; - } -} -#endif - -/* - * Make a mbuf chain for encryption. - * If the original mbuf chain contains a mbuf with a cluster, - * allocate a new cluster and copy the data to the new cluster. - * XXX: this hack is inefficient, but is necessary to handle cases - * of TCP retransmission... - */ -struct mbuf * -ipsec_copypkt(struct mbuf *m) -{ - struct mbuf *n, **mpp, *mnew; - - for (n = m, mpp = &m; n; n = n->m_next) { - if (n->m_flags & M_EXT) { - /* - * Make a copy only if there is more than one - * references to the cluster. - * XXX: is this approach effective? - */ - if (m_sharecount(n) > 1) { - int remain, copied; - struct mbuf *mm; - - if (n->m_flags & M_PKTHDR) { - MGETHDR(mnew, M_NOWAIT, MT_HEADER); - if (mnew == NULL) - goto fail; - if (!m_dup_pkthdr(mnew, n, M_NOWAIT)) { - m_free(mnew); - goto fail; - } - } else { - MGET(mnew, M_NOWAIT, MT_DATA); - if (mnew == NULL) - goto fail; - } - mnew->m_len = 0; - mm = mnew; - - /* - * Copy data. If we don't have enough space to - * store the whole data, allocate a cluster - * or additional mbufs. - * XXX: we don't use m_copyback(), since the - * function does not use clusters and thus is - * inefficient. - */ - remain = n->m_len; - copied = 0; - while (1) { - int len; - struct mbuf *mn; - - if (remain <= (mm->m_flags & M_PKTHDR ? MHLEN : MLEN)) - len = remain; - else { /* allocate a cluster */ - MCLGET(mm, M_NOWAIT); - if (!(mm->m_flags & M_EXT)) { - m_free(mm); - goto fail; - } - len = remain < MCLBYTES ? - remain : MCLBYTES; - } - - bcopy(n->m_data + copied, mm->m_data, - len); - - copied += len; - remain -= len; - mm->m_len = len; - - if (remain <= 0) /* completed? */ - break; - - /* need another mbuf */ - MGETHDR(mn, M_NOWAIT, MT_HEADER); - if (mn == NULL) - goto fail; - mn->m_pkthdr.rcvif = NULL; - mm->m_next = mn; - mm = mn; - } - - /* adjust chain */ - mm->m_next = m_free(n); - n = mm; - *mpp = mnew; - mpp = &n->m_next; - - continue; - } - } - *mpp = n; - mpp = &n->m_next; - } - - return (m); -fail: - m_freem(m); - return (NULL); -} - -void -ipsec_delaux(struct mbuf *m) -{ - struct m_tag *mtag; - - while ((mtag = m_tag_find(m, PACKET_TAG_IPSEC_HISTORY, NULL)) != NULL) - m_tag_delete(m, mtag); -} - -int -ipsec_addhist(struct mbuf *m, int proto, u_int32_t spi) -{ - struct m_tag *mtag; - struct ipsec_history *p; - - mtag = m_tag_get(PACKET_TAG_IPSEC_HISTORY, - sizeof(struct ipsec_history), M_NOWAIT); - if (mtag == NULL) - return ENOBUFS; - p = (struct ipsec_history *)m_tag_data(mtag); - bzero(p, sizeof(*p)); - p->ih_proto = proto; - p->ih_spi = spi; - m_tag_prepend(m, mtag); - return 0; -} - -struct ipsec_history * -ipsec_gethist(struct mbuf *m, int *lenp) -{ - struct m_tag *mtag; - - mtag = m_tag_find(m, PACKET_TAG_IPSEC_HISTORY, NULL); - if (mtag == NULL) - return NULL; - /* XXX NB: noone uses this so fake it */ - if (lenp) - *lenp = sizeof(struct ipsec_history); - return (struct ipsec_history *)m_tag_data(mtag); -} diff --git a/sys/netinet6/ipsec.h b/sys/netinet6/ipsec.h deleted file mode 100644 index cb4d80dba4..0000000000 --- a/sys/netinet6/ipsec.h +++ /dev/null @@ -1,352 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ipsec.h,v 1.4.2.4 2003/01/23 21:06:47 sam Exp $ */ -/* $DragonFly: src/sys/netinet6/ipsec.h,v 1.5 2006/10/24 06:18:42 hsu Exp $ */ -/* $KAME: ipsec.h,v 1.53 2001/11/20 08:32:38 itojun Exp $ */ - -/* - * 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. - */ - -#ifndef _NETINET6_IPSEC_H_ -#define _NETINET6_IPSEC_H_ - -#if defined(_KERNEL) && !defined(_LKM) && !defined(KLD_MODULE) -#include "opt_inet.h" -#include "opt_ipsec.h" -#endif - -#include -#include - -#ifdef _KERNEL - -/* - * Security Policy Index - * Ensure that both address families in the "src" and "dst" are same. - * When the value of the ul_proto is ICMPv6, the port field in "src" - * specifies ICMPv6 type, and the port field in "dst" specifies ICMPv6 code. - */ -struct secpolicyindex { - u_int8_t dir; /* direction of packet flow, see blow */ - struct sockaddr_storage src; /* IP src address for SP */ - struct sockaddr_storage dst; /* IP dst address for SP */ - u_int8_t prefs; /* prefix length in bits for src */ - u_int8_t prefd; /* prefix length in bits for dst */ - u_int16_t ul_proto; /* upper layer Protocol */ -#ifdef notyet - uid_t uids; - uid_t uidd; - gid_t gids; - gid_t gidd; -#endif -}; - -/* Security Policy Data Base */ -struct secpolicy { - LIST_ENTRY(secpolicy) chain; - - int refcnt; /* reference count */ - struct secpolicyindex spidx; /* selector */ - u_int32_t id; /* It's unique number on the system. */ - u_int state; /* 0: dead, others: alive */ -#define IPSEC_SPSTATE_DEAD 0 -#define IPSEC_SPSTATE_ALIVE 1 - - u_int policy; /* DISCARD, NONE or IPSEC, see keyv2.h */ - struct ipsecrequest *req; - /* pointer to the ipsec request tree, */ - /* if policy == IPSEC else this value == NULL.*/ - - /* - * lifetime handler. - * the policy can be used without limitiation if both lifetime and - * validtime are zero. - * "lifetime" is passed by sadb_lifetime.sadb_lifetime_addtime. - * "validtime" is passed by sadb_lifetime.sadb_lifetime_usetime. - */ - long created; /* time created the policy */ - long lastused; /* updated every when kernel sends a packet */ - long lifetime; /* duration of the lifetime of this policy */ - long validtime; /* duration this policy is valid without use */ -}; - -/* Request for IPsec */ -struct ipsecrequest { - struct ipsecrequest *next; - /* pointer to next structure */ - /* If NULL, it means the end of chain. */ - struct secasindex saidx;/* hint for search proper SA */ - /* if __ss_len == 0 then no address specified.*/ - u_int level; /* IPsec level defined below. */ - - struct secasvar *sav; /* place holder of SA for use */ - struct secpolicy *sp; /* back pointer to SP */ -}; - -/* security policy in PCB */ -struct inpcbpolicy { - struct secpolicy *sp_in; - struct secpolicy *sp_out; - int priv; /* privileged socket ? */ -}; - -/* SP acquiring list table. */ -struct secspacq { - LIST_ENTRY(secspacq) chain; - - struct secpolicyindex spidx; - - long created; /* for lifetime */ - int count; /* for lifetime */ - /* XXX: here is mbuf place holder to be sent ? */ -}; -#endif /* _KERNEL */ - -/* according to IANA assignment, port 0x0000 and proto 0xff are reserved. */ -#define IPSEC_PORT_ANY 0 -#define IPSEC_ULPROTO_ANY 255 -#define IPSEC_PROTO_ANY 255 - -/* mode of security protocol */ -/* NOTE: DON'T use IPSEC_MODE_ANY at SPD. It's only use in SAD */ -#define IPSEC_MODE_ANY 0 /* i.e. wildcard. */ -#define IPSEC_MODE_TRANSPORT 1 -#define IPSEC_MODE_TUNNEL 2 -#define IPSEC_MODE_TCPMD5 3 /* TCP MD5 mode */ - -/* - * Direction of security policy. - * NOTE: Since INVALID is used just as flag. - * The other are used for loop counter too. - */ -#define IPSEC_DIR_ANY 0 -#define IPSEC_DIR_INBOUND 1 -#define IPSEC_DIR_OUTBOUND 2 -#define IPSEC_DIR_MAX 3 -#define IPSEC_DIR_INVALID 4 - -/* Policy level */ -/* - * IPSEC, ENTRUST and BYPASS are allowed for setsockopt() in PCB, - * DISCARD, IPSEC and NONE are allowed for setkey() in SPD. - * DISCARD and NONE are allowed for system default. - */ -#define IPSEC_POLICY_DISCARD 0 /* discard the packet */ -#define IPSEC_POLICY_NONE 1 /* bypass IPsec engine */ -#define IPSEC_POLICY_IPSEC 2 /* pass to IPsec */ -#define IPSEC_POLICY_ENTRUST 3 /* consulting SPD if present. */ -#define IPSEC_POLICY_BYPASS 4 /* only for privileged socket. */ -#define IPSEC_POLICY_TCP 5 /* TCP MD5 policy */ - -/* Security protocol level */ -#define IPSEC_LEVEL_DEFAULT 0 /* reference to system default */ -#define IPSEC_LEVEL_USE 1 /* use SA if present. */ -#define IPSEC_LEVEL_REQUIRE 2 /* require SA. */ -#define IPSEC_LEVEL_UNIQUE 3 /* unique SA. */ - -#define IPSEC_MANUAL_REQID_MAX 0x3fff - /* - * if security policy level == unique, this id - * indicate to a relative SA for use, else is - * zero. - * 1 - 0x3fff are reserved for manual keying. - * 0 are reserved for above reason. Others is - * for kernel use. - * Note that this id doesn't identify SA - * by only itself. - */ -#define IPSEC_REPLAYWSIZE 32 - -/* statistics for ipsec processing */ -struct ipsecstat { - u_quad_t in_success; /* succeeded inbound process */ - u_quad_t in_polvio; - /* security policy violation for inbound process */ - u_quad_t in_nosa; /* inbound SA is unavailable */ - u_quad_t in_inval; /* inbound processing failed due to EINVAL */ - u_quad_t in_nomem; /* inbound processing failed due to ENOBUFS */ - u_quad_t in_badspi; /* failed getting a SPI */ - u_quad_t in_ahreplay; /* AH replay check failed */ - u_quad_t in_espreplay; /* ESP replay check failed */ - u_quad_t in_ahauthsucc; /* AH authentication success */ - u_quad_t in_ahauthfail; /* AH authentication failure */ - u_quad_t in_espauthsucc; /* ESP authentication success */ - u_quad_t in_espauthfail; /* ESP authentication failure */ - u_quad_t in_esphist[256]; - u_quad_t in_ahhist[256]; - u_quad_t in_comphist[256]; - u_quad_t out_success; /* succeeded outbound process */ - u_quad_t out_polvio; - /* security policy violation for outbound process */ - u_quad_t out_nosa; /* outbound SA is unavailable */ - u_quad_t out_inval; /* outbound process failed due to EINVAL */ - u_quad_t out_nomem; /* inbound processing failed due to ENOBUFS */ - u_quad_t out_noroute; /* there is no route */ - u_quad_t out_esphist[256]; - u_quad_t out_ahhist[256]; - u_quad_t out_comphist[256]; -}; - -/* - * Definitions for IPsec & Key sysctl operations. - */ -/* - * Names for IPsec & Key sysctl objects - */ -#define IPSECCTL_STATS 1 /* stats */ -#define IPSECCTL_DEF_POLICY 2 -#define IPSECCTL_DEF_ESP_TRANSLEV 3 /* int; ESP transport mode */ -#define IPSECCTL_DEF_ESP_NETLEV 4 /* int; ESP tunnel mode */ -#define IPSECCTL_DEF_AH_TRANSLEV 5 /* int; AH transport mode */ -#define IPSECCTL_DEF_AH_NETLEV 6 /* int; AH tunnel mode */ -#if 0 /* obsolete, do not reuse */ -#define IPSECCTL_INBOUND_CALL_IKE 7 -#endif -#define IPSECCTL_AH_CLEARTOS 8 -#define IPSECCTL_AH_OFFSETMASK 9 -#define IPSECCTL_DFBIT 10 -#define IPSECCTL_ECN 11 -#define IPSECCTL_DEBUG 12 -#define IPSECCTL_ESP_RANDPAD 13 -#define IPSECCTL_MAXID 14 - -#define IPSECCTL_NAMES { \ - { 0, 0 }, \ - { 0, 0 }, \ - { "def_policy", CTLTYPE_INT }, \ - { "esp_trans_deflev", CTLTYPE_INT }, \ - { "esp_net_deflev", CTLTYPE_INT }, \ - { "ah_trans_deflev", CTLTYPE_INT }, \ - { "ah_net_deflev", CTLTYPE_INT }, \ - { 0, 0 }, \ - { "ah_cleartos", CTLTYPE_INT }, \ - { "ah_offsetmask", CTLTYPE_INT }, \ - { "dfbit", CTLTYPE_INT }, \ - { "ecn", CTLTYPE_INT }, \ - { "debug", CTLTYPE_INT }, \ - { "esp_randpad", CTLTYPE_INT }, \ -} - -#define IPSEC6CTL_NAMES { \ - { 0, 0 }, \ - { 0, 0 }, \ - { "def_policy", CTLTYPE_INT }, \ - { "esp_trans_deflev", CTLTYPE_INT }, \ - { "esp_net_deflev", CTLTYPE_INT }, \ - { "ah_trans_deflev", CTLTYPE_INT }, \ - { "ah_net_deflev", CTLTYPE_INT }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { "ecn", CTLTYPE_INT }, \ - { "debug", CTLTYPE_INT }, \ - { "esp_randpad", CTLTYPE_INT }, \ -} - -#ifdef _KERNEL -struct ipsec_output_state { - struct mbuf *m; - struct route *ro; - struct sockaddr *dst; -}; - -struct ipsec_history { - int ih_proto; - u_int32_t ih_spi; -}; - -extern int ipsec_debug; - -extern struct ipsecstat ipsecstat; -extern struct secpolicy ip4_def_policy; -extern int ip4_esp_trans_deflev; -extern int ip4_esp_net_deflev; -extern int ip4_ah_trans_deflev; -extern int ip4_ah_net_deflev; -extern int ip4_ah_cleartos; -extern int ip4_ah_offsetmask; -extern int ip4_ipsec_dfbit; -extern int ip4_ipsec_ecn; -extern int ip4_esp_randpad; - -#define ipseclog(x) do { if (ipsec_debug) log x; } while (0) - -extern struct secpolicy *ipsec4_getpolicybysock - (struct mbuf *, u_int, struct socket *, int *); -extern struct secpolicy *ipsec4_getpolicybyaddr - (struct mbuf *, u_int, int, int *); - -struct inpcb; -extern int ipsec_init_policy (struct socket *, struct inpcbpolicy **); -extern int ipsec_copy_policy - (struct inpcbpolicy *, struct inpcbpolicy *); -extern u_int ipsec_get_reqlevel (struct ipsecrequest *); - -extern int ipsec4_set_policy (struct inpcb *, int, caddr_t, size_t, int); -extern int ipsec4_get_policy (struct inpcb *, caddr_t, size_t, struct mbuf **); -extern int ipsec4_delete_pcbpolicy (struct inpcb *); -extern int ipsec4_in_reject_so (struct mbuf *, struct socket *); -extern int ipsec4_in_reject (struct mbuf *, struct inpcb *); - -struct secas; -struct tcpcb; -extern int ipsec_chkreplay (u_int32_t, struct secasvar *); -extern int ipsec_updatereplay (u_int32_t, struct secasvar *); - -extern size_t ipsec4_hdrsiz (struct mbuf *, u_int, struct inpcb *); -extern size_t ipsec_hdrsiz_tcp (struct tcpcb *); - -struct ip; -extern const char *ipsec4_logpacketstr (struct ip *, u_int32_t); -extern const char *ipsec_logsastr (struct secasvar *); - -extern void ipsec_dumpmbuf (struct mbuf *); - -extern int ipsec4_output (struct ipsec_output_state *, struct secpolicy *, - int); -extern int ipsec4_tunnel_validate (struct mbuf *, int, u_int, - struct secasvar *); -extern struct mbuf *ipsec_copypkt (struct mbuf *); -extern void ipsec_delaux (struct mbuf *); -extern int ipsec_addhist (struct mbuf *, int, u_int32_t); -extern struct ipsec_history *ipsec_gethist (struct mbuf *, int *); -#endif /* _KERNEL */ - -#ifndef _KERNEL -extern caddr_t ipsec_set_policy (char *, int); -extern int ipsec_get_policylen (caddr_t); -extern char *ipsec_dump_policy (caddr_t, char *); - -extern const char *ipsec_strerror (void); -#endif /* !_KERNEL */ - -#endif /* _NETINET6_IPSEC_H_ */ diff --git a/sys/netinet6/ipsec6.h b/sys/netinet6/ipsec6.h deleted file mode 100644 index dfe4da75c3..0000000000 --- a/sys/netinet6/ipsec6.h +++ /dev/null @@ -1,87 +0,0 @@ -/* $FreeBSD: src/sys/netinet6/ipsec6.h,v 1.3.2.2 2001/07/03 11:01:54 ume Exp $ */ -/* $KAME: ipsec.h,v 1.44 2001/03/23 08:08:47 itojun Exp $ */ - -/* - * 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. - */ - -#ifndef _NETINET6_IPSEC6_H_ -#define _NETINET6_IPSEC6_H_ - -#include -#include - -#ifdef _KERNEL - -struct mbuf; -struct inpcb; -struct tcp6cb; -struct ip6_hdr; -struct secasvar; -struct ipsec_output_state; - -extern struct ipsecstat ipsec6stat; -extern struct secpolicy ip6_def_policy; -extern int ip6_esp_trans_deflev; -extern int ip6_esp_net_deflev; -extern int ip6_ah_trans_deflev; -extern int ip6_ah_net_deflev; -extern int ip6_ipsec_ecn; -extern int ip6_esp_randpad; - -extern struct secpolicy *ipsec6_getpolicybysock - (struct mbuf *, u_int, struct socket *, int *); -extern struct secpolicy *ipsec6_getpolicybyaddr - (struct mbuf *, u_int, int, int *); - -extern int ipsec6_in_reject_so (struct mbuf *, struct socket *); -extern int ipsec6_delete_pcbpolicy (struct inpcb *); -extern int ipsec6_set_policy (struct inpcb *inp, int optname, - caddr_t request, size_t len, int priv); -extern int ipsec6_get_policy - (struct inpcb *inp, caddr_t request, size_t len, struct mbuf **mp); -extern int ipsec6_in_reject (struct mbuf *, struct inpcb *); - -extern size_t ipsec6_hdrsiz (struct mbuf *, u_int, struct inpcb *); - -extern const char *ipsec6_logpacketstr (struct ip6_hdr *, u_int32_t); - -extern int ipsec6_output_trans (struct ipsec_output_state *, u_char *, - struct mbuf *, struct secpolicy *, int, boolean_t *); -extern int ipsec6_output_tunnel (struct ipsec_output_state *, - struct secpolicy *, int); -extern int ipsec6_tunnel_validate (struct mbuf *, int, u_int, - struct secasvar *); - -#endif /*_KERNEL*/ - -#endif /*_NETINET6_IPSEC6_H_*/ diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index 1778709cf7..4dbf67b98a 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -32,7 +32,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include "opt_carp.h" #include @@ -67,13 +66,6 @@ #include #include -#ifdef IPSEC -#include -#ifdef INET6 -#include -#endif -#endif - #include #ifdef CARP diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index c890589abb..0572a172f5 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -60,7 +60,6 @@ * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 */ -#include "opt_ipsec.h" #include "opt_inet6.h" #include @@ -99,16 +98,6 @@ #endif #include -#ifdef IPSEC -#include -#include -#endif /*IPSEC*/ - -#ifdef FAST_IPSEC -#include -#include -#endif /* FAST_IPSEC */ - #include #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) @@ -168,25 +157,6 @@ rip6_input(struct mbuf **mp, int *offp, int proto) if (last) { struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); -#ifdef IPSEC - /* - * Check AH/ESP integrity. - */ - if (n && ipsec6_in_reject_so(n, last->inp_socket)) { - m_freem(n); - ipsec6stat.in_polvio++; - /* do not inject data into pcb */ - } else -#endif /*IPSEC*/ -#ifdef FAST_IPSEC - /* - * Check AH/ESP integrity. - */ - if (n && ipsec6_in_reject(n, last)) { - m_freem(n); - /* do not inject data into pcb */ - } else -#endif /*FAST_IPSEC*/ if (n) { struct socket *so; @@ -214,27 +184,6 @@ rip6_input(struct mbuf **mp, int *offp, int proto) } last = in6p; } -#ifdef IPSEC - /* - * Check AH/ESP integrity. - */ - if (last && ipsec6_in_reject_so(m, last->inp_socket)) { - m_freem(m); - ipsec6stat.in_polvio++; - ip6stat.ip6s_delivered--; - /* do not inject data into pcb */ - } else -#endif /*IPSEC*/ -#ifdef FAST_IPSEC - /* - * Check AH/ESP integrity. - */ - if (last && ipsec6_in_reject(m, last)) { - m_freem(m); - ip6stat.ip6s_delivered--; - /* do not inject data into pcb */ - } else -#endif /*FAST_IPSEC*/ if (last) { struct socket *so; diff --git a/sys/netinet6/udp6_output.c b/sys/netinet6/udp6_output.c index 40b76e1253..ff591542be 100644 --- a/sys/netinet6/udp6_output.c +++ b/sys/netinet6/udp6_output.c @@ -61,7 +61,6 @@ * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 */ -#include "opt_ipsec.h" #include "opt_inet.h" #include "opt_inet6.h" @@ -98,13 +97,6 @@ #include #include -#ifdef IPSEC -#include -#ifdef INET6 -#include -#endif -#endif /* IPSEC */ - #include /* diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 229b8d534c..3b1aee7472 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -63,7 +63,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include #include @@ -103,16 +102,6 @@ #include #include -#ifdef IPSEC -#include -#include -#endif /* IPSEC */ - -#ifdef FAST_IPSEC -#include -#include -#endif /* FAST_IPSEC */ - /* * UDP protocol inplementation. * Per RFC 768, August, 1980. @@ -216,7 +205,6 @@ udp6_input(struct mbuf **mp, int *offp, int proto) udp_in6.sin6_port = uh->uh_sport; /* * KAME note: traditionally we dropped udpiphdr from mbuf here. - * We need udphdr for IPsec processing so we do that later. */ /* @@ -257,23 +245,6 @@ udp6_input(struct mbuf **mp, int *offp, int proto) if (last != NULL) { struct mbuf *n; -#ifdef IPSEC - /* - * Check AH/ESP integrity. - */ - if (ipsec6_in_reject_so(m, last->inp_socket)) - ipsec6stat.in_polvio++; - /* do not inject data into pcb */ - else -#endif /* IPSEC */ -#ifdef FAST_IPSEC - /* - * Check AH/ESP integrity. - */ - if (ipsec6_in_reject(m, last)) - ; - else -#endif /* FAST_IPSEC */ if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { /* * KAME NOTE: do not @@ -331,23 +302,6 @@ udp6_input(struct mbuf **mp, int *offp, int proto) udp_stat.udps_noportmcast++; goto bad; } -#ifdef IPSEC - /* - * Check AH/ESP integrity. - */ - if (ipsec6_in_reject_so(m, last->inp_socket)) { - ipsec6stat.in_polvio++; - goto bad; - } -#endif /* IPSEC */ -#ifdef FAST_IPSEC - /* - * Check AH/ESP integrity. - */ - if (ipsec6_in_reject(m, last)) { - goto bad; - } -#endif /* FAST_IPSEC */ if (last->in6p_flags & IN6P_CONTROLOPTS || last->in6p_socket->so_options & SO_TIMESTAMP) ip6_savecontrol(last, &opts, ip6, m); @@ -390,23 +344,6 @@ udp6_input(struct mbuf **mp, int *offp, int proto) icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); return IPPROTO_DONE; } -#ifdef IPSEC - /* - * Check AH/ESP integrity. - */ - if (ipsec6_in_reject_so(m, in6p->in6p_socket)) { - ipsec6stat.in_polvio++; - goto bad; - } -#endif /* IPSEC */ -#ifdef FAST_IPSEC - /* - * Check AH/ESP integrity. - */ - if (ipsec6_in_reject(m, in6p)) { - goto bad; - } -#endif /* FAST_IPSEC */ /* * Construct sockaddr format source address. diff --git a/sys/netproto/ipsec/ah.h b/sys/netproto/ipsec/ah.h deleted file mode 100644 index 0185abca22..0000000000 --- a/sys/netproto/ipsec/ah.h +++ /dev/null @@ -1,57 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/ah.h,v 1.1.4.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/ah.h,v 1.2 2003/06/17 04:28:53 dillon Exp $ */ -/* $KAME: ah.h,v 1.13 2000/10/18 21:28:00 itojun Exp $ */ - -/* - * 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. - */ - -/* - * RFC1826/2402 authentication header. - */ - -#ifndef _NETIPSEC_AH_H_ -#define _NETIPSEC_AH_H_ - -struct ah { - u_int8_t ah_nxt; /* Next Header */ - u_int8_t ah_len; /* Length of data, in 32bit */ - u_int16_t ah_reserve; /* Reserved for future use */ - u_int32_t ah_spi; /* Security parameter index */ - /* variable size, 32bit bound*/ /* Authentication data */ -}; - -struct newah { - u_int8_t ah_nxt; /* Next Header */ - u_int8_t ah_len; /* Length of data + 1, in 32bit */ - u_int16_t ah_reserve; /* Reserved for future use */ - u_int32_t ah_spi; /* Security parameter index */ - u_int32_t ah_seq; /* Sequence number field */ - /* variable size, 32bit bound*/ /* Authentication data */ -}; -#endif /*_NETIPSEC_AH_H_*/ diff --git a/sys/netproto/ipsec/ah_var.h b/sys/netproto/ipsec/ah_var.h deleted file mode 100644 index 022ebea256..0000000000 --- a/sys/netproto/ipsec/ah_var.h +++ /dev/null @@ -1,79 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/ah_var.h,v 1.1.4.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/ah_var.h,v 1.2 2003/06/17 04:28:53 dillon Exp $ */ -/* $OpenBSD: ip_ah.h,v 1.29 2002/06/09 16:26:10 itojun Exp $ */ -/* - * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). - * - * The original version of this code was written by John Ioannidis - * for BSD/OS in Athens, Greece, in November 1995. - * - * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, - * by Angelos D. Keromytis. - * - * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis - * and Niels Provos. - * - * Additional features in 1999 by Angelos D. Keromytis. - * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 John Ioannidis, - * Angelos D. Keromytis and Niels Provos. - * Copyright (c) 2001 Angelos D. Keromytis. - * - * Permission to use, copy, and modify this software with or without fee - * is hereby granted, provided that this entire notice is included in - * all copies of any software which is or includes a copy or - * modification of this software. - * You may use this code under the GNU public license if you so wish. Please - * contribute changes back to the authors under this freer than GPL license - * so that we may further the use of strong encryption without limitations to - * all. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE - * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR - * PURPOSE. - */ - -#ifndef _NETIPSEC_AH_VAR_H_ -#define _NETIPSEC_AH_VAR_H_ - -/* - * These define the algorithm indices into the histogram. They're - * presently based on the PF_KEY v2 protocol values which is bogus; - * they should be decoupled from the protocol at which time we can - * pack them and reduce the size of the array to a minimum. - */ -#define AH_ALG_MAX 16 - -struct ahstat { - u_int32_t ahs_hdrops; /* Packet shorter than header shows */ - u_int32_t ahs_nopf; /* Protocol family not supported */ - u_int32_t ahs_notdb; - u_int32_t ahs_badkcr; - u_int32_t ahs_badauth; - u_int32_t ahs_noxform; - u_int32_t ahs_qfull; - u_int32_t ahs_wrap; - u_int32_t ahs_replay; - u_int32_t ahs_badauthl; /* Bad authenticator length */ - u_int32_t ahs_input; /* Input AH packets */ - u_int32_t ahs_output; /* Output AH packets */ - u_int32_t ahs_invalid; /* Trying to use an invalid TDB */ - u_int64_t ahs_ibytes; /* Input bytes */ - u_int64_t ahs_obytes; /* Output bytes */ - u_int32_t ahs_toobig; /* Packet got larger than IP_MAXPACKET */ - u_int32_t ahs_pdrops; /* Packet blocked due to policy */ - u_int32_t ahs_crypto; /* Crypto processing failure */ - u_int32_t ahs_tunnel; /* Tunnel sanity check failure */ - u_int32_t ahs_hist[AH_ALG_MAX]; /* Per-algorithm op count */ -}; - -#ifdef _KERNEL -extern int ah_enable; -extern int ah_cleartos; -extern struct ahstat ahstat; -#endif /* _KERNEL */ -#endif /*_NETIPSEC_AH_VAR_H_*/ diff --git a/sys/netproto/ipsec/esp.h b/sys/netproto/ipsec/esp.h deleted file mode 100644 index 32748b4894..0000000000 --- a/sys/netproto/ipsec/esp.h +++ /dev/null @@ -1,70 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/esp.h,v 1.1.4.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/esp.h,v 1.2 2003/06/17 04:28:53 dillon Exp $ */ -/* $KAME: esp.h,v 1.16 2000/10/18 21:28:00 itojun Exp $ */ - -/* - * 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. - */ - -/* - * RFC1827/2406 Encapsulated Security Payload. - */ - -#ifndef _NETIPSEC_ESP_H_ -#define _NETIPSEC_ESP_H_ - -struct esp { - u_int32_t esp_spi; /* ESP */ - /*variable size, 32bit bound*/ /* Initialization Vector */ - /*variable size*/ /* Payload data */ - /*variable size*/ /* padding */ - /*8bit*/ /* pad size */ - /*8bit*/ /* next header */ - /*8bit*/ /* next header */ - /*variable size, 32bit bound*/ /* Authentication data (new IPsec) */ -}; - -struct newesp { - u_int32_t esp_spi; /* ESP */ - u_int32_t esp_seq; /* Sequence number */ - /*variable size*/ /* (IV and) Payload data */ - /*variable size*/ /* padding */ - /*8bit*/ /* pad size */ - /*8bit*/ /* next header */ - /*8bit*/ /* next header */ - /*variable size, 32bit bound*/ /* Authentication data */ -}; - -struct esptail { - u_int8_t esp_padlen; /* pad length */ - u_int8_t esp_nxt; /* Next header */ - /*variable size, 32bit bound*/ /* Authentication data (new IPsec)*/ -}; - -#define ESP_ALEN 12 /* 96-bit authenticator */ -#endif /*_NETIPSEC_ESP_H_*/ diff --git a/sys/netproto/ipsec/esp_var.h b/sys/netproto/ipsec/esp_var.h deleted file mode 100644 index e41c6e7eaf..0000000000 --- a/sys/netproto/ipsec/esp_var.h +++ /dev/null @@ -1,82 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/esp_var.h,v 1.1.4.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/esp_var.h,v 1.2 2003/06/17 04:28:53 dillon Exp $ */ -/* $OpenBSD: ip_esp.h,v 1.37 2002/06/09 16:26:10 itojun Exp $ */ -/* - * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). - * - * The original version of this code was written by John Ioannidis - * for BSD/OS in Athens, Greece, in November 1995. - * - * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, - * by Angelos D. Keromytis. - * - * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis - * and Niels Provos. - * - * Additional features in 1999 by Angelos D. Keromytis. - * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, - * Angelos D. Keromytis and Niels Provos. - * Copyright (c) 2001 Angelos D. Keromytis. - * - * Permission to use, copy, and modify this software with or without fee - * is hereby granted, provided that this entire notice is included in - * all copies of any software which is or includes a copy or - * modification of this software. - * You may use this code under the GNU public license if you so wish. Please - * contribute changes back to the authors under this freer than GPL license - * so that we may further the use of strong encryption without limitations to - * all. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE - * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR - * PURPOSE. - */ - -#ifndef _NETIPSEC_ESP_VAR_H_ -#define _NETIPSEC_ESP_VAR_H_ - -/* - * These define the algorithm indices into the histogram. They're - * presently based on the PF_KEY v2 protocol values which is bogus; - * they should be decoupled from the protocol at which time we can - * pack them and reduce the size of the array to a reasonable value. - */ -#define ESP_ALG_MAX 256 /* NB: could be < but skipjack is 249 */ - -struct espstat { - u_int32_t esps_hdrops; /* Packet shorter than header shows */ - u_int32_t esps_nopf; /* Protocol family not supported */ - u_int32_t esps_notdb; - u_int32_t esps_badkcr; - u_int32_t esps_qfull; - u_int32_t esps_noxform; - u_int32_t esps_badilen; - u_int32_t esps_wrap; /* Replay counter wrapped around */ - u_int32_t esps_badenc; /* Bad encryption detected */ - u_int32_t esps_badauth; /* Only valid for transforms with auth */ - u_int32_t esps_replay; /* Possible packet replay detected */ - u_int32_t esps_input; /* Input ESP packets */ - u_int32_t esps_output; /* Output ESP packets */ - u_int32_t esps_invalid; /* Trying to use an invalid TDB */ - u_int64_t esps_ibytes; /* Input bytes */ - u_int64_t esps_obytes; /* Output bytes */ - u_int32_t esps_toobig; /* Packet got larger than IP_MAXPACKET */ - u_int32_t esps_pdrops; /* Packet blocked due to policy */ - u_int32_t esps_crypto; /* Crypto processing failure */ - u_int32_t esps_tunnel; /* Tunnel sanity check failure */ - u_int32_t esps_hist[ESP_ALG_MAX]; /* Per-algorithm op count */ -}; - -#ifdef _KERNEL -extern int esp_enable; -extern int udpencap_enable; -extern int udpencap_port; - -extern struct espstat espstat; -#endif /* _KERNEL */ -#endif /*_NETIPSEC_ESP_VAR_H_*/ diff --git a/sys/netproto/ipsec/ipcomp.h b/sys/netproto/ipsec/ipcomp.h deleted file mode 100644 index b3cf6d291c..0000000000 --- a/sys/netproto/ipsec/ipcomp.h +++ /dev/null @@ -1,56 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/ipcomp.h,v 1.1.4.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/ipcomp.h,v 1.2 2003/06/17 04:28:53 dillon Exp $ */ -/* $KAME: ipcomp.h,v 1.8 2000/09/26 07:55:14 itojun Exp $ */ - -/* - * Copyright (C) 1999 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. - */ - -/* - * RFC2393 IP payload compression protocol (IPComp). - */ - -#ifndef _NETIPSEC_IPCOMP_H_ -#define _NETIPSEC_IPCOMP_H_ - -struct ipcomp { - u_int8_t comp_nxt; /* Next Header */ - u_int8_t comp_flags; /* reserved, must be zero */ - u_int16_t comp_cpi; /* Compression parameter index */ -}; - -#define IPCOMP_HLENGTH 4 /* Length of IPCOMP header */ - -/* well-known algorithm number (in CPI), from RFC2409 */ -#define IPCOMP_OUI 1 /* vendor specific */ -#define IPCOMP_DEFLATE 2 /* RFC2394 */ -#define IPCOMP_LZS 3 /* RFC2395 */ -#define IPCOMP_MAX 4 - -#define IPCOMP_CPI_NEGOTIATE_MIN 256 -#endif /*_NETIPSEC_IPCOMP_H_*/ diff --git a/sys/netproto/ipsec/ipcomp_var.h b/sys/netproto/ipsec/ipcomp_var.h deleted file mode 100644 index edf64b372d..0000000000 --- a/sys/netproto/ipsec/ipcomp_var.h +++ /dev/null @@ -1,68 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/ipcomp_var.h,v 1.1.4.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/ipcomp_var.h,v 1.2 2003/06/17 04:28:53 dillon Exp $ */ -/* $KAME: ipcomp.h,v 1.8 2000/09/26 07:55:14 itojun Exp $ */ - -/* - * Copyright (C) 1999 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. - */ - -#ifndef _NETIPSEC_IPCOMP_VAR_H_ -#define _NETIPSEC_IPCOMP_VAR_H_ - -/* - * These define the algorithm indices into the histogram. They're - * presently based on the PF_KEY v2 protocol values which is bogus; - * they should be decoupled from the protocol at which time we can - * pack them and reduce the size of the array to a minimum. - */ -#define IPCOMP_ALG_MAX 8 - -struct ipcompstat { - u_int32_t ipcomps_hdrops; /* Packet shorter than header shows */ - u_int32_t ipcomps_nopf; /* Protocol family not supported */ - u_int32_t ipcomps_notdb; - u_int32_t ipcomps_badkcr; - u_int32_t ipcomps_qfull; - u_int32_t ipcomps_noxform; - u_int32_t ipcomps_wrap; - u_int32_t ipcomps_input; /* Input IPcomp packets */ - u_int32_t ipcomps_output; /* Output IPcomp packets */ - u_int32_t ipcomps_invalid;/* Trying to use an invalid TDB */ - u_int64_t ipcomps_ibytes; /* Input bytes */ - u_int64_t ipcomps_obytes; /* Output bytes */ - u_int32_t ipcomps_toobig; /* Packet got > IP_MAXPACKET */ - u_int32_t ipcomps_pdrops; /* Packet blocked due to policy */ - u_int32_t ipcomps_crypto; /* "Crypto" processing failure */ - u_int32_t ipcomps_hist[IPCOMP_ALG_MAX];/* Per-algorithm op count */ -}; - -#ifdef _KERNEL -extern int ipcomp_enable; -extern struct ipcompstat ipcompstat; -#endif /* _KERNEL */ -#endif /*_NETIPSEC_IPCOMP_VAR_H_*/ diff --git a/sys/netproto/ipsec/ipip_var.h b/sys/netproto/ipsec/ipip_var.h deleted file mode 100644 index fbf596cf5a..0000000000 --- a/sys/netproto/ipsec/ipip_var.h +++ /dev/null @@ -1,66 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/ipip_var.h,v 1.1.4.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/ipip_var.h,v 1.2 2003/06/17 04:28:53 dillon Exp $ */ -/* $OpenBSD: ip_ipip.h,v 1.5 2002/06/09 16:26:10 itojun Exp $ */ -/* - * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). - * - * The original version of this code was written by John Ioannidis - * for BSD/OS in Athens, Greece, in November 1995. - * - * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, - * by Angelos D. Keromytis. - * - * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis - * and Niels Provos. - * - * Additional features in 1999 by Angelos D. Keromytis. - * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, - * Angelos D. Keromytis and Niels Provos. - * Copyright (c) 2001, Angelos D. Keromytis. - * - * Permission to use, copy, and modify this software with or without fee - * is hereby granted, provided that this entire notice is included in - * all copies of any software which is or includes a copy or - * modification of this software. - * You may use this code under the GNU public license if you so wish. Please - * contribute changes back to the authors under this freer than GPL license - * so that we may further the use of strong encryption without limitations to - * all. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE - * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR - * PURPOSE. - */ - -#ifndef _NETINET_IPIP_H_ -#define _NETINET_IPIP_H_ - -/* - * IP-inside-IP processing. - * Not quite all the functionality of RFC-1853, but the main idea is there. - */ - -struct ipipstat -{ - u_int32_t ipips_ipackets; /* total input packets */ - u_int32_t ipips_opackets; /* total output packets */ - u_int32_t ipips_hdrops; /* packet shorter than header shows */ - u_int32_t ipips_qfull; - u_int64_t ipips_ibytes; - u_int64_t ipips_obytes; - u_int32_t ipips_pdrops; /* packet dropped due to policy */ - u_int32_t ipips_spoof; /* IP spoofing attempts */ - u_int32_t ipips_family; /* Protocol family mismatch */ - u_int32_t ipips_unspec; /* Missing tunnel endpoint address */ -}; - -#ifdef _KERNEL -extern int ipip_allow; -extern struct ipipstat ipipstat; -#endif /* _KERNEL */ -#endif /* _NETINET_IPIP_H_ */ diff --git a/sys/netproto/ipsec/ipsec.c b/sys/netproto/ipsec/ipsec.c deleted file mode 100644 index be21753eab..0000000000 --- a/sys/netproto/ipsec/ipsec.c +++ /dev/null @@ -1,1854 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/ipsec.c,v 1.2.2.1 2003/01/24 05:11:35 sam Exp $ */ -/* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#include -#include /*XXX*/ -#include - -#include -#include -#include - -#include - -#include - -#ifdef IPSEC_DEBUG -int ipsec_debug = 1; -#else -int ipsec_debug = 0; -#endif - -/* NB: name changed so netstat doesn't use it */ -struct newipsecstat newipsecstat; -int ip4_ah_offsetmask = 0; /* maybe IP_DF? */ -int ip4_ipsec_dfbit = 0; /* DF bit on encap. 0: clear 1: set 2: copy */ -int ip4_esp_trans_deflev = IPSEC_LEVEL_USE; -int ip4_esp_net_deflev = IPSEC_LEVEL_USE; -int ip4_ah_trans_deflev = IPSEC_LEVEL_USE; -int ip4_ah_net_deflev = IPSEC_LEVEL_USE; -struct secpolicy ip4_def_policy; -int ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ -int ip4_esp_randpad = -1; -/* - * Crypto support requirements: - * - * 1 require hardware support - * -1 require software support - * 0 take anything - */ -int crypto_support = 0; - -SYSCTL_DECL(_net_inet_ipsec); - -/* net.inet.ipsec */ -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, - def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, - CTLFLAG_RW, &ip4_esp_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, - CTLFLAG_RW, &ip4_esp_net_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, - CTLFLAG_RW, &ip4_ah_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, - CTLFLAG_RW, &ip4_ah_net_deflev, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS, - ah_cleartos, CTLFLAG_RW, &ah_cleartos, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, - ah_offsetmask, CTLFLAG_RW, &ip4_ah_offsetmask, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT, - dfbit, CTLFLAG_RW, &ip4_ipsec_dfbit, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN, - ecn, CTLFLAG_RW, &ip4_ipsec_ecn, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG, - debug, CTLFLAG_RW, &ipsec_debug, 0, ""); -SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD, - esp_randpad, CTLFLAG_RW, &ip4_esp_randpad, 0, ""); -SYSCTL_INT(_net_inet_ipsec, OID_AUTO, - crypto_support, CTLFLAG_RW, &crypto_support,0, ""); -SYSCTL_STRUCT(_net_inet_ipsec, OID_AUTO, - ipsecstats, CTLFLAG_RD, &newipsecstat, newipsecstat, ""); - -#ifdef INET6 -int ip6_esp_trans_deflev = IPSEC_LEVEL_USE; -int ip6_esp_net_deflev = IPSEC_LEVEL_USE; -int ip6_ah_trans_deflev = IPSEC_LEVEL_USE; -int ip6_ah_net_deflev = IPSEC_LEVEL_USE; -int ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ -int ip6_esp_randpad = -1; - -SYSCTL_DECL(_net_inet6_ipsec6); - -/* net.inet6.ipsec6 */ -#ifdef COMPAT_KAME -SYSCTL_OID(_net_inet6_ipsec6, IPSECCTL_STATS, stats, CTLFLAG_RD, - 0,0, compat_ipsecstats_sysctl, "S", ""); -#endif /* COMPAT_KAME */ -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, - def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, - CTLFLAG_RW, &ip6_esp_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, - CTLFLAG_RW, &ip6_esp_net_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, - CTLFLAG_RW, &ip6_ah_trans_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, - CTLFLAG_RW, &ip6_ah_net_deflev, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN, - ecn, CTLFLAG_RW, &ip6_ipsec_ecn, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG, - debug, CTLFLAG_RW, &ipsec_debug, 0, ""); -SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, - esp_randpad, CTLFLAG_RW, &ip6_esp_randpad, 0, ""); -#endif /* INET6 */ - -static int ipsec4_setspidx_inpcb (struct mbuf *, struct inpcb *pcb); -#ifdef INET6 -static int ipsec6_setspidx_in6pcb (struct mbuf *, struct in6pcb *pcb); -#endif -static int ipsec_setspidx (struct mbuf *, struct secpolicyindex *, int); -static void ipsec4_get_ulp (struct mbuf *m, struct secpolicyindex *, int); -static int ipsec4_setspidx_ipaddr (struct mbuf *, struct secpolicyindex *); -#ifdef INET6 -static void ipsec6_get_ulp (struct mbuf *m, struct secpolicyindex *, int); -static int ipsec6_setspidx_ipaddr (struct mbuf *, struct secpolicyindex *); -#endif -static void ipsec_delpcbpolicy (struct inpcbpolicy *); -static struct secpolicy *ipsec_deepcopy_policy (struct secpolicy *src); -static int ipsec_set_policy (struct secpolicy **pcb_sp, - int optname, caddr_t request, size_t len, int priv); -static int ipsec_get_policy (struct secpolicy *pcb_sp, struct mbuf **mp); -static void vshiftl (unsigned char *, int, int); -static size_t ipsec_hdrsiz (struct secpolicy *); - -/* - * Return a held reference to the default SP. - */ -static struct secpolicy * -key_allocsp_default(const char* where, int tag) -{ - struct secpolicy *sp; - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_allocsp_default from %s:%u\n", where, tag)); - - sp = &ip4_def_policy; - if (sp->policy != IPSEC_POLICY_DISCARD && - sp->policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", - sp->policy, IPSEC_POLICY_NONE)); - sp->policy = IPSEC_POLICY_NONE; - } - sp->refcnt++; - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_allocsp_default returns SP:%p (%u)\n", - sp, sp->refcnt)); - return sp; -} -#define KEY_ALLOCSP_DEFAULT() \ - key_allocsp_default(__FILE__, __LINE__) - -/* - * For OUTBOUND packet having a socket. Searching SPD for packet, - * and return a pointer to SP. - * OUT: NULL: no apropreate SP found, the following value is set to error. - * 0 : bypass - * EACCES : discard packet. - * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. - * others: a pointer to SP - * - * NOTE: IPv6 mapped adddress concern is implemented here. - */ -struct secpolicy * -ipsec_getpolicy(struct tdb_ident *tdbi, u_int dir) -{ - struct secpolicy *sp; - - KASSERT(tdbi != NULL, ("ipsec_getpolicy: null tdbi")); - KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, - ("ipsec_getpolicy: invalid direction %u", dir)); - - sp = KEY_ALLOCSP2(tdbi->spi, &tdbi->dst, tdbi->proto, dir); - if (sp == NULL) /*XXX????*/ - sp = KEY_ALLOCSP_DEFAULT(); - KASSERT(sp != NULL, ("ipsec_getpolicy: null SP")); - return sp; -} - -/* - * For OUTBOUND packet having a socket. Searching SPD for packet, - * and return a pointer to SP. - * OUT: NULL: no apropreate SP found, the following value is set to error. - * 0 : bypass - * EACCES : discard packet. - * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. - * others: a pointer to SP - * - * NOTE: IPv6 mapped adddress concern is implemented here. - */ -struct secpolicy * -ipsec_getpolicybysock(struct mbuf *m, u_int dir, struct inpcb *inp, - int *error) -{ - struct inpcbpolicy *pcbsp = NULL; - struct secpolicy *currsp = NULL; /* policy on socket */ - struct secpolicy *sp; - int af; - - KASSERT(m != NULL, ("ipsec_getpolicybysock: null mbuf")); - KASSERT(inp != NULL, ("ipsec_getpolicybysock: null inpcb")); - KASSERT(error != NULL, ("ipsec_getpolicybysock: null error")); - KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, - ("ipsec_getpolicybysock: invalid direction %u", dir)); - - af = inp->inp_socket->so_proto->pr_domain->dom_family; - KASSERT(af == AF_INET || af == AF_INET6, - ("ipsec_getpolicybysock: unexpected protocol family %u", af)); - - switch (af) { - case AF_INET: - /* set spidx in pcb */ - *error = ipsec4_setspidx_inpcb(m, inp); - pcbsp = inp->inp_sp; - break; -#ifdef INET6 - case AF_INET6: - /* set spidx in pcb */ - *error = ipsec6_setspidx_in6pcb(m, inp); - pcbsp = inp->in6p_sp; - break; -#endif - default: - *error = EPFNOSUPPORT; - break; - } - if (*error) - return NULL; - - KASSERT(pcbsp != NULL, ("ipsec_getpolicybysock: null pcbsp")); - switch (dir) { - case IPSEC_DIR_INBOUND: - currsp = pcbsp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - currsp = pcbsp->sp_out; - break; - } - KASSERT(currsp != NULL, ("ipsec_getpolicybysock: null currsp")); - - if (pcbsp->priv) { /* when privilieged socket */ - switch (currsp->policy) { - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; - sp = currsp; - break; - - case IPSEC_POLICY_ENTRUST: - /* look for a policy in SPD */ - sp = KEY_ALLOCSP(&currsp->spidx, dir); - if (sp == NULL) /* no SP found */ - sp = KEY_ALLOCSP_DEFAULT(); - break; - - default: - ipseclog((LOG_ERR, "ipsec_getpolicybysock: " - "Invalid policy for PCB %d\n", currsp->policy)); - *error = EINVAL; - return NULL; - } - } else { /* unpriv, SPD has policy */ - sp = KEY_ALLOCSP(&currsp->spidx, dir); - if (sp == NULL) { /* no SP found */ - switch (currsp->policy) { - case IPSEC_POLICY_BYPASS: - ipseclog((LOG_ERR, "ipsec_getpolicybysock: " - "Illegal policy for non-priviliged defined %d\n", - currsp->policy)); - *error = EINVAL; - return NULL; - - case IPSEC_POLICY_ENTRUST: - sp = KEY_ALLOCSP_DEFAULT(); - break; - - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; - sp = currsp; - break; - - default: - ipseclog((LOG_ERR, "ipsec_getpolicybysock: " - "Invalid policy for PCB %d\n", currsp->policy)); - *error = EINVAL; - return NULL; - } - } - } - KASSERT(sp != NULL, - ("ipsec_getpolicybysock: null SP (priv %u policy %u", - pcbsp->priv, currsp->policy)); - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP ipsec_getpolicybysock (priv %u policy %u) allocates " - "SP:%p (refcnt %u)\n", pcbsp->priv, currsp->policy, - sp, sp->refcnt)); - return sp; -} - -/* - * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet, - * and return a pointer to SP. - * OUT: positive: a pointer to the entry for security policy leaf matched. - * NULL: no apropreate SP found, the following value is set to error. - * 0 : bypass - * EACCES : discard packet. - * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. - */ -struct secpolicy * -ipsec_getpolicybyaddr(struct mbuf *m, u_int dir, int flag, int *error) -{ - struct secpolicyindex spidx; - struct secpolicy *sp; - - KASSERT(m != NULL, ("ipsec_getpolicybyaddr: null mbuf")); - KASSERT(error != NULL, ("ipsec_getpolicybyaddr: null error")); - KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, - ("ipsec4_getpolicybaddr: invalid direction %u", dir)); - - sp = NULL; - if (key_havesp(dir)) { - /* Make an index to look for a policy. */ - *error = ipsec_setspidx(m, &spidx, - (flag & IP_FORWARDING) ? 0 : 1); - if (*error != 0) { - DPRINTF(("ipsec_getpolicybyaddr: setpidx failed," - " dir %u flag %u\n", dir, flag)); - bzero(&spidx, sizeof (spidx)); - return NULL; - } - spidx.dir = dir; - - sp = KEY_ALLOCSP(&spidx, dir); - } - if (sp == NULL) /* no SP found, use system default */ - sp = KEY_ALLOCSP_DEFAULT(); - KASSERT(sp != NULL, ("ipsec_getpolicybyaddr: null SP")); - return sp; -} - -struct secpolicy * -ipsec4_checkpolicy(struct mbuf *m, u_int dir, u_int flag, int *error, - struct inpcb *inp) -{ - struct secpolicy *sp; - - *error = 0; - if (inp == NULL) - sp = ipsec_getpolicybyaddr(m, dir, flag, error); - else - sp = ipsec_getpolicybysock(m, dir, inp, error); - if (sp == NULL) { - KASSERT(*error != 0, - ("ipsec4_checkpolicy: getpolicy failed w/o error")); - newipsecstat.ips_out_inval++; - return NULL; - } - KASSERT(*error == 0, - ("ipsec4_checkpolicy: sp w/ error set to %u", *error)); - switch (sp->policy) { - case IPSEC_POLICY_ENTRUST: - default: - kprintf("ipsec4_checkpolicy: invalid policy %u\n", sp->policy); - /* fall thru... */ - case IPSEC_POLICY_DISCARD: - newipsecstat.ips_out_polvio++; - *error = -EINVAL; /* packet is discarded by caller */ - break; - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_NONE: - KEY_FREESP(&sp); - sp = NULL; /* NB: force NULL result */ - break; - case IPSEC_POLICY_IPSEC: - if (sp->req == NULL) /* acquire an SA */ - *error = key_spdacquire(sp); - break; - } - if (*error != 0) { - KEY_FREESP(&sp); - sp = NULL; - } - return sp; -} - -static int -ipsec4_setspidx_inpcb(struct mbuf *m, struct inpcb *pcb) -{ - int error; - - KASSERT(pcb != NULL, ("ipsec4_setspidx_inpcb: null pcb")); - KASSERT(pcb->inp_sp != NULL, ("ipsec4_setspidx_inpcb: null inp_sp")); - KASSERT(pcb->inp_sp->sp_out != NULL && pcb->inp_sp->sp_in != NULL, - ("ipsec4_setspidx_inpcb: null sp_in || sp_out")); - - error = ipsec_setspidx(m, &pcb->inp_sp->sp_in->spidx, 1); - if (error == 0) { - pcb->inp_sp->sp_in->spidx.dir = IPSEC_DIR_INBOUND; - pcb->inp_sp->sp_out->spidx = pcb->inp_sp->sp_in->spidx; - pcb->inp_sp->sp_out->spidx.dir = IPSEC_DIR_OUTBOUND; - } else { - bzero(&pcb->inp_sp->sp_in->spidx, - sizeof (pcb->inp_sp->sp_in->spidx)); - bzero(&pcb->inp_sp->sp_out->spidx, - sizeof (pcb->inp_sp->sp_in->spidx)); - } - return error; -} - -#ifdef INET6 -static int -ipsec6_setspidx_in6pcb(struct mbuf *m, struct in6pcb *pcb) -{ - struct secpolicyindex *spidx; - int error; - - KASSERT(pcb != NULL, ("ipsec6_setspidx_in6pcb: null pcb")); - KASSERT(pcb->in6p_sp != NULL, ("ipsec6_setspidx_in6pcb: null inp_sp")); - KASSERT(pcb->in6p_sp->sp_out != NULL && pcb->in6p_sp->sp_in != NULL, - ("ipsec6_setspidx_in6pcb: null sp_in || sp_out")); - - bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx)); - bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx)); - - spidx = &pcb->in6p_sp->sp_in->spidx; - error = ipsec_setspidx(m, spidx, 1); - if (error) - goto bad; - spidx->dir = IPSEC_DIR_INBOUND; - - spidx = &pcb->in6p_sp->sp_out->spidx; - error = ipsec_setspidx(m, spidx, 1); - if (error) - goto bad; - spidx->dir = IPSEC_DIR_OUTBOUND; - - return 0; - -bad: - bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx)); - bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx)); - return error; -} -#endif - -/* - * configure security policy index (src/dst/proto/sport/dport) - * by looking at the content of mbuf. - * the caller is responsible for error recovery (like clearing up spidx). - */ -static int -ipsec_setspidx(struct mbuf *m, struct secpolicyindex *spidx, int needport) -{ - struct ip *ip = NULL; - struct ip ipbuf; - u_int v; - struct mbuf *n; - int len; - int error; - - KASSERT(m != NULL, ("ipsec_setspidx: null mbuf")); - - /* - * validate m->m_pkthdr.len. we see incorrect length if we - * mistakenly call this function with inconsistent mbuf chain - * (like 4.4BSD tcp/udp processing). XXX should we panic here? - */ - len = 0; - for (n = m; n; n = n->m_next) - len += n->m_len; - if (m->m_pkthdr.len != len) { - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_setspidx: " - "total of m_len(%d) != pkthdr.len(%d), " - "ignored.\n", - len, m->m_pkthdr.len)); - return EINVAL; - } - - if (m->m_pkthdr.len < sizeof(struct ip)) { - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_setspidx: " - "pkthdr.len(%d) < sizeof(struct ip), ignored.\n", - m->m_pkthdr.len)); - return EINVAL; - } - - if (m->m_len >= sizeof(*ip)) - ip = mtod(m, struct ip *); - else { - m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf); - ip = &ipbuf; - } -#ifdef _IP_VHL - v = _IP_VHL_V(ip->ip_vhl); -#else - v = ip->ip_v; -#endif - switch (v) { - case 4: - error = ipsec4_setspidx_ipaddr(m, spidx); - if (error) - return error; - ipsec4_get_ulp(m, spidx, needport); - return 0; -#ifdef INET6 - case 6: - if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) { - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_setspidx: " - "pkthdr.len(%d) < sizeof(struct ip6_hdr), " - "ignored.\n", m->m_pkthdr.len)); - return EINVAL; - } - error = ipsec6_setspidx_ipaddr(m, spidx); - if (error) - return error; - ipsec6_get_ulp(m, spidx, needport); - return 0; -#endif - default: - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_setspidx: " - "unknown IP version %u, ignored.\n", v)); - return EINVAL; - } -} - -static void -ipsec4_get_ulp(struct mbuf *m, struct secpolicyindex *spidx, int needport) -{ - u_int8_t nxt; - int off; - - /* sanity check */ - KASSERT(m != NULL, ("ipsec4_get_ulp: null mbuf")); - KASSERT(m->m_pkthdr.len >= sizeof(struct ip), - ("ipsec4_get_ulp: packet too short")); - - /* NB: ip_input() flips it into host endian XXX need more checking */ - if (m->m_len < sizeof (struct ip)) { - struct ip *ip = mtod(m, struct ip *); - if (ip->ip_off & (IP_MF | IP_OFFMASK)) - goto done; -#ifdef _IP_VHL - off = _IP_VHL_HL(ip->ip_vhl) << 2; -#else - off = ip->ip_hl << 2; -#endif - nxt = ip->ip_p; - } else { - struct ip ih; - - m_copydata(m, 0, sizeof (struct ip), (caddr_t) &ih); - if (ih.ip_off & (IP_MF | IP_OFFMASK)) - goto done; -#ifdef _IP_VHL - off = _IP_VHL_HL(ih.ip_vhl) << 2; -#else - off = ih.ip_hl << 2; -#endif - 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: - if (off + sizeof(ip6e) > m->m_pkthdr.len) - goto done; - /* XXX sigh, this works but is totally bogus */ - m_copydata(m, off, sizeof(ip6e), (caddr_t) &ip6e); - off += (ip6e.ip6e_len + 2) << 2; - nxt = ip6e.ip6e_nxt; - break; - case IPPROTO_ICMP: - default: - /* XXX intermediate headers??? */ - 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; -} - -/* assumes that m is sane */ -static int -ipsec4_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx) -{ - static const struct sockaddr_in template = { - sizeof (struct sockaddr_in), - AF_INET, - 0, { 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } - }; - - spidx->src.sin = template; - spidx->dst.sin = template; - - if (m->m_len < sizeof (struct ip)) { - m_copydata(m, offsetof(struct ip, ip_src), - sizeof (struct in_addr), - (caddr_t) &spidx->src.sin.sin_addr); - m_copydata(m, offsetof(struct ip, ip_dst), - sizeof (struct in_addr), - (caddr_t) &spidx->dst.sin.sin_addr); - } else { - struct ip *ip = mtod(m, struct ip *); - spidx->src.sin.sin_addr = ip->ip_src; - spidx->dst.sin.sin_addr = ip->ip_dst; - } - - spidx->prefs = sizeof(struct in_addr) << 3; - spidx->prefd = sizeof(struct in_addr) << 3; - - return 0; -} - -#ifdef INET6 -static void -ipsec6_get_ulp(struct mbuf *m, struct secpolicyindex *spidx, int needport) -{ - int off, nxt; - struct tcphdr th; - struct udphdr uh; - - /* sanity check */ - if (m == NULL) - panic("ipsec6_get_ulp: NULL pointer was passed."); - - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec6_get_ulp:\n"); kdebug_mbuf(m)); - - /* set default */ - spidx->ul_proto = IPSEC_ULPROTO_ANY; - ((struct sockaddr_in6 *)&spidx->src)->sin6_port = IPSEC_PORT_ANY; - ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = IPSEC_PORT_ANY; - - 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); - ((struct sockaddr_in6 *)&spidx->src)->sin6_port = th.th_sport; - ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = th.th_dport; - 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); - ((struct sockaddr_in6 *)&spidx->src)->sin6_port = uh.uh_sport; - ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = uh.uh_dport; - break; - case IPPROTO_ICMPV6: - default: - /* XXX intermediate headers??? */ - spidx->ul_proto = nxt; - break; - } -} - -/* assumes that m is sane */ -static int -ipsec6_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx) -{ - struct ip6_hdr *ip6 = NULL; - struct ip6_hdr ip6buf; - struct sockaddr_in6 *sin6; - - if (m->m_len >= sizeof(*ip6)) - ip6 = mtod(m, struct ip6_hdr *); - else { - m_copydata(m, 0, sizeof(ip6buf), (caddr_t)&ip6buf); - ip6 = &ip6buf; - } - - sin6 = (struct sockaddr_in6 *)&spidx->src; - bzero(sin6, sizeof(*sin6)); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(struct sockaddr_in6); - bcopy(&ip6->ip6_src, &sin6->sin6_addr, sizeof(ip6->ip6_src)); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]); - } - spidx->prefs = sizeof(struct in6_addr) << 3; - - sin6 = (struct sockaddr_in6 *)&spidx->dst; - bzero(sin6, sizeof(*sin6)); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(struct sockaddr_in6); - bcopy(&ip6->ip6_dst, &sin6->sin6_addr, sizeof(ip6->ip6_dst)); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]); - } - spidx->prefd = sizeof(struct in6_addr) << 3; - - return 0; -} -#endif - -static void -ipsec_delpcbpolicy(struct inpcbpolicy *p) -{ - kfree(p, M_SECA); -} - -/* initialize policy in PCB */ -int -ipsec_init_policy(struct socket *so, struct inpcbpolicy **pcb_sp) -{ - struct inpcbpolicy *new; - - /* sanity check. */ - if (so == NULL || pcb_sp == NULL) - panic("ipsec_init_policy: NULL pointer was passed."); - - new = kmalloc(sizeof(struct inpcbpolicy), - M_SECA, M_INTWAIT | M_ZERO | M_NULLOK); - if (new == NULL) { - ipseclog((LOG_DEBUG, "ipsec_init_policy: No more memory.\n")); - return ENOBUFS; - } - - if (so->so_cred != 0 && so->so_cred->cr_uid == 0) - new->priv = 1; - else - new->priv = 0; - - if ((new->sp_in = KEY_NEWSP()) == NULL) { - ipsec_delpcbpolicy(new); - return ENOBUFS; - } - new->sp_in->state = IPSEC_SPSTATE_ALIVE; - new->sp_in->policy = IPSEC_POLICY_ENTRUST; - - if ((new->sp_out = KEY_NEWSP()) == NULL) { - KEY_FREESP(&new->sp_in); - ipsec_delpcbpolicy(new); - return ENOBUFS; - } - new->sp_out->state = IPSEC_SPSTATE_ALIVE; - new->sp_out->policy = IPSEC_POLICY_ENTRUST; - - *pcb_sp = new; - - return 0; -} - -/* copy old ipsec policy into new */ -int -ipsec_copy_policy(struct inpcbpolicy *old, struct inpcbpolicy *new) -{ - struct secpolicy *sp; - - sp = ipsec_deepcopy_policy(old->sp_in); - if (sp) { - KEY_FREESP(&new->sp_in); - new->sp_in = sp; - } else - return ENOBUFS; - - sp = ipsec_deepcopy_policy(old->sp_out); - if (sp) { - KEY_FREESP(&new->sp_out); - new->sp_out = sp; - } else - return ENOBUFS; - - new->priv = old->priv; - - return 0; -} - -/* deep-copy a policy in PCB */ -static struct secpolicy * -ipsec_deepcopy_policy(struct secpolicy *src) -{ - struct ipsecrequest *newchain = NULL; - struct ipsecrequest *p; - struct ipsecrequest **q; - struct ipsecrequest *r; - struct secpolicy *dst; - - if (src == NULL) - return NULL; - dst = KEY_NEWSP(); - if (dst == NULL) - return NULL; - - /* - * deep-copy IPsec request chain. This is required since struct - * ipsecrequest is not reference counted. - */ - q = &newchain; - for (p = src->req; p; p = p->next) { - *q = kmalloc(sizeof(struct ipsecrequest), - M_SECA, M_INTWAIT | M_ZERO | M_NULLOK); - if (*q == NULL) - goto fail; - (*q)->next = NULL; - - (*q)->saidx.proto = p->saidx.proto; - (*q)->saidx.mode = p->saidx.mode; - (*q)->level = p->level; - (*q)->saidx.reqid = p->saidx.reqid; - - bcopy(&p->saidx.src, &(*q)->saidx.src, sizeof((*q)->saidx.src)); - bcopy(&p->saidx.dst, &(*q)->saidx.dst, sizeof((*q)->saidx.dst)); - - (*q)->sav = NULL; - (*q)->sp = dst; - - q = &((*q)->next); - } - - dst->req = newchain; - dst->state = src->state; - dst->policy = src->policy; - /* do not touch the refcnt fields */ - - return dst; - -fail: - for (p = newchain; p; p = r) { - r = p->next; - kfree(p, M_SECA); - p = NULL; - } - return NULL; -} - -/* set policy and ipsec request if present. */ -static int -ipsec_set_policy(struct secpolicy **pcb_sp, int optname, caddr_t request, - size_t len, int priv) -{ - struct sadb_x_policy *xpl; - struct secpolicy *newsp = NULL; - int error; - - /* sanity check. */ - if (pcb_sp == NULL || *pcb_sp == NULL || request == NULL) - return EINVAL; - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_set_policy: passed policy\n"); - kdebug_sadb_x_policy((struct sadb_ext *)xpl)); - - /* check policy type */ - /* ipsec_set_policy() accepts IPSEC, ENTRUST and BYPASS. */ - if (xpl->sadb_x_policy_type == IPSEC_POLICY_DISCARD - || xpl->sadb_x_policy_type == IPSEC_POLICY_NONE) - return EINVAL; - - /* check privileged socket */ - if (priv == 0 && xpl->sadb_x_policy_type == IPSEC_POLICY_BYPASS) - return EACCES; - - /* allocation new SP entry */ - if ((newsp = key_msg2sp(xpl, len, &error)) == NULL) - return error; - - newsp->state = IPSEC_SPSTATE_ALIVE; - - /* clear old SP and set new SP */ - KEY_FREESP(pcb_sp); - *pcb_sp = newsp; - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_set_policy: new policy\n"); - kdebug_secpolicy(newsp)); - - return 0; -} - -static int -ipsec_get_policy(struct secpolicy *pcb_sp, struct mbuf **mp) -{ - - /* sanity check. */ - if (pcb_sp == NULL || mp == NULL) - return EINVAL; - - *mp = key_sp2msg(pcb_sp); - if (!*mp) { - ipseclog((LOG_DEBUG, "ipsec_get_policy: No more memory.\n")); - return ENOBUFS; - } - - KKASSERT((*mp)->m_type == MT_DATA); - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_get_policy:\n"); - kdebug_mbuf(*mp)); - - return 0; -} - -int -ipsec4_set_policy(struct inpcb *inp, int optname, caddr_t request, - size_t len, int priv) -{ - struct sadb_x_policy *xpl; - struct secpolicy **pcb_sp; - - /* sanity check. */ - if (inp == NULL || request == NULL) - return EINVAL; - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - /* select direction */ - switch (xpl->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - pcb_sp = &inp->inp_sp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - pcb_sp = &inp->inp_sp->sp_out; - break; - default: - ipseclog((LOG_ERR, "ipsec4_set_policy: invalid direction=%u\n", - xpl->sadb_x_policy_dir)); - return EINVAL; - } - - return ipsec_set_policy(pcb_sp, optname, request, len, priv); -} - -int -ipsec4_get_policy(struct inpcb *inp, caddr_t request, size_t len, - struct mbuf **mp) -{ - struct sadb_x_policy *xpl; - struct secpolicy *pcb_sp; - - /* sanity check. */ - if (inp == NULL || request == NULL || mp == NULL) - return EINVAL; - KASSERT(inp->inp_sp != NULL, ("ipsec4_get_policy: null inp_sp")); - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - /* select direction */ - switch (xpl->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - pcb_sp = inp->inp_sp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - pcb_sp = inp->inp_sp->sp_out; - break; - default: - ipseclog((LOG_ERR, "ipsec4_set_policy: invalid direction=%u\n", - xpl->sadb_x_policy_dir)); - return EINVAL; - } - - return ipsec_get_policy(pcb_sp, mp); -} - -/* delete policy in PCB */ -int -ipsec4_delete_pcbpolicy(struct inpcb *inp) -{ - KASSERT(inp != NULL, ("ipsec4_delete_pcbpolicy: null inp")); - - if (inp->inp_sp == NULL) - return 0; - - if (inp->inp_sp->sp_in != NULL) - KEY_FREESP(&inp->inp_sp->sp_in); - - if (inp->inp_sp->sp_out != NULL) - KEY_FREESP(&inp->inp_sp->sp_out); - - ipsec_delpcbpolicy(inp->inp_sp); - inp->inp_sp = NULL; - - return 0; -} - -#ifdef INET6 -int -ipsec6_set_policy(struct in6pcb *in6p, int optname, caddr_t request, - size_t len, int priv) -{ - struct sadb_x_policy *xpl; - struct secpolicy **pcb_sp; - - /* sanity check. */ - if (in6p == NULL || request == NULL) - return EINVAL; - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - /* select direction */ - switch (xpl->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - pcb_sp = &in6p->in6p_sp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - pcb_sp = &in6p->in6p_sp->sp_out; - break; - default: - ipseclog((LOG_ERR, "ipsec6_set_policy: invalid direction=%u\n", - xpl->sadb_x_policy_dir)); - return EINVAL; - } - - return ipsec_set_policy(pcb_sp, optname, request, len, priv); -} - -int -ipsec6_get_policy(struct in6pcb *in6p, caddr_t request, size_t len, - struct mbuf **mp) -{ - struct sadb_x_policy *xpl; - struct secpolicy *pcb_sp; - - /* sanity check. */ - if (in6p == NULL || request == NULL || mp == NULL) - return EINVAL; - KASSERT(in6p->in6p_sp != NULL, ("ipsec6_get_policy: null in6p_sp")); - if (len < sizeof(*xpl)) - return EINVAL; - xpl = (struct sadb_x_policy *)request; - - /* select direction */ - switch (xpl->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - pcb_sp = in6p->in6p_sp->sp_in; - break; - case IPSEC_DIR_OUTBOUND: - pcb_sp = in6p->in6p_sp->sp_out; - break; - default: - ipseclog((LOG_ERR, "ipsec6_set_policy: invalid direction=%u\n", - xpl->sadb_x_policy_dir)); - return EINVAL; - } - - return ipsec_get_policy(pcb_sp, mp); -} - -int -ipsec6_delete_pcbpolicy(struct in6pcb *in6p) -{ - KASSERT(in6p != NULL, ("ipsec6_delete_pcbpolicy: null in6p")); - - if (in6p->in6p_sp == NULL) - return 0; - - if (in6p->in6p_sp->sp_in != NULL) - KEY_FREESP(&in6p->in6p_sp->sp_in); - - if (in6p->in6p_sp->sp_out != NULL) - KEY_FREESP(&in6p->in6p_sp->sp_out); - - ipsec_delpcbpolicy(in6p->in6p_sp); - in6p->in6p_sp = NULL; - - return 0; -} -#endif - -/* - * return current level. - * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned. - */ -u_int -ipsec_get_reqlevel(struct ipsecrequest *isr) -{ - u_int level = 0; - u_int esp_trans_deflev, esp_net_deflev; - u_int ah_trans_deflev, ah_net_deflev; - - KASSERT(isr != NULL && isr->sp != NULL, - ("ipsec_get_reqlevel: null argument")); - KASSERT(isr->sp->spidx.src.sa.sa_family == isr->sp->spidx.dst.sa.sa_family, - ("ipsec_get_reqlevel: af family mismatch, src %u, dst %u", - isr->sp->spidx.src.sa.sa_family, - isr->sp->spidx.dst.sa.sa_family)); - -/* XXX note that we have ipseclog() expanded here - code sync issue */ -#define IPSEC_CHECK_DEFAULT(lev) \ - (((lev) != IPSEC_LEVEL_USE && (lev) != IPSEC_LEVEL_REQUIRE \ - && (lev) != IPSEC_LEVEL_UNIQUE) \ - ? (ipsec_debug \ - ? log(LOG_INFO, "fixed system default level " #lev ":%d->%d\n",\ - (lev), IPSEC_LEVEL_REQUIRE) \ - : 0), \ - (lev) = IPSEC_LEVEL_REQUIRE, \ - (lev) \ - : (lev)) - - /* set default level */ - switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) { -#ifdef INET - case AF_INET: - esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev); - esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev); - ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev); - ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev); - break; -#endif -#ifdef INET6 - case AF_INET6: - esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev); - esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev); - ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev); - ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev); - break; -#endif /* INET6 */ - default: - panic("key_get_reqlevel: unknown af %u", - isr->sp->spidx.src.sa.sa_family); - } - -#undef IPSEC_CHECK_DEFAULT - - /* set level */ - 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; - break; - case IPPROTO_IPCOMP: - /* - * we don't really care, as IPcomp document says that - * we shouldn't compress small packets - */ - level = IPSEC_LEVEL_USE; - break; - default: - panic("ipsec_get_reqlevel: " - "Illegal protocol defined %u\n", - 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: - panic("ipsec_get_reqlevel: Illegal IPsec level %u", - isr->level); - } - - return level; -} - -/* - * 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 - */ -int -ipsec_in_reject(struct secpolicy *sp, struct mbuf *m) -{ - struct ipsecrequest *isr; - int need_auth; - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec_in_reject: using SP\n"); - kdebug_secpolicy(sp)); - - /* check policy */ - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - return 1; - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_NONE: - return 0; - } - - KASSERT(sp->policy == IPSEC_POLICY_IPSEC, - ("ipsec_in_reject: invalid policy %u", sp->policy)); - - /* XXX should compare policy against ipsec header history */ - - need_auth = 0; - for (isr = sp->req; isr != NULL; isr = isr->next) { - if (ipsec_get_reqlevel(isr) != IPSEC_LEVEL_REQUIRE) - continue; - switch (isr->saidx.proto) { - case IPPROTO_ESP: - if ((m->m_flags & M_DECRYPTED) == 0) { - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_in_reject: ESP m_flags:%x\n", - m->m_flags)); - return 1; - } - - if (!need_auth && - isr->sav != NULL && - isr->sav->tdb_authalgxform != NULL && - (m->m_flags & M_AUTHIPDGM) == 0) { - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_in_reject: ESP/AH m_flags:%x\n", - m->m_flags)); - return 1; - } - break; - case IPPROTO_AH: - need_auth = 1; - if ((m->m_flags & M_AUTHIPHDR) == 0) { - KEYDEBUG(KEYDEBUG_IPSEC_DUMP, - kprintf("ipsec_in_reject: AH m_flags:%x\n", - m->m_flags)); - return 1; - } - break; - case IPPROTO_IPCOMP: - /* - * we don't really care, as IPcomp document - * says that we shouldn't compress small - * packets, IPComp policy should always be - * treated as being in "use" level. - */ - break; - } - } - return 0; /* valid */ -} - -/* - * Check AH/ESP integrity. - * This function is called from tcp_input(), udp_input(), - * and {ah,esp}4_input for tunnel mode - */ -int -ipsec4_in_reject(struct mbuf *m, struct inpcb *inp) -{ - struct secpolicy *sp; - int error; - int result; - - KASSERT(m != NULL, ("ipsec4_in_reject_so: null mbuf")); - - /* get SP for this packet. - * When we are called from ip_forward(), we call - * ipsec_getpolicybyaddr() with IP_FORWARDING flag. - */ - if (inp == NULL) - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error); - else - sp = ipsec_getpolicybysock(m, IPSEC_DIR_INBOUND, inp, &error); - - if (sp != NULL) { - result = ipsec_in_reject(sp, m); - if (result) - newipsecstat.ips_in_polvio++; - KEY_FREESP(&sp); - } else { - result = 0; /* XXX should be panic ? - * -> No, there may be error. */ - } - return result; -} - -#ifdef INET6 -/* - * Check AH/ESP integrity. - * This function is called from tcp6_input(), udp6_input(), - * and {ah,esp}6_input for tunnel mode - */ -int -ipsec6_in_reject(struct mbuf *m, struct inpcb *inp) -{ - struct secpolicy *sp = NULL; - int error; - int result; - - /* sanity check */ - if (m == NULL) - return 0; /* XXX should be panic ? */ - - /* get SP for this packet. - * When we are called from ip_forward(), we call - * ipsec_getpolicybyaddr() with IP_FORWARDING flag. - */ - if (inp == NULL) - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error); - else - sp = ipsec_getpolicybysock(m, IPSEC_DIR_INBOUND, inp, &error); - - if (sp != NULL) { - result = ipsec_in_reject(sp, m); - if (result) - newipsecstat.ips_in_polvio++; - KEY_FREESP(&sp); - } else { - result = 0; - } - return result; -} -#endif - -/* - * compute the byte size to be occupied by IPsec header. - * in case it is tunneled, it includes the size of outer IP header. - * NOTE: SP passed is free in this function. - */ -static size_t -ipsec_hdrsiz(struct secpolicy *sp) -{ - struct ipsecrequest *isr; - size_t siz; - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec_hdrsiz: using SP\n"); - kdebug_secpolicy(sp)); - - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - case IPSEC_POLICY_BYPASS: - case IPSEC_POLICY_NONE: - return 0; - } - - KASSERT(sp->policy == IPSEC_POLICY_IPSEC, - ("ipsec_hdrsiz: invalid policy %u", sp->policy)); - - siz = 0; - for (isr = sp->req; isr != NULL; isr = isr->next) { - size_t clen = 0; - - switch (isr->saidx.proto) { - case IPPROTO_ESP: - clen = esp_hdrsiz(isr->sav); - break; - case IPPROTO_AH: - clen = ah_hdrsiz(isr->sav); - break; - case IPPROTO_IPCOMP: - clen = sizeof(struct ipcomp); - break; - } - - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { - switch (isr->saidx.dst.sa.sa_family) { - case AF_INET: - clen += sizeof(struct ip); - break; -#ifdef INET6 - case AF_INET6: - clen += sizeof(struct ip6_hdr); - break; -#endif - default: - ipseclog((LOG_ERR, "ipsec_hdrsiz: " - "unknown AF %d in IPsec tunnel SA\n", - ((struct sockaddr *)&isr->saidx.dst)->sa_family)); - break; - } - } - siz += clen; - } - - return siz; -} - -/* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */ -size_t -ipsec4_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp) -{ - struct secpolicy *sp; - int error; - size_t size; - - KASSERT(m != NULL, ("ipsec4_hdrsiz: null mbuf")); - KASSERT(inp == NULL || inp->inp_socket != NULL, - ("ipsec4_hdrsize: socket w/o inpcb")); - - /* get SP for this packet. - * When we are called from ip_forward(), we call - * ipsec_getpolicybyaddr() with IP_FORWARDING flag. - */ - if (inp == NULL) - sp = ipsec_getpolicybyaddr(m, dir, IP_FORWARDING, &error); - else - sp = ipsec_getpolicybysock(m, dir, inp, &error); - - if (sp != NULL) { - size = ipsec_hdrsiz(sp); - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec4_hdrsiz: size:%lu.\n", - (unsigned long)size)); - - KEY_FREESP(&sp); - } else { - size = 0; /* XXX should be panic ? */ - } - return size; -} - -#ifdef INET6 -/* This function is called from ipsec6_hdrsize_tcp(), - * and maybe from ip6_forward.() - */ -size_t -ipsec6_hdrsiz(struct mbuf *m, u_int dir, struct in6pcb *in6p) -{ - struct secpolicy *sp; - int error; - size_t size; - - KASSERT(m != NULL, ("ipsec6_hdrsiz: null mbuf")); - KASSERT(in6p == NULL || in6p->in6p_socket != NULL, - ("ipsec6_hdrsize: socket w/o inpcb")); - - /* get SP for this packet */ - /* XXX Is it right to call with IP_FORWARDING. */ - if (in6p == NULL) - sp = ipsec_getpolicybyaddr(m, dir, IP_FORWARDING, &error); - else - sp = ipsec_getpolicybysock(m, dir, in6p, &error); - - if (sp == NULL) - return 0; - size = ipsec_hdrsiz(sp); - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec6_hdrsiz: size:%lu.\n", (unsigned long)size)); - KEY_FREESP(&sp); - - return size; -} -#endif /*INET6*/ - -/* - * 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. - * - * based on RFC 2401. - */ -int -ipsec_chkreplay(u_int32_t seq, struct secasvar *sav) -{ - const struct secreplay *replay; - u_int32_t diff; - int fr; - u_int32_t wsizeb; /* constant: bits of window size */ - int frlast; /* constant: last frame */ - - KASSERT(sav != NULL, ("ipsec_chkreplay: Null SA")); - KASSERT(sav->replay != NULL, ("ipsec_chkreplay: Null replay state")); - - replay = sav->replay; - - if (replay->wsize == 0) - return 1; /* no need to check replay. */ - - /* constant */ - frlast = replay->wsize - 1; - wsizeb = replay->wsize << 3; - - /* sequence number of 0 is invalid */ - if (seq == 0) - return 0; - - /* first time is always okay */ - if (replay->count == 0) - return 1; - - if (seq > replay->lastseq) { - /* larger sequences are okay */ - return 1; - } else { - /* seq is equal or less than lastseq. */ - diff = replay->lastseq - seq; - - /* over range to check, i.e. too old or wrapped */ - if (diff >= wsizeb) - return 0; - - fr = frlast - diff / 8; - - /* this packet already seen ? */ - if ((replay->bitmap)[fr] & (1 << (diff % 8))) - return 0; - - /* out of order but good */ - return 1; - } -} - -/* - * check replay counter whether to update or not. - * OUT: 0: OK - * 1: NG - */ -int -ipsec_updatereplay(u_int32_t seq, struct secasvar *sav) -{ - struct secreplay *replay; - u_int32_t diff; - int fr; - u_int32_t wsizeb; /* constant: bits of window size */ - int frlast; /* constant: last frame */ - - KASSERT(sav != NULL, ("ipsec_updatereplay: Null SA")); - KASSERT(sav->replay != NULL, ("ipsec_updatereplay: Null replay state")); - - replay = sav->replay; - - if (replay->wsize == 0) - goto ok; /* no need to check replay. */ - - /* constant */ - frlast = replay->wsize - 1; - wsizeb = replay->wsize << 3; - - /* sequence number of 0 is invalid */ - if (seq == 0) - return 1; - - /* first time */ - if (replay->count == 0) { - replay->lastseq = seq; - bzero(replay->bitmap, replay->wsize); - (replay->bitmap)[frlast] = 1; - goto ok; - } - - if (seq > replay->lastseq) { - /* seq is larger than lastseq. */ - diff = seq - replay->lastseq; - - /* new larger sequence number */ - if (diff < wsizeb) { - /* In window */ - /* set bit for this packet */ - vshiftl(replay->bitmap, diff, replay->wsize); - (replay->bitmap)[frlast] |= 1; - } else { - /* this packet has a "way larger" */ - bzero(replay->bitmap, replay->wsize); - (replay->bitmap)[frlast] = 1; - } - replay->lastseq = seq; - - /* larger is good */ - } else { - /* seq is equal or less than lastseq. */ - diff = replay->lastseq - seq; - - /* over range to check, i.e. too old or wrapped */ - if (diff >= wsizeb) - return 1; - - fr = frlast - diff / 8; - - /* this packet already seen ? */ - if ((replay->bitmap)[fr] & (1 << (diff % 8))) - return 1; - - /* mark as seen */ - (replay->bitmap)[fr] |= (1 << (diff % 8)); - - /* out of order but good */ - } - -ok: - if (replay->count == ~0) { - - /* set overflow flag */ - replay->overflow++; - - /* don't increment, no more packets accepted */ - if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) - return 1; - - ipseclog((LOG_WARNING, "replay counter made %d cycle. %s\n", - replay->overflow, ipsec_logsastr(sav))); - } - - replay->count++; - - return 0; -} - -/* - * shift variable length buffer to left. - * IN: bitmap: pointer to the buffer - * nbit: the number of to shift. - * wsize: buffer size (bytes). - */ -static void -vshiftl(unsigned char *bitmap, int nbit, int wsize) -{ - int s, j, i; - unsigned char over; - - for (j = 0; j < nbit; j += 8) { - s = (nbit - j < 8) ? (nbit - j): 8; - bitmap[0] <<= s; - for (i = 1; i < wsize; i++) { - over = (bitmap[i] >> (8 - s)); - bitmap[i] <<= s; - bitmap[i-1] |= over; - } - } - - return; -} - -/* Return a printable string for the address. */ -char * -ipsec_address(union sockaddr_union* sa) -{ - /* XXX not MPSAFE */ - static char sbuf[INET_ADDRSTRLEN]; - - switch (sa->sa.sa_family) { -#if INET - case AF_INET: - return kinet_ntoa(sa->sin.sin_addr, sbuf); -#endif /* INET */ - -#if INET6 - case AF_INET6: - return ip6_sprintf(&sa->sin6.sin6_addr); -#endif /* INET6 */ - - default: - return "(unknown address family)"; - } -} - -const char * -ipsec_logsastr(struct secasvar *sav) -{ - static char buf[256]; - char *p; - struct secasindex *saidx = &sav->sah->saidx; - - KASSERT(saidx->src.sa.sa_family == saidx->dst.sa.sa_family, - ("ipsec_logsastr: address family mismatch")); - - p = buf; - ksnprintf(buf, sizeof(buf), "SA(SPI=%u ", (u_int32_t)ntohl(sav->spi)); - while (p && *p) - p++; - /* NB: only use ipsec_address on one address at a time */ - ksnprintf(p, sizeof (buf) - (p - buf), "src=%s ", - ipsec_address(&saidx->src)); - while (p && *p) - p++; - ksnprintf(p, sizeof (buf) - (p - buf), "dst=%s)", - ipsec_address(&saidx->dst)); - - return buf; -} - -void -ipsec_dumpmbuf(struct mbuf *m) -{ - int totlen; - int i; - u_char *p; - - totlen = 0; - kprintf("---\n"); - while (m) { - p = mtod(m, u_char *); - for (i = 0; i < m->m_len; i++) { - kprintf("%02x ", p[i]); - totlen++; - if (totlen % 16 == 0) - kprintf("\n"); - } - m = m->m_next; - } - if (totlen % 16 != 0) - kprintf("\n"); - kprintf("---\n"); -} - -/* XXX this stuff doesn't belong here... */ - -static struct xformsw* xforms = NULL; - -/* - * Register a transform; typically at system startup. - */ -void -xform_register(struct xformsw* xsp) -{ - xsp->xf_next = xforms; - xforms = xsp; -} - -/* - * Initialize transform support in an sav. - */ -int -xform_init(struct secasvar *sav, int xftype) -{ - struct xformsw *xsp; - - if (sav->tdb_xform != NULL) /* previously initialized */ - return 0; - for (xsp = xforms; xsp; xsp = xsp->xf_next) - if (xsp->xf_type == xftype) - return (*xsp->xf_init)(sav, xsp); - return EINVAL; -} diff --git a/sys/netproto/ipsec/ipsec.h b/sys/netproto/ipsec/ipsec.h deleted file mode 100644 index d6b4a63975..0000000000 --- a/sys/netproto/ipsec/ipsec.h +++ /dev/null @@ -1,390 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/ipsec.h,v 1.2.4.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/ipsec.h,v 1.5 2006/12/22 23:57:54 swildner Exp $ */ -/* $KAME: ipsec.h,v 1.53 2001/11/20 08:32:38 itojun Exp $ */ - -/* - * 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. - */ - -#ifndef _NETIPSEC_IPSEC_H_ -#define _NETIPSEC_IPSEC_H_ - -#if defined(_KERNEL) && !defined(_LKM) && !defined(KLD_MODULE) -#include "opt_inet.h" -#include "opt_ipsec.h" -#endif - -#include -#include "keydb.h" - -#ifdef _KERNEL - -/* - * Security Policy Index - * Ensure that both address families in the "src" and "dst" are same. - * When the value of the ul_proto is ICMPv6, the port field in "src" - * specifies ICMPv6 type, and the port field in "dst" specifies ICMPv6 code. - */ -struct secpolicyindex { - u_int8_t dir; /* direction of packet flow, see blow */ - union sockaddr_union src; /* IP src address for SP */ - union sockaddr_union dst; /* IP dst address for SP */ - u_int8_t prefs; /* prefix length in bits for src */ - u_int8_t prefd; /* prefix length in bits for dst */ - u_int16_t ul_proto; /* upper layer Protocol */ -#ifdef notyet - uid_t uids; - uid_t uidd; - gid_t gids; - gid_t gidd; -#endif -}; - -/* Security Policy Data Base */ -struct secpolicy { - LIST_ENTRY(secpolicy) chain; - - u_int refcnt; /* reference count */ - struct secpolicyindex spidx; /* selector */ - u_int32_t id; /* It's unique number on the system. */ - u_int state; /* 0: dead, others: alive */ -#define IPSEC_SPSTATE_DEAD 0 -#define IPSEC_SPSTATE_ALIVE 1 - - u_int policy; /* DISCARD, NONE or IPSEC, see keyv2.h */ - struct ipsecrequest *req; - /* pointer to the ipsec request tree, */ - /* if policy == IPSEC else this value == NULL.*/ - - /* - * lifetime handler. - * the policy can be used without limitiation if both lifetime and - * validtime are zero. - * "lifetime" is passed by sadb_lifetime.sadb_lifetime_addtime. - * "validtime" is passed by sadb_lifetime.sadb_lifetime_usetime. - */ - long created; /* time created the policy */ - long lastused; /* updated every when kernel sends a packet */ - long lifetime; /* duration of the lifetime of this policy */ - long validtime; /* duration this policy is valid without use */ -}; - -/* Request for IPsec */ -struct ipsecrequest { - struct ipsecrequest *next; - /* pointer to next structure */ - /* If NULL, it means the end of chain. */ - struct secasindex saidx;/* hint for search proper SA */ - /* if __ss_len == 0 then no address specified.*/ - u_int level; /* IPsec level defined below. */ - - struct secasvar *sav; /* place holder of SA for use */ - struct secpolicy *sp; /* back pointer to SP */ -}; - -/* security policy in PCB */ -struct inpcbpolicy { - struct secpolicy *sp_in; - struct secpolicy *sp_out; - int priv; /* privileged socket ? */ -}; - -/* SP acquiring list table. */ -struct secspacq { - LIST_ENTRY(secspacq) chain; - - struct secpolicyindex spidx; - - long created; /* for lifetime */ - int count; /* for lifetime */ - /* XXX: here is mbuf place holder to be sent ? */ -}; -#endif /* _KERNEL */ - -/* according to IANA assignment, port 0x0000 and proto 0xff are reserved. */ -#define IPSEC_PORT_ANY 0 -#define IPSEC_ULPROTO_ANY 255 -#define IPSEC_PROTO_ANY 255 - -/* mode of security protocol */ -/* NOTE: DON'T use IPSEC_MODE_ANY at SPD. It's only use in SAD */ -#define IPSEC_MODE_ANY 0 /* i.e. wildcard. */ -#define IPSEC_MODE_TRANSPORT 1 -#define IPSEC_MODE_TUNNEL 2 - -/* - * Direction of security policy. - * NOTE: Since INVALID is used just as flag. - * The other are used for loop counter too. - */ -#define IPSEC_DIR_ANY 0 -#define IPSEC_DIR_INBOUND 1 -#define IPSEC_DIR_OUTBOUND 2 -#define IPSEC_DIR_MAX 3 -#define IPSEC_DIR_INVALID 4 - -/* Policy level */ -/* - * IPSEC, ENTRUST and BYPASS are allowed for setsockopt() in PCB, - * DISCARD, IPSEC and NONE are allowed for setkey() in SPD. - * DISCARD and NONE are allowed for system default. - */ -#define IPSEC_POLICY_DISCARD 0 /* discarding packet */ -#define IPSEC_POLICY_NONE 1 /* through IPsec engine */ -#define IPSEC_POLICY_IPSEC 2 /* do IPsec */ -#define IPSEC_POLICY_ENTRUST 3 /* consulting SPD if present. */ -#define IPSEC_POLICY_BYPASS 4 /* only for privileged socket. */ - -/* Security protocol level */ -#define IPSEC_LEVEL_DEFAULT 0 /* reference to system default */ -#define IPSEC_LEVEL_USE 1 /* use SA if present. */ -#define IPSEC_LEVEL_REQUIRE 2 /* require SA. */ -#define IPSEC_LEVEL_UNIQUE 3 /* unique SA. */ - -#define IPSEC_MANUAL_REQID_MAX 0x3fff - /* - * if security policy level == unique, this id - * indicate to a relative SA for use, else is - * zero. - * 1 - 0x3fff are reserved for manual keying. - * 0 are reserved for above reason. Others is - * for kernel use. - * Note that this id doesn't identify SA - * by only itself. - */ -#define IPSEC_REPLAYWSIZE 32 - -/* old statistics for ipsec processing */ -struct ipsecstat { - u_quad_t in_success; /* succeeded inbound process */ - u_quad_t in_polvio; - /* security policy violation for inbound process */ - u_quad_t in_nosa; /* inbound SA is unavailable */ - u_quad_t in_inval; /* inbound processing failed due to EINVAL */ - u_quad_t in_nomem; /* inbound processing failed due to ENOBUFS */ - u_quad_t in_badspi; /* failed getting a SPI */ - u_quad_t in_ahreplay; /* AH replay check failed */ - u_quad_t in_espreplay; /* ESP replay check failed */ - u_quad_t in_ahauthsucc; /* AH authentication success */ - u_quad_t in_ahauthfail; /* AH authentication failure */ - u_quad_t in_espauthsucc; /* ESP authentication success */ - u_quad_t in_espauthfail; /* ESP authentication failure */ - u_quad_t in_esphist[256]; - u_quad_t in_ahhist[256]; - u_quad_t in_comphist[256]; - u_quad_t out_success; /* succeeded outbound process */ - u_quad_t out_polvio; - /* security policy violation for outbound process */ - u_quad_t out_nosa; /* outbound SA is unavailable */ - u_quad_t out_inval; /* outbound process failed due to EINVAL */ - u_quad_t out_nomem; /* inbound processing failed due to ENOBUFS */ - u_quad_t out_noroute; /* there is no route */ - u_quad_t out_esphist[256]; - u_quad_t out_ahhist[256]; - u_quad_t out_comphist[256]; -}; - -/* statistics for ipsec processing */ -struct newipsecstat { - u_int32_t ips_in_polvio; /* input: sec policy violation */ - u_int32_t ips_out_polvio; /* output: sec policy violation */ - u_int32_t ips_out_nosa; /* output: SA unavailable */ - u_int32_t ips_out_nomem; /* output: no memory available */ - u_int32_t ips_out_noroute; /* output: no route available */ - u_int32_t ips_out_inval; /* output: generic error */ - u_int32_t ips_out_bundlesa; /* output: bundled SA processed */ - u_int32_t ips_mbcoalesced; /* mbufs coalesced during clone */ - u_int32_t ips_clcoalesced; /* clusters coalesced during clone */ - u_int32_t ips_clcopied; /* clusters copied during clone */ - u_int32_t ips_mbinserted; /* mbufs inserted during makespace */ - /* - * Temporary statistics for performance analysis. - */ - /* See where ESP/AH/IPCOMP header land in mbuf on input */ - u_int32_t ips_input_front; - u_int32_t ips_input_middle; - u_int32_t ips_input_end; -}; - -/* - * Definitions for IPsec & Key sysctl operations. - */ -/* - * Names for IPsec & Key sysctl objects - */ -#define IPSECCTL_STATS 1 /* stats */ -#define IPSECCTL_DEF_POLICY 2 -#define IPSECCTL_DEF_ESP_TRANSLEV 3 /* int; ESP transport mode */ -#define IPSECCTL_DEF_ESP_NETLEV 4 /* int; ESP tunnel mode */ -#define IPSECCTL_DEF_AH_TRANSLEV 5 /* int; AH transport mode */ -#define IPSECCTL_DEF_AH_NETLEV 6 /* int; AH tunnel mode */ -#if 0 /* obsolete, do not reuse */ -#define IPSECCTL_INBOUND_CALL_IKE 7 -#endif -#define IPSECCTL_AH_CLEARTOS 8 -#define IPSECCTL_AH_OFFSETMASK 9 -#define IPSECCTL_DFBIT 10 -#define IPSECCTL_ECN 11 -#define IPSECCTL_DEBUG 12 -#define IPSECCTL_ESP_RANDPAD 13 -#define IPSECCTL_MAXID 14 - -#define IPSECCTL_NAMES { \ - { 0, 0 }, \ - { 0, 0 }, \ - { "def_policy", CTLTYPE_INT }, \ - { "esp_trans_deflev", CTLTYPE_INT }, \ - { "esp_net_deflev", CTLTYPE_INT }, \ - { "ah_trans_deflev", CTLTYPE_INT }, \ - { "ah_net_deflev", CTLTYPE_INT }, \ - { 0, 0 }, \ - { "ah_cleartos", CTLTYPE_INT }, \ - { "ah_offsetmask", CTLTYPE_INT }, \ - { "dfbit", CTLTYPE_INT }, \ - { "ecn", CTLTYPE_INT }, \ - { "debug", CTLTYPE_INT }, \ - { "esp_randpad", CTLTYPE_INT }, \ -} - -#define IPSEC6CTL_NAMES { \ - { 0, 0 }, \ - { 0, 0 }, \ - { "def_policy", CTLTYPE_INT }, \ - { "esp_trans_deflev", CTLTYPE_INT }, \ - { "esp_net_deflev", CTLTYPE_INT }, \ - { "ah_trans_deflev", CTLTYPE_INT }, \ - { "ah_net_deflev", CTLTYPE_INT }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { "ecn", CTLTYPE_INT }, \ - { "debug", CTLTYPE_INT }, \ - { "esp_randpad", CTLTYPE_INT }, \ -} - -#ifdef _KERNEL -struct ipsec_output_state { - struct mbuf *m; - struct route *ro; - struct sockaddr *dst; -}; - -struct ipsec_history { - int ih_proto; - u_int32_t ih_spi; -}; - -extern int ipsec_debug; - -extern struct newipsecstat newipsecstat; -extern struct secpolicy ip4_def_policy; -extern int ip4_esp_trans_deflev; -extern int ip4_esp_net_deflev; -extern int ip4_ah_trans_deflev; -extern int ip4_ah_net_deflev; -extern int ip4_ah_cleartos; -extern int ip4_ah_offsetmask; -extern int ip4_ipsec_dfbit; -extern int ip4_ipsec_ecn; -extern int ip4_esp_randpad; -extern int crypto_support; - -#define ipseclog(x) do { if (ipsec_debug) log x; } while (0) -/* for openbsd compatibility */ -#define DPRINTF(x) do { if (ipsec_debug) kprintf x; } while (0) - -struct tdb_ident; -extern struct secpolicy *ipsec_getpolicy (struct tdb_ident*, u_int); -struct inpcb; -extern struct secpolicy *ipsec4_checkpolicy (struct mbuf *, u_int, u_int, - int *, struct inpcb *); -extern struct secpolicy *ipsec_getpolicybysock(struct mbuf *, u_int, - struct inpcb *, int *); -extern struct secpolicy * ipsec_getpolicybyaddr(struct mbuf *, u_int, - int, int *); - -struct inpcb; -extern int ipsec_init_policy (struct socket *so, struct inpcbpolicy **); -extern int ipsec_copy_policy - (struct inpcbpolicy *, struct inpcbpolicy *); -extern u_int ipsec_get_reqlevel (struct ipsecrequest *); -extern int ipsec_in_reject (struct secpolicy *, struct mbuf *); - -extern int ipsec4_set_policy (struct inpcb *inp, int optname, - caddr_t request, size_t len, int priv); -extern int ipsec4_get_policy (struct inpcb *inpcb, caddr_t request, - size_t len, struct mbuf **mp); -extern int ipsec4_delete_pcbpolicy (struct inpcb *); -extern int ipsec4_in_reject (struct mbuf *, struct inpcb *); - -struct secas; -struct tcpcb; -extern int ipsec_chkreplay (u_int32_t, struct secasvar *); -extern int ipsec_updatereplay (u_int32_t, struct secasvar *); - -extern size_t ipsec4_hdrsiz (struct mbuf *, u_int, struct inpcb *); -extern size_t ipsec_hdrsiz_tcp (struct tcpcb *); - -union sockaddr_union; -extern char * ipsec_address(union sockaddr_union* sa); -extern const char *ipsec_logsastr (struct secasvar *); - -extern void ipsec_dumpmbuf (struct mbuf *); - -struct m_tag; -extern int ipsec4_common_input(struct mbuf **m, int *offp, int proto); -extern int ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, - int skip, int protoff, struct m_tag *mt); -extern int ipsec4_process_packet (struct mbuf *, struct ipsecrequest *, - int, int); -extern int ipsec_process_done (struct mbuf *, struct ipsecrequest *); - -extern struct mbuf *ipsec_copypkt (struct mbuf *); - -extern void m_checkalignment(const char* where, struct mbuf *m0, - int off, int len); -extern struct mbuf *m_clone(struct mbuf *m0); -extern struct mbuf *m_makespace(struct mbuf *m0, int skip, int hlen, int *off); -extern caddr_t m_pad(struct mbuf *m, int n); -extern int m_striphdr(struct mbuf *m, int skip, int hlen); -#endif /* _KERNEL */ - -#ifndef _KERNEL -extern caddr_t ipsec_set_policy (char *, int); -extern int ipsec_get_policylen (caddr_t); -extern char *ipsec_dump_policy (caddr_t, char *); - -extern const char *ipsec_strerror (void); -#endif /* !_KERNEL */ - -#endif /* _NETIPSEC_IPSEC_H_ */ diff --git a/sys/netproto/ipsec/ipsec6.h b/sys/netproto/ipsec/ipsec6.h deleted file mode 100644 index 6fc1b22e2e..0000000000 --- a/sys/netproto/ipsec/ipsec6.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/ipsec6.h,v 1.1.4.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/ipsec6.h,v 1.4 2003/08/23 10:06:23 rob Exp $ */ -/* $KAME: ipsec.h,v 1.44 2001/03/23 08:08:47 itojun Exp $ */ - -/* - * 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. - */ - -#ifndef _NETIPSEC_IPSEC6_H_ -#define _NETIPSEC_IPSEC6_H_ - -#include -#include "keydb.h" - -#ifdef _KERNEL -extern int ip6_esp_trans_deflev; -extern int ip6_esp_net_deflev; -extern int ip6_ah_trans_deflev; -extern int ip6_ah_net_deflev; -extern int ip6_ipsec_ecn; -extern int ip6_esp_randpad; - -struct inpcb; -union netmsg; - -/* KAME compatibility shims */ -#define ipsec6_getpolicybyaddr ipsec_getpolicybyaddr -#define ipsec6_getpolicybysock ipsec_getpolicybysock -#define ipsec6stat newipsecstat -#define out_inval ips_out_inval -#define in_polvio ips_in_polvio -#define out_polvio ips_out_polvio -#define key_freesp(_x) KEY_FREESP(&_x) - -extern int ipsec6_delete_pcbpolicy (struct inpcb *); -extern int ipsec6_set_policy (struct inpcb *inp, int optname, - caddr_t request, size_t len, int priv); -extern int ipsec6_get_policy - (struct inpcb *inp, caddr_t request, size_t len, struct mbuf **mp); -extern int ipsec6_in_reject (struct mbuf *, struct inpcb *); - -struct tcp6cb; - -extern size_t ipsec6_hdrsiz (struct mbuf *, u_int, struct inpcb *); - -struct ip6_hdr; -extern const char *ipsec6_logpacketstr (struct ip6_hdr *, u_int32_t); - -struct m_tag; -extern int ipsec6_common_input(struct mbuf **mp, int *offp, int proto); -extern int ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, - int skip, int protoff, struct m_tag *mt); -extern void esp6_ctlinput(union netmsg *); - -struct ipsec_output_state; -extern int ipsec6_output_trans (struct ipsec_output_state *, u_char *, - struct mbuf *, struct secpolicy *, int, int *); -extern int ipsec6_output_tunnel (struct ipsec_output_state *, - struct secpolicy *, int); -#endif /*_KERNEL*/ - -#endif /*_NETIPSEC_IPSEC6_H_*/ diff --git a/sys/netproto/ipsec/ipsec_input.c b/sys/netproto/ipsec/ipsec_input.c deleted file mode 100644 index 615ac4525c..0000000000 --- a/sys/netproto/ipsec/ipsec_input.c +++ /dev/null @@ -1,782 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/ipsec_input.c,v 1.2.4.2 2003/03/28 20:32:53 sam Exp $ */ -/* $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $ */ -/* - * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). - * - * This code was written by John Ioannidis for BSD/OS in Athens, Greece, - * in November 1995. - * - * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, - * by Angelos D. Keromytis. - * - * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis - * and Niels Provos. - * - * Additional features in 1999 by Angelos D. Keromytis. - * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, - * Angelos D. Keromytis and Niels Provos. - * Copyright (c) 2001, Angelos D. Keromytis. - * - * Permission to use, copy, and modify this software with or without fee - * is hereby granted, provided that this entire notice is included in - * all copies of any software which is or includes a copy or - * modification of this software. - * You may use this code under the GNU public license if you so wish. Please - * contribute changes back to the authors under this freer than GPL license - * so that we may further the use of strong encryption without limitations to - * all. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE - * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR - * PURPOSE. - */ - -/* - * IPsec input processing. - */ - -#include "opt_inet.h" -#include "opt_inet6.h" -#include "opt_ipsec.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include - -#define IPSEC_ISTAT(p,x,y,z) ((p) == IPPROTO_ESP ? (x)++ : \ - (p) == IPPROTO_AH ? (y)++ : (z)++) - -/* - * ipsec_common_input gets called when an IPsec-protected packet - * is received by IPv4 or IPv6. It's job is to find the right SA - # and call the appropriate transform. The transform callback - * takes care of further processing (like ingress filtering). - */ -static int -ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto) -{ - union sockaddr_union dst_address; - struct secasvar *sav; - u_int32_t spi; - int error; - - IPSEC_ISTAT(sproto, espstat.esps_input, ahstat.ahs_input, - ipcompstat.ipcomps_input); - - KASSERT(m != NULL, ("ipsec_common_input: null packet")); - - if ((sproto == IPPROTO_ESP && !esp_enable) || - (sproto == IPPROTO_AH && !ah_enable) || - (sproto == IPPROTO_IPCOMP && !ipcomp_enable)) { - m_freem(m); - IPSEC_ISTAT(sproto, espstat.esps_pdrops, ahstat.ahs_pdrops, - ipcompstat.ipcomps_pdrops); - return EOPNOTSUPP; - } - - if (m->m_pkthdr.len - skip < 2 * sizeof (u_int32_t)) { - m_freem(m); - IPSEC_ISTAT(sproto, espstat.esps_hdrops, ahstat.ahs_hdrops, - ipcompstat.ipcomps_hdrops); - DPRINTF(("ipsec_common_input: packet too small\n")); - return EINVAL; - } - - /* Retrieve the SPI from the relevant IPsec header */ - if (sproto == IPPROTO_ESP) - m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi); - else if (sproto == IPPROTO_AH) - m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t), - (caddr_t) &spi); - else if (sproto == IPPROTO_IPCOMP) { - u_int16_t cpi; - m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t), - (caddr_t) &cpi); - spi = ntohl(htons(cpi)); - } - - /* - * Find the SA and (indirectly) call the appropriate - * kernel crypto routine. The resulting mbuf chain is a valid - * IP packet ready to go through input processing. - */ - bzero(&dst_address, sizeof (dst_address)); - dst_address.sa.sa_family = af; - switch (af) { -#ifdef INET - case AF_INET: - dst_address.sin.sin_len = sizeof(struct sockaddr_in); - m_copydata(m, offsetof(struct ip, ip_dst), - sizeof(struct in_addr), - (caddr_t) &dst_address.sin.sin_addr); - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6); - m_copydata(m, offsetof(struct ip6_hdr, ip6_dst), - sizeof(struct in6_addr), - (caddr_t) &dst_address.sin6.sin6_addr); - break; -#endif /* INET6 */ - default: - DPRINTF(("ipsec_common_input: unsupported protocol " - "family %u\n", af)); - m_freem(m); - IPSEC_ISTAT(sproto, espstat.esps_nopf, ahstat.ahs_nopf, - ipcompstat.ipcomps_nopf); - return EPFNOSUPPORT; - } - - crit_enter(); - - /* NB: only pass dst since key_allocsa follows RFC2401 */ - sav = KEY_ALLOCSA(&dst_address, sproto, spi); - if (sav == NULL) { - DPRINTF(("ipsec_common_input: no key association found for" - " SA %s/%08lx/%u\n", - ipsec_address(&dst_address), - (u_long) ntohl(spi), sproto)); - IPSEC_ISTAT(sproto, espstat.esps_notdb, ahstat.ahs_notdb, - ipcompstat.ipcomps_notdb); - crit_exit(); - m_freem(m); - return ENOENT; - } - - if (sav->tdb_xform == NULL) { - DPRINTF(("ipsec_common_input: attempted to use uninitialized" - " SA %s/%08lx/%u\n", - ipsec_address(&dst_address), - (u_long) ntohl(spi), sproto)); - IPSEC_ISTAT(sproto, espstat.esps_noxform, ahstat.ahs_noxform, - ipcompstat.ipcomps_noxform); - KEY_FREESAV(&sav); - crit_exit(); - m_freem(m); - return ENXIO; - } - - /* - * Call appropriate transform and return -- callback takes care of - * everything else. - */ - error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff); - KEY_FREESAV(&sav); - crit_exit(); - return error; -} - -#ifdef INET -/* - * Common input handler for IPv4 AH, ESP, and IPCOMP. - */ -int -ipsec4_common_input(struct mbuf **m, int *offp, int proto) -{ - return ipsec_common_input(*m, *offp, offsetof(struct ip, ip_p), - AF_INET, proto); -} - -/* - * IPsec input callback for INET protocols. - * This routine is called as the transform callback. - * Takes care of filtering and other sanity checks on - * the processed packet. - */ -int -ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, - int skip, int protoff, struct m_tag *mt) -{ - int prot, af, sproto; - struct ip *ip; - struct m_tag *mtag; - struct tdb_ident *tdbi; - struct secasindex *saidx; - int error; - - KASSERT(m != NULL, ("ipsec4_common_input_cb: null mbuf")); - KASSERT(sav != NULL, ("ipsec4_common_input_cb: null SA")); - KASSERT(sav->sah != NULL, ("ipsec4_common_input_cb: null SAH")); - saidx = &sav->sah->saidx; - af = saidx->dst.sa.sa_family; - KASSERT(af == AF_INET, ("ipsec4_common_input_cb: unexpected af %u",af)); - sproto = saidx->proto; - KASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH || - sproto == IPPROTO_IPCOMP, - ("ipsec4_common_input_cb: unexpected security protocol %u", - sproto)); - - /* Sanity check */ - if (m == NULL) { - DPRINTF(("ipsec4_common_input_cb: null mbuf")); - IPSEC_ISTAT(sproto, espstat.esps_badkcr, ahstat.ahs_badkcr, - ipcompstat.ipcomps_badkcr); - KEY_FREESAV(&sav); - return EINVAL; - } - - if (skip != 0) { - /* Fix IPv4 header */ - if (m->m_len < skip && (m = m_pullup(m, skip)) == NULL) { - DPRINTF(("ipsec4_common_input_cb: processing failed " - "for SA %s/%08lx\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - IPSEC_ISTAT(sproto, espstat.esps_hdrops, ahstat.ahs_hdrops, - ipcompstat.ipcomps_hdrops); - error = ENOBUFS; - goto bad; - } - - ip = mtod(m, struct ip *); - ip->ip_len = htons(m->m_pkthdr.len); - ip->ip_off = htons(ip->ip_off); - ip->ip_sum = 0; - ip->ip_sum = in_cksum(m, ip->ip_hl << 2); - } else { - ip = mtod(m, struct ip *); - } - prot = ip->ip_p; - - /* IP-in-IP encapsulation */ - if (prot == IPPROTO_IPIP) { - struct ip ipn; - - if (m->m_pkthdr.len - skip < sizeof(struct ip)) { - IPSEC_ISTAT(sproto, espstat.esps_hdrops, - ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops); - error = EINVAL; - goto bad; - } - - /* ipn will now contain the inner IPv4 header */ - m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn); - -#ifdef notyet - /* XXX PROXY address isn't recorded in SAH */ - /* - * Check that the inner source address is the same as - * the proxy address, if available. - */ - if ((saidx->proxy.sa.sa_family == AF_INET && - saidx->proxy.sin.sin_addr.s_addr != - INADDR_ANY && - ipn.ip_src.s_addr != - saidx->proxy.sin.sin_addr.s_addr) || - (saidx->proxy.sa.sa_family != AF_INET && - saidx->proxy.sa.sa_family != 0)) { - - DPRINTF(("ipsec4_common_input_cb: inner " - "source address %s doesn't correspond to " - "expected proxy source %s, SA %s/%08lx\n", - inet_ntoa4(ipn.ip_src), - ipsp_address(saidx->proxy), - ipsp_address(saidx->dst), - (u_long) ntohl(sav->spi))); - - IPSEC_ISTAT(sproto, espstat.esps_pdrops, - ahstat.ahs_pdrops, - ipcompstat.ipcomps_pdrops); - error = EACCES; - goto bad; - } -#endif /*XXX*/ - } -#if INET6 - /* IPv6-in-IP encapsulation. */ - if (prot == IPPROTO_IPV6) { - struct ip6_hdr ip6n; - - if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) { - IPSEC_ISTAT(sproto, espstat.esps_hdrops, - ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops); - error = EINVAL; - goto bad; - } - - /* ip6n will now contain the inner IPv6 header. */ - m_copydata(m, skip, sizeof(struct ip6_hdr), (caddr_t) &ip6n); - -#ifdef notyet - /* - * Check that the inner source address is the same as - * the proxy address, if available. - */ - if ((saidx->proxy.sa.sa_family == AF_INET6 && - !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) && - !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src, - &saidx->proxy.sin6.sin6_addr)) || - (saidx->proxy.sa.sa_family != AF_INET6 && - saidx->proxy.sa.sa_family != 0)) { - - DPRINTF(("ipsec4_common_input_cb: inner " - "source address %s doesn't correspond to " - "expected proxy source %s, SA %s/%08lx\n", - ip6_sprintf(&ip6n.ip6_src), - ipsec_address(&saidx->proxy), - ipsec_address(&saidx->dst), - (u_long) ntohl(sav->spi))); - - IPSEC_ISTAT(sproto, espstat.esps_pdrops, - ahstat.ahs_pdrops, - ipcompstat.ipcomps_pdrops); - error = EACCES; - goto bad; - } -#endif /*XXX*/ - } -#endif /* INET6 */ - - /* - * Record what we've done to the packet (under what SA it was - * processed). If we've been passed an mtag, it means the packet - * was already processed by an ethernet/crypto combo card and - * thus has a tag attached with all the right information, but - * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to - * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type. - */ - if (mt == NULL && sproto != IPPROTO_IPCOMP) { - mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, - sizeof(struct tdb_ident), M_NOWAIT); - if (mtag == NULL) { - DPRINTF(("ipsec4_common_input_cb: failed to get tag\n")); - IPSEC_ISTAT(sproto, espstat.esps_hdrops, - ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops); - error = ENOMEM; - goto bad; - } - - tdbi = (struct tdb_ident *)m_tag_data(mtag); - bcopy(&saidx->dst, &tdbi->dst, saidx->dst.sa.sa_len); - tdbi->proto = sproto; - tdbi->spi = sav->spi; - - m_tag_prepend(m, mtag); - } else { - mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE; - /* XXX do we need to mark m_flags??? */ - } - - key_sa_recordxfer(sav, m); /* record data transfer */ - - /* - * Re-dispatch via software interrupt. - */ - if (netisr_queue(NETISR_IP, m)) { - IPSEC_ISTAT(sproto, espstat.esps_qfull, ahstat.ahs_qfull, - ipcompstat.ipcomps_qfull); - - DPRINTF(("ipsec4_common_input_cb: queue full; " - "proto %u packet dropped\n", sproto)); - return ENOBUFS; - } - return 0; -bad: - m_freem(m); - return error; -} -#endif /* INET */ - -#ifdef INET6 -/* IPv6 AH wrapper. */ -int -ipsec6_common_input(struct mbuf **mp, int *offp, int proto) -{ - int l = 0; - int protoff; - struct ip6_ext ip6e; - - if (*offp < sizeof(struct ip6_hdr)) { - DPRINTF(("ipsec6_common_input: bad offset %u\n", *offp)); - return IPPROTO_DONE; - } else if (*offp == sizeof(struct ip6_hdr)) { - protoff = offsetof(struct ip6_hdr, ip6_nxt); - } else { - /* Chase down the header chain... */ - protoff = sizeof(struct ip6_hdr); - - do { - protoff += l; - m_copydata(*mp, protoff, sizeof(ip6e), - (caddr_t) &ip6e); - - if (ip6e.ip6e_nxt == IPPROTO_AH) - l = (ip6e.ip6e_len + 2) << 2; - else - l = (ip6e.ip6e_len + 1) << 3; - KASSERT(l > 0, ("ah6_input: l went zero or negative")); - } while (protoff + l < *offp); - - /* Malformed packet check */ - if (protoff + l != *offp) { - DPRINTF(("ipsec6_common_input: bad packet header chain, " - "protoff %u, l %u, off %u\n", protoff, l, *offp)); - IPSEC_ISTAT(proto, espstat.esps_hdrops, - ahstat.ahs_hdrops, - ipcompstat.ipcomps_hdrops); - m_freem(*mp); - *mp = NULL; - return IPPROTO_DONE; - } - protoff += offsetof(struct ip6_ext, ip6e_nxt); - } - ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto); - return IPPROTO_DONE; -} - -void -esp6_ctlinput(netmsg_t msg) -{ - int cmd = msg->ctlinput.nm_cmd; - struct sockaddr *sa = msg->ctlinput.nm_arg; - void *d = msg->ctlinput.nm_extra; - - if (sa->sa_family != AF_INET6 || - sa->sa_len != sizeof(struct sockaddr_in6)) - return; - if ((unsigned)cmd >= PRC_NCMDS) - return; - - /* if the parameter is from icmp6, decode it. */ - if (d != NULL) { - struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d; - struct mbuf *m = ip6cp->ip6c_m; - int off = ip6cp->ip6c_off; - - struct ip6ctlparam ip6cp1; - - /* - * Notify the error to all possible sockets via kpfctlinput2. - * Since the upper layer information (such as protocol type, - * source and destination ports) is embedded in the encrypted - * data and might have been cut, we can't directly call - * an upper layer ctlinput function. However, the pcbnotify - * function will consider source and destination addresses - * as well as the flow info value, and may be able to find - * some PCB that should be notified. - * Although kpfctlinput2 will call esp6_ctlinput(), there is - * no possibility of an infinite loop of function calls, - * because we don't pass the inner IPv6 header. - */ - bzero(&ip6cp1, sizeof(ip6cp1)); - ip6cp1.ip6c_src = ip6cp->ip6c_src; - kpfctlinput2(cmd, sa, (void *)&ip6cp1); - - /* - * Then go to special cases that need ESP header information. - * XXX: We assume that when ip6 is non NULL, - * M and OFF are valid. - */ - - if (cmd == PRC_MSGSIZE) { - struct secasvar *sav; - u_int32_t spi; - int valid; - - /* check header length before using m_copydata */ - if (m->m_pkthdr.len < off + sizeof (struct esp)) - return; - m_copydata(m, off + offsetof(struct esp, esp_spi), - sizeof(u_int32_t), (caddr_t) &spi); - /* - * Check to see if we have a valid SA corresponding to - * the address in the ICMP message payload. - */ - sav = KEY_ALLOCSA((union sockaddr_union *)sa, - IPPROTO_ESP, spi); - valid = (sav != NULL); - if (sav) - KEY_FREESAV(&sav); - - /* XXX Further validation? */ - - /* - * Depending on whether the SA is "valid" and - * routing table size (mtudisc_{hi,lo}wat), we will: - * - recalcurate the new MTU and create the - * corresponding routing entry, or - * - ignore the MTU change notification. - */ - icmp6_mtudisc_update(ip6cp, valid); - } - } else { - /* we normally notify any pcb here */ - } -} - -extern struct protosw inet6sw[]; -extern u_char ip6_protox[]; - -/* - * IPsec input callback, called by the transform callback. Takes care of - * filtering and other sanity checks on the processed packet. - */ -int -ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int protoff, - struct m_tag *mt) -{ - int prot, af, sproto; - struct ip6_hdr *ip6; - struct m_tag *mtag; - struct tdb_ident *tdbi; - struct secasindex *saidx; - int nxt; - u_int8_t nxt8; - int error, nest; - - KASSERT(m != NULL, ("ipsec6_common_input_cb: null mbuf")); - KASSERT(sav != NULL, ("ipsec6_common_input_cb: null SA")); - KASSERT(sav->sah != NULL, ("ipsec6_common_input_cb: null SAH")); - saidx = &sav->sah->saidx; - af = saidx->dst.sa.sa_family; - KASSERT(af == AF_INET6, - ("ipsec6_common_input_cb: unexpected af %u", af)); - sproto = saidx->proto; - KASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH || - sproto == IPPROTO_IPCOMP, - ("ipsec6_common_input_cb: unexpected security protocol %u", - sproto)); - - /* Sanity check */ - if (m == NULL) { - DPRINTF(("ipsec4_common_input_cb: null mbuf")); - IPSEC_ISTAT(sproto, espstat.esps_badkcr, ahstat.ahs_badkcr, - ipcompstat.ipcomps_badkcr); - error = EINVAL; - goto bad; - } - - /* Fix IPv6 header */ - if (m->m_len < sizeof(struct ip6_hdr) && - (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { - - DPRINTF(("ipsec_common_input_cb: processing failed " - "for SA %s/%08lx\n", ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - - IPSEC_ISTAT(sproto, espstat.esps_hdrops, ahstat.ahs_hdrops, - ipcompstat.ipcomps_hdrops); - error = EACCES; - goto bad; - } - - ip6 = mtod(m, struct ip6_hdr *); - ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); - - /* Save protocol */ - m_copydata(m, protoff, 1, (unsigned char *) &prot); - -#ifdef INET - /* IP-in-IP encapsulation */ - if (prot == IPPROTO_IPIP) { - struct ip ipn; - - if (m->m_pkthdr.len - skip < sizeof(struct ip)) { - IPSEC_ISTAT(sproto, espstat.esps_hdrops, - ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops); - error = EINVAL; - goto bad; - } - - /* ipn will now contain the inner IPv4 header */ - m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn); - -#ifdef notyet - /* - * Check that the inner source address is the same as - * the proxy address, if available. - */ - if ((saidx->proxy.sa.sa_family == AF_INET && - saidx->proxy.sin.sin_addr.s_addr != INADDR_ANY && - ipn.ip_src.s_addr != saidx->proxy.sin.sin_addr.s_addr) || - (saidx->proxy.sa.sa_family != AF_INET && - saidx->proxy.sa.sa_family != 0)) { - - DPRINTF(("ipsec_common_input_cb: inner " - "source address %s doesn't correspond to " - "expected proxy source %s, SA %s/%08lx\n", - inet_ntoa4(ipn.ip_src), - ipsec_address(&saidx->proxy), - ipsec_address(&saidx->dst), - (u_long) ntohl(sav->spi))); - - IPSEC_ISTATsproto, (espstat.esps_pdrops, - ahstat.ahs_pdrops, ipcompstat.ipcomps_pdrops); - error = EACCES; - goto bad; - } -#endif /*XXX*/ - } -#endif /* INET */ - - /* IPv6-in-IP encapsulation */ - if (prot == IPPROTO_IPV6) { - struct ip6_hdr ip6n; - - if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) { - IPSEC_ISTAT(sproto, espstat.esps_hdrops, - ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops); - error = EINVAL; - goto bad; - } - - /* ip6n will now contain the inner IPv6 header. */ - m_copydata(m, skip, sizeof(struct ip6_hdr), (caddr_t) &ip6n); - -#ifdef notyet - /* - * Check that the inner source address is the same as - * the proxy address, if available. - */ - if ((saidx->proxy.sa.sa_family == AF_INET6 && - !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) && - !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src, - &saidx->proxy.sin6.sin6_addr)) || - (saidx->proxy.sa.sa_family != AF_INET6 && - saidx->proxy.sa.sa_family != 0)) { - - DPRINTF(("ipsec_common_input_cb: inner " - "source address %s doesn't correspond to " - "expected proxy source %s, SA %s/%08lx\n", - ip6_sprintf(&ip6n.ip6_src), - ipsec_address(&saidx->proxy), - ipsec_address(&saidx->dst), - (u_long) ntohl(sav->spi))); - - IPSEC_ISTAT(sproto, espstat.esps_pdrops, - ahstat.ahs_pdrops, ipcompstat.ipcomps_pdrops); - error = EACCES; - goto bad; - } -#endif /*XXX*/ - } - - /* - * Record what we've done to the packet (under what SA it was - * processed). If we've been passed an mtag, it means the packet - * was already processed by an ethernet/crypto combo card and - * thus has a tag attached with all the right information, but - * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to - * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type. - */ - if (mt == NULL && sproto != IPPROTO_IPCOMP) { - mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, - sizeof(struct tdb_ident), M_NOWAIT); - if (mtag == NULL) { - DPRINTF(("ipsec_common_input_cb: failed to " - "get tag\n")); - IPSEC_ISTAT(sproto, espstat.esps_hdrops, - ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops); - error = ENOMEM; - goto bad; - } - - tdbi = (struct tdb_ident *)m_tag_data(mtag); - bcopy(&saidx->dst, &tdbi->dst, sizeof(union sockaddr_union)); - tdbi->proto = sproto; - tdbi->spi = sav->spi; - - m_tag_prepend(m, mtag); - } else { - mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE; - /* XXX do we need to mark m_flags??? */ - } - - key_sa_recordxfer(sav, m); - - /* Retrieve new protocol */ - m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8); - - /* - * See the end of ip6_input for this logic. - * IPPROTO_IPV[46] case will be processed just like other ones - */ - nest = 0; - nxt = nxt8; - while (nxt != IPPROTO_DONE) { - if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { - ip6stat.ip6s_toomanyhdr++; - error = EINVAL; - goto bad; - } - - /* - * Protection against faulty packet - there should be - * more sanity checks in header chain processing. - */ - if (m->m_pkthdr.len < skip) { - ip6stat.ip6s_tooshort++; - in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); - error = EINVAL; - goto bad; - } - /* - * Enforce IPsec policy checking if we are seeing last header. - * note that we do not visit this with protocols with pcb layer - * code - like udp/tcp/raw ip. - */ - if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && - ipsec6_in_reject(m, NULL)) { - error = EINVAL; - goto bad; - } - nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt); - } - return 0; -bad: - if (m) - m_freem(m); - return error; -} -#endif /* INET6 */ diff --git a/sys/netproto/ipsec/ipsec_mbuf.c b/sys/netproto/ipsec/ipsec_mbuf.c deleted file mode 100644 index 4c042990d1..0000000000 --- a/sys/netproto/ipsec/ipsec_mbuf.c +++ /dev/null @@ -1,479 +0,0 @@ -/*- - * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/netipsec/ipsec_mbuf.c,v 1.5.2.2 2003/03/28 20:32:53 sam Exp $ - */ - -/* - * IPsec-specific mbuf routines. - */ - -#include "opt_param.h" - -#include -#include -#include -#include - -#include -#include - -#include - -/* - * Create a writable copy of the mbuf chain. While doing this - * we compact the chain with a goal of producing a chain with - * at most two mbufs. The second mbuf in this chain is likely - * to be a cluster. The primary purpose of this work is to create - * a writable packet for encryption, compression, etc. The - * secondary goal is to linearize the data so the data can be - * passed to crypto hardware in the most efficient manner possible. - */ -struct mbuf * -m_clone(struct mbuf *m0) -{ - struct mbuf *m, *mprev; - struct mbuf *n, *mfirst, *mlast; - int len, off; - - KASSERT(m0 != NULL, ("m_clone: null mbuf")); - - mprev = NULL; - for (m = m0; m != NULL; m = mprev->m_next) { - /* - * Regular mbufs are ignored unless there's a cluster - * in front of it that we can use to coalesce. We do - * the latter mainly so later clusters can be coalesced - * also w/o having to handle them specially (i.e. convert - * mbuf+cluster -> cluster). This optimization is heavily - * influenced by the assumption that we're running over - * Ethernet where MCLBYTES is large enough that the max - * packet size will permit lots of coalescing into a - * single cluster. This in turn permits efficient - * crypto operations, especially when using hardware. - */ - if ((m->m_flags & M_EXT) == 0) { - if (mprev && (mprev->m_flags & M_EXT) && - m->m_len <= M_TRAILINGSPACE(mprev)) { - /* XXX: this ignores mbuf types */ - memcpy(mtod(mprev, caddr_t) + mprev->m_len, - mtod(m, caddr_t), m->m_len); - mprev->m_len += m->m_len; - mprev->m_next = m->m_next; /* unlink from chain */ - m_free(m); /* reclaim mbuf */ - newipsecstat.ips_mbcoalesced++; - } else { - mprev = m; - } - continue; - } - /* - * Writable mbufs are left alone (for now). Note - * that for 4.x systems it's not possible to identify - * whether or not mbufs with external buffers are - * writable unless they use clusters. - */ - if (M_EXT_WRITABLE(m)) { - mprev = m; - continue; - } - - /* - * Not writable, replace with a copy or coalesce with - * the previous mbuf if possible (since we have to copy - * it anyway, we try to reduce the number of mbufs and - * clusters so that future work is easier). - */ - KASSERT(m->m_flags & M_EXT, - ("m_clone: m_flags 0x%x", m->m_flags)); - /* NB: we only coalesce into a cluster or larger */ - if (mprev != NULL && (mprev->m_flags & M_EXT) && - m->m_len <= M_TRAILINGSPACE(mprev)) { - /* XXX: this ignores mbuf types */ - memcpy(mtod(mprev, caddr_t) + mprev->m_len, - mtod(m, caddr_t), m->m_len); - mprev->m_len += m->m_len; - mprev->m_next = m->m_next; /* unlink from chain */ - m_free(m); /* reclaim mbuf */ - newipsecstat.ips_clcoalesced++; - continue; - } - - /* - * Allocate new space to hold the copy... - */ - /* XXX why can M_PKTHDR be set past the first mbuf? */ - if (mprev == NULL && (m->m_flags & M_PKTHDR)) { - /* - * NB: if a packet header is present we must - * allocate the mbuf separately from any cluster - * because M_MOVE_PKTHDR will smash the data - * pointer and drop the M_EXT marker. - */ - MGETHDR(n, M_NOWAIT, m->m_type); - if (n == NULL) { - m_freem(m0); - return (NULL); - } - M_MOVE_PKTHDR(n, m); - MCLGET(n, M_NOWAIT); - if ((n->m_flags & M_EXT) == 0) { - m_free(n); - m_freem(m0); - return (NULL); - } - } else { - n = m_getcl(M_NOWAIT, m->m_type, m->m_flags); - if (n == NULL) { - m_freem(m0); - return (NULL); - } - } - /* - * ... and copy the data. We deal with jumbo mbufs - * (i.e. m_len > MCLBYTES) by splitting them into - * clusters. We could just malloc a buffer and make - * it external but too many device drivers don't know - * how to break up the non-contiguous memory when - * doing DMA. - */ - len = m->m_len; - off = 0; - mfirst = n; - mlast = NULL; - for (;;) { - int cc = min(len, MCLBYTES); - memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + off, cc); - n->m_len = cc; - if (mlast != NULL) - mlast->m_next = n; - mlast = n; - newipsecstat.ips_clcopied++; - - len -= cc; - if (len <= 0) - break; - off += cc; - - n = m_getcl(M_NOWAIT, m->m_type, m->m_flags); - if (n == NULL) { - m_freem(mfirst); - m_freem(m0); - return (NULL); - } - } - n->m_next = m->m_next; - if (mprev == NULL) - m0 = mfirst; /* new head of chain */ - else - mprev->m_next = mfirst; /* replace old mbuf */ - m_free(m); /* release old mbuf */ - mprev = mfirst; - } - return (m0); -} - -/* - * Make space for a new header of length hlen at skip bytes - * into the packet. When doing this we allocate new mbufs only - * when absolutely necessary. The mbuf where the new header - * is to go is returned together with an offset into the mbuf. - * If NULL is returned then the mbuf chain may have been modified; - * the caller is assumed to always free the chain. - */ -struct mbuf * -m_makespace(struct mbuf *m0, int skip, int hlen, int *off) -{ - struct mbuf *m; - unsigned remain; - - KASSERT(m0 != NULL, ("m_dmakespace: null mbuf")); - KASSERT(hlen < MHLEN, ("m_makespace: hlen too big: %u", hlen)); - - for (m = m0; m && skip > m->m_len; m = m->m_next) - skip -= m->m_len; - if (m == NULL) - return (NULL); - /* - * At this point skip is the offset into the mbuf m - * where the new header should be placed. Figure out - * if there's space to insert the new header. If so, - * and copying the remainder makese sense then do so. - * Otherwise insert a new mbuf in the chain, splitting - * the contents of m as needed. - */ - remain = m->m_len - skip; /* data to move */ - if (hlen > M_TRAILINGSPACE(m)) { - struct mbuf *n; - - /* XXX code doesn't handle clusters XXX */ - KASSERT(remain < MLEN, - ("m_makespace: remainder too big: %u", remain)); - /* - * Not enough space in m, split the contents - * of m, inserting new mbufs as required. - * - * NB: this ignores mbuf types. - */ - MGET(n, M_NOWAIT, MT_DATA); - if (n == NULL) - return (NULL); - n->m_next = m->m_next; /* splice new mbuf */ - m->m_next = n; - newipsecstat.ips_mbinserted++; - if (hlen <= M_TRAILINGSPACE(m) + remain) { - /* - * New header fits in the old mbuf if we copy - * the remainder; just do the copy to the new - * mbuf and we're good to go. - */ - memcpy(mtod(n, caddr_t), - mtod(m, caddr_t) + skip, remain); - n->m_len = remain; - m->m_len = skip + hlen; - *off = skip; - } else { - /* - * No space in the old mbuf for the new header. - * Make space in the new mbuf and check the - * remainder'd data fits too. If not then we - * must allocate an additional mbuf (yech). - */ - n->m_len = 0; - if (remain + hlen > M_TRAILINGSPACE(n)) { - struct mbuf *n2; - - MGET(n2, M_NOWAIT, MT_DATA); - /* NB: new mbuf is on chain, let caller free */ - if (n2 == NULL) - return (NULL); - n2->m_len = 0; - memcpy(mtod(n2, caddr_t), - mtod(m, caddr_t) + skip, remain); - n2->m_len = remain; - /* splice in second mbuf */ - n2->m_next = n->m_next; - n->m_next = n2; - newipsecstat.ips_mbinserted++; - } else { - memcpy(mtod(n, caddr_t) + hlen, - mtod(m, caddr_t) + skip, remain); - n->m_len += remain; - } - m->m_len -= remain; - n->m_len += hlen; - m = n; /* header is at front ... */ - *off = 0; /* ... of new mbuf */ - } - } else { - /* - * Copy the remainder to the back of the mbuf - * so there's space to write the new header. - */ - /* XXX can this be memcpy? does it handle overlap? */ - bcopy(mtod(m, caddr_t) + skip, - mtod(m, caddr_t) + skip + hlen, remain); - m->m_len += hlen; - *off = skip; - } - m0->m_pkthdr.len += hlen; /* adjust packet length */ - return m; -} - -/* - * m_pad(m, n) pads with bytes at the end. The packet header - * length is updated, and a pointer to the first byte of the padding - * (which is guaranteed to be all in one mbuf) is returned. - */ -caddr_t -m_pad(struct mbuf *m, int n) -{ - struct mbuf *m0, *m1; - int len, pad; - caddr_t retval; - - if (n <= 0) { /* No stupid arguments. */ - DPRINTF(("m_pad: pad length invalid (%d)\n", n)); - m_freem(m); - return NULL; - } - - len = m->m_pkthdr.len; - pad = n; - m0 = m; - - while (m0->m_len < len) { -KASSERT(m0->m_next != NULL, ("m_pad: m0 null, len %u m_len %u", len, m0->m_len));/*XXX*/ - len -= m0->m_len; - m0 = m0->m_next; - } - - if (m0->m_len != len) { - DPRINTF(("m_pad: length mismatch (should be %d instead of %d)\n", - m->m_pkthdr.len, m->m_pkthdr.len + m0->m_len - len)); - - m_freem(m); - return NULL; - } - - /* Check for zero-length trailing mbufs, and find the last one. */ - for (m1 = m0; m1->m_next; m1 = m1->m_next) { - if (m1->m_next->m_len != 0) { - DPRINTF(("m_pad: length mismatch (should be %d " - "instead of %d)\n", - m->m_pkthdr.len, - m->m_pkthdr.len + m1->m_next->m_len)); - - m_freem(m); - return NULL; - } - - m0 = m1->m_next; - } - - if (pad > M_TRAILINGSPACE(m0)) { - /* Add an mbuf to the chain. */ - MGET(m1, M_NOWAIT, MT_DATA); - if (m1 == NULL) { - m_freem(m0); - DPRINTF(("m_pad: unable to get extra mbuf\n")); - return NULL; - } - - m0->m_next = m1; - m0 = m1; - m0->m_len = 0; - } - - retval = m0->m_data + m0->m_len; - m0->m_len += pad; - m->m_pkthdr.len += pad; - - return retval; -} - -/* - * Remove hlen data at offset skip in the packet. This is used by - * the protocols strip protocol headers and associated data (e.g. IV, - * authenticator) on input. - */ -int -m_striphdr(struct mbuf *m, int skip, int hlen) -{ - struct mbuf *m1; - int roff; - - /* Find beginning of header */ - m1 = m_getptr(m, skip, &roff); - if (m1 == NULL) - return (EINVAL); - - /* Remove the header and associated data from the mbuf. */ - if (roff == 0) { - /* The header was at the beginning of the mbuf */ - newipsecstat.ips_input_front++; - m_adj(m1, hlen); - if ((m1->m_flags & M_PKTHDR) == 0) - m->m_pkthdr.len -= hlen; - } else if (roff + hlen >= m1->m_len) { - struct mbuf *mo; - - /* - * Part or all of the header is at the end of this mbuf, - * so first let's remove the remainder of the header from - * the beginning of the remainder of the mbuf chain, if any. - */ - newipsecstat.ips_input_end++; - if (roff + hlen > m1->m_len) { - /* Adjust the next mbuf by the remainder */ - m_adj(m1->m_next, roff + hlen - m1->m_len); - - /* The second mbuf is guaranteed not to have a pkthdr... */ - m->m_pkthdr.len -= (roff + hlen - m1->m_len); - } - - /* Now, let's unlink the mbuf chain for a second...*/ - mo = m1->m_next; - m1->m_next = NULL; - - /* ...and trim the end of the first part of the chain...sick */ - m_adj(m1, -(m1->m_len - roff)); - if ((m1->m_flags & M_PKTHDR) == 0) - m->m_pkthdr.len -= (m1->m_len - roff); - - /* Finally, let's relink */ - m1->m_next = mo; - } else { - /* - * The header lies in the "middle" of the mbuf; copy - * the remainder of the mbuf down over the header. - */ - newipsecstat.ips_input_middle++; - bcopy(mtod(m1, u_char *) + roff + hlen, - mtod(m1, u_char *) + roff, - m1->m_len - (roff + hlen)); - m1->m_len -= hlen; - m->m_pkthdr.len -= hlen; - } - return (0); -} - -/* - * Diagnostic routine to check mbuf alignment as required by the - * crypto device drivers (that use DMA). - */ -void -m_checkalignment(const char* where, struct mbuf *m0, int off, int len) -{ - int roff; - struct mbuf *m = m_getptr(m0, off, &roff); - caddr_t addr; - - if (m == NULL) - return; - kprintf("%s (off %u len %u): ", where, off, len); - addr = mtod(m, caddr_t) + roff; - do { - int mlen; - - if (((uintptr_t) addr) & 3) { - kprintf("addr misaligned %p,", addr); - break; - } - mlen = m->m_len; - if (mlen > len) - mlen = len; - len -= mlen; - if (len && (mlen & 3)) { - kprintf("len mismatch %u,", mlen); - break; - } - m = m->m_next; - addr = m ? mtod(m, caddr_t) : NULL; - } while (m && len > 0); - for (m = m0; m; m = m->m_next) - kprintf(" [%p:%u]", mtod(m, caddr_t), m->m_len); - kprintf("\n"); -} diff --git a/sys/netproto/ipsec/ipsec_output.c b/sys/netproto/ipsec/ipsec_output.c deleted file mode 100644 index b7f54cd748..0000000000 --- a/sys/netproto/ipsec/ipsec_output.c +++ /dev/null @@ -1,754 +0,0 @@ -/*- - * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/netipsec/ipsec_output.c,v 1.3.2.2 2003/03/28 20:32:53 sam Exp $ - */ - -/* - * IPsec output processing. - */ -#include "opt_inet.h" -#include "opt_inet6.h" -#include "opt_ipsec.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#ifdef INET6 -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif - -#include -#ifdef INET6 -#include -#endif -#include -#include -#include - -#include - -#include -#include -#include - -int -ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr) -{ - struct tdb_ident *tdbi; - struct m_tag *mtag; - struct secasvar *sav; - struct secasindex *saidx; - int error; - - KASSERT(m != NULL, ("ipsec_process_done: null mbuf")); - KASSERT(isr != NULL, ("ipsec_process_done: null ISR")); - sav = isr->sav; - KASSERT(sav != NULL, ("ipsec_process_done: null SA")); - KASSERT(sav->sah != NULL, ("ipsec_process_done: null SAH")); - - saidx = &sav->sah->saidx; - switch (saidx->dst.sa.sa_family) { -#ifdef INET - case AF_INET: - /* Fix the header length, for AH processing. */ - mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - /* Fix the header length, for AH processing. */ - if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) { - error = ENXIO; - goto bad; - } - if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) { - /* No jumbogram support. */ - error = ENXIO; /*?*/ - goto bad; - } - mtod(m, struct ip6_hdr *)->ip6_plen = - htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); - break; -#endif /* INET6 */ - default: - DPRINTF(("ipsec_process_done: unknown protocol family %u\n", - saidx->dst.sa.sa_family)); - error = ENXIO; - goto bad; - } - - /* - * Add a record of what we've done or what needs to be done to the - * packet. - */ - mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, - sizeof(struct tdb_ident), M_NOWAIT); - if (mtag == NULL) { - DPRINTF(("ipsec_process_done: could not get packet tag\n")); - error = ENOMEM; - goto bad; - } - - tdbi = (struct tdb_ident *)m_tag_data(mtag); - tdbi->dst = saidx->dst; - tdbi->proto = saidx->proto; - tdbi->spi = sav->spi; - m_tag_prepend(m, mtag); - - /* - * If there's another (bundled) SA to apply, do so. - * Note that this puts a burden on the kernel stack size. - * If this is a problem we'll need to introduce a queue - * to set the packet on so we can unwind the stack before - * doing further processing. - */ - if (isr->next) { - newipsecstat.ips_out_bundlesa++; - return ipsec4_process_packet(m, isr->next, 0, 0); - } - - /* - * We're done with IPsec processing, transmit the packet using the - * appropriate network protocol (IP or IPv6). SPD lookup will be - * performed again there. - */ - switch (saidx->dst.sa.sa_family) { -#ifdef INET - struct ip *ip; - case AF_INET: - ip = mtod(m, struct ip *); - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); - - return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL); -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - /* - * We don't need massage, IPv6 header fields are always in - * net endian. - */ - return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); -#endif /* INET6 */ - } - panic("ipsec_process_done"); -bad: - m_freem(m); - KEY_FREESAV(&sav); - return (error); -} - -static struct ipsecrequest * -ipsec_nextisr( - struct mbuf *m, - struct ipsecrequest *isr, - int af, - struct secasindex *saidx, - int *error -) -{ -#define IPSEC_OSTAT(x,y,z) (isr->saidx.proto == IPPROTO_ESP ? (x)++ : \ - isr->saidx.proto == IPPROTO_AH ? (y)++ : (z)++) - struct secasvar *sav; - - KASSERT(af == AF_INET || af == AF_INET6, - ("ipsec_nextisr: invalid address family %u", af)); -again: - /* - * Craft SA index to search for proper SA. Note that - * we only fillin unspecified SA peers for transport - * mode; for tunnel mode they must already be filled in. - */ - *saidx = isr->saidx; - if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) { - /* Fillin unspecified SA peers only for transport mode */ - if (af == AF_INET) { - struct sockaddr_in *sin; - struct ip *ip = mtod(m, struct ip *); - - if (saidx->src.sa.sa_len == 0) { - sin = &saidx->src.sin; - sin->sin_len = sizeof(*sin); - sin->sin_family = AF_INET; - sin->sin_port = IPSEC_PORT_ANY; - sin->sin_addr = ip->ip_src; - } - if (saidx->dst.sa.sa_len == 0) { - sin = &saidx->dst.sin; - sin->sin_len = sizeof(*sin); - sin->sin_family = AF_INET; - sin->sin_port = IPSEC_PORT_ANY; - sin->sin_addr = ip->ip_dst; - } - } else { - struct sockaddr_in6 *sin6; - struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); - - if (saidx->src.sin6.sin6_len == 0) { - sin6 = (struct sockaddr_in6 *)&saidx->src; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = IPSEC_PORT_ANY; - sin6->sin6_addr = ip6->ip6_src; - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { - /* fix scope id for comparing SPD */ - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = - ntohs(ip6->ip6_src.s6_addr16[1]); - } - } - if (saidx->dst.sin6.sin6_len == 0) { - sin6 = (struct sockaddr_in6 *)&saidx->dst; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = IPSEC_PORT_ANY; - sin6->sin6_addr = ip6->ip6_dst; - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { - /* fix scope id for comparing SPD */ - sin6->sin6_addr.s6_addr16[1] = 0; - sin6->sin6_scope_id = - ntohs(ip6->ip6_dst.s6_addr16[1]); - } - } - } - } - - /* - * Lookup SA and validate it. - */ - *error = key_checkrequest(isr, saidx); - if (*error != 0) { - /* - * IPsec processing is required, but no SA found. - * I assume that key_acquire() had been called - * to get/establish the SA. Here I discard - * this packet because it is responsibility for - * upper layer to retransmit the packet. - */ - newipsecstat.ips_out_nosa++; - goto bad; - } - sav = isr->sav; - if (sav == NULL) { /* XXX valid return */ - KASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE, - ("ipsec_nextisr: no SA found, but required; level %u", - ipsec_get_reqlevel(isr))); - isr = isr->next; - if (isr == NULL) { - /*XXXstatistic??*/ - *error = EINVAL; /*XXX*/ - return isr; - } - goto again; - } - - /* - * Check system global policy controls. - */ - if ((isr->saidx.proto == IPPROTO_ESP && !esp_enable) || - (isr->saidx.proto == IPPROTO_AH && !ah_enable) || - (isr->saidx.proto == IPPROTO_IPCOMP && !ipcomp_enable)) { - DPRINTF(("ipsec_nextisr: IPsec outbound packet dropped due" - " to policy (check your sysctls)\n")); - IPSEC_OSTAT(espstat.esps_pdrops, ahstat.ahs_pdrops, - ipcompstat.ipcomps_pdrops); - *error = EHOSTUNREACH; - goto bad; - } - - /* - * Sanity check the SA contents for the caller - * before they invoke the xform output method. - */ - if (sav->tdb_xform == NULL) { - DPRINTF(("ipsec_nextisr: no transform for SA\n")); - IPSEC_OSTAT(espstat.esps_noxform, ahstat.ahs_noxform, - ipcompstat.ipcomps_noxform); - *error = EHOSTUNREACH; - goto bad; - } - return isr; -bad: - KASSERT(*error != 0, ("ipsec_nextisr: error return w/ no error code")); - return NULL; -#undef IPSEC_OSTAT -} - -#ifdef INET -/* - * IPsec output logic for IPv4. - */ -int -ipsec4_process_packet( - struct mbuf *m, - struct ipsecrequest *isr, - int flags, - int tunalready) -{ - struct secasindex saidx; - struct secasvar *sav; - struct ip *ip; - int error, i, off; - - KASSERT(m != NULL, ("ipsec4_process_packet: null mbuf")); - KASSERT(isr != NULL, ("ipsec4_process_packet: null isr")); - - crit_enter(); - - isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error); - if (isr == NULL) - goto bad; - - sav = isr->sav; - if (!tunalready) { - union sockaddr_union *dst = &sav->sah->saidx.dst; - int setdf; - - /* - * Collect IP_DF state from the outer header. - */ - if (dst->sa.sa_family == AF_INET) { - if (m->m_len < sizeof (struct ip) && - (m = m_pullup(m, sizeof (struct ip))) == NULL) { - error = ENOBUFS; - goto bad; - } - ip = mtod(m, struct ip *); - /* Honor system-wide control of how to handle IP_DF */ - switch (ip4_ipsec_dfbit) { - case 0: /* clear in outer header */ - case 1: /* set in outer header */ - setdf = ip4_ipsec_dfbit; - break; - default: /* propagate to outer header */ - setdf = ntohs(ip->ip_off & IP_DF); - break; - } - } else { - ip = NULL; /* keep compiler happy */ - setdf = 0; - } - /* Do the appropriate encapsulation, if necessary */ - if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ - dst->sa.sa_family != AF_INET || /* PF mismatch */ -#if 0 - (sav->flags & SADB_X_SAFLAGS_TUNNEL) || /* Tunnel requ'd */ - sav->tdb_xform->xf_type == XF_IP4 || /* ditto */ -#endif - (dst->sa.sa_family == AF_INET && /* Proxy */ - dst->sin.sin_addr.s_addr != INADDR_ANY && - dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) { - struct mbuf *mp; - - /* Fix IPv4 header checksum and length */ - if (m->m_len < sizeof (struct ip) && - (m = m_pullup(m, sizeof (struct ip))) == NULL) { - error = ENOBUFS; - goto bad; - } - ip = mtod(m, struct ip *); - ip->ip_len = htons(m->m_pkthdr.len); - ip->ip_sum = 0; -#ifdef _IP_VHL - if (ip->ip_vhl == IP_VHL_BORING) - ip->ip_sum = in_cksum_hdr(ip); - else - ip->ip_sum = in_cksum(m, - _IP_VHL_HL(ip->ip_vhl) << 2); -#else - ip->ip_sum = in_cksum(m, ip->ip_hl << 2); -#endif - - /* Encapsulate the packet */ - error = ipip_output(m, isr, &mp, 0, 0); - if (mp == NULL && !error) { - /* Should never happen. */ - DPRINTF(("ipsec4_process_packet: ipip_output " - "returns no mbuf and no error!")); - error = EFAULT; - } - if (error) { - if (mp) - m_freem(mp); - goto bad; - } - m = mp, mp = NULL; - /* - * ipip_output clears IP_DF in the new header. If - * we need to propagate IP_DF from the outer header, - * then we have to do it here. - * - * XXX shouldn't assume what ipip_output does. - */ - if (dst->sa.sa_family == AF_INET && setdf) { - if (m->m_len < sizeof (struct ip) && - (m = m_pullup(m, sizeof (struct ip))) == NULL) { - error = ENOBUFS; - goto bad; - } - ip = mtod(m, struct ip *); - ip->ip_off = ntohs(ip->ip_off); - ip->ip_off |= IP_DF; - ip->ip_off = htons(ip->ip_off); - } - } - } - - /* - * Dispatch to the appropriate IPsec transform logic. The - * packet will be returned for transmission after crypto - * processing, etc. are completed. For encapsulation we - * bypass this call because of the explicit call done above - * (necessary to deal with IP_DF handling for IPv4). - * - * NB: m & sav are ``passed to caller'' who's reponsible for - * for reclaiming their resources. - */ - if (sav->tdb_xform->xf_type != XF_IP4) { - ip = mtod(m, struct ip *); - i = ip->ip_hl << 2; - off = offsetof(struct ip, ip_p); - error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off); - } else { - error = ipsec_process_done(m, isr); - } - crit_exit(); - return error; -bad: - crit_exit(); - if (m) - m_freem(m); - return error; -} -#endif - -#ifdef INET6 -/* - * Chop IP6 header from the payload. - */ -static struct mbuf * -ipsec6_splithdr(struct mbuf *m) -{ - struct mbuf *mh; - struct ip6_hdr *ip6; - int hlen; - - KASSERT(m->m_len >= sizeof (struct ip6_hdr), - ("ipsec6_splithdr: first mbuf too short, len %u", m->m_len)); - ip6 = mtod(m, struct ip6_hdr *); - hlen = sizeof(struct ip6_hdr); - if (m->m_len > hlen) { - MGETHDR(mh, M_NOWAIT, MT_HEADER); - if (!mh) { - m_freem(m); - return NULL; - } - M_MOVE_PKTHDR(mh, m); - MH_ALIGN(mh, hlen); - m->m_len -= hlen; - m->m_data += hlen; - mh->m_next = m; - m = mh; - m->m_len = hlen; - bcopy((caddr_t)ip6, mtod(m, caddr_t), hlen); - } else if (m->m_len < hlen) { - m = m_pullup(m, hlen); - if (!m) - return NULL; - } - return m; -} - -/* - * IPsec output logic for IPv6, transport mode. - */ -int -ipsec6_output_trans( - struct ipsec_output_state *state, - u_char *nexthdrp, - struct mbuf *mprev, - struct secpolicy *sp, - int flags, - int *tun) -{ - struct ipsecrequest *isr; - struct secasindex saidx; - int error = 0; - struct mbuf *m; - - KASSERT(state != NULL, ("ipsec6_output: null state")); - KASSERT(state->m != NULL, ("ipsec6_output: null m")); - KASSERT(nexthdrp != NULL, ("ipsec6_output: null nexthdrp")); - KASSERT(mprev != NULL, ("ipsec6_output: null mprev")); - KASSERT(sp != NULL, ("ipsec6_output: null sp")); - KASSERT(tun != NULL, ("ipsec6_output: null tun")); - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec6_output_trans: applyed SP\n"); - kdebug_secpolicy(sp)); - - isr = sp->req; - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { - /* the rest will be handled by ipsec6_output_tunnel() */ - *tun = 1; /* need tunnel-mode processing */ - return 0; - } - - *tun = 0; - m = state->m; - - isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error); - if (isr == NULL) { -#ifdef notdef - /* XXX should notification be done for all errors ? */ - /* - * Notify the fact that the packet is discarded - * to ourselves. I believe this is better than - * just silently discarding. (jinmei@kame.net) - * XXX: should we restrict the error to TCP packets? - * XXX: should we directly notify sockets via - * kpfctlinputs? - */ - icmp6_error(m, ICMP6_DST_UNREACH, - ICMP6_DST_UNREACH_ADMIN, 0); - m = NULL; /* NB: icmp6_error frees mbuf */ -#endif - goto bad; - } - - return (*isr->sav->tdb_xform->xf_output)(m, isr, NULL, - sizeof (struct ip6_hdr), - offsetof(struct ip6_hdr, ip6_nxt)); -bad: - if (m) - m_freem(m); - state->m = NULL; - return error; -} - -static int -ipsec6_encapsulate(struct mbuf *m, struct secasvar *sav) -{ - struct ip6_hdr *oip6; - struct ip6_hdr *ip6; - size_t plen; - - /* can't tunnel between different AFs */ - if (sav->sah->saidx.src.sa.sa_family != AF_INET6 || - sav->sah->saidx.dst.sa.sa_family != AF_INET6) { - m_freem(m); - return EINVAL; - } - KASSERT(m->m_len != sizeof (struct ip6_hdr), - ("ipsec6_encapsulate: mbuf wrong size; len %u", m->m_len)); - - - /* - * grow the mbuf to accomodate the new IPv6 header. - */ - plen = m->m_pkthdr.len; - if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) { - struct mbuf *n; - MGET(n, M_NOWAIT, MT_DATA); - if (!n) { - m_freem(m); - return ENOBUFS; - } - n->m_len = sizeof(struct ip6_hdr); - n->m_next = m->m_next; - m->m_next = n; - m->m_pkthdr.len += sizeof(struct ip6_hdr); - oip6 = mtod(n, struct ip6_hdr *); - } else { - m->m_next->m_len += sizeof(struct ip6_hdr); - m->m_next->m_data -= sizeof(struct ip6_hdr); - m->m_pkthdr.len += sizeof(struct ip6_hdr); - oip6 = mtod(m->m_next, struct ip6_hdr *); - } - ip6 = mtod(m, struct ip6_hdr *); - bcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr)); - - /* Fake link-local scope-class addresses */ - if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src)) - oip6->ip6_src.s6_addr16[1] = 0; - if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst)) - oip6->ip6_dst.s6_addr16[1] = 0; - - /* construct new IPv6 header. see RFC 2401 5.1.2.2 */ - /* ECN consideration. */ - ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow); - if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr)) - ip6->ip6_plen = htons(plen); - else { - /* ip6->ip6_plen will be updated in ip6_output() */ - } - ip6->ip6_nxt = IPPROTO_IPV6; - sav->sah->saidx.src.sin6.sin6_addr = ip6->ip6_src; - sav->sah->saidx.dst.sin6.sin6_addr = ip6->ip6_dst; - ip6->ip6_hlim = IPV6_DEFHLIM; - - /* XXX Should ip6_src be updated later ? */ - - return 0; -} - -/* - * IPsec output logic for IPv6, tunnel mode. - */ -int -ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int flags) -{ - struct ip6_hdr *ip6; - struct ipsecrequest *isr; - struct secasindex saidx; - int error; - struct sockaddr_in6* dst6; - struct mbuf *m; - - KASSERT(state != NULL, ("ipsec6_output: null state")); - KASSERT(state->m != NULL, ("ipsec6_output: null m")); - KASSERT(sp != NULL, ("ipsec6_output: null sp")); - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("ipsec6_output_tunnel: applyed SP\n"); - kdebug_secpolicy(sp)); - - m = state->m; - /* - * transport mode ipsec (before the 1st tunnel mode) is already - * processed by ipsec6_output_trans(). - */ - for (isr = sp->req; isr; isr = isr->next) { - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) - break; - } - isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error); - if (isr == NULL) - goto bad; - - /* - * There may be the case that SA status will be changed when - * we are refering to one. So calling splsoftnet(). - */ - if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { - /* - * build IPsec tunnel. - */ - /* XXX should be processed with other familiy */ - if (isr->sav->sah->saidx.src.sa.sa_family != AF_INET6) { - ipseclog((LOG_ERR, "ipsec6_output_tunnel: " - "family mismatched between inner and outer, spi=%u\n", - ntohl(isr->sav->spi))); - newipsecstat.ips_out_inval++; - error = EAFNOSUPPORT; - goto bad; - } - - m = ipsec6_splithdr(m); - if (!m) { - newipsecstat.ips_out_nomem++; - error = ENOMEM; - goto bad; - } - error = ipsec6_encapsulate(m, isr->sav); - if (error) { - m = NULL; - goto bad; - } - ip6 = mtod(m, struct ip6_hdr *); - - state->ro = &isr->sav->sah->sa_route; - state->dst = (struct sockaddr *)&state->ro->ro_dst; - dst6 = (struct sockaddr_in6 *)state->dst; - if (state->ro->ro_rt - && ((state->ro->ro_rt->rt_flags & RTF_UP) == 0 - || !IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ip6->ip6_dst))) { - RTFREE(state->ro->ro_rt); - state->ro->ro_rt = NULL; - } - if (state->ro->ro_rt == 0) { - bzero(dst6, sizeof(*dst6)); - dst6->sin6_family = AF_INET6; - dst6->sin6_len = sizeof(*dst6); - dst6->sin6_addr = ip6->ip6_dst; - rtalloc(state->ro); - } - if (state->ro->ro_rt == 0) { - ip6stat.ip6s_noroute++; - newipsecstat.ips_out_noroute++; - error = EHOSTUNREACH; - goto bad; - } - - /* adjust state->dst if tunnel endpoint is offlink */ - if (state->ro->ro_rt->rt_flags & RTF_GATEWAY) { - state->dst = (struct sockaddr *)state->ro->ro_rt->rt_gateway; - dst6 = (struct sockaddr_in6 *)state->dst; - } - } - - m = ipsec6_splithdr(m); - if (!m) { - newipsecstat.ips_out_nomem++; - error = ENOMEM; - goto bad; - } - ip6 = mtod(m, struct ip6_hdr *); - return (*isr->sav->tdb_xform->xf_output)(m, isr, NULL, - sizeof (struct ip6_hdr), - offsetof(struct ip6_hdr, ip6_nxt)); -bad: - if (m) - m_freem(m); - state->m = NULL; - return error; -} -#endif /*INET6*/ diff --git a/sys/netproto/ipsec/key.c b/sys/netproto/ipsec/key.c deleted file mode 100644 index 814f9beb46..0000000000 --- a/sys/netproto/ipsec/key.c +++ /dev/null @@ -1,6966 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.1 2003/01/24 05:11:35 sam Exp $ */ -/* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ - -/* - * 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. - */ - -/* - * This code is referd to RFC 2367 - */ - -#include "opt_inet.h" -#include "opt_inet6.h" -#include "opt_ipsec.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#ifdef INET6 -#include -#include -#include -#endif /* INET6 */ - -#ifdef INET -#include -#endif -#ifdef INET6 -#include -#endif /* INET6 */ - -#include -#include -#include -#include -#include - -#include -#ifdef INET6 -#include -#endif - -#include - -#include - -/* randomness */ -#include - -#include - -#define FULLMASK 0xff -#define _BITS(bytes) ((bytes) << 3) - -/* - * Note on SA reference counting: - * - SAs that are not in DEAD state will have (total external reference + 1) - * following value in reference count field. they cannot be freed and are - * referenced from SA header. - * - SAs that are in DEAD state will have (total external reference) - * in reference count field. they are ready to be freed. reference from - * SA header will be removed in key_delsav(), when the reference count - * field hits 0 (= no external reference other than from SA header. - */ - -#ifndef IPSEC_DEBUG2 -static struct callout key_timehandler_ch; -#endif -u_int32_t key_debug_level = 0; -static u_int key_spi_trycnt = 1000; -static u_int32_t key_spi_minval = 0x100; -static u_int32_t key_spi_maxval = 0x0fffffff; /* XXX */ -static u_int32_t policy_id = 0; -static u_int key_int_random = 60; /*interval to initialize randseed,1(m)*/ -static u_int key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/ -static int key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/ -static int key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/ -static int key_prefered_oldsa = 1; /* prefered old sa rather than new sa.*/ - -static u_int32_t acq_seq = 0; -static int key_tick_init_random = 0; - -static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */ -static LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */ -static LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1]; - /* registed list */ -#ifndef IPSEC_NONBLOCK_ACQUIRE -static LIST_HEAD(_acqtree, secacq) acqtree; /* acquiring list */ -#endif -static LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */ - -/* search order for SAs */ -static u_int saorder_state_valid[] = { - SADB_SASTATE_DYING, SADB_SASTATE_MATURE, - /* - * This order is important because we must select the oldest SA - * for outbound processing. For inbound, This is not important. - */ -}; -static u_int saorder_state_alive[] = { - /* except DEAD */ - SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL -}; -static u_int saorder_state_any[] = { - SADB_SASTATE_MATURE, SADB_SASTATE_DYING, - SADB_SASTATE_LARVAL, SADB_SASTATE_DEAD -}; - -static const int minsize[] = { - sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ - sizeof(struct sadb_sa), /* SADB_EXT_SA */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ - sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_SRC */ - sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_DST */ - sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_PROXY */ - sizeof(struct sadb_key), /* SADB_EXT_KEY_AUTH */ - sizeof(struct sadb_key), /* SADB_EXT_KEY_ENCRYPT */ - sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_SRC */ - sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_DST */ - sizeof(struct sadb_sens), /* SADB_EXT_SENSITIVITY */ - sizeof(struct sadb_prop), /* SADB_EXT_PROPOSAL */ - sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_AUTH */ - sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_ENCRYPT */ - sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ - 0, /* SADB_X_EXT_KMPRIVATE */ - sizeof(struct sadb_x_policy), /* SADB_X_EXT_POLICY */ - sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */ -}; -static const int maxsize[] = { - sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ - sizeof(struct sadb_sa), /* SADB_EXT_SA */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ - 0, /* SADB_EXT_ADDRESS_SRC */ - 0, /* SADB_EXT_ADDRESS_DST */ - 0, /* SADB_EXT_ADDRESS_PROXY */ - 0, /* SADB_EXT_KEY_AUTH */ - 0, /* SADB_EXT_KEY_ENCRYPT */ - 0, /* SADB_EXT_IDENTITY_SRC */ - 0, /* SADB_EXT_IDENTITY_DST */ - 0, /* SADB_EXT_SENSITIVITY */ - 0, /* SADB_EXT_PROPOSAL */ - 0, /* SADB_EXT_SUPPORTED_AUTH */ - 0, /* SADB_EXT_SUPPORTED_ENCRYPT */ - sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ - 0, /* SADB_X_EXT_KMPRIVATE */ - 0, /* SADB_X_EXT_POLICY */ - sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */ -}; - -static int ipsec_esp_keymin = 256; -static int ipsec_esp_auth = 0; -static int ipsec_ah_keymin = 128; - -#ifdef SYSCTL_DECL -SYSCTL_DECL(_net_key); -#endif - -SYSCTL_INT(_net_key, KEYCTL_DEBUG_LEVEL, debug, CTLFLAG_RW, \ - &key_debug_level, 0, ""); - -/* max count of trial for the decision of spi value */ -SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ - &key_spi_trycnt, 0, ""); - -/* minimum spi value to allocate automatically. */ -SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ - &key_spi_minval, 0, ""); - -/* maximun spi value to allocate automatically. */ -SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ - &key_spi_maxval, 0, ""); - -/* interval to initialize randseed */ -SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ - &key_int_random, 0, ""); - -/* lifetime for larval SA */ -SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ - &key_larval_lifetime, 0, ""); - -/* counter for blocking to send SADB_ACQUIRE to IKEd */ -SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \ - &key_blockacq_count, 0, ""); - -/* lifetime for blocking to send SADB_ACQUIRE to IKEd */ -SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ - &key_blockacq_lifetime, 0, ""); - -/* ESP auth */ -SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \ - &ipsec_esp_auth, 0, ""); - -/* minimum ESP key length */ -SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \ - &ipsec_esp_keymin, 0, ""); - -/* minimum AH key length */ -SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \ - &ipsec_ah_keymin, 0, ""); - -/* perfered old SA rather than new SA */ -SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW,\ - &key_prefered_oldsa, 0, ""); - -#define __LIST_CHAINED(elm) \ - (!((elm)->chain.le_next == NULL && (elm)->chain.le_prev == NULL)) -#define LIST_INSERT_TAIL(head, elm, type, field) \ -do {\ - struct type *curelm = LIST_FIRST(head); \ - if (curelm == NULL) {\ - LIST_INSERT_HEAD(head, elm, field); \ - } else { \ - while (LIST_NEXT(curelm, field)) \ - curelm = LIST_NEXT(curelm, field);\ - LIST_INSERT_AFTER(curelm, elm, field);\ - }\ -} while (0) - -#define KEY_CHKSASTATE(head, sav, name) \ -do { \ - if ((head) != (sav)) { \ - ipseclog((LOG_DEBUG, "%s: state mismatched (TREE=%d SA=%d)\n", \ - (name), (head), (sav))); \ - continue; \ - } \ -} while (0) - -#define KEY_CHKSPDIR(head, sp, name) \ -do { \ - if ((head) != (sp)) { \ - ipseclog((LOG_DEBUG, "%s: direction mismatched (TREE=%d SP=%d), " \ - "anyway continue.\n", \ - (name), (head), (sp))); \ - } \ -} while (0) - -MALLOC_DEFINE(M_SECA, "key mgmt", "security associations, key management"); - -#if 1 -#define KMALLOC(p, t, n) \ - ((p) = (t) kmalloc((unsigned long)(n), M_SECA, M_INTWAIT | M_NULLOK)) -#define KFREE(p) \ - kfree((caddr_t)(p), M_SECA) -#else -#define KMALLOC(p, t, n) \ -do { \ - ((p) = (t)kmalloc((unsigned long)(n), M_SECA, M_INTWAIT | M_NULLOK)); \ - kprintf("%s %d: %p <- KMALLOC(%s, %d)\n", \ - __FILE__, __LINE__, (p), #t, n); \ -} while (0) - -#define KFREE(p) \ - do { \ - kprintf("%s %d: %p -> KFREE()\n", __FILE__, __LINE__, (p)); \ - kfree((caddr_t)(p), M_SECA); \ - } while (0) -#endif - -/* - * set parameters into secpolicyindex buffer. - * Must allocate secpolicyindex buffer passed to this function. - */ -#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, idx) \ -do { \ - bzero((idx), sizeof(struct secpolicyindex)); \ - (idx)->dir = (_dir); \ - (idx)->prefs = (ps); \ - (idx)->prefd = (pd); \ - (idx)->ul_proto = (ulp); \ - bcopy((s), &(idx)->src, ((const struct sockaddr *)(s))->sa_len); \ - bcopy((d), &(idx)->dst, ((const struct sockaddr *)(d))->sa_len); \ -} while (0) - -/* - * set parameters into secasindex buffer. - * Must allocate secasindex buffer before calling this function. - */ -#define KEY_SETSECASIDX(p, m, r, s, d, idx) \ -do { \ - bzero((idx), sizeof(struct secasindex)); \ - (idx)->proto = (p); \ - (idx)->mode = (m); \ - (idx)->reqid = (r); \ - bcopy((s), &(idx)->src, ((const struct sockaddr *)(s))->sa_len); \ - bcopy((d), &(idx)->dst, ((const struct sockaddr *)(d))->sa_len); \ -} while (0) - -/* key statistics */ -struct _keystat { - u_long getspi_count; /* the avarage of count to try to get new SPI */ -} keystat; - -struct sadb_msghdr { - struct sadb_msg *msg; - struct sadb_ext *ext[SADB_EXT_MAX + 1]; - int extoff[SADB_EXT_MAX + 1]; - int extlen[SADB_EXT_MAX + 1]; -}; - -static struct secasvar *key_allocsa_policy (const struct secasindex *); -static void key_freesp_so (struct secpolicy **); -static struct secasvar *key_do_allocsa_policy (struct secashead *, u_int); -static void key_delsp (struct secpolicy *); -static struct secpolicy *key_getsp (struct secpolicyindex *); -static struct secpolicy *key_getspbyid (u_int32_t); -static u_int32_t key_newreqid (void); -static struct mbuf *key_gather_mbuf (struct mbuf *, - const struct sadb_msghdr *, int, int, ...); -static int key_spdadd (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static u_int32_t key_getnewspid (void); -static int key_spddelete (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_spddelete2 (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_spdget (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_spdflush (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_spddump (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static struct mbuf *key_setdumpsp (struct secpolicy *, - u_int8_t, u_int32_t, u_int32_t); -static u_int key_getspreqmsglen (struct secpolicy *); -static int key_spdexpire (struct secpolicy *); -static struct secashead *key_newsah (struct secasindex *); -static void key_delsah (struct secashead *); -static struct secasvar *key_newsav (struct mbuf *, - const struct sadb_msghdr *, struct secashead *, int *, - const char*, int); -#define KEY_NEWSAV(m, sadb, sah, e) \ - key_newsav(m, sadb, sah, e, __FILE__, __LINE__) -static void key_delsav (struct secasvar *); -static struct secashead *key_getsah (struct secasindex *); -static struct secasvar *key_checkspidup (struct secasindex *, u_int32_t); -static struct secasvar *key_getsavbyspi (struct secashead *, u_int32_t); -static int key_setsaval (struct secasvar *, struct mbuf *, - const struct sadb_msghdr *); -static int key_mature (struct secasvar *); -static struct mbuf *key_setdumpsa (struct secasvar *, u_int8_t, - u_int8_t, u_int32_t, u_int32_t); -static struct mbuf *key_setsadbmsg (u_int8_t, u_int16_t, u_int8_t, - u_int32_t, pid_t, u_int16_t); -static struct mbuf *key_setsadbsa (struct secasvar *); -static struct mbuf *key_setsadbaddr (u_int16_t, - const struct sockaddr *, u_int8_t, u_int16_t); -#if 0 -static struct mbuf *key_setsadbident (u_int16_t, u_int16_t, caddr_t, - int, u_int64_t); -#endif -static struct mbuf *key_setsadbxsa2 (u_int8_t, u_int32_t, u_int32_t); -static struct mbuf *key_setsadbxpolicy (u_int16_t, u_int8_t, - u_int32_t); -static void *key_newbuf (const void *, u_int); -#ifdef INET6 -static int key_ismyaddr6 (struct sockaddr_in6 *); -#endif - -/* flags for key_cmpsaidx() */ -#define CMP_HEAD 1 /* protocol, addresses. */ -#define CMP_MODE_REQID 2 /* additionally HEAD, reqid, mode. */ -#define CMP_REQID 3 /* additionally HEAD, reaid. */ -#define CMP_EXACTLY 4 /* all elements. */ -static int key_cmpsaidx - (const struct secasindex *, const struct secasindex *, int); - -static int key_cmpspidx_exactly - (struct secpolicyindex *, struct secpolicyindex *); -static int key_cmpspidx_withmask - (struct secpolicyindex *, struct secpolicyindex *); -static int key_sockaddrcmp (const struct sockaddr *, const struct sockaddr *, int); -static int key_bbcmp (const void *, const void *, u_int); -static void key_srandom (void); -static u_int16_t key_satype2proto (u_int8_t); -static u_int8_t key_proto2satype (u_int16_t); - -static int key_getspi (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static u_int32_t key_do_getnewspi (struct sadb_spirange *, - struct secasindex *); -static int key_update (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -#ifdef IPSEC_DOSEQCHECK -static struct secasvar *key_getsavbyseq (struct secashead *, u_int32_t); -#endif -static int key_add (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_setident (struct secashead *, struct mbuf *, - const struct sadb_msghdr *); -static struct mbuf *key_getmsgbuf_x1 (struct mbuf *, - const struct sadb_msghdr *); -static int key_delete (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_get (struct socket *, struct mbuf *, - const struct sadb_msghdr *); - -static void key_getcomb_setlifetime (struct sadb_comb *); -static struct mbuf *key_getcomb_esp (void); -static struct mbuf *key_getcomb_ah (void); -static struct mbuf *key_getcomb_ipcomp (void); -static struct mbuf *key_getprop (const struct secasindex *); - -static int key_acquire (const struct secasindex *, struct secpolicy *); -#ifndef IPSEC_NONBLOCK_ACQUIRE -static struct secacq *key_newacq (const struct secasindex *); -static struct secacq *key_getacq (const struct secasindex *); -static struct secacq *key_getacqbyseq (u_int32_t); -#endif -static struct secspacq *key_newspacq (struct secpolicyindex *); -static struct secspacq *key_getspacq (struct secpolicyindex *); -static int key_acquire2 (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_register (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_expire (struct secasvar *); -static int key_flush (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_dump (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_promisc (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_senderror (struct socket *, struct mbuf *, int); -static int key_validate_ext (const struct sadb_ext *, int); -static int key_align (struct mbuf *, struct sadb_msghdr *); -#if 0 -static const char *key_getfqdn (void); -static const char *key_getuserfqdn (void); -#endif -static void key_sa_chgstate (struct secasvar *, u_int8_t); -static struct mbuf *key_alloc_mbuf (int); - -#define SA_ADDREF(p) do { \ - (p)->refcnt++; \ - KASSERT((p)->refcnt != 0, \ - ("SA refcnt overflow at %s:%u", __FILE__, __LINE__)); \ -} while (0) -#define SA_DELREF(p) do { \ - KASSERT((p)->refcnt > 0, \ - ("SA refcnt underflow at %s:%u", __FILE__, __LINE__)); \ - (p)->refcnt--; \ -} while (0) - -#define SP_ADDREF(p) do { \ - (p)->refcnt++; \ - KASSERT((p)->refcnt != 0, \ - ("SP refcnt overflow at %s:%u", __FILE__, __LINE__)); \ -} while (0) -#define SP_DELREF(p) do { \ - KASSERT((p)->refcnt > 0, \ - ("SP refcnt underflow at %s:%u", __FILE__, __LINE__)); \ - (p)->refcnt--; \ -} while (0) - -/* - * Return 0 when there are known to be no SP's for the specified - * direction. Otherwise return 1. This is used by IPsec code - * to optimize performance. - */ -int -key_havesp(u_int dir) -{ - return (dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND ? - LIST_FIRST(&sptree[dir]) != NULL : 1); -} - -/* %%% IPsec policy management */ -/* - * allocating a SP for OUTBOUND or INBOUND packet. - * Must call key_freesp() later. - * OUT: NULL: not found - * others: found and return the pointer. - */ -struct secpolicy * -key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag) -{ - struct secpolicy *sp; - - - KASSERT(spidx != NULL, ("key_allocsp: null spidx")); - KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, - ("key_allocsp: invalid direction %u", dir)); - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_allocsp from %s:%u\n", where, tag)); - - /* get a SP entry */ - crit_enter(); - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("*** objects\n"); kdebug_secpolicyindex(spidx)); - - LIST_FOREACH(sp, &sptree[dir], chain) { - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("*** in SPD\n"); - kdebug_secpolicyindex(&sp->spidx)); - - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (key_cmpspidx_withmask(&sp->spidx, spidx)) - goto found; - } - sp = NULL; -found: - if (sp) { - /* sanity check */ - KEY_CHKSPDIR(sp->spidx.dir, dir, "key_allocsp"); - - /* found a SPD entry */ - sp->lastused = time_second; - SP_ADDREF(sp); - } - crit_exit(); - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_allocsp return SP:%p (ID=%u) refcnt %u\n", - sp, sp ? sp->id : 0, sp ? sp->refcnt : 0)); - return sp; -} - -/* - * allocating a SP for OUTBOUND or INBOUND packet. - * Must call key_freesp() later. - * OUT: NULL: not found - * others: found and return the pointer. - */ -struct secpolicy * -key_allocsp2(u_int32_t spi, - union sockaddr_union *dst, - u_int8_t proto, - u_int dir, - const char* where, int tag) -{ - struct secpolicy *sp; - - - KASSERT(dst != NULL, ("key_allocsp2: null dst")); - KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, - ("key_allocsp2: invalid direction %u", dir)); - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_allocsp2 from %s:%u\n", where, tag)); - - /* get a SP entry */ - crit_enter(); - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("*** objects\n"); - kprintf("spi %u proto %u dir %u\n", spi, proto, dir); - kdebug_sockaddr(&dst->sa)); - - LIST_FOREACH(sp, &sptree[dir], chain) { - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("*** in SPD\n"); - kdebug_secpolicyindex(&sp->spidx)); - - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - /* compare simple values, then dst address */ - if (sp->spidx.ul_proto != proto) - continue; - /* NB: spi's must exist and match */ - if (!sp->req || !sp->req->sav || sp->req->sav->spi != spi) - continue; - if (key_sockaddrcmp(&sp->spidx.dst.sa, &dst->sa, 1) == 0) - goto found; - } - sp = NULL; -found: - if (sp) { - /* sanity check */ - KEY_CHKSPDIR(sp->spidx.dir, dir, "key_allocsp2"); - - /* found a SPD entry */ - sp->lastused = time_second; - SP_ADDREF(sp); - } - crit_exit(); - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_allocsp2 return SP:%p (ID=%u) refcnt %u\n", - sp, sp ? sp->id : 0, sp ? sp->refcnt : 0)); - return sp; -} - -/* - * return a policy that matches this particular inbound packet. - * XXX slow - */ -struct secpolicy * -key_gettunnel(const struct sockaddr *osrc, - const struct sockaddr *odst, - const struct sockaddr *isrc, - const struct sockaddr *idst, - const char* where, int tag) -{ - struct secpolicy *sp; - const int dir = IPSEC_DIR_INBOUND; - - struct ipsecrequest *r1, *r2, *p; - struct secpolicyindex spidx; - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_gettunnel from %s:%u\n", where, tag)); - - if (isrc->sa_family != idst->sa_family) { - ipseclog((LOG_ERR, "protocol family mismatched %d != %d\n.", - isrc->sa_family, idst->sa_family)); - sp = NULL; - goto done; - } - - crit_enter(); - LIST_FOREACH(sp, &sptree[dir], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - - r1 = r2 = NULL; - for (p = sp->req; p; p = p->next) { - if (p->saidx.mode != IPSEC_MODE_TUNNEL) - continue; - - r1 = r2; - r2 = p; - - if (!r1) { - /* here we look at address matches only */ - spidx = sp->spidx; - if (isrc->sa_len > sizeof(spidx.src) || - idst->sa_len > sizeof(spidx.dst)) - continue; - bcopy(isrc, &spidx.src, isrc->sa_len); - bcopy(idst, &spidx.dst, idst->sa_len); - if (!key_cmpspidx_withmask(&sp->spidx, &spidx)) - continue; - } else { - if (key_sockaddrcmp(&r1->saidx.src.sa, isrc, 0) || - key_sockaddrcmp(&r1->saidx.dst.sa, idst, 0)) - continue; - } - - if (key_sockaddrcmp(&r2->saidx.src.sa, osrc, 0) || - key_sockaddrcmp(&r2->saidx.dst.sa, odst, 0)) - continue; - - goto found; - } - } - sp = NULL; -found: - if (sp) { - sp->lastused = time_second; - SP_ADDREF(sp); - } - crit_exit(); -done: - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_gettunnel return SP:%p (ID=%u) refcnt %u\n", - sp, sp ? sp->id : 0, sp ? sp->refcnt : 0)); - return sp; -} - -/* - * allocating an SA entry for an *OUTBOUND* packet. - * checking each request entries in SP, and acquire an SA if need. - * OUT: 0: there are valid requests. - * ENOENT: policy may be valid, but SA with REQUIRE is on acquiring. - */ -int -key_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx) -{ - u_int level; - int error; - - KASSERT(isr != NULL, ("key_checkrequest: null isr")); - KASSERT(saidx != NULL, ("key_checkrequest: null saidx")); - KASSERT(saidx->mode == IPSEC_MODE_TRANSPORT || - saidx->mode == IPSEC_MODE_TUNNEL, - ("key_checkrequest: unexpected policy %u", saidx->mode)); - - /* get current level */ - level = ipsec_get_reqlevel(isr); - - /* - * XXX guard against protocol callbacks from the crypto - * thread as they reference ipsecrequest.sav which we - * temporarily null out below. Need to rethink how we - * handle bundled SA's in the callback thread. - */ -#if 0 - /* - * We do allocate new SA only if the state of SA in the holder is - * SADB_SASTATE_DEAD. The SA for outbound must be the oldest. - */ - if (isr->sav != NULL) { - if (isr->sav->sah == NULL) - panic("key_checkrequest: sah is null."); - if (isr->sav == (struct secasvar *)LIST_FIRST( - &isr->sav->sah->savtree[SADB_SASTATE_DEAD])) { - KEY_FREESAV(&isr->sav); - isr->sav = NULL; - } - } -#else - /* - * we free any SA stashed in the IPsec request because a different - * SA may be involved each time this request is checked, either - * because new SAs are being configured, or this request is - * associated with an unconnected datagram socket, or this request - * is associated with a system default policy. - * - * The operation may have negative impact to performance. We may - * want to check cached SA carefully, rather than picking new SA - * every time. - */ - if (isr->sav != NULL) { - KEY_FREESAV(&isr->sav); - isr->sav = NULL; - } -#endif - - /* - * new SA allocation if no SA found. - * key_allocsa_policy should allocate the oldest SA available. - * See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt. - */ - if (isr->sav == NULL) - isr->sav = key_allocsa_policy(saidx); - - /* When there is SA. */ - if (isr->sav != NULL) { - if (isr->sav->state != SADB_SASTATE_MATURE && - isr->sav->state != SADB_SASTATE_DYING) - return EINVAL; - return 0; - } - - /* there is no SA */ - error = key_acquire(saidx, isr->sp); - if (error != 0) { - /* XXX What should I do ? */ - ipseclog((LOG_DEBUG, "key_checkrequest: error %d returned " - "from key_acquire.\n", error)); - return error; - } - - if (level != IPSEC_LEVEL_REQUIRE) { - /* XXX sigh, the interface to this routine is botched */ - KASSERT(isr->sav == NULL, ("key_checkrequest: unexpected SA")); - return 0; - } else { - return ENOENT; - } -} - -/* - * allocating a SA for policy entry from SAD. - * NOTE: searching SAD of aliving state. - * OUT: NULL: not found. - * others: found and return the pointer. - */ -static struct secasvar * -key_allocsa_policy(const struct secasindex *saidx) -{ - struct secashead *sah; - struct secasvar *sav; - u_int stateidx, state; - - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) - goto found; - } - - return NULL; - - found: - - /* search valid state */ - for (stateidx = 0; - stateidx < NELEM(saorder_state_valid); - stateidx++) { - - state = saorder_state_valid[stateidx]; - - sav = key_do_allocsa_policy(sah, state); - if (sav != NULL) - return sav; - } - - return NULL; -} - -/* - * searching SAD with direction, protocol, mode and state. - * called by key_allocsa_policy(). - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -static struct secasvar * -key_do_allocsa_policy(struct secashead *sah, u_int state) -{ - struct secasvar *sav, *nextsav, *candidate = NULL, *d; - - LIST_FOREACH_MUTABLE(sav, &sah->savtree[state], chain, nextsav) { - /* sanity check */ - KEY_CHKSASTATE(sav->state, state, "key_do_allocsa_policy"); - - /* initialize */ - if (candidate == NULL) { - candidate = sav; - continue; - } - - /* Which SA is the better ? */ - - /* sanity check 2 */ - if (candidate->lft_c == NULL || sav->lft_c == NULL) - panic("key_do_allocsa_policy: " - "lifetime_current is NULL.\n"); - - /* What the best method is to compare ? */ - if (key_prefered_oldsa) { - if (candidate->lft_c->sadb_lifetime_addtime > - sav->lft_c->sadb_lifetime_addtime) { - candidate = sav; - } - continue; - } - - /* prefered new sa rather than old sa */ - if (candidate->lft_c->sadb_lifetime_addtime < - sav->lft_c->sadb_lifetime_addtime) { - d = candidate; - candidate = sav; - } else - d = sav; - - /* - * prepared to delete the SA when there is more - * suitable candidate and the lifetime of the SA is not - * permanent. - */ - if (d->lft_c->sadb_lifetime_addtime != 0) { - struct mbuf *m, *result; - u_int8_t satype; - - key_sa_chgstate(d, SADB_SASTATE_DEAD); - - KASSERT(d->refcnt > 0, - ("key_do_allocsa_policy: bogus ref count")); - - satype = key_proto2satype(d->sah->saidx.proto); - if (satype == 0) - goto msgfail; - - m = key_setsadbmsg(SADB_DELETE, 0, satype, 0, 0, - d->refcnt - 1); - if (!m) - goto msgfail; - result = m; - - /* set sadb_address for saidx's. */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - &d->sah->saidx.src.sa, - d->sah->saidx.src.sa.sa_len << 3, - IPSEC_ULPROTO_ANY); - if (!m) - goto msgfail; - m_cat(result, m); - - /* set sadb_address for saidx's. */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - &d->sah->saidx.dst.sa, - d->sah->saidx.dst.sa.sa_len << 3, - IPSEC_ULPROTO_ANY); - if (!m) - goto msgfail; - m_cat(result, m); - - /* create SA extension */ - m = key_setsadbsa(d); - if (!m) - goto msgfail; - m_cat(result, m); - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, - sizeof(struct sadb_msg)); - if (result == NULL) - goto msgfail; - } - - result->m_pkthdr.len = m_lengthm(result, NULL); - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - if (key_sendup_mbuf(NULL, result, - KEY_SENDUP_REGISTERED)) - goto msgfail; - msgfail: - KEY_FREESAV(&d); - } - } - - if (candidate) { - SA_ADDREF(candidate); - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP allocsa_policy cause refcnt++:%d SA:%p\n", - candidate->refcnt, candidate)); - } - return candidate; -} - -/* - * allocating a usable SA entry for a *INBOUND* packet. - * Must call key_freesav() later. - * OUT: positive: pointer to a usable sav (i.e. MATURE or DYING state). - * NULL: not found, or error occured. - * - * In the comparison, no source address is used--for RFC2401 conformance. - * To quote, from section 4.1: - * A security association is uniquely identified by a triple consisting - * of a Security Parameter Index (SPI), an IP Destination Address, and a - * security protocol (AH or ESP) identifier. - * Note that, however, we do need to keep source address in IPsec SA. - * IKE specification and PF_KEY specification do assume that we - * keep source address in IPsec SA. We see a tricky situation here. - */ -struct secasvar * -key_allocsa( - union sockaddr_union *dst, - u_int proto, - u_int32_t spi, - const char* where, int tag) -{ - struct secashead *sah; - struct secasvar *sav; - u_int stateidx, state; - - - KASSERT(dst != NULL, ("key_allocsa: null dst address")); - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_allocsa from %s:%u\n", where, tag)); - - /* - * searching SAD. - * XXX: to be checked internal IP header somewhere. Also when - * IPsec tunnel packet is received. But ESP tunnel mode is - * encrypted so we can't check internal IP header. - */ - crit_enter(); - LIST_FOREACH(sah, &sahtree, chain) { - /* search valid state */ - for (stateidx = 0; - stateidx < NELEM(saorder_state_valid); - stateidx++) { - state = saorder_state_valid[stateidx]; - LIST_FOREACH(sav, &sah->savtree[state], chain) { - /* sanity check */ - KEY_CHKSASTATE(sav->state, state, "key_allocsav"); - /* do not return entries w/ unusable state */ - if (sav->state != SADB_SASTATE_MATURE && - sav->state != SADB_SASTATE_DYING) - continue; - if (proto != sav->sah->saidx.proto) - continue; - if (spi != sav->spi) - continue; -#if 0 /* don't check src */ - /* check src address */ - if (key_sockaddrcmp(&src->sa, &sav->sah->saidx.src.sa, 0) != 0) - continue; -#endif - /* check dst address */ - if (key_sockaddrcmp(&dst->sa, &sav->sah->saidx.dst.sa, 0) != 0) - continue; - SA_ADDREF(sav); - goto done; - } - } - } - sav = NULL; -done: - crit_exit(); - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_allocsa return SA:%p; refcnt %u\n", - sav, sav ? sav->refcnt : 0)); - return sav; -} - -/* - * Must be called after calling key_allocsp(). - * For both the packet without socket and key_freeso(). - */ -void -_key_freesp(struct secpolicy **spp, const char* where, int tag) -{ - struct secpolicy *sp = *spp; - - KASSERT(sp != NULL, ("key_freesp: null sp")); - - SP_DELREF(sp); - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_freesp SP:%p (ID=%u) from %s:%u; refcnt now %u\n", - sp, sp->id, where, tag, sp->refcnt)); - - if (sp->refcnt == 0) { - *spp = NULL; - key_delsp(sp); - } -} - -/* - * Must be called after calling key_allocsp(). - * For the packet with socket. - */ -void -key_freeso(struct socket *so) -{ - /* sanity check */ - KASSERT(so != NULL, ("key_freeso: null so")); - - switch (so->so_proto->pr_domain->dom_family) { -#ifdef INET - case PF_INET: - { - struct inpcb *pcb = so->so_pcb; - - /* Does it have a PCB ? */ - if (pcb == NULL) - return; - key_freesp_so(&pcb->inp_sp->sp_in); - key_freesp_so(&pcb->inp_sp->sp_out); - } - break; -#endif -#ifdef INET6 - case PF_INET6: - { -#ifdef HAVE_NRL_INPCB - struct inpcb *pcb = so->so_pcb; - - /* Does it have a PCB ? */ - if (pcb == NULL) - return; - key_freesp_so(&pcb->inp_sp->sp_in); - key_freesp_so(&pcb->inp_sp->sp_out); -#else - struct in6pcb *pcb = so->so_pcb; - - /* Does it have a PCB ? */ - if (pcb == NULL) - return; - key_freesp_so(&pcb->in6p_sp->sp_in); - key_freesp_so(&pcb->in6p_sp->sp_out); -#endif - } - break; -#endif /* INET6 */ - default: - ipseclog((LOG_DEBUG, "key_freeso: unknown address family=%d.\n", - so->so_proto->pr_domain->dom_family)); - return; - } -} - -static void -key_freesp_so(struct secpolicy **sp) -{ - KASSERT(sp != NULL && *sp != NULL, ("key_freesp_so: null sp")); - - if ((*sp)->policy == IPSEC_POLICY_ENTRUST || - (*sp)->policy == IPSEC_POLICY_BYPASS) - return; - - KASSERT((*sp)->policy == IPSEC_POLICY_IPSEC, - ("key_freesp_so: invalid policy %u", (*sp)->policy)); - KEY_FREESP(sp); -} - -/* - * Must be called after calling key_allocsa(). - * This function is called by key_freesp() to free some SA allocated - * for a policy. - */ -void -key_freesav(struct secasvar **psav, const char* where, int tag) -{ - struct secasvar *sav = *psav; - - KASSERT(sav != NULL, ("key_freesav: null sav")); - - SA_DELREF(sav); - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_freesav SA:%p (SPI %u) from %s:%u; refcnt now %u\n", - sav, ntohl(sav->spi), where, tag, sav->refcnt)); - - if (sav->refcnt == 0) { - *psav = NULL; - key_delsav(sav); - } -} - -/* %%% SPD management */ -/* - * free security policy entry. - */ -static void -key_delsp(struct secpolicy *sp) -{ - - - KASSERT(sp != NULL, ("key_delsp: null sp")); - - sp->state = IPSEC_SPSTATE_DEAD; - - KASSERT(sp->refcnt == 0, - ("key_delsp: SP with references deleted (refcnt %u)", - sp->refcnt)); - - crit_enter(); - /* remove from SP index */ - if (__LIST_CHAINED(sp)) - LIST_REMOVE(sp, chain); - - { - struct ipsecrequest *isr = sp->req, *nextisr; - - while (isr != NULL) { - if (isr->sav != NULL) { - KEY_FREESAV(&isr->sav); - isr->sav = NULL; - } - - nextisr = isr->next; - KFREE(isr); - isr = nextisr; - } - } - - KFREE(sp); - - crit_exit(); -} - -/* - * search SPD - * OUT: NULL : not found - * others : found, pointer to a SP. - */ -static struct secpolicy * -key_getsp(struct secpolicyindex *spidx) -{ - struct secpolicy *sp; - - KASSERT(spidx != NULL, ("key_getsp: null spidx")); - - LIST_FOREACH(sp, &sptree[spidx->dir], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (key_cmpspidx_exactly(spidx, &sp->spidx)) { - SP_ADDREF(sp); - return sp; - } - } - - return NULL; -} - -/* - * get SP by index. - * OUT: NULL : not found - * others : found, pointer to a SP. - */ -static struct secpolicy * -key_getspbyid(u_int32_t id) -{ - struct secpolicy *sp; - - LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (sp->id == id) { - SP_ADDREF(sp); - return sp; - } - } - - LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (sp->id == id) { - SP_ADDREF(sp); - return sp; - } - } - - return NULL; -} - -struct secpolicy * -key_newsp(const char* where, int tag) -{ - struct secpolicy *newsp = NULL; - - newsp = kmalloc(sizeof(struct secpolicy), M_SECA, - M_INTWAIT | M_ZERO | M_NULLOK); - if (newsp) { - newsp->refcnt = 1; - newsp->req = NULL; - } - - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_newsp from %s:%u return SP:%p\n", - where, tag, newsp)); - return newsp; -} - -/* - * create secpolicy structure from sadb_x_policy structure. - * NOTE: `state', `secpolicyindex' in secpolicy structure are not set, - * so must be set properly later. - */ -struct secpolicy * -key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error) -{ - struct secpolicy *newsp; - - /* sanity check */ - if (xpl0 == NULL) - panic("key_msg2sp: NULL pointer was passed."); - if (len < sizeof(*xpl0)) - panic("key_msg2sp: invalid length."); - if (len != PFKEY_EXTLEN(xpl0)) { - ipseclog((LOG_DEBUG, "key_msg2sp: Invalid msg length.\n")); - *error = EINVAL; - return NULL; - } - - if ((newsp = KEY_NEWSP()) == NULL) { - *error = ENOBUFS; - return NULL; - } - - newsp->spidx.dir = xpl0->sadb_x_policy_dir; - newsp->policy = xpl0->sadb_x_policy_type; - - /* check policy */ - switch (xpl0->sadb_x_policy_type) { - case IPSEC_POLICY_DISCARD: - case IPSEC_POLICY_NONE: - case IPSEC_POLICY_ENTRUST: - case IPSEC_POLICY_BYPASS: - newsp->req = NULL; - break; - - case IPSEC_POLICY_IPSEC: - { - int tlen; - struct sadb_x_ipsecrequest *xisr; - struct ipsecrequest **p_isr = &newsp->req; - - /* validity check */ - if (PFKEY_EXTLEN(xpl0) < sizeof(*xpl0)) { - ipseclog((LOG_DEBUG, - "key_msg2sp: Invalid msg length.\n")); - KEY_FREESP(&newsp); - *error = EINVAL; - return NULL; - } - - tlen = PFKEY_EXTLEN(xpl0) - sizeof(*xpl0); - xisr = (struct sadb_x_ipsecrequest *)(xpl0 + 1); - - while (tlen > 0) { - /* length check */ - if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) { - ipseclog((LOG_DEBUG, "key_msg2sp: " - "invalid ipsecrequest length.\n")); - KEY_FREESP(&newsp); - *error = EINVAL; - return NULL; - } - - /* allocate request buffer */ - KMALLOC(*p_isr, struct ipsecrequest *, sizeof(**p_isr)); - if ((*p_isr) == NULL) { - ipseclog((LOG_DEBUG, - "key_msg2sp: No more memory.\n")); - KEY_FREESP(&newsp); - *error = ENOBUFS; - return NULL; - } - bzero(*p_isr, sizeof(**p_isr)); - - /* set values */ - (*p_isr)->next = NULL; - - switch (xisr->sadb_x_ipsecrequest_proto) { - case IPPROTO_ESP: - case IPPROTO_AH: - case IPPROTO_IPCOMP: - break; - default: - ipseclog((LOG_DEBUG, - "key_msg2sp: invalid proto type=%u\n", - xisr->sadb_x_ipsecrequest_proto)); - KEY_FREESP(&newsp); - *error = EPROTONOSUPPORT; - return NULL; - } - (*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto; - - switch (xisr->sadb_x_ipsecrequest_mode) { - case IPSEC_MODE_TRANSPORT: - case IPSEC_MODE_TUNNEL: - break; - case IPSEC_MODE_ANY: - default: - ipseclog((LOG_DEBUG, - "key_msg2sp: invalid mode=%u\n", - xisr->sadb_x_ipsecrequest_mode)); - KEY_FREESP(&newsp); - *error = EINVAL; - return NULL; - } - (*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode; - - switch (xisr->sadb_x_ipsecrequest_level) { - case IPSEC_LEVEL_DEFAULT: - case IPSEC_LEVEL_USE: - case IPSEC_LEVEL_REQUIRE: - break; - case IPSEC_LEVEL_UNIQUE: - /* validity check */ - /* - * If range violation of reqid, kernel will - * update it, don't refuse it. - */ - if (xisr->sadb_x_ipsecrequest_reqid - > IPSEC_MANUAL_REQID_MAX) { - ipseclog((LOG_DEBUG, - "key_msg2sp: reqid=%d range " - "violation, updated by kernel.\n", - xisr->sadb_x_ipsecrequest_reqid)); - xisr->sadb_x_ipsecrequest_reqid = 0; - } - - /* allocate new reqid id if reqid is zero. */ - if (xisr->sadb_x_ipsecrequest_reqid == 0) { - u_int32_t reqid; - if ((reqid = key_newreqid()) == 0) { - KEY_FREESP(&newsp); - *error = ENOBUFS; - return NULL; - } - (*p_isr)->saidx.reqid = reqid; - xisr->sadb_x_ipsecrequest_reqid = reqid; - } else { - /* set it for manual keying. */ - (*p_isr)->saidx.reqid = - xisr->sadb_x_ipsecrequest_reqid; - } - break; - - default: - ipseclog((LOG_DEBUG, "key_msg2sp: invalid level=%u\n", - xisr->sadb_x_ipsecrequest_level)); - KEY_FREESP(&newsp); - *error = EINVAL; - return NULL; - } - (*p_isr)->level = xisr->sadb_x_ipsecrequest_level; - - /* set IP addresses if there */ - if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) { - struct sockaddr *paddr; - - paddr = (struct sockaddr *)(xisr + 1); - - /* validity check */ - if (paddr->sa_len - > sizeof((*p_isr)->saidx.src)) { - ipseclog((LOG_DEBUG, "key_msg2sp: invalid request " - "address length.\n")); - KEY_FREESP(&newsp); - *error = EINVAL; - return NULL; - } - bcopy(paddr, &(*p_isr)->saidx.src, - paddr->sa_len); - - paddr = (struct sockaddr *)((caddr_t)paddr - + paddr->sa_len); - - /* validity check */ - if (paddr->sa_len - > sizeof((*p_isr)->saidx.dst)) { - ipseclog((LOG_DEBUG, "key_msg2sp: invalid request " - "address length.\n")); - KEY_FREESP(&newsp); - *error = EINVAL; - return NULL; - } - bcopy(paddr, &(*p_isr)->saidx.dst, - paddr->sa_len); - } - - (*p_isr)->sav = NULL; - (*p_isr)->sp = newsp; - - /* initialization for the next. */ - p_isr = &(*p_isr)->next; - tlen -= xisr->sadb_x_ipsecrequest_len; - - /* validity check */ - if (tlen < 0) { - ipseclog((LOG_DEBUG, "key_msg2sp: becoming tlen < 0.\n")); - KEY_FREESP(&newsp); - *error = EINVAL; - return NULL; - } - - xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr - + xisr->sadb_x_ipsecrequest_len); - } - } - break; - default: - ipseclog((LOG_DEBUG, "key_msg2sp: invalid policy type.\n")); - KEY_FREESP(&newsp); - *error = EINVAL; - return NULL; - } - - *error = 0; - return newsp; -} - -static u_int32_t -key_newreqid(void) -{ - static u_int32_t auto_reqid = IPSEC_MANUAL_REQID_MAX + 1; - - auto_reqid = (auto_reqid == ~0 - ? IPSEC_MANUAL_REQID_MAX + 1 : auto_reqid + 1); - - /* XXX should be unique check */ - - return auto_reqid; -} - -/* - * copy secpolicy struct to sadb_x_policy structure indicated. - */ -struct mbuf * -key_sp2msg(struct secpolicy *sp) -{ - struct sadb_x_policy *xpl; - int tlen; - caddr_t p; - struct mbuf *m; - - /* sanity check. */ - if (sp == NULL) - panic("key_sp2msg: NULL pointer was passed."); - - tlen = key_getspreqmsglen(sp); - - m = key_alloc_mbuf(tlen); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - m->m_len = tlen; - m->m_next = NULL; - xpl = mtod(m, struct sadb_x_policy *); - bzero(xpl, tlen); - - xpl->sadb_x_policy_len = PFKEY_UNIT64(tlen); - xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY; - xpl->sadb_x_policy_type = sp->policy; - xpl->sadb_x_policy_dir = sp->spidx.dir; - xpl->sadb_x_policy_id = sp->id; - p = (caddr_t)xpl + sizeof(*xpl); - - /* if is the policy for ipsec ? */ - if (sp->policy == IPSEC_POLICY_IPSEC) { - struct sadb_x_ipsecrequest *xisr; - struct ipsecrequest *isr; - - for (isr = sp->req; isr != NULL; isr = isr->next) { - - xisr = (struct sadb_x_ipsecrequest *)p; - - xisr->sadb_x_ipsecrequest_proto = isr->saidx.proto; - xisr->sadb_x_ipsecrequest_mode = isr->saidx.mode; - xisr->sadb_x_ipsecrequest_level = isr->level; - xisr->sadb_x_ipsecrequest_reqid = isr->saidx.reqid; - - p += sizeof(*xisr); - bcopy(&isr->saidx.src, p, isr->saidx.src.sa.sa_len); - p += isr->saidx.src.sa.sa_len; - bcopy(&isr->saidx.dst, p, isr->saidx.dst.sa.sa_len); - p += isr->saidx.src.sa.sa_len; - - xisr->sadb_x_ipsecrequest_len = - PFKEY_ALIGN8(sizeof(*xisr) - + isr->saidx.src.sa.sa_len - + isr->saidx.dst.sa.sa_len); - } - } - - return m; -} - -/* m will not be freed nor modified */ -static struct mbuf * -key_gather_mbuf(struct mbuf *m, const struct sadb_msghdr *mhp, - int ndeep, int nitem, ...) -{ - __va_list ap; - int idx; - int i; - struct mbuf *result = NULL, *n; - int len; - - if (m == NULL || mhp == NULL) - panic("null pointer passed to key_gather"); - - __va_start(ap, nitem); - for (i = 0; i < nitem; i++) { - idx = __va_arg(ap, int); - if (idx < 0 || idx > SADB_EXT_MAX) - goto fail; - /* don't attempt to pull empty extension */ - if (idx == SADB_EXT_RESERVED && mhp->msg == NULL) - continue; - if (idx != SADB_EXT_RESERVED && - (mhp->ext[idx] == NULL || mhp->extlen[idx] == 0)) - continue; - - if (idx == SADB_EXT_RESERVED) { - len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); -#ifdef DIAGNOSTIC - if (len > MHLEN) - panic("assumption failed"); -#endif - MGETHDR(n, M_NOWAIT, MT_DATA); - if (!n) - goto fail; - n->m_len = len; - n->m_next = NULL; - m_copydata(m, 0, sizeof(struct sadb_msg), - mtod(n, caddr_t)); - } else if (i < ndeep) { - len = mhp->extlen[idx]; - n = key_alloc_mbuf(len); - if (!n || n->m_next) { /*XXX*/ - if (n) - m_freem(n); - goto fail; - } - m_copydata(m, mhp->extoff[idx], mhp->extlen[idx], - mtod(n, caddr_t)); - } else { - n = m_copym(m, mhp->extoff[idx], mhp->extlen[idx], - M_NOWAIT); - } - if (n == NULL) - goto fail; - - if (result) - m_cat(result, n); - else - result = n; - } - __va_end(ap); - - if (result->m_flags & M_PKTHDR) - result->m_pkthdr.len = m_lengthm(result, NULL); - - return result; - -fail: - m_freem(result); - return NULL; -} - -/* - * SADB_X_SPDADD, SADB_X_SPDSETIDX or SADB_X_SPDUPDATE processing - * add an entry to SP database, when received - * - * from the user(?). - * Adding to SP database, - * and send - * - * to the socket which was send. - * - * SPDADD set a unique policy entry. - * SPDSETIDX like SPDADD without a part of policy requests. - * SPDUPDATE replace a unique policy entry. - * - * m will always be freed. - */ -static int -key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_address *src0, *dst0; - struct sadb_x_policy *xpl0, *xpl; - struct sadb_lifetime *lft = NULL; - struct secpolicyindex spidx; - struct secpolicy *newsp; - struct sockaddr *saddr, *daddr; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spdadd: NULL pointer is passed."); - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - mhp->ext[SADB_X_EXT_POLICY] == NULL) { - ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { - ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL) { - if (mhp->extlen[SADB_EXT_LIFETIME_HARD] - < sizeof(struct sadb_lifetime)) { - ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - lft = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD]; - } - - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY]; - - /* make secindex */ - /* XXX boundary check against sa_len */ - KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, - src0 + 1, - dst0 + 1, - src0->sadb_address_prefixlen, - dst0->sadb_address_prefixlen, - src0->sadb_address_proto, - &spidx); - - /* checking the direciton. */ - switch (xpl0->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - case IPSEC_DIR_OUTBOUND: - break; - default: - ipseclog((LOG_DEBUG, "key_spdadd: Invalid SP direction.\n")); - mhp->msg->sadb_msg_errno = EINVAL; - return 0; - } - - /* check policy */ - /* key_spdadd() accepts DISCARD, NONE and IPSEC. */ - if (xpl0->sadb_x_policy_type == IPSEC_POLICY_ENTRUST - || xpl0->sadb_x_policy_type == IPSEC_POLICY_BYPASS) { - ipseclog((LOG_DEBUG, "key_spdadd: Invalid policy type.\n")); - return key_senderror(so, m, EINVAL); - } - - /* policy requests are mandatory when action is ipsec. */ - if (mhp->msg->sadb_msg_type != SADB_X_SPDSETIDX - && xpl0->sadb_x_policy_type == IPSEC_POLICY_IPSEC - && mhp->extlen[SADB_X_EXT_POLICY] <= sizeof(*xpl0)) { - ipseclog((LOG_DEBUG, "key_spdadd: some policy requests part required.\n")); - return key_senderror(so, m, EINVAL); - } - - /* - * checking there is SP already or not. - * SPDUPDATE doesn't depend on whether there is a SP or not. - * If the type is either SPDADD or SPDSETIDX AND a SP is found, - * then error. - */ - newsp = key_getsp(&spidx); - if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { - if (newsp) { - newsp->state = IPSEC_SPSTATE_DEAD; - KEY_FREESP(&newsp); - } - } else { - if (newsp != NULL) { - KEY_FREESP(&newsp); - ipseclog((LOG_DEBUG, "key_spdadd: a SP entry exists already.\n")); - return key_senderror(so, m, EEXIST); - } - } - - /* allocation new SP entry */ - if ((newsp = key_msg2sp(xpl0, PFKEY_EXTLEN(xpl0), &error)) == NULL) { - return key_senderror(so, m, error); - } - - if ((newsp->id = key_getnewspid()) == 0) { - KFREE(newsp); - return key_senderror(so, m, ENOBUFS); - } - - /* XXX boundary check against sa_len */ - KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, - src0 + 1, - dst0 + 1, - src0->sadb_address_prefixlen, - dst0->sadb_address_prefixlen, - src0->sadb_address_proto, - &newsp->spidx); - - /* sanity check on addr pair */ - saddr = (struct sockaddr *)(src0 + 1); - daddr = (struct sockaddr *)(dst0 + 1); - if (saddr->sa_family != daddr->sa_family) { - KFREE(newsp); - return key_senderror(so, m, EINVAL); - } - if (saddr->sa_len != daddr->sa_len) { - KFREE(newsp); - return key_senderror(so, m, EINVAL); - } -#if 1 - if (newsp->req && newsp->req->saidx.src.sa.sa_family) { - if (saddr->sa_family != newsp->req->saidx.src.sa.sa_family) { - KFREE(newsp); - return key_senderror(so, m, EINVAL); - } - } - if (newsp->req && newsp->req->saidx.dst.sa.sa_family) { - if (daddr->sa_family != newsp->req->saidx.dst.sa.sa_family) { - KFREE(newsp); - return key_senderror(so, m, EINVAL); - } - } -#endif - - newsp->created = time_second; - newsp->lastused = newsp->created; - newsp->lifetime = lft ? lft->sadb_lifetime_addtime : 0; - newsp->validtime = lft ? lft->sadb_lifetime_usetime : 0; - - newsp->refcnt = 1; /* do not reclaim until I say I do */ - newsp->state = IPSEC_SPSTATE_ALIVE; - LIST_INSERT_TAIL(&sptree[newsp->spidx.dir], newsp, secpolicy, chain); - - /* delete the entry in spacqtree */ - if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { - struct secspacq *spacq; - if ((spacq = key_getspacq(&spidx)) != NULL) { - /* reset counter in order to deletion by timehandler. */ - spacq->created = time_second; - spacq->count = 0; - } - } - - { - struct mbuf *n, *mpolicy; - struct sadb_msg *newmsg; - int off; - - /* create new sadb_msg to reply. */ - if (lft) { - n = key_gather_mbuf(m, mhp, 2, 5, SADB_EXT_RESERVED, - SADB_X_EXT_POLICY, SADB_EXT_LIFETIME_HARD, - SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - } else { - n = key_gather_mbuf(m, mhp, 2, 4, SADB_EXT_RESERVED, - SADB_X_EXT_POLICY, - SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - } - if (!n) - return key_senderror(so, m, ENOBUFS); - - if (n->m_len < sizeof(*newmsg)) { - n = m_pullup(n, sizeof(*newmsg)); - if (!n) - return key_senderror(so, m, ENOBUFS); - } - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - off = 0; - mpolicy = m_pulldown(n, PFKEY_ALIGN8(sizeof(struct sadb_msg)), - sizeof(*xpl), &off); - if (mpolicy == NULL) { - /* n is already freed */ - return key_senderror(so, m, ENOBUFS); - } - xpl = (struct sadb_x_policy *)(mtod(mpolicy, caddr_t) + off); - if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) { - m_freem(n); - return key_senderror(so, m, EINVAL); - } - xpl->sadb_x_policy_id = newsp->id; - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * get new policy id. - * OUT: - * 0: failure. - * others: success. - */ -static u_int32_t -key_getnewspid(void) -{ - u_int32_t newid = 0; - int count = key_spi_trycnt; /* XXX */ - struct secpolicy *sp; - - /* when requesting to allocate spi ranged */ - while (count--) { - newid = (policy_id = (policy_id == ~0 ? 1 : policy_id + 1)); - - if ((sp = key_getspbyid(newid)) == NULL) - break; - - KEY_FREESP(&sp); - } - - if (count == 0 || newid == 0) { - ipseclog((LOG_DEBUG, "key_getnewspid: to allocate policy id is failed.\n")); - return 0; - } - - return newid; -} - -/* - * SADB_SPDDELETE processing - * receive - * - * from the user(?), and set SADB_SASTATE_DEAD, - * and send, - * - * to the ikmpd. - * policy(*) including direction of policy. - * - * m will always be freed. - */ -static int -key_spddelete(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_address *src0, *dst0; - struct sadb_x_policy *xpl0; - struct secpolicyindex spidx; - struct secpolicy *sp; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spddelete: NULL pointer is passed."); - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - mhp->ext[SADB_X_EXT_POLICY] == NULL) { - ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { - ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY]; - - /* make secindex */ - /* XXX boundary check against sa_len */ - KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, - src0 + 1, - dst0 + 1, - src0->sadb_address_prefixlen, - dst0->sadb_address_prefixlen, - src0->sadb_address_proto, - &spidx); - - /* checking the direciton. */ - switch (xpl0->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - case IPSEC_DIR_OUTBOUND: - break; - default: - ipseclog((LOG_DEBUG, "key_spddelete: Invalid SP direction.\n")); - return key_senderror(so, m, EINVAL); - } - - /* Is there SP in SPD ? */ - if ((sp = key_getsp(&spidx)) == NULL) { - ipseclog((LOG_DEBUG, "key_spddelete: no SP found.\n")); - return key_senderror(so, m, EINVAL); - } - - /* save policy id to buffer to be returned. */ - xpl0->sadb_x_policy_id = sp->id; - - sp->state = IPSEC_SPSTATE_DEAD; - KEY_FREESP(&sp); - - { - struct mbuf *n; - struct sadb_msg *newmsg; - - /* create new sadb_msg to reply. */ - n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED, - SADB_X_EXT_POLICY, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - if (!n) - return key_senderror(so, m, ENOBUFS); - - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * SADB_SPDDELETE2 processing - * receive - * - * from the user(?), and set SADB_SASTATE_DEAD, - * and send, - * - * to the ikmpd. - * policy(*) including direction of policy. - * - * m will always be freed. - */ -static int -key_spddelete2(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - u_int32_t id; - struct secpolicy *sp; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spddelete2: NULL pointer is passed."); - - if (mhp->ext[SADB_X_EXT_POLICY] == NULL || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { - ipseclog((LOG_DEBUG, "key_spddelete2: invalid message is passed.\n")); - key_senderror(so, m, EINVAL); - return 0; - } - - id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; - - /* Is there SP in SPD ? */ - if ((sp = key_getspbyid(id)) == NULL) { - ipseclog((LOG_DEBUG, "key_spddelete2: no SP found id:%u.\n", id)); - key_senderror(so, m, EINVAL); - } - - sp->state = IPSEC_SPSTATE_DEAD; - KEY_FREESP(&sp); - - { - struct mbuf *n; - struct sadb_msg *newmsg; - int off, len; - - /* create new sadb_msg to reply. */ - len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); - - if (len > MCLBYTES) - return key_senderror(so, m, ENOBUFS); - n = m_getb(len, M_NOWAIT, MT_DATA, M_PKTHDR); - if (!n) - return key_senderror(so, m, ENOBUFS); - n->m_len = len; - - m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t)); - off = PFKEY_ALIGN8(sizeof(struct sadb_msg)); - -#ifdef DIAGNOSTIC - if (off != len) - panic("length inconsistency in key_spddelete2"); -#endif - - n->m_next = m_copym(m, mhp->extoff[SADB_X_EXT_POLICY], - mhp->extlen[SADB_X_EXT_POLICY], M_NOWAIT); - if (!n->m_next) { - m_freem(n); - return key_senderror(so, m, ENOBUFS); - } - n->m_pkthdr.len = m_lengthm(n, NULL); - - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * SADB_X_GET processing - * receive - * - * from the user(?), - * and send, - * - * to the ikmpd. - * policy(*) including direction of policy. - * - * m will always be freed. - */ -static int -key_spdget(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - u_int32_t id; - struct secpolicy *sp; - struct mbuf *n; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spdget: NULL pointer is passed."); - - if (mhp->ext[SADB_X_EXT_POLICY] == NULL || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { - ipseclog((LOG_DEBUG, "key_spdget: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; - - /* Is there SP in SPD ? */ - if ((sp = key_getspbyid(id)) == NULL) { - ipseclog((LOG_DEBUG, "key_spdget: no SP found id:%u.\n", id)); - return key_senderror(so, m, ENOENT); - } - - n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid); - if (n != NULL) { - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } else - return key_senderror(so, m, ENOBUFS); -} - -/* - * SADB_X_SPDACQUIRE processing. - * Acquire policy and SA(s) for a *OUTBOUND* packet. - * send - * - * to KMD, and expect to receive - * with SADB_X_SPDACQUIRE if error occured, - * or - * - * with SADB_X_SPDUPDATE from KMD by PF_KEY. - * policy(*) is without policy requests. - * - * 0 : succeed - * others: error number - */ -int -key_spdacquire(struct secpolicy *sp) -{ - struct mbuf *result = NULL, *m; - struct secspacq *newspacq; - int error; - - /* sanity check */ - if (sp == NULL) - panic("key_spdacquire: NULL pointer is passed."); - if (sp->req != NULL) - panic("key_spdacquire: called but there is request."); - if (sp->policy != IPSEC_POLICY_IPSEC) - panic("key_spdacquire: policy mismatched. IPsec is expected."); - - /* Get an entry to check whether sent message or not. */ - if ((newspacq = key_getspacq(&sp->spidx)) != NULL) { - if (key_blockacq_count < newspacq->count) { - /* reset counter and do send message. */ - newspacq->count = 0; - } else { - /* increment counter and do nothing. */ - newspacq->count++; - return 0; - } - } else { - /* make new entry for blocking to send SADB_ACQUIRE. */ - if ((newspacq = key_newspacq(&sp->spidx)) == NULL) - return ENOBUFS; - - /* add to acqtree */ - LIST_INSERT_HEAD(&spacqtree, newspacq, chain); - } - - /* create new sadb_msg to reply. */ - m = key_setsadbmsg(SADB_X_SPDACQUIRE, 0, 0, 0, 0, 0); - if (!m) { - error = ENOBUFS; - goto fail; - } - result = m; - result->m_pkthdr.len = m_lengthm(result, NULL); - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED); - -fail: - if (result) - m_freem(result); - return error; -} - -/* - * SADB_SPDFLUSH processing - * receive - * - * from the user, and free all entries in secpctree. - * and send, - * - * to the user. - * NOTE: what to do is only marking SADB_SASTATE_DEAD. - * - * m will always be freed. - */ -static int -key_spdflush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_msg *newmsg; - struct secpolicy *sp; - u_int dir; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spdflush: NULL pointer is passed."); - - if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg))) - return key_senderror(so, m, EINVAL); - - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH(sp, &sptree[dir], chain) { - sp->state = IPSEC_SPSTATE_DEAD; - } - } - - if (sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) { - ipseclog((LOG_DEBUG, "key_spdflush: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - - if (m->m_next) - m_freem(m->m_next); - m->m_next = NULL; - m->m_pkthdr.len = m->m_len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); - newmsg = mtod(m, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); -} - -/* - * SADB_SPDDUMP processing - * receive - * - * from the user, and dump all SP leaves - * and send, - * ..... - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_spddump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct secpolicy *sp; - int cnt; - u_int dir; - struct mbuf *n; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spddump: NULL pointer is passed."); - - /* search SPD entry and get buffer size. */ - cnt = 0; - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH(sp, &sptree[dir], chain) { - cnt++; - } - } - - if (cnt == 0) - return key_senderror(so, m, ENOENT); - - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH(sp, &sptree[dir], chain) { - --cnt; - n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, - mhp->msg->sadb_msg_pid); - - if (n) - key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } - } - - m_freem(m); - return 0; -} - -static struct mbuf * -key_setdumpsp(struct secpolicy *sp, u_int8_t type, u_int32_t seq, - u_int32_t pid) -{ - struct mbuf *result = NULL, *m; - - m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt); - if (!m) - goto fail; - result = m; - - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - &sp->spidx.src.sa, sp->spidx.prefs, - sp->spidx.ul_proto); - if (!m) - goto fail; - m_cat(result, m); - - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - &sp->spidx.dst.sa, sp->spidx.prefd, - sp->spidx.ul_proto); - if (!m) - goto fail; - m_cat(result, m); - - m = key_sp2msg(sp); - if (!m) - goto fail; - m_cat(result, m); - - if ((result->m_flags & M_PKTHDR) == 0) - goto fail; - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) - goto fail; - } - result->m_pkthdr.len = m_lengthm(result, NULL); - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - return result; - -fail: - m_freem(result); - return NULL; -} - -/* - * get PFKEY message length for security policy and request. - */ -static u_int -key_getspreqmsglen(struct secpolicy *sp) -{ - struct ipsecrequest *isr; - u_int tlen, len; - - tlen = sizeof(struct sadb_x_policy); - - /* if is the policy for ipsec ? */ - if (sp->policy != IPSEC_POLICY_IPSEC) - return tlen; - - /* get length of ipsec requests */ - for (isr = sp->req; isr != NULL; isr = isr->next) { - len = sizeof(struct sadb_x_ipsecrequest) + - isr->saidx.src.sa.sa_len + isr->saidx.dst.sa.sa_len; - - tlen += PFKEY_ALIGN8(len); - } - - return tlen; -} - -/* - * SADB_SPDEXPIRE processing - * send - * - * to KMD by PF_KEY. - * - * OUT: 0 : succeed - * others : error number - */ -static int -key_spdexpire(struct secpolicy *sp) -{ - - struct mbuf *result = NULL, *m; - int len; - int error = -1; - struct sadb_lifetime *lt; - - /* XXX: Why do we lock ? */ - crit_enter(); - - /* sanity check */ - if (sp == NULL) - panic("key_spdexpire: NULL pointer is passed."); - - /* set msg header */ - m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0); - if (!m) { - error = ENOBUFS; - goto fail; - } - result = m; - - /* create lifetime extension (current and hard) */ - len = PFKEY_ALIGN8(sizeof(*lt)) * 2; - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - error = ENOBUFS; - goto fail; - } - bzero(mtod(m, caddr_t), len); - lt = mtod(m, struct sadb_lifetime *); - lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); - lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; - lt->sadb_lifetime_allocations = 0; - lt->sadb_lifetime_bytes = 0; - lt->sadb_lifetime_addtime = sp->created; - lt->sadb_lifetime_usetime = sp->lastused; - lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2); - lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); - lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; - lt->sadb_lifetime_allocations = 0; - lt->sadb_lifetime_bytes = 0; - lt->sadb_lifetime_addtime = sp->lifetime; - lt->sadb_lifetime_usetime = sp->validtime; - m_cat(result, m); - - /* set sadb_address for source */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - &sp->spidx.src.sa, - sp->spidx.prefs, sp->spidx.ul_proto); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* set sadb_address for destination */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - &sp->spidx.dst.sa, - sp->spidx.prefd, sp->spidx.ul_proto); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* set secpolicy */ - m = key_sp2msg(sp); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - if ((result->m_flags & M_PKTHDR) == 0) { - error = EINVAL; - goto fail; - } - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) { - error = ENOBUFS; - goto fail; - } - } - result->m_pkthdr.len = m_lengthm(result, NULL); - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - error = key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); - crit_exit(); - return error; - - fail: - if (result) - m_freem(result); - crit_exit(); - return error; -} - -/* %%% SAD management */ -/* - * allocating a memory for new SA head, and copy from the values of mhp. - * OUT: NULL : failure due to the lack of memory. - * others : pointer to new SA head. - */ -static struct secashead * -key_newsah(struct secasindex *saidx) -{ - struct secashead *newsah; - - KASSERT(saidx != NULL, ("key_newsaidx: null saidx")); - - newsah = kmalloc(sizeof(struct secashead), M_SECA, - M_INTWAIT | M_ZERO | M_NULLOK); - if (newsah != NULL) { - int i; - for (i = 0; i < NELEM(newsah->savtree); i++) - LIST_INIT(&newsah->savtree[i]); - newsah->saidx = *saidx; - - /* add to saidxtree */ - newsah->state = SADB_SASTATE_MATURE; - LIST_INSERT_HEAD(&sahtree, newsah, chain); - } - return(newsah); -} - -/* - * Delete SA index and all registered SAs. - */ -static void -key_delsah(struct secashead *sah) -{ - struct secasvar *sav, *nextsav; - u_int stateidx; - int nzombies = 0; - - /* sanity check */ - if (sah == NULL) - panic("key_delsah: NULL pointer is passed."); - - crit_enter(); - - /* searching all SA registerd in the secindex. */ - for (stateidx = 0; stateidx < NELEM(saorder_state_any); - stateidx++) { - u_int state = saorder_state_any[stateidx]; - - LIST_FOREACH_MUTABLE(sav, &sah->savtree[state], chain, nextsav) - if (sav->refcnt == 0) { - /* sanity check */ - KEY_CHKSASTATE(state, sav->state, __func__); - KEY_FREESAV(&sav); - } else { - /* give up to delete this SA */ - nzombies++; - } - } - - /* Delete sah it has are no savs. */ - if (nzombies == 0) { - /* remove from tree of SA index */ - if (__LIST_CHAINED(sah)) - LIST_REMOVE(sah, chain); - if (sah->sa_route.ro_rt) { - RTFREE(sah->sa_route.ro_rt); - sah->sa_route.ro_rt = NULL; - } - KFREE(sah); - } - - crit_exit(); - return; -} - -/* - * allocating a new SA with LARVAL state. key_add() and key_getspi() call, - * and copy the values of mhp into new buffer. - * When SAD message type is GETSPI: - * to set sequence number from acq_seq++, - * to set zero to SPI. - * not to call key_setsava(). - * OUT: NULL : fail - * others : pointer to new secasvar. - * - * does not modify mbuf. does not free mbuf on error. - */ -static struct secasvar * -key_newsav(struct mbuf *m, const struct sadb_msghdr *mhp, struct secashead *sah, - int *errp, const char *where, int tag) -{ - struct secasvar *newsav; - const struct sadb_sa *xsa; - - /* sanity check */ - if (m == NULL || mhp == NULL || mhp->msg == NULL || sah == NULL) - panic("key_newsa: NULL pointer is passed."); - - KMALLOC(newsav, struct secasvar *, sizeof(struct secasvar)); - if (newsav == NULL) { - ipseclog((LOG_DEBUG, "key_newsa: No more memory.\n")); - *errp = ENOBUFS; - goto done; - } - bzero((caddr_t)newsav, sizeof(struct secasvar)); - - switch (mhp->msg->sadb_msg_type) { - case SADB_GETSPI: - newsav->spi = 0; - -#ifdef IPSEC_DOSEQCHECK - /* sync sequence number */ - if (mhp->msg->sadb_msg_seq == 0) - newsav->seq = - (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq)); - else -#endif - newsav->seq = mhp->msg->sadb_msg_seq; - break; - - case SADB_ADD: - /* sanity check */ - if (mhp->ext[SADB_EXT_SA] == NULL) { - KFREE(newsav), newsav = NULL; - ipseclog((LOG_DEBUG, "key_newsa: invalid message is passed.\n")); - *errp = EINVAL; - goto done; - } - xsa = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - newsav->spi = xsa->sadb_sa_spi; - newsav->seq = mhp->msg->sadb_msg_seq; - break; - default: - KFREE(newsav), newsav = NULL; - *errp = EINVAL; - goto done; - } - - /* copy sav values */ - if (mhp->msg->sadb_msg_type != SADB_GETSPI) { - *errp = key_setsaval(newsav, m, mhp); - if (*errp) { - KFREE(newsav), newsav = NULL; - goto done; - } - } - - /* reset created */ - newsav->created = time_second; - newsav->pid = mhp->msg->sadb_msg_pid; - - /* add to satree */ - newsav->sah = sah; - newsav->refcnt = 1; - newsav->state = SADB_SASTATE_LARVAL; - LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav, - secasvar, chain); -done: - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_newsav from %s:%u return SP:%p\n", - where, tag, newsav)); - - return newsav; -} - -/* - * free() SA variable entry. - */ -static void -key_delsav(struct secasvar *sav) -{ - KASSERT(sav != NULL, ("key_delsav: null sav")); - KASSERT(sav->refcnt == 0, - ("key_delsav: reference count %u > 0", sav->refcnt)); - - /* remove from SA header */ - if (__LIST_CHAINED(sav)) - LIST_REMOVE(sav, chain); - - /* - * Cleanup xform state. Note that zeroize'ing causes the - * keys to be cleared; otherwise we must do it ourself. - */ - if (sav->tdb_xform != NULL) { - sav->tdb_xform->xf_zeroize(sav); - sav->tdb_xform = NULL; - } else { - if (sav->key_auth != NULL) - bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth)); - if (sav->key_enc != NULL) - bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc)); - } - if (sav->key_auth != NULL) { - KFREE(sav->key_auth); - sav->key_auth = NULL; - } - if (sav->key_enc != NULL) { - KFREE(sav->key_enc); - sav->key_enc = NULL; - } - if (sav->sched) { - bzero(sav->sched, sav->schedlen); - KFREE(sav->sched); - sav->sched = NULL; - } - if (sav->replay != NULL) { - KFREE(sav->replay); - sav->replay = NULL; - } - if (sav->lft_c != NULL) { - KFREE(sav->lft_c); - sav->lft_c = NULL; - } - if (sav->lft_h != NULL) { - KFREE(sav->lft_h); - sav->lft_h = NULL; - } - if (sav->lft_s != NULL) { - KFREE(sav->lft_s); - sav->lft_s = NULL; - } - if (sav->iv != NULL) { - KFREE(sav->iv); - sav->iv = NULL; - } - - KFREE(sav); - - return; -} - -/* - * search SAD. - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -static struct secashead * -key_getsah(struct secasindex *saidx) -{ - struct secashead *sah; - - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID)) - return sah; - } - - return NULL; -} - -/* - * check not to be duplicated SPI. - * NOTE: this function is too slow due to searching all SAD. - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -static struct secasvar * -key_checkspidup(struct secasindex *saidx, u_int32_t spi) -{ - struct secashead *sah; - struct secasvar *sav; - - /* check address family */ - if (saidx->src.sa.sa_family != saidx->dst.sa.sa_family) { - ipseclog((LOG_DEBUG, "key_checkspidup: address family mismatched.\n")); - return NULL; - } - - /* check all SAD */ - LIST_FOREACH(sah, &sahtree, chain) { - if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst)) - continue; - sav = key_getsavbyspi(sah, spi); - if (sav != NULL) - return sav; - } - - return NULL; -} - -/* - * search SAD litmited alive SA, protocol, SPI. - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -static struct secasvar * -key_getsavbyspi(struct secashead *sah, u_int32_t spi) -{ - struct secasvar *sav; - u_int stateidx; - - /* search all status */ - for (stateidx = 0; stateidx < NELEM(saorder_state_alive); - stateidx++) { - u_int state = saorder_state_alive[stateidx]; - - LIST_FOREACH(sav, &sah->savtree[state], chain) { - /* sanity check */ - if (sav->state != state) { - ipseclog((LOG_DEBUG, "key_getsavbyspi: " - "invalid sav->state (queue: %d SA: %d)\n", - state, sav->state)); - continue; - } - - if (sav->spi == spi) - return sav; - } - } - - return NULL; -} - -/* - * copy SA values from PF_KEY message except *SPI, SEQ, PID, STATE and TYPE*. - * You must update these if need. - * OUT: 0: success. - * !0: failure. - * - * does not modify mbuf. does not free mbuf on error. - */ -static int -key_setsaval(struct secasvar *sav, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - int error = 0; - - /* sanity check */ - if (m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_setsaval: NULL pointer is passed."); - - /* initialization */ - sav->replay = NULL; - sav->key_auth = NULL; - sav->key_enc = NULL; - sav->sched = NULL; - sav->schedlen = 0; - sav->iv = NULL; - sav->lft_c = NULL; - sav->lft_h = NULL; - sav->lft_s = NULL; - sav->tdb_xform = NULL; /* transform */ - sav->tdb_encalgxform = NULL; /* encoding algorithm */ - sav->tdb_authalgxform = NULL; /* authentication algorithm */ - sav->tdb_compalgxform = NULL; /* compression algorithm */ - - /* SA */ - if (mhp->ext[SADB_EXT_SA] != NULL) { - const struct sadb_sa *sa0; - - sa0 = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - if (mhp->extlen[SADB_EXT_SA] < sizeof(*sa0)) { - error = EINVAL; - goto fail; - } - - sav->alg_auth = sa0->sadb_sa_auth; - sav->alg_enc = sa0->sadb_sa_encrypt; - sav->flags = sa0->sadb_sa_flags; - - /* replay window */ - if ((sa0->sadb_sa_flags & SADB_X_EXT_OLD) == 0) { - sav->replay = - kmalloc(sizeof(struct secreplay)+sa0->sadb_sa_replay, - M_SECA, M_INTWAIT | M_ZERO | M_NULLOK); - if (sav->replay == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - if (sa0->sadb_sa_replay != 0) - sav->replay->bitmap = (caddr_t)(sav->replay+1); - sav->replay->wsize = sa0->sadb_sa_replay; - } - } - - /* Authentication keys */ - if (mhp->ext[SADB_EXT_KEY_AUTH] != NULL) { - const struct sadb_key *key0; - int len; - - key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_AUTH]; - len = mhp->extlen[SADB_EXT_KEY_AUTH]; - - error = 0; - if (len < sizeof(*key0)) { - error = EINVAL; - goto fail; - } - switch (mhp->msg->sadb_msg_satype) { - case SADB_SATYPE_AH: - case SADB_SATYPE_ESP: - if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) && - sav->alg_auth != SADB_X_AALG_NULL) - error = EINVAL; - break; - case SADB_X_SATYPE_IPCOMP: - default: - error = EINVAL; - break; - } - if (error) { - ipseclog((LOG_DEBUG, "key_setsaval: invalid key_auth values.\n")); - goto fail; - } - - sav->key_auth = (struct sadb_key *)key_newbuf(key0, len); - if (sav->key_auth == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - } - - /* Encryption key */ - if (mhp->ext[SADB_EXT_KEY_ENCRYPT] != NULL) { - const struct sadb_key *key0; - int len; - - key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_ENCRYPT]; - len = mhp->extlen[SADB_EXT_KEY_ENCRYPT]; - - error = 0; - if (len < sizeof(*key0)) { - error = EINVAL; - goto fail; - } - switch (mhp->msg->sadb_msg_satype) { - case SADB_SATYPE_ESP: - if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) && - sav->alg_enc != SADB_EALG_NULL) { - error = EINVAL; - break; - } - sav->key_enc = (struct sadb_key *)key_newbuf(key0, len); - if (sav->key_enc == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - break; - case SADB_X_SATYPE_IPCOMP: - if (len != PFKEY_ALIGN8(sizeof(struct sadb_key))) - error = EINVAL; - sav->key_enc = NULL; /*just in case*/ - break; - case SADB_SATYPE_AH: - default: - error = EINVAL; - break; - } - if (error) { - ipseclog((LOG_DEBUG, "key_setsatval: invalid key_enc value.\n")); - goto fail; - } - } - - /* set iv */ - sav->ivlen = 0; - - switch (mhp->msg->sadb_msg_satype) { - case SADB_SATYPE_AH: - error = xform_init(sav, XF_AH); - break; - case SADB_SATYPE_ESP: - error = xform_init(sav, XF_ESP); - break; - case SADB_X_SATYPE_IPCOMP: - error = xform_init(sav, XF_IPCOMP); - break; - } - if (error) { - ipseclog((LOG_DEBUG, - "key_setsaval: unable to initialize SA type %u.\n", - mhp->msg->sadb_msg_satype)); - goto fail; - } - - /* reset created */ - sav->created = time_second; - - /* make lifetime for CURRENT */ - KMALLOC(sav->lft_c, struct sadb_lifetime *, - sizeof(struct sadb_lifetime)); - if (sav->lft_c == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - - sav->lft_c->sadb_lifetime_len = - PFKEY_UNIT64(sizeof(struct sadb_lifetime)); - sav->lft_c->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; - sav->lft_c->sadb_lifetime_allocations = 0; - sav->lft_c->sadb_lifetime_bytes = 0; - sav->lft_c->sadb_lifetime_addtime = time_second; - sav->lft_c->sadb_lifetime_usetime = 0; - - /* lifetimes for HARD and SOFT */ - { - const struct sadb_lifetime *lft0; - - lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD]; - if (lft0 != NULL) { - if (mhp->extlen[SADB_EXT_LIFETIME_HARD] < sizeof(*lft0)) { - error = EINVAL; - goto fail; - } - sav->lft_h = (struct sadb_lifetime *)key_newbuf(lft0, - sizeof(*lft0)); - if (sav->lft_h == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - /* to be initialize ? */ - } - - lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_SOFT]; - if (lft0 != NULL) { - if (mhp->extlen[SADB_EXT_LIFETIME_SOFT] < sizeof(*lft0)) { - error = EINVAL; - goto fail; - } - sav->lft_s = (struct sadb_lifetime *)key_newbuf(lft0, - sizeof(*lft0)); - if (sav->lft_s == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - /* to be initialize ? */ - } - } - - return 0; - - fail: - /* initialization */ - if (sav->replay != NULL) { - KFREE(sav->replay); - sav->replay = NULL; - } - if (sav->key_auth != NULL) { - KFREE(sav->key_auth); - sav->key_auth = NULL; - } - if (sav->key_enc != NULL) { - KFREE(sav->key_enc); - sav->key_enc = NULL; - } - if (sav->sched) { - KFREE(sav->sched); - sav->sched = NULL; - } - if (sav->iv != NULL) { - KFREE(sav->iv); - sav->iv = NULL; - } - if (sav->lft_c != NULL) { - KFREE(sav->lft_c); - sav->lft_c = NULL; - } - if (sav->lft_h != NULL) { - KFREE(sav->lft_h); - sav->lft_h = NULL; - } - if (sav->lft_s != NULL) { - KFREE(sav->lft_s); - sav->lft_s = NULL; - } - - return error; -} - -/* - * validation with a secasvar entry, and set SADB_SATYPE_MATURE. - * OUT: 0: valid - * other: errno - */ -static int -key_mature(struct secasvar *sav) -{ - int error; - - /* check SPI value */ - switch (sav->sah->saidx.proto) { - case IPPROTO_ESP: - case IPPROTO_AH: - if (ntohl(sav->spi) >= 0 && ntohl(sav->spi) <= 255) { - ipseclog((LOG_DEBUG, - "key_mature: illegal range of SPI %u.\n", - (u_int32_t)ntohl(sav->spi))); - return EINVAL; - } - break; - } - - /* check satype */ - switch (sav->sah->saidx.proto) { - case IPPROTO_ESP: - /* check flags */ - if ((sav->flags & (SADB_X_EXT_OLD|SADB_X_EXT_DERIV)) == - (SADB_X_EXT_OLD|SADB_X_EXT_DERIV)) { - ipseclog((LOG_DEBUG, "key_mature: " - "invalid flag (derived) given to old-esp.\n")); - return EINVAL; - } - error = xform_init(sav, XF_ESP); - break; - case IPPROTO_AH: - /* check flags */ - if (sav->flags & SADB_X_EXT_DERIV) { - ipseclog((LOG_DEBUG, "key_mature: " - "invalid flag (derived) given to AH SA.\n")); - return EINVAL; - } - if (sav->alg_enc != SADB_EALG_NONE) { - ipseclog((LOG_DEBUG, "key_mature: " - "protocol and algorithm mismated.\n")); - return(EINVAL); - } - error = xform_init(sav, XF_AH); - break; - case IPPROTO_IPCOMP: - if (sav->alg_auth != SADB_AALG_NONE) { - ipseclog((LOG_DEBUG, "key_mature: " - "protocol and algorithm mismated.\n")); - return(EINVAL); - } - if ((sav->flags & SADB_X_EXT_RAWCPI) == 0 - && ntohl(sav->spi) >= 0x10000) { - ipseclog((LOG_DEBUG, "key_mature: invalid cpi for IPComp.\n")); - return(EINVAL); - } - error = xform_init(sav, XF_IPCOMP); - break; - default: - ipseclog((LOG_DEBUG, "key_mature: Invalid satype.\n")); - error = EPROTONOSUPPORT; - break; - } - if (error == 0) - key_sa_chgstate(sav, SADB_SASTATE_MATURE); - return (error); -} - -/* - * subroutine for SADB_GET and SADB_DUMP. - */ -static struct mbuf * -key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype, - u_int32_t seq, u_int32_t pid) -{ - struct mbuf *result = NULL, *tres = NULL, *m; - int l = 0; - int i; - void *p; - int dumporder[] = { - SADB_EXT_SA, SADB_X_EXT_SA2, - SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT, - SADB_EXT_LIFETIME_CURRENT, SADB_EXT_ADDRESS_SRC, - SADB_EXT_ADDRESS_DST, SADB_EXT_ADDRESS_PROXY, SADB_EXT_KEY_AUTH, - SADB_EXT_KEY_ENCRYPT, SADB_EXT_IDENTITY_SRC, - SADB_EXT_IDENTITY_DST, SADB_EXT_SENSITIVITY, - }; - - m = key_setsadbmsg(type, 0, satype, seq, pid, sav->refcnt); - if (m == NULL) - goto fail; - result = m; - - for (i = NELEM(dumporder) - 1; i >= 0; i--) { - m = NULL; - p = NULL; - switch (dumporder[i]) { - case SADB_EXT_SA: - m = key_setsadbsa(sav); - if (!m) - goto fail; - break; - - case SADB_X_EXT_SA2: - m = key_setsadbxsa2(sav->sah->saidx.mode, - sav->replay ? sav->replay->count : 0, - sav->sah->saidx.reqid); - if (!m) - goto fail; - break; - - case SADB_EXT_ADDRESS_SRC: - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - &sav->sah->saidx.src.sa, - FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) - goto fail; - break; - - case SADB_EXT_ADDRESS_DST: - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - &sav->sah->saidx.dst.sa, - FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) - goto fail; - break; - - case SADB_EXT_KEY_AUTH: - if (!sav->key_auth) - continue; - l = PFKEY_UNUNIT64(sav->key_auth->sadb_key_len); - p = sav->key_auth; - break; - - case SADB_EXT_KEY_ENCRYPT: - if (!sav->key_enc) - continue; - l = PFKEY_UNUNIT64(sav->key_enc->sadb_key_len); - p = sav->key_enc; - break; - - case SADB_EXT_LIFETIME_CURRENT: - if (!sav->lft_c) - continue; - l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_c)->sadb_ext_len); - p = sav->lft_c; - break; - - case SADB_EXT_LIFETIME_HARD: - if (!sav->lft_h) - continue; - l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_h)->sadb_ext_len); - p = sav->lft_h; - break; - - case SADB_EXT_LIFETIME_SOFT: - if (!sav->lft_s) - continue; - l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_s)->sadb_ext_len); - p = sav->lft_s; - break; - - case SADB_EXT_ADDRESS_PROXY: - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - /* XXX: should we brought from SPD ? */ - case SADB_EXT_SENSITIVITY: - default: - continue; - } - - if ((!m && !p) || (m && p)) - goto fail; - if (p && tres) { - M_PREPEND(tres, l, M_NOWAIT); - if (!tres) - goto fail; - bcopy(p, mtod(tres, caddr_t), l); - continue; - } - if (p) { - m = key_alloc_mbuf(l); - if (!m) - goto fail; - m_copyback(m, 0, l, p); - } - - if (tres) - m_cat(m, tres); - tres = m; - } - - m_cat(result, tres); - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) - goto fail; - } - result->m_pkthdr.len = m_lengthm(result, NULL); - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - return result; - -fail: - m_freem(result); - m_freem(tres); - return NULL; -} - -/* - * set data into sadb_msg. - */ -static struct mbuf * -key_setsadbmsg(u_int8_t type, u_int16_t tlen, u_int8_t satype, u_int32_t seq, - pid_t pid, u_int16_t reserved) -{ - struct mbuf *m; - struct sadb_msg *p; - int len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); - if (len > MCLBYTES) - return NULL; - m = m_getb(len, M_NOWAIT, MT_DATA, M_PKTHDR); - if (!m) - return NULL; - m->m_pkthdr.len = m->m_len = len; - - p = mtod(m, struct sadb_msg *); - - bzero(p, len); - p->sadb_msg_version = PF_KEY_V2; - p->sadb_msg_type = type; - p->sadb_msg_errno = 0; - p->sadb_msg_satype = satype; - p->sadb_msg_len = PFKEY_UNIT64(tlen); - p->sadb_msg_reserved = reserved; - p->sadb_msg_seq = seq; - p->sadb_msg_pid = (u_int32_t)pid; - - return m; -} - -/* - * copy secasvar data into sadb_address. - */ -static struct mbuf * -key_setsadbsa(struct secasvar *sav) -{ - struct mbuf *m; - struct sadb_sa *p; - int len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_sa)); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_sa *); - - bzero(p, len); - p->sadb_sa_len = PFKEY_UNIT64(len); - p->sadb_sa_exttype = SADB_EXT_SA; - p->sadb_sa_spi = sav->spi; - p->sadb_sa_replay = (sav->replay != NULL ? sav->replay->wsize : 0); - p->sadb_sa_state = sav->state; - p->sadb_sa_auth = sav->alg_auth; - p->sadb_sa_encrypt = sav->alg_enc; - p->sadb_sa_flags = sav->flags; - - return m; -} - -/* - * set data into sadb_address. - */ -static struct mbuf * -key_setsadbaddr(u_int16_t exttype, const struct sockaddr *saddr, u_int8_t prefixlen, - u_int16_t ul_proto) -{ - struct mbuf *m; - struct sadb_address *p; - size_t len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_address)) + - PFKEY_ALIGN8(saddr->sa_len); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_address *); - - bzero(p, len); - p->sadb_address_len = PFKEY_UNIT64(len); - p->sadb_address_exttype = exttype; - p->sadb_address_proto = ul_proto; - if (prefixlen == FULLMASK) { - switch (saddr->sa_family) { - case AF_INET: - prefixlen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - prefixlen = sizeof(struct in6_addr) << 3; - break; - default: - ; /*XXX*/ - } - } - p->sadb_address_prefixlen = prefixlen; - p->sadb_address_reserved = 0; - - bcopy(saddr, - mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_address)), - saddr->sa_len); - - return m; -} - -#if 0 -/* - * set data into sadb_ident. - */ -static struct mbuf * -key_setsadbident(u_int16_t exttype, u_int16_t idtype, caddr_t string, - int stringlen, u_int64_t id) -{ - struct mbuf *m; - struct sadb_ident *p; - size_t len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_ident)) + PFKEY_ALIGN8(stringlen); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_ident *); - - bzero(p, len); - p->sadb_ident_len = PFKEY_UNIT64(len); - p->sadb_ident_exttype = exttype; - p->sadb_ident_type = idtype; - p->sadb_ident_reserved = 0; - p->sadb_ident_id = id; - - bcopy(string, - mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_ident)), - stringlen); - - return m; -} -#endif - -/* - * set data into sadb_x_sa2. - */ -static struct mbuf * -key_setsadbxsa2(u_int8_t mode, u_int32_t seq, u_int32_t reqid) -{ - struct mbuf *m; - struct sadb_x_sa2 *p; - size_t len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_x_sa2)); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_x_sa2 *); - - bzero(p, len); - p->sadb_x_sa2_len = PFKEY_UNIT64(len); - p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; - p->sadb_x_sa2_mode = mode; - p->sadb_x_sa2_reserved1 = 0; - p->sadb_x_sa2_reserved2 = 0; - p->sadb_x_sa2_sequence = seq; - p->sadb_x_sa2_reqid = reqid; - - return m; -} - -/* - * set data into sadb_x_policy - */ -static struct mbuf * -key_setsadbxpolicy(u_int16_t type, u_int8_t dir, u_int32_t id) -{ - struct mbuf *m; - struct sadb_x_policy *p; - size_t len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_x_policy)); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_x_policy *); - - bzero(p, len); - p->sadb_x_policy_len = PFKEY_UNIT64(len); - p->sadb_x_policy_exttype = SADB_X_EXT_POLICY; - p->sadb_x_policy_type = type; - p->sadb_x_policy_dir = dir; - p->sadb_x_policy_id = id; - - return m; -} - -/* %%% utilities */ -/* - * copy a buffer into the new buffer allocated. - */ -static void * -key_newbuf(const void *src, u_int len) -{ - caddr_t new; - - KMALLOC(new, caddr_t, len); - if (new == NULL) { - ipseclog((LOG_DEBUG, "key_newbuf: No more memory.\n")); - return NULL; - } - bcopy(src, new, len); - - return new; -} - -/* compare my own address - * OUT: 1: true, i.e. my address. - * 0: false - */ -int -key_ismyaddr(struct sockaddr *sa) -{ -#ifdef INET - struct sockaddr_in *sin; - struct in_ifaddr_container *iac; -#endif - - /* sanity check */ - if (sa == NULL) - panic("key_ismyaddr: NULL pointer is passed."); - - switch (sa->sa_family) { -#ifdef INET - case AF_INET: - sin = (struct sockaddr_in *)sa; - TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { - struct in_ifaddr *ia = iac->ia; - - if (sin->sin_family == ia->ia_addr.sin_family && - sin->sin_len == ia->ia_addr.sin_len && - sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr) - { - return 1; - } - } - break; -#endif -#ifdef INET6 - case AF_INET6: - return key_ismyaddr6((struct sockaddr_in6 *)sa); -#endif - } - - return 0; -} - -#ifdef INET6 -/* - * compare my own address for IPv6. - * 1: ours - * 0: other - * NOTE: derived ip6_input() in KAME. This is necessary to modify more. - */ -static int -key_ismyaddr6(struct sockaddr_in6 *sin6) -{ - struct in6_ifaddr *ia; - struct in6_multi *in6m; - - for (ia = in6_ifaddr; ia; ia = ia->ia_next) { - if (key_sockaddrcmp((struct sockaddr *)&sin6, - (struct sockaddr *)&ia->ia_addr, 0) == 0) - return 1; - - /* - * XXX Multicast - * XXX why do we care about multlicast here while we don't care - * about IPv4 multicast?? - * XXX scope - */ - in6m = IN6_LOOKUP_MULTI(&sin6->sin6_addr, ia->ia_ifp); - if (in6m) - return 1; - } - - /* loopback, just for safety */ - if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) - return 1; - - return 0; -} -#endif /*INET6*/ - -/* - * compare two secasindex structure. - * flag can specify to compare 2 saidxes. - * compare two secasindex structure without both mode and reqid. - * don't compare port. - * IN: - * saidx0: source, it can be in SAD. - * saidx1: object. - * OUT: - * 1 : equal - * 0 : not equal - */ -static int -key_cmpsaidx( - const struct secasindex *saidx0, - const struct secasindex *saidx1, - int flag) -{ - /* sanity */ - if (saidx0 == NULL && saidx1 == NULL) - return 1; - - if (saidx0 == NULL || saidx1 == NULL) - return 0; - - if (saidx0->proto != saidx1->proto) - return 0; - - if (flag == CMP_EXACTLY) { - if (saidx0->mode != saidx1->mode) - return 0; - if (saidx0->reqid != saidx1->reqid) - return 0; - if (bcmp(&saidx0->src, &saidx1->src, saidx0->src.sa.sa_len) != 0 || - bcmp(&saidx0->dst, &saidx1->dst, saidx0->dst.sa.sa_len) != 0) - return 0; - } else { - - /* CMP_MODE_REQID, CMP_REQID, CMP_HEAD */ - if (flag == CMP_MODE_REQID - ||flag == CMP_REQID) { - /* - * If reqid of SPD is non-zero, unique SA is required. - * The result must be of same reqid in this case. - */ - if (saidx1->reqid != 0 && saidx0->reqid != saidx1->reqid) - return 0; - } - - if (flag == CMP_MODE_REQID) { - if (saidx0->mode != IPSEC_MODE_ANY - && saidx0->mode != saidx1->mode) - return 0; - } - - if (key_sockaddrcmp(&saidx0->src.sa, &saidx1->src.sa, 0) != 0) { - return 0; - } - if (key_sockaddrcmp(&saidx0->dst.sa, &saidx1->dst.sa, 0) != 0) { - return 0; - } - } - - return 1; -} - -/* - * compare two secindex structure exactly. - * IN: - * spidx0: source, it is often in SPD. - * spidx1: object, it is often from PFKEY message. - * OUT: - * 1 : equal - * 0 : not equal - */ -static int -key_cmpspidx_exactly( - struct secpolicyindex *spidx0, - struct secpolicyindex *spidx1) -{ - /* sanity */ - if (spidx0 == NULL && spidx1 == NULL) - return 1; - - if (spidx0 == NULL || spidx1 == NULL) - return 0; - - if (spidx0->prefs != spidx1->prefs - || spidx0->prefd != spidx1->prefd - || spidx0->ul_proto != spidx1->ul_proto) - return 0; - - return key_sockaddrcmp(&spidx0->src.sa, &spidx1->src.sa, 1) == 0 && - key_sockaddrcmp(&spidx0->dst.sa, &spidx1->dst.sa, 1) == 0; -} - -/* - * compare two secindex structure with mask. - * IN: - * spidx0: source, it is often in SPD. - * spidx1: object, it is often from IP header. - * OUT: - * 1 : equal - * 0 : not equal - */ -static int -key_cmpspidx_withmask( - struct secpolicyindex *spidx0, - struct secpolicyindex *spidx1) -{ - /* sanity */ - if (spidx0 == NULL && spidx1 == NULL) - return 1; - - if (spidx0 == NULL || spidx1 == NULL) - return 0; - - if (spidx0->src.sa.sa_family != spidx1->src.sa.sa_family || - spidx0->dst.sa.sa_family != spidx1->dst.sa.sa_family || - spidx0->src.sa.sa_len != spidx1->src.sa.sa_len || - spidx0->dst.sa.sa_len != spidx1->dst.sa.sa_len) - return 0; - - /* if spidx.ul_proto == IPSEC_ULPROTO_ANY, ignore. */ - if (spidx0->ul_proto != (u_int16_t)IPSEC_ULPROTO_ANY - && spidx0->ul_proto != spidx1->ul_proto) - return 0; - - switch (spidx0->src.sa.sa_family) { - case AF_INET: - if (spidx0->src.sin.sin_port != IPSEC_PORT_ANY - && spidx0->src.sin.sin_port != spidx1->src.sin.sin_port) - return 0; - if (!key_bbcmp(&spidx0->src.sin.sin_addr, - &spidx1->src.sin.sin_addr, spidx0->prefs)) - return 0; - break; - case AF_INET6: - if (spidx0->src.sin6.sin6_port != IPSEC_PORT_ANY - && spidx0->src.sin6.sin6_port != spidx1->src.sin6.sin6_port) - return 0; - /* - * scope_id check. if sin6_scope_id is 0, we regard it - * as a wildcard scope, which matches any scope zone ID. - */ - if (spidx0->src.sin6.sin6_scope_id && - spidx1->src.sin6.sin6_scope_id && - spidx0->src.sin6.sin6_scope_id != spidx1->src.sin6.sin6_scope_id) - return 0; - if (!key_bbcmp(&spidx0->src.sin6.sin6_addr, - &spidx1->src.sin6.sin6_addr, spidx0->prefs)) - return 0; - break; - default: - /* XXX */ - if (bcmp(&spidx0->src, &spidx1->src, spidx0->src.sa.sa_len) != 0) - return 0; - break; - } - - switch (spidx0->dst.sa.sa_family) { - case AF_INET: - if (spidx0->dst.sin.sin_port != IPSEC_PORT_ANY - && spidx0->dst.sin.sin_port != spidx1->dst.sin.sin_port) - return 0; - if (!key_bbcmp(&spidx0->dst.sin.sin_addr, - &spidx1->dst.sin.sin_addr, spidx0->prefd)) - return 0; - break; - case AF_INET6: - if (spidx0->dst.sin6.sin6_port != IPSEC_PORT_ANY - && spidx0->dst.sin6.sin6_port != spidx1->dst.sin6.sin6_port) - return 0; - /* - * scope_id check. if sin6_scope_id is 0, we regard it - * as a wildcard scope, which matches any scope zone ID. - */ - if (spidx0->dst.sin6.sin6_scope_id && - spidx1->dst.sin6.sin6_scope_id && - spidx0->dst.sin6.sin6_scope_id != spidx1->dst.sin6.sin6_scope_id) - return 0; - if (!key_bbcmp(&spidx0->dst.sin6.sin6_addr, - &spidx1->dst.sin6.sin6_addr, spidx0->prefd)) - return 0; - break; - default: - /* XXX */ - if (bcmp(&spidx0->dst, &spidx1->dst, spidx0->dst.sa.sa_len) != 0) - return 0; - break; - } - - /* XXX Do we check other field ? e.g. flowinfo */ - - return 1; -} - -/* returns 0 on match */ -static int -key_sockaddrcmp( - const struct sockaddr *sa1, - const struct sockaddr *sa2, - int port) -{ -#ifdef satosin -#undef satosin -#endif -#define satosin(s) ((const struct sockaddr_in *)s) -#ifdef satosin6 -#undef satosin6 -#endif -#define satosin6(s) ((const struct sockaddr_in6 *)s) - if (sa1->sa_family != sa2->sa_family || sa1->sa_len != sa2->sa_len) - return 1; - - switch (sa1->sa_family) { - case AF_INET: - if (sa1->sa_len != sizeof(struct sockaddr_in)) - return 1; - if (satosin(sa1)->sin_addr.s_addr != - satosin(sa2)->sin_addr.s_addr) { - return 1; - } - if (port && satosin(sa1)->sin_port != satosin(sa2)->sin_port) - return 1; - break; - case AF_INET6: - if (sa1->sa_len != sizeof(struct sockaddr_in6)) - return 1; /*EINVAL*/ - if (satosin6(sa1)->sin6_scope_id != - satosin6(sa2)->sin6_scope_id) { - return 1; - } - if (!IN6_ARE_ADDR_EQUAL(&satosin6(sa1)->sin6_addr, - &satosin6(sa2)->sin6_addr)) { - return 1; - } - if (port && - satosin6(sa1)->sin6_port != satosin6(sa2)->sin6_port) { - return 1; - } - default: - if (bcmp(sa1, sa2, sa1->sa_len) != 0) - return 1; - break; - } - - return 0; -#undef satosin -#undef satosin6 -} - -/* - * compare two buffers with mask. - * IN: - * addr1: source - * addr2: object - * bits: Number of bits to compare - * OUT: - * 1 : equal - * 0 : not equal - */ -static int -key_bbcmp(const void *a1, const void *a2, u_int bits) -{ - const unsigned char *p1 = a1; - const unsigned char *p2 = a2; - - /* XXX: This could be considerably faster if we compare a word - * at a time, but it is complicated on LSB Endian machines */ - - /* Handle null pointers */ - if (p1 == NULL || p2 == NULL) - return (p1 == p2); - - while (bits >= 8) { - if (*p1++ != *p2++) - return 0; - bits -= 8; - } - - if (bits > 0) { - u_int8_t mask = ~((1<<(8-bits))-1); - if ((*p1 & mask) != (*p2 & mask)) - return 0; - } - return 1; /* Match! */ -} - -/* - * time handler. - * scanning SPD and SAD to check status for each entries, - * and do to remove or to expire. - * XXX: year 2038 problem may remain. - */ -void -key_timehandler(void *unused) -{ - u_int dir; - time_t now = time_second; - struct secspacq *spacq, *nextspacq; - - crit_enter(); - - /* SPD */ - { - struct secpolicy *sp, *nextsp; - - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH_MUTABLE(sp, &sptree[dir], chain, nextsp) { - if (sp->state == IPSEC_SPSTATE_DEAD) { - KEY_FREESP(&sp); - continue; - } - - if (sp->lifetime == 0 && sp->validtime == 0) - continue; - - /* the deletion will occur next time */ - if ((sp->lifetime && now - sp->created > sp->lifetime) - || (sp->validtime && now - sp->lastused > sp->validtime)) { - sp->state = IPSEC_SPSTATE_DEAD; - key_spdexpire(sp); - continue; - } - } - } - } - - /* SAD */ - { - struct secashead *sah, *nextsah; - struct secasvar *sav, *nextsav; - - LIST_FOREACH_MUTABLE(sah, &sahtree, chain, nextsah) { - /* if sah has been dead, then delete it and process next sah. */ - if (sah->state == SADB_SASTATE_DEAD) { - key_delsah(sah); - continue; - } - - /* if LARVAL entry doesn't become MATURE, delete it. */ - LIST_FOREACH_MUTABLE(sav, &sah->savtree[SADB_SASTATE_LARVAL], - chain, nextsav) { - if (now - sav->created > key_larval_lifetime) { - KEY_FREESAV(&sav); - } - } - - /* - * check MATURE entry to start to send expire message - * whether or not. - */ - LIST_FOREACH_MUTABLE(sav, &sah->savtree[SADB_SASTATE_MATURE], - chain, nextsav) { - /* we don't need to check. */ - if (sav->lft_s == NULL) - continue; - - /* sanity check */ - if (sav->lft_c == NULL) { - ipseclog((LOG_DEBUG,"key_timehandler: " - "There is no CURRENT time, why?\n")); - continue; - } - - /* check SOFT lifetime */ - if (sav->lft_s->sadb_lifetime_addtime != 0 - && now - sav->created > sav->lft_s->sadb_lifetime_addtime) { - /* - * check SA to be used whether or not. - * when SA hasn't been used, delete it. - */ - if (sav->lft_c->sadb_lifetime_usetime == 0) { - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - KEY_FREESAV(&sav); - } else { - key_sa_chgstate(sav, SADB_SASTATE_DYING); - /* - * XXX If we keep to send expire - * message in the status of - * DYING. Do remove below code. - */ - key_expire(sav); - } - } - /* check SOFT lifetime by bytes */ - /* - * XXX I don't know the way to delete this SA - * when new SA is installed. Caution when it's - * installed too big lifetime by time. - */ - else if (sav->lft_s->sadb_lifetime_bytes != 0 - && sav->lft_s->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) { - - key_sa_chgstate(sav, SADB_SASTATE_DYING); - /* - * XXX If we keep to send expire - * message in the status of - * DYING. Do remove below code. - */ - key_expire(sav); - } - } - - /* check DYING entry to change status to DEAD. */ - LIST_FOREACH_MUTABLE(sav, &sah->savtree[SADB_SASTATE_DYING], - chain, nextsav) { - /* we don't need to check. */ - if (sav->lft_h == NULL) - continue; - - /* sanity check */ - if (sav->lft_c == NULL) { - ipseclog((LOG_DEBUG, "key_timehandler: " - "There is no CURRENT time, why?\n")); - continue; - } - - if (sav->lft_h->sadb_lifetime_addtime != 0 - && now - sav->created > sav->lft_h->sadb_lifetime_addtime) { - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - KEY_FREESAV(&sav); - } -#if 0 /* XXX Should we keep to send expire message until HARD lifetime ? */ - else if (sav->lft_s != NULL - && sav->lft_s->sadb_lifetime_addtime != 0 - && now - sav->created > sav->lft_s->sadb_lifetime_addtime) { - /* - * XXX: should be checked to be - * installed the valid SA. - */ - - /* - * If there is no SA then sending - * expire message. - */ - key_expire(sav); - } -#endif - /* check HARD lifetime by bytes */ - else if (sav->lft_h->sadb_lifetime_bytes != 0 - && sav->lft_h->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) { - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - KEY_FREESAV(&sav); - } - } - - /* delete entry in DEAD */ - LIST_FOREACH_MUTABLE(sav, &sah->savtree[SADB_SASTATE_DEAD], - chain, nextsav) { - /* sanity check */ - if (sav->state != SADB_SASTATE_DEAD) { - ipseclog((LOG_DEBUG, "key_timehandler: " - "invalid sav->state " - "(queue: %d SA: %d): " - "kill it anyway\n", - SADB_SASTATE_DEAD, sav->state)); - } - - /* - * do not call key_freesav() here. - * sav should already be freed, and sav->refcnt - * shows other references to sav - * (such as from SPD). - */ - } - } - } - -#ifndef IPSEC_NONBLOCK_ACQUIRE - /* ACQ tree */ - { - struct secacq *acq, *nextacq; - - LIST_FOREACH_MUTABLE(acq, &acqtree, chain, nextacq) { - if (now - acq->created > key_blockacq_lifetime && - __LIST_CHAINED(acq)) { - LIST_REMOVE(acq, chain); - KFREE(acq); - } - } - } -#endif - - /* SP ACQ tree */ - LIST_FOREACH_MUTABLE(spacq, &spacqtree, chain, nextspacq) { - if (now - spacq->created > key_blockacq_lifetime && - __LIST_CHAINED(spacq)) { - LIST_REMOVE(spacq, chain); - KFREE(spacq); - } - } - - /* initialize random seed */ - if (key_tick_init_random++ > key_int_random) { - key_tick_init_random = 0; - key_srandom(); - } - -#ifndef IPSEC_DEBUG2 - /* do exchange to tick time !! */ - callout_reset(&key_timehandler_ch, hz, key_timehandler, NULL); -#endif - - crit_exit(); - return; -} - -/* - * to initialize a seed for random() - */ -static void -key_srandom(void) -{ - skrandom(time_second); -} - -u_long -key_random(void) -{ - u_long value; - - key_randomfill(&value, sizeof(value)); - return value; -} - -void -key_randomfill(void *p, size_t l) -{ - size_t n; - u_long v; - static int warn = 1; - - n = (size_t)read_random(p, (u_int)l); - /* last resort */ - while (n < l) { - v = krandom(); - bcopy(&v, (u_int8_t *)p + n, - l - n < sizeof(v) ? l - n : sizeof(v)); - n += sizeof(v); - - if (warn) { - kprintf("WARNING: pseudo-random number generator " - "used for IPsec processing\n"); - warn = 0; - } - } -} - -/* - * map SADB_SATYPE_* to IPPROTO_*. - * if satype == SADB_SATYPE then satype is mapped to ~0. - * OUT: - * 0: invalid satype. - */ -static u_int16_t -key_satype2proto(u_int8_t satype) -{ - switch (satype) { - case SADB_SATYPE_UNSPEC: - return IPSEC_PROTO_ANY; - case SADB_SATYPE_AH: - return IPPROTO_AH; - case SADB_SATYPE_ESP: - return IPPROTO_ESP; - case SADB_X_SATYPE_IPCOMP: - return IPPROTO_IPCOMP; - default: - return 0; - } - /* NOTREACHED */ -} - -/* - * map IPPROTO_* to SADB_SATYPE_* - * OUT: - * 0: invalid protocol type. - */ -static u_int8_t -key_proto2satype(u_int16_t proto) -{ - switch (proto) { - case IPPROTO_AH: - return SADB_SATYPE_AH; - case IPPROTO_ESP: - return SADB_SATYPE_ESP; - case IPPROTO_IPCOMP: - return SADB_X_SATYPE_IPCOMP; - default: - return 0; - } - /* NOTREACHED */ -} - -/* %%% PF_KEY */ -/* - * SADB_GETSPI processing is to receive - * - * from the IKMPd, to assign a unique spi value, to hang on the INBOUND - * tree with the status of LARVAL, and send - * - * to the IKMPd. - * - * IN: mhp: pointer to the pointer to each header. - * OUT: NULL if fail. - * other if success, return pointer to the message to send. - */ -static int -key_getspi(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *newsah; - struct secasvar *newsav; - struct sockaddr *saddr, *daddr; - u_int8_t proto; - u_int32_t spi; - u_int8_t mode; - u_int32_t reqid; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_getspi: NULL pointer is passed."); - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { - ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->ext[SADB_X_EXT_SA2] != NULL) { - mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; - reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; - } else { - mode = IPSEC_MODE_ANY; - reqid = 0; - } - - src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_getspi: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - /* make sure if port number is zero. */ - saddr = (struct sockaddr *)(src0 + 1); - daddr = (struct sockaddr *)(dst0 + 1); - switch (saddr->sa_family) { - case AF_INET: - if (saddr->sa_len != sizeof(struct sockaddr_in)) - return key_senderror(so, m, EINVAL); - ((struct sockaddr_in *)(src0 + 1))->sin_port = 0; - break; - case AF_INET6: - if (saddr->sa_len != sizeof(struct sockaddr_in6)) - return key_senderror(so, m, EINVAL); - ((struct sockaddr_in6 *)(src0 + 1))->sin6_port = 0; - break; - default: - ; /*???*/ - } - switch (daddr->sa_family) { - case AF_INET: - if (daddr->sa_len != sizeof(struct sockaddr_in)) - return key_senderror(so, m, EINVAL); - ((struct sockaddr_in *)(dst0 + 1))->sin_port = 0; - break; - case AF_INET6: - if (daddr->sa_len != sizeof(struct sockaddr_in6)) - return key_senderror(so, m, EINVAL); - ((struct sockaddr_in6 *)(dst0 + 1))->sin6_port = 0; - break; - default: - ; /*???*/ - } - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - - /* SPI allocation */ - spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE], - &saidx); - if (spi == 0) - return key_senderror(so, m, EINVAL); - - /* get a SA index */ - if ((newsah = key_getsah(&saidx)) == NULL) { - /* create a new SA index */ - if ((newsah = key_newsah(&saidx)) == NULL) { - ipseclog((LOG_DEBUG, "key_getspi: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - } - - /* get a new SA */ - /* XXX rewrite */ - newsav = KEY_NEWSAV(m, mhp, newsah, &error); - if (newsav == NULL) { - /* XXX don't free new SA index allocated in above. */ - return key_senderror(so, m, error); - } - - /* set spi */ - newsav->spi = htonl(spi); - -#ifndef IPSEC_NONBLOCK_ACQUIRE - /* delete the entry in acqtree */ - if (mhp->msg->sadb_msg_seq != 0) { - struct secacq *acq; - if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) != NULL) { - /* reset counter in order to deletion by timehandler. */ - acq->created = time_second; - acq->count = 0; - } - } -#endif - - { - struct mbuf *n; - struct sadb_sa *m_sa; - struct sadb_msg *newmsg; - int off, len; - - /* create new sadb_msg to reply. */ - len = PFKEY_ALIGN8(sizeof(struct sadb_msg)) + - PFKEY_ALIGN8(sizeof(struct sadb_sa)); - if (len > MCLBYTES) - return key_senderror(so, m, ENOBUFS); - n = m_getb(len, M_NOWAIT, MT_DATA, M_PKTHDR); - if (!n) - return key_senderror(so, m, ENOBUFS); - n->m_len = len; - - m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t)); - off = PFKEY_ALIGN8(sizeof(struct sadb_msg)); - - m_sa = (struct sadb_sa *)(mtod(n, caddr_t) + off); - m_sa->sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa)); - m_sa->sadb_sa_exttype = SADB_EXT_SA; - m_sa->sadb_sa_spi = htonl(spi); - off += PFKEY_ALIGN8(sizeof(struct sadb_sa)); - -#ifdef DIAGNOSTIC - if (off != len) - panic("length inconsistency in key_getspi"); -#endif - - n->m_next = key_gather_mbuf(m, mhp, 0, 2, SADB_EXT_ADDRESS_SRC, - SADB_EXT_ADDRESS_DST); - if (!n->m_next) { - m_freem(n); - return key_senderror(so, m, ENOBUFS); - } - - if (n->m_len < sizeof(struct sadb_msg)) { - n = m_pullup(n, sizeof(struct sadb_msg)); - if (n == NULL) - return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); - } - n->m_pkthdr.len = m_lengthm(n, NULL); - - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_seq = newsav->seq; - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } -} - -/* - * allocating new SPI - * called by key_getspi(). - * OUT: - * 0: failure. - * others: success. - */ -static u_int32_t -key_do_getnewspi(struct sadb_spirange *spirange, struct secasindex *saidx) -{ - u_int32_t newspi; - u_int32_t min, max; - int count = key_spi_trycnt; - - /* set spi range to allocate */ - if (spirange != NULL) { - min = spirange->sadb_spirange_min; - max = spirange->sadb_spirange_max; - } else { - min = key_spi_minval; - max = key_spi_maxval; - } - /* IPCOMP needs 2-byte SPI */ - if (saidx->proto == IPPROTO_IPCOMP) { - u_int32_t t; - if (min >= 0x10000) - min = 0xffff; - if (max >= 0x10000) - max = 0xffff; - if (min > max) { - t = min; min = max; max = t; - } - } - - if (min == max) { - if (key_checkspidup(saidx, min) != NULL) { - ipseclog((LOG_DEBUG, "key_do_getnewspi: SPI %u exists already.\n", min)); - return 0; - } - - count--; /* taking one cost. */ - newspi = min; - - } else { - - /* init SPI */ - newspi = 0; - - /* when requesting to allocate spi ranged */ - while (count--) { - /* generate pseudo-random SPI value ranged. */ - newspi = min + (key_random() % (max - min + 1)); - - if (key_checkspidup(saidx, newspi) == NULL) - break; - } - - if (count == 0 || newspi == 0) { - ipseclog((LOG_DEBUG, "key_do_getnewspi: to allocate spi is failed.\n")); - return 0; - } - } - - /* statistics */ - keystat.getspi_count = - (keystat.getspi_count + key_spi_trycnt - count) / 2; - - return newspi; -} - -/* - * SADB_UPDATE processing - * receive - * - * from the ikmpd, and update a secasvar entry whose status is SADB_SASTATE_LARVAL. - * and send - * - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_update(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_sa *sa0; - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - struct secasvar *sav; - u_int16_t proto; - u_int8_t mode; - u_int32_t reqid; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_update: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_update: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_SA] == NULL || - mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP && - mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) || - (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH && - mhp->ext[SADB_EXT_KEY_AUTH] == NULL) || - (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL && - mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) || - (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL && - mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) { - ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || - mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->ext[SADB_X_EXT_SA2] != NULL) { - mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; - reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; - } else { - mode = IPSEC_MODE_ANY; - reqid = 0; - } - /* XXX boundary checking for other extensions */ - - sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ - if ((sah = key_getsah(&saidx)) == NULL) { - ipseclog((LOG_DEBUG, "key_update: no SA index found.\n")); - return key_senderror(so, m, ENOENT); - } - - /* set spidx if there */ - /* XXX rewrite */ - error = key_setident(sah, m, mhp); - if (error) - return key_senderror(so, m, error); - - /* find a SA with sequence number. */ -#ifdef IPSEC_DOSEQCHECK - if (mhp->msg->sadb_msg_seq != 0 - && (sav = key_getsavbyseq(sah, mhp->msg->sadb_msg_seq)) == NULL) { - ipseclog((LOG_DEBUG, - "key_update: no larval SA with sequence %u exists.\n", - mhp->msg->sadb_msg_seq)); - return key_senderror(so, m, ENOENT); - } -#else - if ((sav = key_getsavbyspi(sah, sa0->sadb_sa_spi)) == NULL) { - ipseclog((LOG_DEBUG, - "key_update: no such a SA found (spi:%u)\n", - (u_int32_t)ntohl(sa0->sadb_sa_spi))); - return key_senderror(so, m, EINVAL); - } -#endif - - /* validity check */ - if (sav->sah->saidx.proto != proto) { - ipseclog((LOG_DEBUG, - "key_update: protocol mismatched (DB=%u param=%u)\n", - sav->sah->saidx.proto, proto)); - return key_senderror(so, m, EINVAL); - } -#ifdef IPSEC_DOSEQCHECK - if (sav->spi != sa0->sadb_sa_spi) { - ipseclog((LOG_DEBUG, - "key_update: SPI mismatched (DB:%u param:%u)\n", - (u_int32_t)ntohl(sav->spi), - (u_int32_t)ntohl(sa0->sadb_sa_spi))); - return key_senderror(so, m, EINVAL); - } -#endif - if (sav->pid != mhp->msg->sadb_msg_pid) { - ipseclog((LOG_DEBUG, - "key_update: pid mismatched (DB:%u param:%u)\n", - sav->pid, mhp->msg->sadb_msg_pid)); - return key_senderror(so, m, EINVAL); - } - - /* copy sav values */ - error = key_setsaval(sav, m, mhp); - if (error) { - KEY_FREESAV(&sav); - return key_senderror(so, m, error); - } - - /* check SA values to be mature. */ - if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) { - KEY_FREESAV(&sav); - return key_senderror(so, m, 0); - } - - { - struct mbuf *n; - - /* set msg buf from mhp */ - n = key_getmsgbuf_x1(m, mhp); - if (n == NULL) { - ipseclog((LOG_DEBUG, "key_update: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * search SAD with sequence for a SA which state is SADB_SASTATE_LARVAL. - * only called by key_update(). - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -#ifdef IPSEC_DOSEQCHECK -static struct secasvar * -key_getsavbyseq(struct secashead *sah, u_int32_t seq) -{ - struct secasvar *sav; - u_int state; - - state = SADB_SASTATE_LARVAL; - - /* search SAD with sequence number ? */ - LIST_FOREACH(sav, &sah->savtree[state], chain) { - - KEY_CHKSASTATE(state, sav->state, "key_getsabyseq"); - - if (sav->seq == seq) { - SA_ADDREF(sav); - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_getsavbyseq cause " - "refcnt++:%d SA:%p\n", - sav->refcnt, sav)); - return sav; - } - } - - return NULL; -} -#endif - -/* - * SADB_ADD processing - * add an entry to SA database, when received - * - * from the ikmpd, - * and send - * - * to the ikmpd. - * - * IGNORE identity and sensitivity messages. - * - * m will always be freed. - */ -static int -key_add(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_sa *sa0; - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *newsah; - struct secasvar *newsav; - u_int16_t proto; - u_int8_t mode; - u_int32_t reqid; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_add: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_add: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_SA] == NULL || - mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP && - mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) || - (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH && - mhp->ext[SADB_EXT_KEY_AUTH] == NULL) || - (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL && - mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) || - (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL && - mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) { - ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || - mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - /* XXX need more */ - ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->ext[SADB_X_EXT_SA2] != NULL) { - mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; - reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; - } else { - mode = IPSEC_MODE_ANY; - reqid = 0; - } - - sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ - if ((newsah = key_getsah(&saidx)) == NULL) { - /* create a new SA header */ - if ((newsah = key_newsah(&saidx)) == NULL) { - ipseclog((LOG_DEBUG, "key_add: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - } - - /* set spidx if there */ - /* XXX rewrite */ - error = key_setident(newsah, m, mhp); - if (error) { - return key_senderror(so, m, error); - } - - /* create new SA entry. */ - /* We can create new SA only if SPI is differenct. */ - if (key_getsavbyspi(newsah, sa0->sadb_sa_spi)) { - ipseclog((LOG_DEBUG, "key_add: SA already exists.\n")); - return key_senderror(so, m, EEXIST); - } - newsav = KEY_NEWSAV(m, mhp, newsah, &error); - if (newsav == NULL) { - return key_senderror(so, m, error); - } - - /* check SA values to be mature. */ - if ((error = key_mature(newsav)) != 0) { - KEY_FREESAV(&newsav); - return key_senderror(so, m, error); - } - - /* - * don't call key_freesav() here, as we would like to keep the SA - * in the database on success. - */ - - { - struct mbuf *n; - - /* set msg buf from mhp */ - n = key_getmsgbuf_x1(m, mhp); - if (n == NULL) { - ipseclog((LOG_DEBUG, "key_update: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* m is retained */ -static int -key_setident(struct secashead *sah, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - const struct sadb_ident *idsrc, *iddst; - int idsrclen, iddstlen; - - /* sanity check */ - if (sah == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_setident: NULL pointer is passed."); - - /* don't make buffer if not there */ - if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL && - mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) { - sah->idents = NULL; - sah->identd = NULL; - return 0; - } - - if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL || - mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) { - ipseclog((LOG_DEBUG, "key_setident: invalid identity.\n")); - return EINVAL; - } - - idsrc = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_SRC]; - iddst = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_DST]; - idsrclen = mhp->extlen[SADB_EXT_IDENTITY_SRC]; - iddstlen = mhp->extlen[SADB_EXT_IDENTITY_DST]; - - /* validity check */ - if (idsrc->sadb_ident_type != iddst->sadb_ident_type) { - ipseclog((LOG_DEBUG, "key_setident: ident type mismatch.\n")); - return EINVAL; - } - - switch (idsrc->sadb_ident_type) { - case SADB_IDENTTYPE_PREFIX: - case SADB_IDENTTYPE_FQDN: - case SADB_IDENTTYPE_USERFQDN: - default: - /* XXX do nothing */ - sah->idents = NULL; - sah->identd = NULL; - return 0; - } - - /* make structure */ - KMALLOC(sah->idents, struct sadb_ident *, idsrclen); - if (sah->idents == NULL) { - ipseclog((LOG_DEBUG, "key_setident: No more memory.\n")); - return ENOBUFS; - } - KMALLOC(sah->identd, struct sadb_ident *, iddstlen); - if (sah->identd == NULL) { - KFREE(sah->idents); - sah->idents = NULL; - ipseclog((LOG_DEBUG, "key_setident: No more memory.\n")); - return ENOBUFS; - } - bcopy(idsrc, sah->idents, idsrclen); - bcopy(iddst, sah->identd, iddstlen); - - return 0; -} - -/* - * m will not be freed on return. - * it is caller's responsibility to free the result. - */ -static struct mbuf * -key_getmsgbuf_x1(struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct mbuf *n; - - /* sanity check */ - if (m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_getmsgbuf_x1: NULL pointer is passed."); - - /* create new sadb_msg to reply. */ - n = key_gather_mbuf(m, mhp, 1, 9, SADB_EXT_RESERVED, - SADB_EXT_SA, SADB_X_EXT_SA2, - SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST, - SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT, - SADB_EXT_IDENTITY_SRC, SADB_EXT_IDENTITY_DST); - if (!n) - return NULL; - - if (n->m_len < sizeof(struct sadb_msg)) { - n = m_pullup(n, sizeof(struct sadb_msg)); - if (n == NULL) - return NULL; - } - mtod(n, struct sadb_msg *)->sadb_msg_errno = 0; - mtod(n, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(n->m_pkthdr.len); - - return n; -} - -static int key_delete_all (struct socket *, struct mbuf *, - const struct sadb_msghdr *, u_int16_t); - -/* - * SADB_DELETE processing - * receive - * - * from the ikmpd, and set SADB_SASTATE_DEAD, - * and send, - * - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_delete(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_sa *sa0; - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - struct secasvar *sav = NULL; - u_int16_t proto; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_delete: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_delete: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { - ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_SA] == NULL) { - /* - * Caller wants us to delete all non-LARVAL SAs - * that match the src/dst. This is used during - * IKE INITIAL-CONTACT. - */ - ipseclog((LOG_DEBUG, "key_delete: doing delete all.\n")); - return key_delete_all(so, m, mhp, proto); - } else if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa)) { - ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) - continue; - - /* get a SA with SPI. */ - sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); - if (sav) - break; - } - if (sah == NULL) { - ipseclog((LOG_DEBUG, "key_delete: no SA found.\n")); - return key_senderror(so, m, ENOENT); - } - - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - KEY_FREESAV(&sav); - - { - struct mbuf *n; - struct sadb_msg *newmsg; - - /* create new sadb_msg to reply. */ - n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED, - SADB_EXT_SA, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - if (!n) - return key_senderror(so, m, ENOBUFS); - - if (n->m_len < sizeof(struct sadb_msg)) { - n = m_pullup(n, sizeof(struct sadb_msg)); - if (n == NULL) - return key_senderror(so, m, ENOBUFS); - } - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * delete all SAs for src/dst. Called from key_delete(). - */ -static int -key_delete_all(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp, u_int16_t proto) -{ - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - struct secasvar *sav, *nextsav; - u_int stateidx, state; - struct mbuf *n; - struct sadb_msg *newmsg; - - src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) - continue; - - /* Delete all non-LARVAL SAs. */ - for (stateidx = 0; stateidx < NELEM(saorder_state_alive); - stateidx++) { - state = saorder_state_alive[stateidx]; - if (state == SADB_SASTATE_LARVAL) - continue; - LIST_FOREACH_MUTABLE(sav, &sah->savtree[state], chain, - nextsav) { - /* sanity check */ - if (sav->state != state) { - ipseclog((LOG_DEBUG, "key_delete_all: " - "invalid sav->state " - "(queue: %d SA: %d)\n", - state, sav->state)); - continue; - } - - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - KEY_FREESAV(&sav); - } - } - } - - /* create new sadb_msg to reply. */ - n = key_gather_mbuf(m, mhp, 1, 3, SADB_EXT_RESERVED, - SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - if (!n) - return key_senderror(so, m, ENOBUFS); - - if (n->m_len < sizeof(struct sadb_msg)) { - n = m_pullup(n, sizeof(struct sadb_msg)); - if (n == NULL) - return key_senderror(so, m, ENOBUFS); - } - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); -} - -/* - * SADB_GET processing - * receive - * - * from the ikmpd, and get a SP and a SA to respond, - * and send, - * - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_get(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_sa *sa0; - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - struct secasvar *sav = NULL; - u_int16_t proto; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_get: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_get: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_SA] == NULL || - mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { - ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || - mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) - continue; - - /* get a SA with SPI. */ - sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); - if (sav) - break; - } - if (sah == NULL) { - ipseclog((LOG_DEBUG, "key_get: no SA found.\n")); - return key_senderror(so, m, ENOENT); - } - - { - struct mbuf *n; - u_int8_t satype; - - /* map proto to satype */ - if ((satype = key_proto2satype(sah->saidx.proto)) == 0) { - ipseclog((LOG_DEBUG, "key_get: there was invalid proto in SAD.\n")); - return key_senderror(so, m, EINVAL); - } - - /* create new sadb_msg to reply. */ - n = key_setdumpsa(sav, SADB_GET, satype, mhp->msg->sadb_msg_seq, - mhp->msg->sadb_msg_pid); - if (!n) - return key_senderror(so, m, ENOBUFS); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } -} - -/* XXX make it sysctl-configurable? */ -static void -key_getcomb_setlifetime(struct sadb_comb *comb) -{ - - comb->sadb_comb_soft_allocations = 1; - comb->sadb_comb_hard_allocations = 1; - comb->sadb_comb_soft_bytes = 0; - comb->sadb_comb_hard_bytes = 0; - comb->sadb_comb_hard_addtime = 86400; /* 1 day */ - comb->sadb_comb_soft_addtime = comb->sadb_comb_soft_addtime * 80 / 100; - comb->sadb_comb_soft_usetime = 28800; /* 8 hours */ - comb->sadb_comb_hard_usetime = comb->sadb_comb_hard_usetime * 80 / 100; -} - -/* - * XXX reorder combinations by preference - * XXX no idea if the user wants ESP authentication or not - */ -static struct mbuf * -key_getcomb_esp(void) -{ - struct sadb_comb *comb; - struct enc_xform *algo; - struct mbuf *result = NULL, *m, *n; - int encmin; - int i, off, o; - int totlen; - const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); - - m = NULL; - for (i = 1; i <= SADB_EALG_MAX; i++) { - algo = esp_algorithm_lookup(i); - if (algo == NULL) - continue; - - /* discard algorithms with key size smaller than system min */ - if (_BITS(algo->maxkey) < ipsec_esp_keymin) - continue; - if (_BITS(algo->minkey) < ipsec_esp_keymin) - encmin = ipsec_esp_keymin; - else - encmin = _BITS(algo->minkey); - - if (ipsec_esp_auth) - m = key_getcomb_ah(); - else { - KASSERT(l <= MLEN, - ("key_getcomb_esp: l=%u > MLEN=%lu", - l, (u_long) MLEN)); - MGET(m, M_NOWAIT, MT_DATA); - if (m) { - M_ALIGN(m, l); - m->m_len = l; - m->m_next = NULL; - bzero(mtod(m, caddr_t), m->m_len); - } - } - if (!m) - goto fail; - - totlen = m_lengthm(m, NULL); - KASSERT((totlen % l) == 0, - ("key_getcomb_esp: totlen=%u, l=%u", totlen, l)); - - for (off = 0; off < totlen; off += l) { - n = m_pulldown(m, off, l, &o); - if (!n) { - /* m is already freed */ - goto fail; - } - comb = (struct sadb_comb *)(mtod(n, caddr_t) + o); - bzero(comb, sizeof(*comb)); - key_getcomb_setlifetime(comb); - comb->sadb_comb_encrypt = i; - comb->sadb_comb_encrypt_minbits = encmin; - comb->sadb_comb_encrypt_maxbits = _BITS(algo->maxkey); - } - - if (!result) - result = m; - else - m_cat(result, m); - } - - return result; - - fail: - if (result) - m_freem(result); - return NULL; -} - -static void -key_getsizes_ah( - const struct auth_hash *ah, - int alg, - u_int16_t* min, - u_int16_t* max) -{ - *min = *max = ah->keysize; - if (ah->keysize == 0) { - /* - * Transform takes arbitrary key size but algorithm - * key size is restricted. Enforce this here. - */ - switch (alg) { - case SADB_X_AALG_MD5: *min = *max = 16; break; - case SADB_X_AALG_SHA: *min = *max = 20; break; - case SADB_X_AALG_NULL: *min = 1; *max = 256; break; - default: - DPRINTF(("key_getsizes_ah: unknown AH algorithm %u\n", - alg)); - break; - } - } -} - -/* - * XXX reorder combinations by preference - */ -static struct mbuf * -key_getcomb_ah(void) -{ - struct sadb_comb *comb; - struct auth_hash *algo; - struct mbuf *m; - u_int16_t minkeysize, maxkeysize; - int i; - const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); - - m = NULL; - for (i = 1; i <= SADB_AALG_MAX; i++) { -#if 1 - /* we prefer HMAC algorithms, not old algorithms */ - if (i != SADB_AALG_SHA1HMAC && i != SADB_AALG_MD5HMAC) - continue; -#endif - algo = ah_algorithm_lookup(i); - if (!algo) - continue; - key_getsizes_ah(algo, i, &minkeysize, &maxkeysize); - /* discard algorithms with key size smaller than system min */ - if (_BITS(minkeysize) < ipsec_ah_keymin) - continue; - - if (!m) { - KASSERT(l <= MLEN, - ("key_getcomb_ah: l=%u > MLEN=%lu", - l, (u_long) MLEN)); - MGET(m, M_NOWAIT, MT_DATA); - if (m) { - M_ALIGN(m, l); - m->m_len = l; - m->m_next = NULL; - } - } else - M_PREPEND(m, l, M_NOWAIT); - if (!m) - return NULL; - - comb = mtod(m, struct sadb_comb *); - bzero(comb, sizeof(*comb)); - key_getcomb_setlifetime(comb); - comb->sadb_comb_auth = i; - comb->sadb_comb_auth_minbits = _BITS(minkeysize); - comb->sadb_comb_auth_maxbits = _BITS(maxkeysize); - } - - return m; -} - -/* - * not really an official behavior. discussed in pf_key@inner.net in Sep2000. - * XXX reorder combinations by preference - */ -static struct mbuf * -key_getcomb_ipcomp(void) -{ - struct sadb_comb *comb; - struct comp_algo *algo; - struct mbuf *m; - int i; - const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); - - m = NULL; - for (i = 1; i <= SADB_X_CALG_MAX; i++) { - algo = ipcomp_algorithm_lookup(i); - if (!algo) - continue; - - if (!m) { - KASSERT(l <= MLEN, - ("key_getcomb_ipcomp: l=%u > MLEN=%lu", - l, (u_long) MLEN)); - MGET(m, M_NOWAIT, MT_DATA); - if (m) { - M_ALIGN(m, l); - m->m_len = l; - m->m_next = NULL; - } - } else - M_PREPEND(m, l, M_NOWAIT); - if (!m) - return NULL; - - comb = mtod(m, struct sadb_comb *); - bzero(comb, sizeof(*comb)); - key_getcomb_setlifetime(comb); - comb->sadb_comb_encrypt = i; - /* what should we set into sadb_comb_*_{min,max}bits? */ - } - - return m; -} - -/* - * XXX no way to pass mode (transport/tunnel) to userland - * XXX replay checking? - * XXX sysctl interface to ipsec_{ah,esp}_keymin - */ -static struct mbuf * -key_getprop(const struct secasindex *saidx) -{ - struct sadb_prop *prop; - struct mbuf *m; - const int l = PFKEY_ALIGN8(sizeof(struct sadb_prop)); - - switch (saidx->proto) { - case IPPROTO_ESP: - m = key_getcomb_esp(); - break; - case IPPROTO_AH: - m = key_getcomb_ah(); - break; - case IPPROTO_IPCOMP: - m = key_getcomb_ipcomp(); - break; - default: - return NULL; - } - - if (!m) - return NULL; - M_PREPEND(m, l, M_NOWAIT); - if (!m) - return NULL; - - prop = mtod(m, struct sadb_prop *); - bzero(prop, sizeof(*prop)); - prop->sadb_prop_len = PFKEY_UNIT64(m_lengthm(m, NULL)); - prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; - prop->sadb_prop_replay = 32; /* XXX */ - - return m; -} - -/* - * SADB_ACQUIRE processing called by key_checkrequest() and key_acquire2(). - * send - * - * to KMD, and expect to receive - * with SADB_ACQUIRE if error occured, - * or - * with SADB_GETSPI - * from KMD by PF_KEY. - * - * XXX x_policy is outside of RFC2367 (KAME extension). - * XXX sensitivity is not supported. - * XXX for ipcomp, RFC2367 does not define how to fill in proposal. - * see comment for key_getcomb_ipcomp(). - * - * OUT: - * 0 : succeed - * others: error number - */ -static int -key_acquire(const struct secasindex *saidx, struct secpolicy *sp) -{ - struct mbuf *result = NULL, *m; -#ifndef IPSEC_NONBLOCK_ACQUIRE - struct secacq *newacq; -#endif - u_int8_t satype; - int error = -1; - u_int32_t seq; - - /* sanity check */ - KASSERT(saidx != NULL, ("key_acquire: null saidx")); - satype = key_proto2satype(saidx->proto); - KASSERT(satype != 0, - ("key_acquire: null satype, protocol %u", saidx->proto)); - -#ifndef IPSEC_NONBLOCK_ACQUIRE - /* - * We never do anything about acquirng SA. There is anather - * solution that kernel blocks to send SADB_ACQUIRE message until - * getting something message from IKEd. In later case, to be - * managed with ACQUIRING list. - */ - /* Get an entry to check whether sending message or not. */ - if ((newacq = key_getacq(saidx)) != NULL) { - if (key_blockacq_count < newacq->count) { - /* reset counter and do send message. */ - newacq->count = 0; - } else { - /* increment counter and do nothing. */ - newacq->count++; - return 0; - } - } else { - /* make new entry for blocking to send SADB_ACQUIRE. */ - if ((newacq = key_newacq(saidx)) == NULL) - return ENOBUFS; - - /* add to acqtree */ - LIST_INSERT_HEAD(&acqtree, newacq, chain); - } -#endif - - -#ifndef IPSEC_NONBLOCK_ACQUIRE - seq = newacq->seq; -#else - seq = (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq)); -#endif - m = key_setsadbmsg(SADB_ACQUIRE, 0, satype, seq, 0, 0); - if (!m) { - error = ENOBUFS; - goto fail; - } - result = m; - - /* set sadb_address for saidx's. */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - &saidx->src.sa, FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - &saidx->dst.sa, FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* XXX proxy address (optional) */ - - /* set sadb_x_policy */ - if (sp) { - m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - } - - /* XXX identity (optional) */ -#if 0 - if (idexttype && fqdn) { - /* create identity extension (FQDN) */ - struct sadb_ident *id; - int fqdnlen; - - fqdnlen = strlen(fqdn) + 1; /* +1 for terminating-NUL */ - id = (struct sadb_ident *)p; - bzero(id, sizeof(*id) + PFKEY_ALIGN8(fqdnlen)); - id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(fqdnlen)); - id->sadb_ident_exttype = idexttype; - id->sadb_ident_type = SADB_IDENTTYPE_FQDN; - bcopy(fqdn, id + 1, fqdnlen); - p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(fqdnlen); - } - - if (idexttype) { - /* create identity extension (USERFQDN) */ - struct sadb_ident *id; - int userfqdnlen; - - if (userfqdn) { - /* +1 for terminating-NUL */ - userfqdnlen = strlen(userfqdn) + 1; - } else - userfqdnlen = 0; - id = (struct sadb_ident *)p; - bzero(id, sizeof(*id) + PFKEY_ALIGN8(userfqdnlen)); - id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(userfqdnlen)); - id->sadb_ident_exttype = idexttype; - id->sadb_ident_type = SADB_IDENTTYPE_USERFQDN; - /* XXX is it correct? */ - if (curproc && curproc->p_cred) - id->sadb_ident_id = curproc->p_cred->p_ruid; - if (userfqdn && userfqdnlen) - bcopy(userfqdn, id + 1, userfqdnlen); - p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(userfqdnlen); - } -#endif - - /* XXX sensitivity (optional) */ - - /* create proposal/combination extension */ - m = key_getprop(saidx); -#if 0 - /* - * spec conformant: always attach proposal/combination extension, - * the problem is that we have no way to attach it for ipcomp, - * due to the way sadb_comb is declared in RFC2367. - */ - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); -#else - /* - * outside of spec; make proposal/combination extension optional. - */ - if (m) - m_cat(result, m); -#endif - - if ((result->m_flags & M_PKTHDR) == 0) { - error = EINVAL; - goto fail; - } - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) { - error = ENOBUFS; - goto fail; - } - } - result->m_pkthdr.len = m_lengthm(result, NULL); - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); - - fail: - if (result) - m_freem(result); - return error; -} - -#ifndef IPSEC_NONBLOCK_ACQUIRE -static struct secacq * -key_newacq(const struct secasindex *saidx) -{ - struct secacq *newacq; - - /* get new entry */ - KMALLOC(newacq, struct secacq *, sizeof(struct secacq)); - if (newacq == NULL) { - ipseclog((LOG_DEBUG, "key_newacq: No more memory.\n")); - return NULL; - } - bzero(newacq, sizeof(*newacq)); - - /* copy secindex */ - bcopy(saidx, &newacq->saidx, sizeof(newacq->saidx)); - newacq->seq = (acq_seq == ~0 ? 1 : ++acq_seq); - newacq->created = time_second; - newacq->count = 0; - - return newacq; -} - -static struct secacq * -key_getacq(const struct secasindex *saidx) -{ - struct secacq *acq; - - LIST_FOREACH(acq, &acqtree, chain) { - if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY)) - return acq; - } - - return NULL; -} - -static struct secacq * -key_getacqbyseq(u_int32_t seq) -{ - struct secacq *acq; - - LIST_FOREACH(acq, &acqtree, chain) { - if (acq->seq == seq) - return acq; - } - - return NULL; -} -#endif - -static struct secspacq * -key_newspacq(struct secpolicyindex *spidx) -{ - struct secspacq *acq; - - /* get new entry */ - KMALLOC(acq, struct secspacq *, sizeof(struct secspacq)); - if (acq == NULL) { - ipseclog((LOG_DEBUG, "key_newspacq: No more memory.\n")); - return NULL; - } - bzero(acq, sizeof(*acq)); - - /* copy secindex */ - bcopy(spidx, &acq->spidx, sizeof(acq->spidx)); - acq->created = time_second; - acq->count = 0; - - return acq; -} - -static struct secspacq * -key_getspacq(struct secpolicyindex *spidx) -{ - struct secspacq *acq; - - LIST_FOREACH(acq, &spacqtree, chain) { - if (key_cmpspidx_exactly(spidx, &acq->spidx)) - return acq; - } - - return NULL; -} - -/* - * SADB_ACQUIRE processing, - * in first situation, is receiving - * - * from the ikmpd, and clear sequence of its secasvar entry. - * - * In second situation, is receiving - * - * from a user land process, and return - * - * to the socket. - * - * m will always be freed. - */ -static int -key_acquire2(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - const struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - u_int16_t proto; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_acquire2: NULL pointer is passed."); - - /* - * Error message from KMd. - * We assume that if error was occured in IKEd, the length of PFKEY - * message is equal to the size of sadb_msg structure. - * We do not raise error even if error occured in this function. - */ - if (mhp->msg->sadb_msg_len == PFKEY_UNIT64(sizeof(struct sadb_msg))) { -#ifndef IPSEC_NONBLOCK_ACQUIRE - struct secacq *acq; - - /* check sequence number */ - if (mhp->msg->sadb_msg_seq == 0) { - ipseclog((LOG_DEBUG, "key_acquire2: must specify sequence number.\n")); - m_freem(m); - return 0; - } - - if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) == NULL) { - /* - * the specified larval SA is already gone, or we got - * a bogus sequence number. we can silently ignore it. - */ - m_freem(m); - return 0; - } - - /* reset acq counter in order to deletion by timehander. */ - acq->created = time_second; - acq->count = 0; -#endif - m_freem(m); - return 0; - } - - /* - * This message is from user land. - */ - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_acquire2: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - mhp->ext[SADB_EXT_PROPOSAL] == NULL) { - /* error */ - ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_PROPOSAL] < sizeof(struct sadb_prop)) { - /* error */ - ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - /* get a SA index */ - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE_REQID)) - break; - } - if (sah != NULL) { - ipseclog((LOG_DEBUG, "key_acquire2: a SA exists already.\n")); - return key_senderror(so, m, EEXIST); - } - - error = key_acquire(&saidx, NULL); - if (error != 0) { - ipseclog((LOG_DEBUG, "key_acquire2: error %d returned " - "from key_acquire.\n", mhp->msg->sadb_msg_errno)); - return key_senderror(so, m, error); - } - - return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED); -} - -/* - * SADB_REGISTER processing. - * If SATYPE_UNSPEC has been passed as satype, only return sabd_supported. - * receive - * - * from the ikmpd, and register a socket to send PF_KEY messages, - * and send - * - * to KMD by PF_KEY. - * If socket is detached, must free from regnode. - * - * m will always be freed. - */ -static int -key_register(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct secreg *reg, *newreg = NULL; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_register: NULL pointer is passed."); - - /* check for invalid register message */ - if (mhp->msg->sadb_msg_satype >= NELEM(regtree)) - return key_senderror(so, m, EINVAL); - - /* When SATYPE_UNSPEC is specified, only return sabd_supported. */ - if (mhp->msg->sadb_msg_satype == SADB_SATYPE_UNSPEC) - goto setmsg; - - /* check whether existing or not */ - LIST_FOREACH(reg, ®tree[mhp->msg->sadb_msg_satype], chain) { - if (reg->so == so) { - ipseclog((LOG_DEBUG, "key_register: socket exists already.\n")); - return key_senderror(so, m, EEXIST); - } - } - - /* create regnode */ - KMALLOC(newreg, struct secreg *, sizeof(*newreg)); - if (newreg == NULL) { - ipseclog((LOG_DEBUG, "key_register: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - bzero((caddr_t)newreg, sizeof(*newreg)); - - newreg->so = so; - ((struct keycb *)sotorawcb(so))->kp_registered++; - - /* add regnode to regtree. */ - LIST_INSERT_HEAD(®tree[mhp->msg->sadb_msg_satype], newreg, chain); - - setmsg: - { - struct mbuf *n; - struct sadb_msg *newmsg; - struct sadb_supported *sup; - u_int len, alen, elen; - int off; - int i; - struct sadb_alg *alg; - - /* create new sadb_msg to reply. */ - alen = 0; - for (i = 1; i <= SADB_AALG_MAX; i++) { - if (ah_algorithm_lookup(i)) - alen += sizeof(struct sadb_alg); - } - if (alen) - alen += sizeof(struct sadb_supported); - elen = 0; - for (i = 1; i <= SADB_EALG_MAX; i++) { - if (esp_algorithm_lookup(i)) - elen += sizeof(struct sadb_alg); - } - if (elen) - elen += sizeof(struct sadb_supported); - - len = sizeof(struct sadb_msg) + alen + elen; - - if (len > MCLBYTES) - return key_senderror(so, m, ENOBUFS); - n = m_getb(len, M_NOWAIT, MT_DATA, M_PKTHDR); - if (!n) - return key_senderror(so, m, ENOBUFS); - n->m_pkthdr.len = n->m_len = len; - - m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t)); - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(len); - off = PFKEY_ALIGN8(sizeof(struct sadb_msg)); - - /* for authentication algorithm */ - if (alen) { - sup = (struct sadb_supported *)(mtod(n, caddr_t) + off); - sup->sadb_supported_len = PFKEY_UNIT64(alen); - sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH; - off += PFKEY_ALIGN8(sizeof(*sup)); - - for (i = 1; i <= SADB_AALG_MAX; i++) { - struct auth_hash *aalgo; - u_int16_t minkeysize, maxkeysize; - - aalgo = ah_algorithm_lookup(i); - if (!aalgo) - continue; - alg = (struct sadb_alg *)(mtod(n, caddr_t) + off); - alg->sadb_alg_id = i; - alg->sadb_alg_ivlen = 0; - key_getsizes_ah(aalgo, i, &minkeysize, &maxkeysize); - alg->sadb_alg_minbits = _BITS(minkeysize); - alg->sadb_alg_maxbits = _BITS(maxkeysize); - off += PFKEY_ALIGN8(sizeof(*alg)); - } - } - - /* for encryption algorithm */ - if (elen) { - sup = (struct sadb_supported *)(mtod(n, caddr_t) + off); - sup->sadb_supported_len = PFKEY_UNIT64(elen); - sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT; - off += PFKEY_ALIGN8(sizeof(*sup)); - - for (i = 1; i <= SADB_EALG_MAX; i++) { - struct enc_xform *ealgo; - - ealgo = esp_algorithm_lookup(i); - if (!ealgo) - continue; - alg = (struct sadb_alg *)(mtod(n, caddr_t) + off); - alg->sadb_alg_id = i; - alg->sadb_alg_ivlen = ealgo->blocksize; - alg->sadb_alg_minbits = _BITS(ealgo->minkey); - alg->sadb_alg_maxbits = _BITS(ealgo->maxkey); - off += PFKEY_ALIGN8(sizeof(struct sadb_alg)); - } - } - -#ifdef DIGAGNOSTIC - if (off != len) - panic("length assumption failed in key_register"); -#endif - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED); - } -} - -/* - * free secreg entry registered. - * XXX: I want to do free a socket marked done SADB_RESIGER to socket. - */ -void -key_freereg(struct socket *so) -{ - struct secreg *reg; - int i; - - /* sanity check */ - if (so == NULL) - panic("key_freereg: NULL pointer is passed."); - - /* - * check whether existing or not. - * check all type of SA, because there is a potential that - * one socket is registered to multiple type of SA. - */ - for (i = 0; i <= SADB_SATYPE_MAX; i++) { - LIST_FOREACH(reg, ®tree[i], chain) { - if (reg->so == so - && __LIST_CHAINED(reg)) { - LIST_REMOVE(reg, chain); - KFREE(reg); - break; - } - } - } - - return; -} - -/* - * SADB_EXPIRE processing - * send - * - * to KMD by PF_KEY. - * NOTE: We send only soft lifetime extension. - * - * OUT: 0 : succeed - * others : error number - */ -static int -key_expire(struct secasvar *sav) -{ - - int satype; - struct mbuf *result = NULL, *m; - int len; - int error = -1; - struct sadb_lifetime *lt; - - /* XXX: Why do we lock ? */ - crit_enter(); - - /* sanity check */ - if (sav == NULL) - panic("key_expire: NULL pointer is passed."); - if (sav->sah == NULL) - panic("key_expire: Why was SA index in SA NULL."); - if ((satype = key_proto2satype(sav->sah->saidx.proto)) == 0) - panic("key_expire: invalid proto is passed."); - - /* set msg header */ - m = key_setsadbmsg(SADB_EXPIRE, 0, satype, sav->seq, 0, sav->refcnt); - if (!m) { - error = ENOBUFS; - goto fail; - } - result = m; - - /* create SA extension */ - m = key_setsadbsa(sav); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* create SA extension */ - m = key_setsadbxsa2(sav->sah->saidx.mode, - sav->replay ? sav->replay->count : 0, - sav->sah->saidx.reqid); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* create lifetime extension (current and soft) */ - len = PFKEY_ALIGN8(sizeof(*lt)) * 2; - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - error = ENOBUFS; - goto fail; - } - bzero(mtod(m, caddr_t), len); - lt = mtod(m, struct sadb_lifetime *); - lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); - lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; - lt->sadb_lifetime_allocations = sav->lft_c->sadb_lifetime_allocations; - lt->sadb_lifetime_bytes = sav->lft_c->sadb_lifetime_bytes; - lt->sadb_lifetime_addtime = sav->lft_c->sadb_lifetime_addtime; - lt->sadb_lifetime_usetime = sav->lft_c->sadb_lifetime_usetime; - lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2); - bcopy(sav->lft_s, lt, sizeof(*lt)); - m_cat(result, m); - - /* set sadb_address for source */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - &sav->sah->saidx.src.sa, - FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* set sadb_address for destination */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - &sav->sah->saidx.dst.sa, - FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - if ((result->m_flags & M_PKTHDR) == 0) { - error = EINVAL; - goto fail; - } - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) { - error = ENOBUFS; - goto fail; - } - } - result->m_pkthdr.len = m_lengthm(result, NULL); - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - crit_exit(); - return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); - - fail: - if (result) - m_freem(result); - crit_exit(); - return error; -} - -/* - * SADB_FLUSH processing - * receive - * - * from the ikmpd, and free all entries in secastree. - * and send, - * - * to the ikmpd. - * NOTE: to do is only marking SADB_SASTATE_DEAD. - * - * m will always be freed. - */ -static int -key_flush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_msg *newmsg; - struct secashead *sah; - u_int16_t proto; - u_int stateidx; - - /* sanity check */ - if (so == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_flush: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_flush: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - /* no SATYPE specified, i.e. flushing all SA. */ - LIST_FOREACH(sah, &sahtree, chain) { - if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC && - proto != sah->saidx.proto) - continue; - - for (stateidx = 0; stateidx < NELEM(saorder_state_alive); - stateidx++) { - struct secasvar *sav, *nextsav; - u_int8_t state = saorder_state_any[stateidx]; - - LIST_FOREACH_MUTABLE(sav, &sah->savtree[state], chain, - nextsav) { - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - KEY_FREESAV(&sav); - } - } - - sah->state = SADB_SASTATE_DEAD; - } - - if (m->m_len < sizeof(struct sadb_msg) || - sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) { - ipseclog((LOG_DEBUG, "key_flush: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - - if (m->m_next) - m_freem(m->m_next); - m->m_next = NULL; - m->m_pkthdr.len = m->m_len = sizeof(struct sadb_msg); - newmsg = mtod(m, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); -} - -/* - * SADB_DUMP processing - * dump all entries including status of DEAD in SAD. - * receive - * - * from the ikmpd, and dump all secasvar leaves - * and send, - * ..... - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_dump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct secashead *sah; - struct secasvar *sav; - u_int16_t proto; - u_int stateidx; - u_int8_t satype; - u_int8_t state; - int cnt; - struct mbuf *n; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_dump: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_dump: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - /* count sav entries to be sent to the userland. */ - cnt = 0; - LIST_FOREACH(sah, &sahtree, chain) { - if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC && - proto != sah->saidx.proto) - continue; - - for (stateidx = 0; stateidx < NELEM(saorder_state_any); - stateidx++) { - state = saorder_state_any[stateidx]; - LIST_FOREACH(sav, &sah->savtree[state], chain) { - cnt++; - } - } - } - - if (cnt == 0) - return key_senderror(so, m, ENOENT); - - /* send this to the userland, one at a time. */ - LIST_FOREACH(sah, &sahtree, chain) { - if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC - && proto != sah->saidx.proto) - continue; - - /* map proto to satype */ - if ((satype = key_proto2satype(sah->saidx.proto)) == 0) { - ipseclog((LOG_DEBUG, "key_dump: there was invalid proto in SAD.\n")); - return key_senderror(so, m, EINVAL); - } - - for (stateidx = 0; stateidx < NELEM(saorder_state_any); - stateidx++) { - state = saorder_state_any[stateidx]; - LIST_FOREACH(sav, &sah->savtree[state], chain) { - n = key_setdumpsa(sav, SADB_DUMP, satype, - --cnt, mhp->msg->sadb_msg_pid); - if (!n) - return key_senderror(so, m, ENOBUFS); - - key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } - } - } - - m_freem(m); - return 0; -} - -/* - * SADB_X_PROMISC processing - * - * m will always be freed. - */ -static int -key_promisc(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - int olen; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_promisc: NULL pointer is passed."); - - olen = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); - - if (olen < sizeof(struct sadb_msg)) { -#if 1 - return key_senderror(so, m, EINVAL); -#else - m_freem(m); - return 0; -#endif - } else if (olen == sizeof(struct sadb_msg)) { - /* enable/disable promisc mode */ - struct keycb *kp; - - if ((kp = (struct keycb *)sotorawcb(so)) == NULL) - return key_senderror(so, m, EINVAL); - mhp->msg->sadb_msg_errno = 0; - switch (mhp->msg->sadb_msg_satype) { - case 0: - case 1: - kp->kp_promisc = mhp->msg->sadb_msg_satype; - break; - default: - return key_senderror(so, m, EINVAL); - } - - /* send the original message back to everyone */ - mhp->msg->sadb_msg_errno = 0; - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); - } else { - /* send packet as is */ - - m_adj(m, PFKEY_ALIGN8(sizeof(struct sadb_msg))); - - /* TODO: if sadb_msg_seq is specified, send to specific pid */ - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); - } -} - -static int (*key_typesw[]) (struct socket *, struct mbuf *, - const struct sadb_msghdr *) = { - NULL, /* SADB_RESERVED */ - key_getspi, /* SADB_GETSPI */ - key_update, /* SADB_UPDATE */ - key_add, /* SADB_ADD */ - key_delete, /* SADB_DELETE */ - key_get, /* SADB_GET */ - key_acquire2, /* SADB_ACQUIRE */ - key_register, /* SADB_REGISTER */ - NULL, /* SADB_EXPIRE */ - key_flush, /* SADB_FLUSH */ - key_dump, /* SADB_DUMP */ - key_promisc, /* SADB_X_PROMISC */ - NULL, /* SADB_X_PCHANGE */ - key_spdadd, /* SADB_X_SPDUPDATE */ - key_spdadd, /* SADB_X_SPDADD */ - key_spddelete, /* SADB_X_SPDDELETE */ - key_spdget, /* SADB_X_SPDGET */ - NULL, /* SADB_X_SPDACQUIRE */ - key_spddump, /* SADB_X_SPDDUMP */ - key_spdflush, /* SADB_X_SPDFLUSH */ - key_spdadd, /* SADB_X_SPDSETIDX */ - NULL, /* SADB_X_SPDEXPIRE */ - key_spddelete2, /* SADB_X_SPDDELETE2 */ -}; - -/* - * parse sadb_msg buffer to process PFKEYv2, - * and create a data to response if needed. - * I think to be dealed with mbuf directly. - * IN: - * msgp : pointer to pointer to a received buffer pulluped. - * This is rewrited to response. - * so : pointer to socket. - * OUT: - * length for buffer to send to user process. - */ -int -key_parse(struct mbuf *m, struct socket *so) -{ - struct sadb_msg *msg; - struct sadb_msghdr mh; - u_int orglen; - int error; - int target; - - /* sanity check */ - if (m == NULL || so == NULL) - panic("key_parse: NULL pointer is passed."); - -#if 0 /*kdebug_sadb assumes msg in linear buffer*/ - KEYDEBUG(KEYDEBUG_KEY_DUMP, - ipseclog((LOG_DEBUG, "key_parse: passed sadb_msg\n")); - kdebug_sadb(msg)); -#endif - - if (m->m_len < sizeof(struct sadb_msg)) { - m = m_pullup(m, sizeof(struct sadb_msg)); - if (!m) - return ENOBUFS; - } - msg = mtod(m, struct sadb_msg *); - orglen = PFKEY_UNUNIT64(msg->sadb_msg_len); - target = KEY_SENDUP_ONE; - - if ((m->m_flags & M_PKTHDR) == 0 || - m->m_pkthdr.len != m->m_pkthdr.len) { - ipseclog((LOG_DEBUG, "key_parse: invalid message length.\n")); - pfkeystat.out_invlen++; - error = EINVAL; - goto senderror; - } - - if (msg->sadb_msg_version != PF_KEY_V2) { - ipseclog((LOG_DEBUG, - "key_parse: PF_KEY version %u is mismatched.\n", - msg->sadb_msg_version)); - pfkeystat.out_invver++; - error = EINVAL; - goto senderror; - } - - if (msg->sadb_msg_type > SADB_MAX) { - ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n", - msg->sadb_msg_type)); - pfkeystat.out_invmsgtype++; - error = EINVAL; - goto senderror; - } - - /* for old-fashioned code - should be nuked */ - if (m->m_pkthdr.len > MCLBYTES) { - m_freem(m); - return ENOBUFS; - } - if (m->m_next) { - struct mbuf *n; - - n = m_getb(m->m_pkthdr.len, M_NOWAIT, MT_DATA, M_PKTHDR); - if (!n) { - m_freem(m); - return ENOBUFS; - } - m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t)); - n->m_pkthdr.len = n->m_len = m->m_pkthdr.len; - m_freem(m); - m = n; - } - - /* align the mbuf chain so that extensions are in contiguous region. */ - error = key_align(m, &mh); - if (error) - return error; - - msg = mh.msg; - - /* check SA type */ - switch (msg->sadb_msg_satype) { - case SADB_SATYPE_UNSPEC: - switch (msg->sadb_msg_type) { - case SADB_GETSPI: - case SADB_UPDATE: - case SADB_ADD: - case SADB_DELETE: - case SADB_GET: - case SADB_ACQUIRE: - case SADB_EXPIRE: - ipseclog((LOG_DEBUG, "key_parse: must specify satype " - "when msg type=%u.\n", msg->sadb_msg_type)); - pfkeystat.out_invsatype++; - error = EINVAL; - goto senderror; - } - break; - case SADB_SATYPE_AH: - case SADB_SATYPE_ESP: - case SADB_X_SATYPE_IPCOMP: - switch (msg->sadb_msg_type) { - case SADB_X_SPDADD: - case SADB_X_SPDDELETE: - case SADB_X_SPDGET: - case SADB_X_SPDDUMP: - case SADB_X_SPDFLUSH: - case SADB_X_SPDSETIDX: - case SADB_X_SPDUPDATE: - case SADB_X_SPDDELETE2: - ipseclog((LOG_DEBUG, "key_parse: illegal satype=%u\n", - msg->sadb_msg_type)); - pfkeystat.out_invsatype++; - error = EINVAL; - goto senderror; - } - break; - case SADB_SATYPE_RSVP: - case SADB_SATYPE_OSPFV2: - case SADB_SATYPE_RIPV2: - case SADB_SATYPE_MIP: - ipseclog((LOG_DEBUG, "key_parse: type %u isn't supported.\n", - msg->sadb_msg_satype)); - pfkeystat.out_invsatype++; - error = EOPNOTSUPP; - goto senderror; - case 1: /* XXX: What does it do? */ - if (msg->sadb_msg_type == SADB_X_PROMISC) - break; - /*FALLTHROUGH*/ - default: - ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n", - msg->sadb_msg_satype)); - pfkeystat.out_invsatype++; - error = EINVAL; - goto senderror; - } - - /* check field of upper layer protocol and address family */ - if (mh.ext[SADB_EXT_ADDRESS_SRC] != NULL - && mh.ext[SADB_EXT_ADDRESS_DST] != NULL) { - struct sadb_address *src0, *dst0; - u_int plen; - - src0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_DST]); - - /* check upper layer protocol */ - if (src0->sadb_address_proto != dst0->sadb_address_proto) { - ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n")); - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - - /* check family */ - if (PFKEY_ADDR_SADDR(src0)->sa_family != - PFKEY_ADDR_SADDR(dst0)->sa_family) { - ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n")); - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - if (PFKEY_ADDR_SADDR(src0)->sa_len != - PFKEY_ADDR_SADDR(dst0)->sa_len) { - ipseclog((LOG_DEBUG, - "key_parse: address struct size mismatched.\n")); - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - - switch (PFKEY_ADDR_SADDR(src0)->sa_family) { - case AF_INET: - if (PFKEY_ADDR_SADDR(src0)->sa_len != - sizeof(struct sockaddr_in)) { - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - break; - case AF_INET6: - if (PFKEY_ADDR_SADDR(src0)->sa_len != - sizeof(struct sockaddr_in6)) { - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - break; - default: - ipseclog((LOG_DEBUG, - "key_parse: unsupported address family.\n")); - pfkeystat.out_invaddr++; - error = EAFNOSUPPORT; - goto senderror; - } - - switch (PFKEY_ADDR_SADDR(src0)->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - plen = 0; /*fool gcc*/ - break; - } - - /* check max prefix length */ - if (src0->sadb_address_prefixlen > plen || - dst0->sadb_address_prefixlen > plen) { - ipseclog((LOG_DEBUG, - "key_parse: illegal prefixlen.\n")); - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - - /* - * prefixlen == 0 is valid because there can be a case when - * all addresses are matched. - */ - } - - if (msg->sadb_msg_type >= NELEM(key_typesw) || - key_typesw[msg->sadb_msg_type] == NULL) { - pfkeystat.out_invmsgtype++; - error = EINVAL; - goto senderror; - } - - return (*key_typesw[msg->sadb_msg_type])(so, m, &mh); - -senderror: - msg->sadb_msg_errno = error; - return key_sendup_mbuf(so, m, target); -} - -static int -key_senderror(struct socket *so, struct mbuf *m, int code) -{ - struct sadb_msg *msg; - - if (m->m_len < sizeof(struct sadb_msg)) - panic("invalid mbuf passed to key_senderror"); - - msg = mtod(m, struct sadb_msg *); - msg->sadb_msg_errno = code; - return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); -} - -/* - * set the pointer to each header into message buffer. - * m will be freed on error. - * XXX larger-than-MCLBYTES extension? - */ -static int -key_align(struct mbuf *m, struct sadb_msghdr *mhp) -{ - struct mbuf *n; - struct sadb_ext *ext; - size_t off, end; - int extlen; - int toff; - - /* sanity check */ - if (m == NULL || mhp == NULL) - panic("key_align: NULL pointer is passed."); - if (m->m_len < sizeof(struct sadb_msg)) - panic("invalid mbuf passed to key_align"); - - /* initialize */ - bzero(mhp, sizeof(*mhp)); - - mhp->msg = mtod(m, struct sadb_msg *); - mhp->ext[0] = (struct sadb_ext *)mhp->msg; /*XXX backward compat */ - - end = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); - extlen = end; /*just in case extlen is not updated*/ - for (off = sizeof(struct sadb_msg); off < end; off += extlen) { - n = m_pulldown(m, off, sizeof(struct sadb_ext), &toff); - if (!n) { - /* m is already freed */ - return ENOBUFS; - } - ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff); - - /* set pointer */ - switch (ext->sadb_ext_type) { - case SADB_EXT_SA: - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - case SADB_EXT_LIFETIME_CURRENT: - case SADB_EXT_LIFETIME_HARD: - case SADB_EXT_LIFETIME_SOFT: - case SADB_EXT_KEY_AUTH: - case SADB_EXT_KEY_ENCRYPT: - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - case SADB_EXT_SENSITIVITY: - case SADB_EXT_PROPOSAL: - case SADB_EXT_SUPPORTED_AUTH: - case SADB_EXT_SUPPORTED_ENCRYPT: - case SADB_EXT_SPIRANGE: - case SADB_X_EXT_POLICY: - case SADB_X_EXT_SA2: - /* duplicate check */ - /* - * XXX Are there duplication payloads of either - * KEY_AUTH or KEY_ENCRYPT ? - */ - if (mhp->ext[ext->sadb_ext_type] != NULL) { - ipseclog((LOG_DEBUG, - "key_align: duplicate ext_type %u " - "is passed.\n", ext->sadb_ext_type)); - m_freem(m); - pfkeystat.out_dupext++; - return EINVAL; - } - break; - default: - ipseclog((LOG_DEBUG, - "key_align: invalid ext_type %u is passed.\n", - ext->sadb_ext_type)); - m_freem(m); - pfkeystat.out_invexttype++; - return EINVAL; - } - - extlen = PFKEY_UNUNIT64(ext->sadb_ext_len); - - if (key_validate_ext(ext, extlen)) { - m_freem(m); - pfkeystat.out_invlen++; - return EINVAL; - } - - n = m_pulldown(m, off, extlen, &toff); - if (!n) { - /* m is already freed */ - return ENOBUFS; - } - ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff); - - mhp->ext[ext->sadb_ext_type] = ext; - mhp->extoff[ext->sadb_ext_type] = off; - mhp->extlen[ext->sadb_ext_type] = extlen; - } - - if (off != end) { - m_freem(m); - pfkeystat.out_invlen++; - return EINVAL; - } - - return 0; -} - -static int -key_validate_ext(const struct sadb_ext *ext, int len) -{ - const struct sockaddr *sa; - enum { NONE, ADDR } checktype = NONE; - int baselen = 0; - const int sal = offsetof(struct sockaddr, sa_len) + sizeof(sa->sa_len); - - if (len != PFKEY_UNUNIT64(ext->sadb_ext_len)) - return EINVAL; - - /* if it does not match minimum/maximum length, bail */ - if (ext->sadb_ext_type >= NELEM(minsize) || - ext->sadb_ext_type >= NELEM(maxsize)) - return EINVAL; - if (!minsize[ext->sadb_ext_type] || len < minsize[ext->sadb_ext_type]) - return EINVAL; - if (maxsize[ext->sadb_ext_type] && len > maxsize[ext->sadb_ext_type]) - return EINVAL; - - /* more checks based on sadb_ext_type XXX need more */ - switch (ext->sadb_ext_type) { - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - baselen = PFKEY_ALIGN8(sizeof(struct sadb_address)); - checktype = ADDR; - break; - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - if (((const struct sadb_ident *)ext)->sadb_ident_type == - SADB_X_IDENTTYPE_ADDR) { - baselen = PFKEY_ALIGN8(sizeof(struct sadb_ident)); - checktype = ADDR; - } else - checktype = NONE; - break; - default: - checktype = NONE; - break; - } - - switch (checktype) { - case NONE: - break; - case ADDR: - sa = (const struct sockaddr *)(((const u_int8_t*)ext)+baselen); - if (len < baselen + sal) - return EINVAL; - if (baselen + PFKEY_ALIGN8(sa->sa_len) != len) - return EINVAL; - break; - } - - return 0; -} - -void -key_init(void) -{ - int i; - - for (i = 0; i < IPSEC_DIR_MAX; i++) { - LIST_INIT(&sptree[i]); - } - - LIST_INIT(&sahtree); - - for (i = 0; i <= SADB_SATYPE_MAX; i++) { - LIST_INIT(®tree[i]); - } - -#ifndef IPSEC_NONBLOCK_ACQUIRE - LIST_INIT(&acqtree); -#endif - LIST_INIT(&spacqtree); - - /* system default */ - ip4_def_policy.policy = IPSEC_POLICY_NONE; - ip4_def_policy.refcnt++; /*never reclaim this*/ - -#ifndef IPSEC_DEBUG2 - callout_init(&key_timehandler_ch); - callout_reset(&key_timehandler_ch, hz, key_timehandler, NULL); -#endif /*IPSEC_DEBUG2*/ - - /* initialize key statistics */ - keystat.getspi_count = 1; - - kprintf("IPsec: Initialized Security Association Processing.\n"); - - return; -} - -/* - * XXX: maybe This function is called after INBOUND IPsec processing. - * - * Special check for tunnel-mode packets. - * We must make some checks for consistency between inner and outer IP header. - * - * xxx more checks to be provided - */ -int -key_checktunnelsanity(struct secasvar *sav, u_int family, caddr_t src, - caddr_t dst) -{ - /* sanity check */ - if (sav->sah == NULL) - panic("sav->sah == NULL at key_checktunnelsanity"); - - /* XXX: check inner IP header */ - - return 1; -} - -#if 0 -#define hostnamelen strlen(hostname) - -/* - * Get FQDN for the host. - * If the administrator configured hostname (by hostname(1)) without - * domain name, returns nothing. - */ -static const char * -key_getfqdn(void) -{ - int i; - int hasdot; - static char fqdn[MAXHOSTNAMELEN + 1]; - - if (!hostnamelen) - return NULL; - - /* check if it comes with domain name. */ - hasdot = 0; - for (i = 0; i < hostnamelen; i++) { - if (hostname[i] == '.') - hasdot++; - } - if (!hasdot) - return NULL; - - /* NOTE: hostname may not be NUL-terminated. */ - bzero(fqdn, sizeof(fqdn)); - bcopy(hostname, fqdn, hostnamelen); - fqdn[hostnamelen] = '\0'; - return fqdn; -} - -/* - * get username@FQDN for the host/user. - */ -static const char * -key_getuserfqdn(void) -{ - const char *host; - static char userfqdn[MAXHOSTNAMELEN + MAXLOGNAME + 2]; - struct proc *p = curproc; - char *q; - - if (!p || !p->p_pgrp || !p->p_pgrp->pg_session) - return NULL; - if (!(host = key_getfqdn())) - return NULL; - - /* NOTE: s_login may not be-NUL terminated. */ - bzero(userfqdn, sizeof(userfqdn)); - bcopy(p->p_pgrp->pg_session->s_login, userfqdn, MAXLOGNAME); - userfqdn[MAXLOGNAME] = '\0'; /* safeguard */ - q = userfqdn + strlen(userfqdn); - *q++ = '@'; - bcopy(host, q, strlen(host)); - q += strlen(host); - *q++ = '\0'; - - return userfqdn; -} -#endif - -/* record data transfer on SA, and update timestamps */ -void -key_sa_recordxfer(struct secasvar *sav, struct mbuf *m) -{ - KASSERT(sav != NULL, ("key_sa_recordxfer: Null secasvar")); - KASSERT(m != NULL, ("key_sa_recordxfer: Null mbuf")); - if (!sav->lft_c) - return; - - /* - * XXX Currently, there is a difference of bytes size - * between inbound and outbound processing. - */ - sav->lft_c->sadb_lifetime_bytes += m->m_pkthdr.len; - /* to check bytes lifetime is done in key_timehandler(). */ - - /* - * We use the number of packets as the unit of - * sadb_lifetime_allocations. We increment the variable - * whenever {esp,ah}_{in,out}put is called. - */ - sav->lft_c->sadb_lifetime_allocations++; - /* XXX check for expires? */ - - /* - * NOTE: We record CURRENT sadb_lifetime_usetime by using wall clock, - * in seconds. HARD and SOFT lifetime are measured by the time - * difference (again in seconds) from sadb_lifetime_usetime. - * - * usetime - * v expire expire - * -----+-----+--------+---> t - * <--------------> HARD - * <-----> SOFT - */ - sav->lft_c->sadb_lifetime_usetime = time_second; - /* XXX check for expires? */ - - return; -} - -/* dumb version */ -void -key_sa_routechange(struct sockaddr *dst) -{ - struct secashead *sah; - struct route *ro; - - LIST_FOREACH(sah, &sahtree, chain) { - ro = &sah->sa_route; - if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len - && bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) { - RTFREE(ro->ro_rt); - ro->ro_rt = NULL; - } - } - - return; -} - -static void -key_sa_chgstate(struct secasvar *sav, u_int8_t state) -{ - if (sav == NULL) - panic("key_sa_chgstate called with sav == NULL"); - - if (sav->state == state) - return; - - if (__LIST_CHAINED(sav)) - LIST_REMOVE(sav, chain); - - sav->state = state; - LIST_INSERT_HEAD(&sav->sah->savtree[state], sav, chain); -} - -void -key_sa_stir_iv(struct secasvar *sav) -{ - - if (!sav->iv) - panic("key_sa_stir_iv called with sav == NULL"); - key_randomfill(sav->iv, sav->ivlen); -} - -/* XXX too much? */ -static struct mbuf * -key_alloc_mbuf(int l) -{ - struct mbuf *m = NULL, *n; - int len, t; - - len = l; - while (len > 0) { - n = m_getb(len, M_NOWAIT, MT_DATA, 0); - if (!n) { - m_freem(m); - return NULL; - } - n->m_len = 0; - n->m_len = M_TRAILINGSPACE(n); - /* use the bottom of mbuf, hoping we can prepend afterwards */ - if (n->m_len > len) { - t = (n->m_len - len) & ~(sizeof(long) - 1); - n->m_data += t; - n->m_len = len; - } - - len -= n->m_len; - - if (m) - m_cat(m, n); - else - m = n; - } - - return m; -} diff --git a/sys/netproto/ipsec/key.h b/sys/netproto/ipsec/key.h deleted file mode 100644 index d2f8043028..0000000000 --- a/sys/netproto/ipsec/key.h +++ /dev/null @@ -1,115 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/key.h,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/key.h,v 1.4 2004/10/15 22:59:10 hsu Exp $ */ -/* $KAME: key.h,v 1.21 2001/07/27 03:51:30 itojun Exp $ */ - -/* - * 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. - */ - -#ifndef _NETIPSEC_KEY_H_ -#define _NETIPSEC_KEY_H_ - -#ifdef _KERNEL - -struct secpolicy; -struct secpolicyindex; -struct ipsecrequest; -struct secasvar; -struct sockaddr; -struct socket; -struct sadb_msg; -struct sadb_x_policy; -struct secasindex; -union sockaddr_union; - -extern int key_havesp(u_int dir); -extern struct secpolicy *key_allocsp(struct secpolicyindex *, u_int, - const char*, int); -extern struct secpolicy *key_allocsp2(u_int32_t spi, union sockaddr_union *dst, - u_int8_t proto, u_int dir, const char*, int); -extern struct secpolicy *key_newsp(const char*, int); -extern struct secpolicy *key_gettunnel(const struct sockaddr *, - const struct sockaddr *, const struct sockaddr *, - const struct sockaddr *, const char*, int); -/* NB: prepend with _ for KAME IPv6 compatbility */ -extern void _key_freesp(struct secpolicy **, const char*, int); - -/* - * Access to the SADB are interlocked with splnet. In particular, - * holders of SA's use this to block accesses by protocol processing - * that can happen either by network swi's or by continuations that - * occur on crypto callbacks. Much of this could go away if - * key_checkrequest were redone. - */ -#define KEY_ALLOCSP(spidx, dir) \ - key_allocsp(spidx, dir, __FILE__, __LINE__) -#define KEY_ALLOCSP2(spi, dst, proto, dir) \ - key_allocsp2(spi, dst, proto, dir, __FILE__, __LINE__) -#define KEY_NEWSP() \ - key_newsp(__FILE__, __LINE__) -#define KEY_GETTUNNEL(osrc, odst, isrc, idst) \ - key_gettunnel(osrc, odst, isrc, idst, __FILE__, __LINE__) -#define KEY_FREESP(spp) \ - _key_freesp(spp, __FILE__, __LINE__) - -extern struct secasvar *key_allocsa(union sockaddr_union *, u_int, u_int32_t, - const char*, int); -extern void key_freesav(struct secasvar **, const char*, int); - -#define KEY_ALLOCSA(dst, proto, spi) \ - key_allocsa(dst, proto, spi, __FILE__, __LINE__) -#define KEY_FREESAV(psav) \ - key_freesav(psav, __FILE__, __LINE__) - -extern void key_freeso (struct socket *); -extern int key_checktunnelsanity (struct secasvar *, u_int, - caddr_t, caddr_t); -extern int key_checkrequest - (struct ipsecrequest *isr, const struct secasindex *); - -extern struct secpolicy *key_msg2sp (struct sadb_x_policy *, - size_t, int *); -extern struct mbuf *key_sp2msg (struct secpolicy *); -extern int key_ismyaddr (struct sockaddr *); -extern int key_spdacquire (struct secpolicy *); -extern void key_timehandler (void *); -extern u_long key_random (void); -extern void key_randomfill (void *, size_t); -extern void key_freereg (struct socket *); -extern int key_parse (struct mbuf *, struct socket *); -extern void key_init (void); -extern void key_sa_recordxfer (struct secasvar *, struct mbuf *); -extern void key_sa_routechange (struct sockaddr *); -extern void key_sa_stir_iv (struct secasvar *); - -#ifdef MALLOC_DECLARE -MALLOC_DECLARE(M_SECA); -#endif /* MALLOC_DECLARE */ - -#endif /* defined(_KERNEL) */ -#endif /* _NETIPSEC_KEY_H_ */ diff --git a/sys/netproto/ipsec/key_debug.c b/sys/netproto/ipsec/key_debug.c deleted file mode 100644 index a5631b1733..0000000000 --- a/sys/netproto/ipsec/key_debug.c +++ /dev/null @@ -1,725 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/key_debug.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ -/* $KAME: key_debug.c,v 1.26 2001/06/27 10:46:50 sakane Exp $ */ - -/* - * 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. - */ - -#ifdef _KERNEL -#include "opt_inet.h" -#include "opt_inet6.h" -#include "opt_ipsec.h" -#endif - -#include -#include -#ifdef _KERNEL -#include -#include -#include -#endif -#include - -#include - -#include -#include - -#include -#include - -#ifndef _KERNEL -#include -#include -#include -#endif /* !_KERNEL */ - -static void kdebug_sadb_prop (struct sadb_ext *); -static void kdebug_sadb_identity (struct sadb_ext *); -static void kdebug_sadb_supported (struct sadb_ext *); -static void kdebug_sadb_lifetime (struct sadb_ext *); -static void kdebug_sadb_sa (struct sadb_ext *); -static void kdebug_sadb_address (struct sadb_ext *); -static void kdebug_sadb_key (struct sadb_ext *); -static void kdebug_sadb_x_sa2 (struct sadb_ext *); - -#ifdef _KERNEL -static void kdebug_secreplay (struct secreplay *); -#endif - -#ifndef _KERNEL -#define panic(param) { kprintf(param); exit(-1); } -#endif - -/* NOTE: host byte order */ - -/* %%%: about struct sadb_msg */ -void -kdebug_sadb(struct sadb_msg *base) -{ - struct sadb_ext *ext; - int tlen, extlen; - - /* sanity check */ - if (base == NULL) - panic("kdebug_sadb: NULL pointer was passed."); - - kprintf("sadb_msg{ version=%u type=%u errno=%u satype=%u\n", - base->sadb_msg_version, base->sadb_msg_type, - base->sadb_msg_errno, base->sadb_msg_satype); - kprintf(" len=%u reserved=%u seq=%u pid=%u\n", - base->sadb_msg_len, base->sadb_msg_reserved, - base->sadb_msg_seq, base->sadb_msg_pid); - - tlen = PFKEY_UNUNIT64(base->sadb_msg_len) - sizeof(struct sadb_msg); - ext = (struct sadb_ext *)((caddr_t)base + sizeof(struct sadb_msg)); - - while (tlen > 0) { - kprintf("sadb_ext{ len=%u type=%u }\n", - ext->sadb_ext_len, ext->sadb_ext_type); - - if (ext->sadb_ext_len == 0) { - kprintf("kdebug_sadb: invalid ext_len=0 was passed.\n"); - return; - } - if (ext->sadb_ext_len > tlen) { - kprintf("kdebug_sadb: ext_len exceeds end of buffer.\n"); - return; - } - - switch (ext->sadb_ext_type) { - case SADB_EXT_SA: - kdebug_sadb_sa(ext); - break; - case SADB_EXT_LIFETIME_CURRENT: - case SADB_EXT_LIFETIME_HARD: - case SADB_EXT_LIFETIME_SOFT: - kdebug_sadb_lifetime(ext); - break; - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - kdebug_sadb_address(ext); - break; - case SADB_EXT_KEY_AUTH: - case SADB_EXT_KEY_ENCRYPT: - kdebug_sadb_key(ext); - break; - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - kdebug_sadb_identity(ext); - break; - case SADB_EXT_SENSITIVITY: - break; - case SADB_EXT_PROPOSAL: - kdebug_sadb_prop(ext); - break; - case SADB_EXT_SUPPORTED_AUTH: - case SADB_EXT_SUPPORTED_ENCRYPT: - kdebug_sadb_supported(ext); - break; - case SADB_EXT_SPIRANGE: - case SADB_X_EXT_KMPRIVATE: - break; - case SADB_X_EXT_POLICY: - kdebug_sadb_x_policy(ext); - break; - case SADB_X_EXT_SA2: - kdebug_sadb_x_sa2(ext); - break; - default: - kprintf("kdebug_sadb: invalid ext_type %u was passed.\n", - ext->sadb_ext_type); - return; - } - - extlen = PFKEY_UNUNIT64(ext->sadb_ext_len); - tlen -= extlen; - ext = (struct sadb_ext *)((caddr_t)ext + extlen); - } - - return; -} - -static void -kdebug_sadb_prop(struct sadb_ext *ext) -{ - struct sadb_prop *prop = (struct sadb_prop *)ext; - struct sadb_comb *comb; - int len; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_prop: NULL pointer was passed."); - - len = (PFKEY_UNUNIT64(prop->sadb_prop_len) - sizeof(*prop)) - / sizeof(*comb); - comb = (struct sadb_comb *)(prop + 1); - kprintf("sadb_prop{ replay=%u\n", prop->sadb_prop_replay); - - while (len--) { - kprintf("sadb_comb{ auth=%u encrypt=%u " - "flags=0x%04x reserved=0x%08x\n", - comb->sadb_comb_auth, comb->sadb_comb_encrypt, - comb->sadb_comb_flags, comb->sadb_comb_reserved); - - kprintf(" auth_minbits=%u auth_maxbits=%u " - "encrypt_minbits=%u encrypt_maxbits=%u\n", - comb->sadb_comb_auth_minbits, - comb->sadb_comb_auth_maxbits, - comb->sadb_comb_encrypt_minbits, - comb->sadb_comb_encrypt_maxbits); - - kprintf(" soft_alloc=%u hard_alloc=%u " - "soft_bytes=%lu hard_bytes=%lu\n", - comb->sadb_comb_soft_allocations, - comb->sadb_comb_hard_allocations, - (unsigned long)comb->sadb_comb_soft_bytes, - (unsigned long)comb->sadb_comb_hard_bytes); - - kprintf(" soft_alloc=%lu hard_alloc=%lu " - "soft_bytes=%lu hard_bytes=%lu }\n", - (unsigned long)comb->sadb_comb_soft_addtime, - (unsigned long)comb->sadb_comb_hard_addtime, - (unsigned long)comb->sadb_comb_soft_usetime, - (unsigned long)comb->sadb_comb_hard_usetime); - comb++; - } - kprintf("}\n"); - - return; -} - -static void -kdebug_sadb_identity(struct sadb_ext *ext) -{ - struct sadb_ident *id = (struct sadb_ident *)ext; - int len; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_identity: NULL pointer was passed."); - - len = PFKEY_UNUNIT64(id->sadb_ident_len) - sizeof(*id); - kprintf("sadb_ident_%s{", - id->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC ? "src" : "dst"); - switch (id->sadb_ident_type) { - default: - kprintf(" type=%d id=%lu", - id->sadb_ident_type, (u_long)id->sadb_ident_id); - if (len) { -#ifdef _KERNEL - ipsec_hexdump((caddr_t)(id + 1), len); /*XXX cast ?*/ -#else - char *p, *ep; - kprintf("\n str=\""); - p = (char *)(id + 1); - ep = p + len; - for (/*nothing*/; *p && p < ep; p++) { - if (isprint(*p)) - kprintf("%c", *p & 0xff); - else - kprintf("\\%03o", *p & 0xff); - } -#endif - kprintf("\""); - } - break; - } - - kprintf(" }\n"); - - return; -} - -static void -kdebug_sadb_supported(struct sadb_ext *ext) -{ - struct sadb_supported *sup = (struct sadb_supported *)ext; - struct sadb_alg *alg; - int len; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_supported: NULL pointer was passed."); - - len = (PFKEY_UNUNIT64(sup->sadb_supported_len) - sizeof(*sup)) - / sizeof(*alg); - alg = (struct sadb_alg *)(sup + 1); - kprintf("sadb_sup{\n"); - while (len--) { - kprintf(" { id=%d ivlen=%d min=%d max=%d }\n", - alg->sadb_alg_id, alg->sadb_alg_ivlen, - alg->sadb_alg_minbits, alg->sadb_alg_maxbits); - alg++; - } - kprintf("}\n"); - - return; -} - -static void -kdebug_sadb_lifetime(struct sadb_ext *ext) -{ - struct sadb_lifetime *lft = (struct sadb_lifetime *)ext; - - /* sanity check */ - if (ext == NULL) - kprintf("kdebug_sadb_lifetime: NULL pointer was passed.\n"); - - kprintf("sadb_lifetime{ alloc=%u, bytes=%u\n", - lft->sadb_lifetime_allocations, - (u_int32_t)lft->sadb_lifetime_bytes); - kprintf(" addtime=%u, usetime=%u }\n", - (u_int32_t)lft->sadb_lifetime_addtime, - (u_int32_t)lft->sadb_lifetime_usetime); - - return; -} - -static void -kdebug_sadb_sa(struct sadb_ext *ext) -{ - struct sadb_sa *sa = (struct sadb_sa *)ext; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_sa: NULL pointer was passed."); - - kprintf("sadb_sa{ spi=%u replay=%u state=%u\n", - (u_int32_t)ntohl(sa->sadb_sa_spi), sa->sadb_sa_replay, - sa->sadb_sa_state); - kprintf(" auth=%u encrypt=%u flags=0x%08x }\n", - sa->sadb_sa_auth, sa->sadb_sa_encrypt, sa->sadb_sa_flags); - - return; -} - -static void -kdebug_sadb_address(struct sadb_ext *ext) -{ - struct sadb_address *addr = (struct sadb_address *)ext; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_address: NULL pointer was passed."); - - kprintf("sadb_address{ proto=%u prefixlen=%u reserved=0x%02x%02x }\n", - addr->sadb_address_proto, addr->sadb_address_prefixlen, - ((u_char *)&addr->sadb_address_reserved)[0], - ((u_char *)&addr->sadb_address_reserved)[1]); - - kdebug_sockaddr((struct sockaddr *)((caddr_t)ext + sizeof(*addr))); - - return; -} - -static void -kdebug_sadb_key(struct sadb_ext *ext) -{ - struct sadb_key *key = (struct sadb_key *)ext; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_key: NULL pointer was passed."); - - kprintf("sadb_key{ bits=%u reserved=%u\n", - key->sadb_key_bits, key->sadb_key_reserved); - kprintf(" key="); - - /* sanity check 2 */ - if ((key->sadb_key_bits >> 3) > - (PFKEY_UNUNIT64(key->sadb_key_len) - sizeof(struct sadb_key))) { - kprintf("kdebug_sadb_key: key length mismatch, bit:%d len:%ld.\n", - key->sadb_key_bits >> 3, - (long)PFKEY_UNUNIT64(key->sadb_key_len) - sizeof(struct sadb_key)); - } - - ipsec_hexdump((caddr_t)key + sizeof(struct sadb_key), - key->sadb_key_bits >> 3); - kprintf(" }\n"); - return; -} - -static void -kdebug_sadb_x_sa2(struct sadb_ext *ext) -{ - struct sadb_x_sa2 *sa2 = (struct sadb_x_sa2 *)ext; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_x_sa2: NULL pointer was passed."); - - kprintf("sadb_x_sa2{ mode=%u reqid=%u\n", - sa2->sadb_x_sa2_mode, sa2->sadb_x_sa2_reqid); - kprintf(" reserved1=%u reserved2=%u sequence=%u }\n", - sa2->sadb_x_sa2_reserved1, sa2->sadb_x_sa2_reserved2, - sa2->sadb_x_sa2_sequence); - - return; -} - -void -kdebug_sadb_x_policy(struct sadb_ext *ext) -{ - struct sadb_x_policy *xpl = (struct sadb_x_policy *)ext; - struct sockaddr *addr; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_x_policy: NULL pointer was passed."); - - kprintf("sadb_x_policy{ type=%u dir=%u id=%x }\n", - xpl->sadb_x_policy_type, xpl->sadb_x_policy_dir, - xpl->sadb_x_policy_id); - - if (xpl->sadb_x_policy_type == IPSEC_POLICY_IPSEC) { - int tlen; - struct sadb_x_ipsecrequest *xisr; - - tlen = PFKEY_UNUNIT64(xpl->sadb_x_policy_len) - sizeof(*xpl); - xisr = (struct sadb_x_ipsecrequest *)(xpl + 1); - - while (tlen > 0) { - kprintf(" { len=%u proto=%u mode=%u level=%u reqid=%u\n", - xisr->sadb_x_ipsecrequest_len, - xisr->sadb_x_ipsecrequest_proto, - xisr->sadb_x_ipsecrequest_mode, - xisr->sadb_x_ipsecrequest_level, - xisr->sadb_x_ipsecrequest_reqid); - - if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) { - addr = (struct sockaddr *)(xisr + 1); - kdebug_sockaddr(addr); - addr = (struct sockaddr *)((caddr_t)addr - + addr->sa_len); - kdebug_sockaddr(addr); - } - - kprintf(" }\n"); - - /* prevent infinite loop */ - if (xisr->sadb_x_ipsecrequest_len <= 0) { - kprintf("kdebug_sadb_x_policy: wrong policy struct.\n"); - return; - } - /* prevent overflow */ - if (xisr->sadb_x_ipsecrequest_len > tlen) { - kprintf("invalid ipsec policy length\n"); - return; - } - - tlen -= xisr->sadb_x_ipsecrequest_len; - - xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr - + xisr->sadb_x_ipsecrequest_len); - } - - if (tlen != 0) - panic("kdebug_sadb_x_policy: wrong policy struct."); - } - - return; -} - -#ifdef _KERNEL -/* %%%: about SPD and SAD */ -void -kdebug_secpolicy(struct secpolicy *sp) -{ - /* sanity check */ - if (sp == NULL) - panic("kdebug_secpolicy: NULL pointer was passed."); - - kprintf("secpolicy{ refcnt=%u state=%u policy=%u\n", - sp->refcnt, sp->state, sp->policy); - - kdebug_secpolicyindex(&sp->spidx); - - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - kprintf(" type=discard }\n"); - break; - case IPSEC_POLICY_NONE: - kprintf(" type=none }\n"); - break; - case IPSEC_POLICY_IPSEC: - { - struct ipsecrequest *isr; - for (isr = sp->req; isr != NULL; isr = isr->next) { - - kprintf(" level=%u\n", isr->level); - kdebug_secasindex(&isr->saidx); - - if (isr->sav != NULL) - kdebug_secasv(isr->sav); - } - kprintf(" }\n"); - } - break; - case IPSEC_POLICY_BYPASS: - kprintf(" type=bypass }\n"); - break; - case IPSEC_POLICY_ENTRUST: - kprintf(" type=entrust }\n"); - break; - default: - kprintf("kdebug_secpolicy: Invalid policy found. %d\n", - sp->policy); - break; - } - - return; -} - -void -kdebug_secpolicyindex(struct secpolicyindex *spidx) -{ - /* sanity check */ - if (spidx == NULL) - panic("kdebug_secpolicyindex: NULL pointer was passed."); - - kprintf("secpolicyindex{ dir=%u prefs=%u prefd=%u ul_proto=%u\n", - spidx->dir, spidx->prefs, spidx->prefd, spidx->ul_proto); - - ipsec_hexdump((caddr_t)&spidx->src, - ((struct sockaddr *)&spidx->src)->sa_len); - kprintf("\n"); - ipsec_hexdump((caddr_t)&spidx->dst, - ((struct sockaddr *)&spidx->dst)->sa_len); - kprintf("}\n"); - - return; -} - -void -kdebug_secasindex(struct secasindex *saidx) -{ - /* sanity check */ - if (saidx == NULL) - panic("kdebug_secpolicyindex: NULL pointer was passed."); - - kprintf("secasindex{ mode=%u proto=%u\n", - saidx->mode, saidx->proto); - - ipsec_hexdump((caddr_t)&saidx->src, - ((struct sockaddr *)&saidx->src)->sa_len); - kprintf("\n"); - ipsec_hexdump((caddr_t)&saidx->dst, - ((struct sockaddr *)&saidx->dst)->sa_len); - kprintf("\n"); - - return; -} - -void -kdebug_secasv(struct secasvar *sav) -{ - /* sanity check */ - if (sav == NULL) - panic("kdebug_secasv: NULL pointer was passed."); - - kprintf("secas{"); - kdebug_secasindex(&sav->sah->saidx); - - kprintf(" refcnt=%u state=%u auth=%u enc=%u\n", - sav->refcnt, sav->state, sav->alg_auth, sav->alg_enc); - kprintf(" spi=%u flags=%u\n", - (u_int32_t)ntohl(sav->spi), sav->flags); - - if (sav->key_auth != NULL) - kdebug_sadb_key((struct sadb_ext *)sav->key_auth); - if (sav->key_enc != NULL) - kdebug_sadb_key((struct sadb_ext *)sav->key_enc); - if (sav->iv != NULL) { - kprintf(" iv="); - ipsec_hexdump(sav->iv, sav->ivlen ? sav->ivlen : 8); - kprintf("\n"); - } - - if (sav->replay != NULL) - kdebug_secreplay(sav->replay); - if (sav->lft_c != NULL) - kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_c); - if (sav->lft_h != NULL) - kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_h); - if (sav->lft_s != NULL) - kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_s); - -#if notyet - /* XXX: misc[123] ? */ -#endif - - return; -} - -static void -kdebug_secreplay(struct secreplay *rpl) -{ - int len, l; - - /* sanity check */ - if (rpl == NULL) - panic("kdebug_secreplay: NULL pointer was passed."); - - kprintf(" secreplay{ count=%u wsize=%u seq=%u lastseq=%u", - rpl->count, rpl->wsize, rpl->seq, rpl->lastseq); - - if (rpl->bitmap == NULL) { - kprintf(" }\n"); - return; - } - - kprintf("\n bitmap { "); - - for (len = 0; len < rpl->wsize; len++) { - for (l = 7; l >= 0; l--) - kprintf("%u", (((rpl->bitmap)[len] >> l) & 1) ? 1 : 0); - } - kprintf(" }\n"); - - return; -} - -void -kdebug_mbufhdr(struct mbuf *m) -{ - /* sanity check */ - if (m == NULL) - return; - - kprintf("mbuf(%p){ m_next:%p m_nextpkt:%p m_data:%p " - "m_len:%d m_type:0x%02x m_flags:0x%02x }\n", - m, m->m_next, m->m_nextpkt, m->m_data, - m->m_len, m->m_type, m->m_flags); - - if (m->m_flags & M_PKTHDR) { - kprintf(" m_pkthdr{ len:%d rcvif:%p }\n", - m->m_pkthdr.len, m->m_pkthdr.rcvif); - } - - if (m->m_flags & M_EXT) { - kprintf(" m_ext{ ext_buf:%p ext_free:%p " - "ext_size:%u ext_ref:%p }\n", - m->m_ext.ext_buf, m->m_ext.ext_free, - m->m_ext.ext_size, m->m_ext.ext_ref); - } - - return; -} - -void -kdebug_mbuf(struct mbuf *m0) -{ - struct mbuf *m = m0; - int i, j; - - for (j = 0; m; m = m->m_next) { - kdebug_mbufhdr(m); - kprintf(" m_data:\n"); - for (i = 0; i < m->m_len; i++) { - if (i && i % 32 == 0) - kprintf("\n"); - if (i % 4 == 0) - kprintf(" "); - kprintf("%02x", mtod(m, u_char *)[i]); - j++; - } - kprintf("\n"); - } - - return; -} -#endif /* _KERNEL */ - -void -kdebug_sockaddr(struct sockaddr *addr) -{ - struct sockaddr_in *sin4; -#ifdef INET6 - struct sockaddr_in6 *sin6; -#endif - - /* sanity check */ - if (addr == NULL) - panic("kdebug_sockaddr: NULL pointer was passed."); - - /* NOTE: We deal with port number as host byte order. */ - kprintf("sockaddr{ len=%u family=%u", addr->sa_len, addr->sa_family); - - switch (addr->sa_family) { - case AF_INET: - sin4 = (struct sockaddr_in *)addr; - kprintf(" port=%u\n", ntohs(sin4->sin_port)); - ipsec_hexdump((caddr_t)&sin4->sin_addr, sizeof(sin4->sin_addr)); - break; -#ifdef INET6 - case AF_INET6: - sin6 = (struct sockaddr_in6 *)addr; - kprintf(" port=%u\n", ntohs(sin6->sin6_port)); - kprintf(" flowinfo=0x%08x, scope_id=0x%08x\n", - sin6->sin6_flowinfo, sin6->sin6_scope_id); - ipsec_hexdump((caddr_t)&sin6->sin6_addr, - sizeof(sin6->sin6_addr)); - break; -#endif - } - - kprintf(" }\n"); - - return; -} - -void -ipsec_bindump(caddr_t buf, int len) -{ - int i; - - for (i = 0; i < len; i++) - kprintf("%c", (unsigned char)buf[i]); - - return; -} - - -void -ipsec_hexdump(caddr_t buf, int len) -{ - int i; - - for (i = 0; i < len; i++) { - if (i != 0 && i % 32 == 0) kprintf("\n"); - if (i % 4 == 0) kprintf(" "); - kprintf("%02x", (unsigned char)buf[i]); - } -#if 0 - if (i % 32 != 0) kprintf("\n"); -#endif - - return; -} diff --git a/sys/netproto/ipsec/key_debug.h b/sys/netproto/ipsec/key_debug.h deleted file mode 100644 index 5201e27102..0000000000 --- a/sys/netproto/ipsec/key_debug.h +++ /dev/null @@ -1,89 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/key_debug.h,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/key_debug.h,v 1.3 2003/08/23 10:06:23 rob Exp $ */ -/* $KAME: key_debug.h,v 1.10 2001/08/05 08:37:52 itojun Exp $ */ - -/* - * 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. - */ - -#ifndef _NETIPSEC_KEY_DEBUG_H_ -#define _NETIPSEC_KEY_DEBUG_H_ - -#ifdef _KERNEL -/* debug flags */ -#define KEYDEBUG_STAMP 0x00000001 /* path */ -#define KEYDEBUG_DATA 0x00000002 /* data */ -#define KEYDEBUG_DUMP 0x00000004 /* dump */ - -#define KEYDEBUG_KEY 0x00000010 /* key processing */ -#define KEYDEBUG_ALG 0x00000020 /* ciph & auth algorithm */ -#define KEYDEBUG_IPSEC 0x00000040 /* ipsec processing */ - -#define KEYDEBUG_KEY_STAMP (KEYDEBUG_KEY | KEYDEBUG_STAMP) -#define KEYDEBUG_KEY_DATA (KEYDEBUG_KEY | KEYDEBUG_DATA) -#define KEYDEBUG_KEY_DUMP (KEYDEBUG_KEY | KEYDEBUG_DUMP) -#define KEYDEBUG_ALG_STAMP (KEYDEBUG_ALG | KEYDEBUG_STAMP) -#define KEYDEBUG_ALG_DATA (KEYDEBUG_ALG | KEYDEBUG_DATA) -#define KEYDEBUG_ALG_DUMP (KEYDEBUG_ALG | KEYDEBUG_DUMP) -#define KEYDEBUG_IPSEC_STAMP (KEYDEBUG_IPSEC | KEYDEBUG_STAMP) -#define KEYDEBUG_IPSEC_DATA (KEYDEBUG_IPSEC | KEYDEBUG_DATA) -#define KEYDEBUG_IPSEC_DUMP (KEYDEBUG_IPSEC | KEYDEBUG_DUMP) - -#define KEYDEBUG(lev,arg) \ - do { if ((key_debug_level & (lev)) == (lev)) { arg; } } while (0) - -extern u_int32_t key_debug_level; -#endif /*_KERNEL*/ - -struct sadb_msg; -struct sadb_ext; -extern void kdebug_sadb (struct sadb_msg *); -extern void kdebug_sadb_x_policy (struct sadb_ext *); - -#ifdef _KERNEL -struct secpolicy; -struct secpolicyindex; -struct secasindex; -struct secasvar; -struct secreplay; -struct mbuf; -extern void kdebug_secpolicy (struct secpolicy *); -extern void kdebug_secpolicyindex (struct secpolicyindex *); -extern void kdebug_secasindex (struct secasindex *); -extern void kdebug_secasv (struct secasvar *); -extern void kdebug_mbufhdr (struct mbuf *); -extern void kdebug_mbuf (struct mbuf *); -#endif /*_KERNEL*/ - -struct sockaddr; -extern void kdebug_sockaddr (struct sockaddr *); - -extern void ipsec_hexdump (caddr_t, int); -extern void ipsec_bindump (caddr_t, int); - -#endif /* _NETIPSEC_KEY_DEBUG_H_ */ diff --git a/sys/netproto/ipsec/key_var.h b/sys/netproto/ipsec/key_var.h deleted file mode 100644 index e5f1d33d12..0000000000 --- a/sys/netproto/ipsec/key_var.h +++ /dev/null @@ -1,73 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/key_var.h,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ -/* $KAME: key_var.h,v 1.11 2001/09/12 23:05:07 sakane Exp $ */ - -/* - * 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. - */ - -#ifndef _NETIPSEC_KEY_VAR_H_ -#define _NETIPSEC_KEY_VAR_H_ - -/* sysctl */ -#define KEYCTL_DEBUG_LEVEL 1 -#define KEYCTL_SPI_TRY 2 -#define KEYCTL_SPI_MIN_VALUE 3 -#define KEYCTL_SPI_MAX_VALUE 4 -#define KEYCTL_RANDOM_INT 5 -#define KEYCTL_LARVAL_LIFETIME 6 -#define KEYCTL_BLOCKACQ_COUNT 7 -#define KEYCTL_BLOCKACQ_LIFETIME 8 -#define KEYCTL_ESP_KEYMIN 9 -#define KEYCTL_ESP_AUTH 10 -#define KEYCTL_AH_KEYMIN 11 -#define KEYCTL_PREFERED_OLDSA 12 -#define KEYCTL_MAXID 13 - -#define KEYCTL_NAMES { \ - { 0, 0 }, \ - { "debug", CTLTYPE_INT }, \ - { "spi_try", CTLTYPE_INT }, \ - { "spi_min_value", CTLTYPE_INT }, \ - { "spi_max_value", CTLTYPE_INT }, \ - { "random_int", CTLTYPE_INT }, \ - { "larval_lifetime", CTLTYPE_INT }, \ - { "blockacq_count", CTLTYPE_INT }, \ - { "blockacq_lifetime", CTLTYPE_INT }, \ - { "esp_keymin", CTLTYPE_INT }, \ - { "esp_auth", CTLTYPE_INT }, \ - { "ah_keymin", CTLTYPE_INT }, \ - { "prefered_oldsa", CTLTYPE_INT }, \ -} - -#ifdef _KERNEL -#define _KEYLEN(key) ((u_int)((key)->sadb_key_bits >> 3)) -#define _KEYBITS(key) ((u_int)((key)->sadb_key_bits)) -#define _KEYBUF(key) ((caddr_t)((caddr_t)(key) + sizeof(struct sadb_key))) -#endif /*_KERNEL*/ - -#endif /* _NETIPSEC_KEY_VAR_H_ */ diff --git a/sys/netproto/ipsec/keydb.h b/sys/netproto/ipsec/keydb.h deleted file mode 100644 index f319be1028..0000000000 --- a/sys/netproto/ipsec/keydb.h +++ /dev/null @@ -1,182 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/keydb.h,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/keydb.h,v 1.4 2003/08/23 10:06:23 rob Exp $ */ -/* $KAME: keydb.h,v 1.14 2000/08/02 17:58:26 sakane Exp $ */ - -/* - * 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. - */ - -#ifndef _NETIPSEC_KEYDB_H_ -#define _NETIPSEC_KEYDB_H_ - -#ifdef _KERNEL - -#include "key_var.h" - -/* - * The union of all possible address formats we handle. - */ -union sockaddr_union { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; -}; - -/* Security Assocciation Index */ -/* NOTE: Ensure to be same address family */ -struct secasindex { - union sockaddr_union src; /* srouce address for SA */ - union sockaddr_union dst; /* destination address for SA */ - u_int16_t proto; /* IPPROTO_ESP or IPPROTO_AH */ - u_int8_t mode; /* mode of protocol, see ipsec.h */ - u_int32_t reqid; /* reqid id who owned this SA */ - /* see IPSEC_MANUAL_REQID_MAX. */ -}; - -/* Security Association Data Base */ -struct secashead { - LIST_ENTRY(secashead) chain; - - struct secasindex saidx; - - struct sadb_ident *idents; /* source identity */ - struct sadb_ident *identd; /* destination identity */ - /* XXX I don't know how to use them. */ - - u_int8_t state; /* MATURE or DEAD. */ - LIST_HEAD(_satree, secasvar) savtree[SADB_SASTATE_MAX+1]; - /* SA chain */ - /* The first of this list is newer SA */ - - struct route sa_route; /* route cache */ -}; - -struct xformsw; -struct enc_xform; -struct auth_hash; -struct comp_algo; - -/* Security Association */ -struct secasvar { - LIST_ENTRY(secasvar) chain; - - u_int refcnt; /* reference count */ - u_int8_t state; /* Status of this Association */ - - u_int8_t alg_auth; /* Authentication Algorithm Identifier*/ - u_int8_t alg_enc; /* Cipher Algorithm Identifier */ - u_int8_t alg_comp; /* Compression Algorithm Identifier */ - u_int32_t spi; /* SPI Value, network byte order */ - u_int32_t flags; /* holder for SADB_KEY_FLAGS */ - - struct sadb_key *key_auth; /* Key for Authentication */ - struct sadb_key *key_enc; /* Key for Encryption */ - caddr_t iv; /* Initilization Vector */ - u_int ivlen; /* length of IV */ - void *sched; /* intermediate encryption key */ - size_t schedlen; - - struct secreplay *replay; /* replay prevention */ - long created; /* for lifetime */ - - struct sadb_lifetime *lft_c; /* CURRENT lifetime, it's constant. */ - struct sadb_lifetime *lft_h; /* HARD lifetime */ - struct sadb_lifetime *lft_s; /* SOFT lifetime */ - - u_int32_t seq; /* sequence number */ - pid_t pid; /* message's pid */ - - struct secashead *sah; /* back pointer to the secashead */ - - /* - * NB: Fields with a tdb_ prefix are part of the "glue" used - * to interface to the OpenBSD crypto support. This was done - * to distinguish this code from the mainline KAME code. - */ - struct xformsw *tdb_xform; /* transform */ - struct enc_xform *tdb_encalgxform; /* encoding algorithm */ - struct auth_hash *tdb_authalgxform; /* authentication algorithm */ - struct comp_algo *tdb_compalgxform; /* compression algorithm */ - u_int64_t tdb_cryptoid; /* crypto session id */ -}; - -/* replay prevention */ -struct secreplay { - u_int32_t count; - u_int wsize; /* window size, i.g. 4 bytes */ - u_int32_t seq; /* used by sender */ - u_int32_t lastseq; /* used by receiver */ - caddr_t bitmap; /* used by receiver */ - int overflow; /* overflow flag */ -}; - -/* socket table due to send PF_KEY messages. */ -struct secreg { - LIST_ENTRY(secreg) chain; - - struct socket *so; -}; - -#ifndef IPSEC_NONBLOCK_ACQUIRE -/* acquiring list table. */ -struct secacq { - LIST_ENTRY(secacq) chain; - - struct secasindex saidx; - - u_int32_t seq; /* sequence number */ - long created; /* for lifetime */ - int count; /* for lifetime */ -}; -#endif - -/* Sensitivity Level Specification */ -/* nothing */ - -#define SADB_KILL_INTERVAL 600 /* six seconds */ - -/* secpolicy */ -extern struct secpolicy *keydb_newsecpolicy (void); -extern void keydb_delsecpolicy (struct secpolicy *); -/* secashead */ -extern struct secashead *keydb_newsecashead (void); -extern void keydb_delsecashead (struct secashead *); -/* secasvar */ -extern struct secasvar *keydb_newsecasvar (void); -extern void keydb_refsecasvar (struct secasvar *); -extern void keydb_freesecasvar (struct secasvar *); -/* secreplay */ -extern struct secreplay *keydb_newsecreplay (size_t); -extern void keydb_delsecreplay (struct secreplay *); -/* secreg */ -extern struct secreg *keydb_newsecreg (void); -extern void keydb_delsecreg (struct secreg *); - -#endif /* _KERNEL */ - -#endif /* _NETIPSEC_KEYDB_H_ */ diff --git a/sys/netproto/ipsec/keysock.c b/sys/netproto/ipsec/keysock.c deleted file mode 100644 index 60c508cd7d..0000000000 --- a/sys/netproto/ipsec/keysock.c +++ /dev/null @@ -1,584 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/keysock.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */ -/* $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $ */ - -/* - * 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. - */ - -#include "opt_ipsec.h" - -/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -typedef int pr_output_t (struct mbuf *, struct socket *); - -struct key_cb { - int key_count; - int any_count; -}; -static struct key_cb key_cb; - -static struct sockaddr key_dst = { 2, PF_KEY, }; -static struct sockaddr key_src = { 2, PF_KEY, }; - -static int key_sendup0 (struct rawcb *, struct mbuf *, int); - -struct pfkeystat pfkeystat; - -/* - * key_output() - */ -int -key_output(struct mbuf *m, struct socket *so, ...) -{ - struct sadb_msg *msg; - int len, error = 0; - - - if (m == NULL) - panic("key_output: NULL pointer was passed."); - - pfkeystat.out_total++; - pfkeystat.out_bytes += m->m_pkthdr.len; - - len = m->m_pkthdr.len; - if (len < sizeof(struct sadb_msg)) { - pfkeystat.out_tooshort++; - error = EINVAL; - goto end; - } - - if (m->m_len < sizeof(struct sadb_msg)) { - if ((m = m_pullup(m, sizeof(struct sadb_msg))) == NULL) { - pfkeystat.out_nomem++; - error = ENOBUFS; - goto end; - } - } - - if ((m->m_flags & M_PKTHDR) == 0) - panic("key_output: not M_PKTHDR ??"); - - KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); - - msg = mtod(m, struct sadb_msg *); - pfkeystat.out_msgtype[msg->sadb_msg_type]++; - if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { - pfkeystat.out_invlen++; - error = EINVAL; - goto end; - } - - /*XXX giant lock*/ - crit_enter(); - error = key_parse(m, so); - m = NULL; - crit_exit(); -end: - if (m) - m_freem(m); - return error; -} - -/* - * send message to the socket. - */ -static int -key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc) -{ - int error; - - if (promisc) { - struct sadb_msg *pmsg; - - M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT); - if (m && m->m_len < sizeof(struct sadb_msg)) - m = m_pullup(m, sizeof(struct sadb_msg)); - if (!m) { - pfkeystat.in_nomem++; - m_freem(m); - return ENOBUFS; - } - m->m_pkthdr.len += sizeof(*pmsg); - - pmsg = mtod(m, struct sadb_msg *); - bzero(pmsg, sizeof(*pmsg)); - pmsg->sadb_msg_version = PF_KEY_V2; - pmsg->sadb_msg_type = SADB_X_PROMISC; - pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - /* pid and seq? */ - - pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; - } - - if (!ssb_appendaddr(&rp->rcb_socket->so_rcv, &key_src, m, NULL)) { - pfkeystat.in_nomem++; - m_freem(m); - error = ENOBUFS; - } else - error = 0; - sorwakeup(rp->rcb_socket); - return error; -} - -/* - * XXX this interface should be obsoleted. - * - * Parameters: - * target: target of the resulting message - */ -int -key_sendup(struct socket *so, struct sadb_msg *msg, u_int len, int target) -{ - struct mbuf *m, *n, *mprev; - int tlen; - - /* sanity check */ - if (so == NULL || msg == NULL) - panic("key_sendup: NULL pointer was passed."); - - KEYDEBUG(KEYDEBUG_KEY_DUMP, - kprintf("key_sendup: \n"); - kdebug_sadb(msg)); - - /* - * we increment statistics here, just in case we have ENOBUFS - * in this function. - */ - pfkeystat.in_total++; - pfkeystat.in_bytes += len; - pfkeystat.in_msgtype[msg->sadb_msg_type]++; - - /* - * Get mbuf chain whenever possible (not clusters), - * to save socket buffer. We'll be generating many SADB_ACQUIRE - * messages to listening key sockets. If we simply allocate clusters, - * ssb_appendaddr() will raise ENOBUFS due to too little ssb_space(). - * ssb_space() computes # of actual data bytes AND mbuf region. - * - * TODO: SADB_ACQUIRE filters should be implemented. - */ - tlen = len; - m = mprev = NULL; - while (tlen > 0) { - int nsize; - - n = m_getl(tlen, M_NOWAIT, MT_DATA, - (tlen == len) ? M_PKTHDR : 0, &nsize); - if (n == NULL) { - m_freem(m); - pfkeystat.in_nomem++; - return ENOBUFS; - } - n->m_len = (tlen < n->m_len) ? tlen : nsize; - - if (m == NULL) - m = mprev = n; - else { - mprev->m_next = n; - mprev = n; - } - tlen -= n->m_len; - } - m->m_pkthdr.len = len; - m_copyback(m, 0, len, (caddr_t)msg); - - /* avoid duplicated statistics */ - pfkeystat.in_total--; - pfkeystat.in_bytes -= len; - pfkeystat.in_msgtype[msg->sadb_msg_type]--; - - return key_sendup_mbuf(so, m, target); -} - -/* so can be NULL if target != KEY_SENDUP_ONE */ -int -key_sendup_mbuf(struct socket *so, struct mbuf *m, int target) -{ - struct mbuf *n; - struct keycb *kp; - int sendup; - struct rawcb *rp; - int error = 0; - - if (m == NULL) - panic("key_sendup_mbuf: NULL pointer was passed."); - if (so == NULL && target == KEY_SENDUP_ONE) - panic("key_sendup_mbuf: NULL pointer was passed."); - - pfkeystat.in_total++; - pfkeystat.in_bytes += m->m_pkthdr.len; - if (m->m_len < sizeof(struct sadb_msg)) { -#if 1 - m = m_pullup(m, sizeof(struct sadb_msg)); - if (m == NULL) { - pfkeystat.in_nomem++; - return ENOBUFS; - } -#else - /* don't bother pulling it up just for stats */ -#endif - } - if (m->m_len >= sizeof(struct sadb_msg)) { - struct sadb_msg *msg; - msg = mtod(m, struct sadb_msg *); - pfkeystat.in_msgtype[msg->sadb_msg_type]++; - } - - LIST_FOREACH(rp, &rawcb_list, list) - { - if (rp->rcb_proto.sp_family != PF_KEY) - continue; - if (rp->rcb_proto.sp_protocol - && rp->rcb_proto.sp_protocol != PF_KEY_V2) { - continue; - } - - kp = (struct keycb *)rp; - - /* - * If you are in promiscuous mode, and when you get broadcasted - * reply, you'll get two PF_KEY messages. - * (based on pf_key@inner.net message on 14 Oct 1998) - */ - if (((struct keycb *)rp)->kp_promisc) { - if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { - key_sendup0(rp, n, 1); - n = NULL; - } - } - - /* the exact target will be processed later */ - if (so && sotorawcb(so) == rp) - continue; - - sendup = 0; - switch (target) { - case KEY_SENDUP_ONE: - /* the statement has no effect */ - if (so && sotorawcb(so) == rp) - sendup++; - break; - case KEY_SENDUP_ALL: - sendup++; - break; - case KEY_SENDUP_REGISTERED: - if (kp->kp_registered) - sendup++; - break; - } - pfkeystat.in_msgtarget[target]++; - - if (!sendup) - continue; - - if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { - m_freem(m); - pfkeystat.in_nomem++; - return ENOBUFS; - } - - if ((error = key_sendup0(rp, n, 0)) != 0) { - m_freem(m); - return error; - } - - n = NULL; - } - - if (so) { - error = key_sendup0(sotorawcb(so), m, 0); - m = NULL; - } else { - error = 0; - m_freem(m); - } - return error; -} - -/* - * key_abort() - * derived from net/rtsock.c:rts_abort() - */ -static void -key_abort(netmsg_t msg) -{ - /* XXX needs token protection */ - raw_usrreqs.pru_abort(msg); -} - -/* - * key_attach() - * derived from net/rtsock.c:rts_attach() - */ -static void -key_attach(netmsg_t msg) -{ - struct socket *so = msg->attach.base.nm_so; - int proto = msg->attach.nm_proto; - struct pru_attach_info *ai = msg->attach.nm_ai; - struct keycb *kp; - struct netmsg_pru_attach smsg; - int error; - - if (sotorawcb(so) != NULL) { - error = EISCONN; /* XXX panic? */ - goto out; - } - kp = (struct keycb *)kmalloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */ - - /* - * The critical section is necessary to block protocols from sending - * error notifications (like RTM_REDIRECT or RTM_LOSING) while - * this PCB is extant but incompletely initialized. - * Probably we should try to do more of this work beforehand and - * eliminate the spl. - */ - /* XXX needs token protection */ - crit_enter(); - so->so_pcb = (caddr_t)kp; - - netmsg_init(&smsg.base, so, &netisr_adone_rport, 0, - raw_usrreqs.pru_attach); - smsg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); - smsg.base.lmsg.ms_flags |= MSGF_SYNC; - smsg.nm_proto = proto; - smsg.nm_ai = ai; - raw_usrreqs.pru_attach((netmsg_t)&smsg); - error = smsg.base.lmsg.ms_error; - - kp = (struct keycb *)sotorawcb(so); - if (error) { - kfree(kp, M_PCB); - so->so_pcb = (caddr_t) 0; - crit_exit(); - goto out; - } - - kp->kp_promisc = kp->kp_registered = 0; - - if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ - key_cb.key_count++; - key_cb.any_count++; - kp->kp_raw.rcb_laddr = &key_src; - kp->kp_raw.rcb_faddr = &key_dst; - soisconnected(so); - so->so_options |= SO_USELOOPBACK; - - crit_exit(); -out: - lwkt_replymsg(&msg->attach.base.lmsg, error); -} - -/* - * key_bind() - * derived from net/rtsock.c:rts_bind() - */ -static void -key_bind(netmsg_t msg) -{ - /* XXX needs token protection */ - raw_usrreqs.pru_bind(msg); /* XXX just EINVAL */ -} - -/* - * key_connect() - * derived from net/rtsock.c:rts_connect() - */ -static void -key_connect(netmsg_t msg) -{ - /* XXX needs token protection */ - raw_usrreqs.pru_connect(msg); /* XXX just EINVAL */ -} - -/* - * key_detach() - * derived from net/rtsock.c:rts_detach() - */ -static void -key_detach(netmsg_t msg) -{ - struct socket *so = msg->detach.base.nm_so; - struct keycb *kp = (struct keycb *)sotorawcb(so); - - /* XXX needs token protection */ - if (kp != NULL) { - if (kp->kp_raw.rcb_proto.sp_protocol - == PF_KEY) /* XXX: AF_KEY */ - key_cb.key_count--; - key_cb.any_count--; - - key_freereg(so); - } - raw_usrreqs.pru_detach(msg); - -} - -/* - * key_disconnect() - * derived from net/rtsock.c:key_disconnect() - */ -static void -key_disconnect(netmsg_t msg) -{ - /* XXX needs token protection */ - raw_usrreqs.pru_disconnect(msg); -} - -/* - * key_peeraddr() - * derived from net/rtsock.c:rts_peeraddr() - */ -static void -key_peeraddr(netmsg_t msg) -{ - /* XXX needs token protection */ - raw_usrreqs.pru_peeraddr(msg); -} - -/* - * key_send() - * derived from net/rtsock.c:rts_send() - */ -static void -key_send(netmsg_t msg) -{ - /* XXX needs token protection */ - raw_usrreqs.pru_send(msg); -} - -/* - * key_shutdown() - * derived from net/rtsock.c:rts_shutdown() - */ -static void -key_shutdown(netmsg_t msg) -{ - /* XXX needs token protection */ - raw_usrreqs.pru_shutdown(msg); -} - -/* - * key_sockaddr() - * derived from net/rtsock.c:rts_sockaddr() - */ -static void -key_sockaddr(netmsg_t msg) -{ - /* XXX needs token protection */ - raw_usrreqs.pru_sockaddr(msg); -} - -struct pr_usrreqs key_usrreqs = { - .pru_abort = key_abort, - .pru_accept = pr_generic_notsupp, - .pru_attach = key_attach, - .pru_bind = key_bind, - .pru_connect = key_connect, - .pru_connect2 = pr_generic_notsupp, - .pru_control = pr_generic_notsupp, - .pru_detach = key_detach, - .pru_disconnect = key_disconnect, - .pru_listen = pr_generic_notsupp, - .pru_peeraddr = key_peeraddr, - .pru_rcvd = pr_generic_notsupp, - .pru_rcvoob = pr_generic_notsupp, - .pru_send = key_send, - .pru_sense = pru_sense_null, - .pru_shutdown = key_shutdown, - .pru_sockaddr = key_sockaddr, - .pru_sosend = sosend, - .pru_soreceive = soreceive -}; - -/* sysctl */ -SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family"); - -/* - * Definitions of protocols supported in the KEY domain. - */ - -extern struct domain keydomain; - -struct protosw keysw[] = { - { - .pr_type = SOCK_RAW, - .pr_domain = &keydomain, - .pr_protocol = PF_KEY_V2, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = NULL, - .pr_output = key_output, - .pr_ctlinput = raw_ctlinput, - .pr_ctloutput = NULL, - - .pr_ctlport = cpu0_ctlport, - .pr_init = raw_init, - .pr_usrreqs = &key_usrreqs - } -}; - -static void -key_init0(void) -{ - bzero((caddr_t)&key_cb, sizeof(key_cb)); - key_init(); -} - -struct domain keydomain = { - PF_KEY, "key", key_init0, NULL, NULL, - keysw, &keysw[NELEM(keysw)], -}; - -DOMAIN_SET(key); diff --git a/sys/netproto/ipsec/keysock.h b/sys/netproto/ipsec/keysock.h deleted file mode 100644 index 5838bd6b9b..0000000000 --- a/sys/netproto/ipsec/keysock.h +++ /dev/null @@ -1,83 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/keysock.h,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/keysock.h,v 1.4 2004/10/15 22:59:10 hsu Exp $ */ -/* $KAME: keysock.h,v 1.8 2000/03/27 05:11:06 sumikawa Exp $ */ - -/* - * 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. - */ - -#ifndef _NETIPSEC_KEYSOCK_H_ -#define _NETIPSEC_KEYSOCK_H_ - -/* statistics for pfkey socket */ -struct pfkeystat { - /* kernel -> userland */ - u_quad_t out_total; /* # of total calls */ - u_quad_t out_bytes; /* total bytecount */ - u_quad_t out_msgtype[256]; /* message type histogram */ - u_quad_t out_invlen; /* invalid length field */ - u_quad_t out_invver; /* invalid version field */ - u_quad_t out_invmsgtype; /* invalid message type field */ - u_quad_t out_tooshort; /* msg too short */ - u_quad_t out_nomem; /* memory allocation failure */ - u_quad_t out_dupext; /* duplicate extension */ - u_quad_t out_invexttype; /* invalid extension type */ - u_quad_t out_invsatype; /* invalid sa type */ - u_quad_t out_invaddr; /* invalid address extension */ - /* userland -> kernel */ - u_quad_t in_total; /* # of total calls */ - u_quad_t in_bytes; /* total bytecount */ - u_quad_t in_msgtype[256]; /* message type histogram */ - u_quad_t in_msgtarget[3]; /* one/all/registered */ - u_quad_t in_nomem; /* memory allocation failure */ - /* others */ - u_quad_t sockerr; /* # of socket related errors */ -}; - -#define KEY_SENDUP_ONE 0 -#define KEY_SENDUP_ALL 1 -#define KEY_SENDUP_REGISTERED 2 - -#ifdef _KERNEL -struct keycb { - struct rawcb kp_raw; /* rawcb */ - int kp_promisc; /* promiscuous mode */ - int kp_registered; /* registered socket */ -}; - -extern struct pfkeystat pfkeystat; - -extern int key_output (struct mbuf *, struct socket *, ...); -extern int key_usrreq (struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *); - -extern int key_sendup (struct socket *, struct sadb_msg *, u_int, int); -extern int key_sendup_mbuf (struct socket *, struct mbuf *, int); -#endif /* _KERNEL */ - -#endif /*_NETIPSEC_KEYSOCK_H_*/ diff --git a/sys/netproto/ipsec/xform.h b/sys/netproto/ipsec/xform.h deleted file mode 100644 index 51cbad36b1..0000000000 --- a/sys/netproto/ipsec/xform.h +++ /dev/null @@ -1,127 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/xform.h,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/xform.h,v 1.2 2003/06/17 04:28:53 dillon Exp $ */ -/* $OpenBSD: ip_ipsp.h,v 1.119 2002/03/14 01:27:11 millert Exp $ */ -/* - * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr), - * Niels Provos (provos@physnet.uni-hamburg.de) and - * Niklas Hallqvist (niklas@appli.se). - * - * The original version of this code was written by John Ioannidis - * for BSD/OS in Athens, Greece, in November 1995. - * - * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, - * by Angelos D. Keromytis. - * - * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis - * and Niels Provos. - * - * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist. - * - * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, - * Angelos D. Keromytis and Niels Provos. - * Copyright (c) 1999 Niklas Hallqvist. - * Copyright (c) 2001, Angelos D. Keromytis. - * - * Permission to use, copy, and modify this software with or without fee - * is hereby granted, provided that this entire notice is included in - * all copies of any software which is or includes a copy or - * modification of this software. - * You may use this code under the GNU public license if you so wish. Please - * contribute changes back to the authors under this freer than GPL license - * so that we may further the use of strong encryption without limitations to - * all. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE - * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR - * PURPOSE. - */ - -#ifndef _NETIPSEC_XFORM_H_ -#define _NETIPSEC_XFORM_H_ - -#include -#include -#include - -#define AH_HMAC_HASHLEN 12 /* 96 bits of authenticator */ -#define AH_HMAC_INITIAL_RPL 1 /* replay counter initial value */ - -/* - * Packet tag assigned on completion of IPsec processing; used - * to speedup processing when/if the packet comes back for more - * processing. - */ -struct tdb_ident { - u_int32_t spi; - union sockaddr_union dst; - u_int8_t proto; -}; - -/* - * Opaque data structure hung off a crypto operation descriptor. - */ -struct tdb_crypto { - struct ipsecrequest *tc_isr; /* ipsec request state */ - u_int32_t tc_spi; /* associated SPI */ - union sockaddr_union tc_dst; /* dst addr of packet */ - u_int8_t tc_proto; /* current protocol, e.g. AH */ - u_int8_t tc_nxt; /* next protocol, e.g. IPV4 */ - int tc_protoff; /* current protocol offset */ - int tc_skip; /* data offset */ - caddr_t tc_ptr; /* associated crypto data */ -}; - -struct secasvar; -struct ipescrequest; - -struct xformsw { - u_short xf_type; /* xform ID */ -#define XF_IP4 1 /* IP inside IP */ -#define XF_AH 2 /* AH */ -#define XF_ESP 3 /* ESP */ -#define XF_TCPSIGNATURE 5 /* TCP MD5 Signature option, RFC 2358 */ -#define XF_IPCOMP 6 /* IPCOMP */ - u_short xf_flags; -#define XFT_AUTH 0x0001 -#define XFT_CONF 0x0100 -#define XFT_COMP 0x1000 - char *xf_name; /* human-readable name */ - int (*xf_init)(struct secasvar*, struct xformsw*); /* setup */ - int (*xf_zeroize)(struct secasvar*); /* cleanup */ - int (*xf_input)(struct mbuf*, struct secasvar*, /* input */ - int, int); - int (*xf_output)(struct mbuf*, /* output */ - struct ipsecrequest *, struct mbuf **, int, int); - struct xformsw *xf_next; /* list of registered xforms */ -}; - -#ifdef _KERNEL -extern void xform_register(struct xformsw*); -extern int xform_init(struct secasvar *sav, int xftype); - -struct cryptoini; - -/* XF_IP4 */ -extern int ip4_input6(struct mbuf **mp, int *offp, int proto); -extern int ip4_input(struct mbuf **mp, int *offp, int proto); -extern int ipip_output(struct mbuf *, struct ipsecrequest *, - struct mbuf **, int, int); - -/* XF_AH */ -extern int ah_init0(struct secasvar *, struct xformsw *, struct cryptoini *); -extern int ah_zeroize(struct secasvar *sav); -extern struct auth_hash *ah_algorithm_lookup(int alg); -extern size_t ah_hdrsiz(struct secasvar *); - -/* XF_ESP */ -extern struct enc_xform *esp_algorithm_lookup(int alg); -extern size_t esp_hdrsiz(struct secasvar *sav); - -/* XF_COMP */ -extern struct comp_algo *ipcomp_algorithm_lookup(int alg); - -#endif /* _KERNEL */ -#endif /* _NETIPSEC_XFORM_H_ */ diff --git a/sys/netproto/ipsec/xform_ah.c b/sys/netproto/ipsec/xform_ah.c deleted file mode 100644 index 512211a8c4..0000000000 --- a/sys/netproto/ipsec/xform_ah.c +++ /dev/null @@ -1,1205 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/xform_ah.c,v 1.1.4.2 2003/02/26 00:14:05 sam Exp $ */ -/* $OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */ -/* - * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). - * - * The original version of this code was written by John Ioannidis - * for BSD/OS in Athens, Greece, in November 1995. - * - * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, - * by Angelos D. Keromytis. - * - * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis - * and Niels Provos. - * - * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist. - * - * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, - * Angelos D. Keromytis and Niels Provos. - * Copyright (c) 1999 Niklas Hallqvist. - * Copyright (c) 2001 Angelos D. Keromytis. - * - * Permission to use, copy, and modify this software with or without fee - * is hereby granted, provided that this entire notice is included in - * all copies of any software which is or includes a copy or - * modification of this software. - * You may use this code under the GNU public license if you so wish. Please - * contribute changes back to the authors under this freer than GPL license - * so that we may further the use of strong encryption without limitations to - * all. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE - * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR - * PURPOSE. - */ -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef INET6 -#include -#include -#include -#endif - -#include -#include - -#include -#include - -/* - * Return header size in bytes. The old protocol did not support - * the replay counter; the new protocol always includes the counter. - */ -#define HDRSIZE(sav) \ - (((sav)->flags & SADB_X_EXT_OLD) ? \ - sizeof (struct ah) : sizeof (struct ah) + sizeof (u_int32_t)) -/* - * Return authenticator size in bytes. The old protocol is known - * to use a fixed 16-byte authenticator. The new algorithm gets - * this size from the xform but is (currently) always 12. - */ -#define AUTHSIZE(sav) \ - ((sav->flags & SADB_X_EXT_OLD) ? 16 : (sav)->tdb_authalgxform->blocksize) - -int ah_enable = 1; /* control flow of packets with AH */ -int ah_cleartos = 1; /* clear ip_tos when doing AH calc */ -struct ahstat ahstat; - -SYSCTL_DECL(_net_inet_ah); -SYSCTL_INT(_net_inet_ah, OID_AUTO, - ah_enable, CTLFLAG_RW, &ah_enable, 0, ""); -SYSCTL_INT(_net_inet_ah, OID_AUTO, - ah_cleartos, CTLFLAG_RW, &ah_cleartos, 0, ""); -SYSCTL_STRUCT(_net_inet_ah, IPSECCTL_STATS, - stats, CTLFLAG_RD, &ahstat, ahstat, ""); - -static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */ - -static int ah_input_cb(struct cryptop*); -static int ah_output_cb(struct cryptop*); - -/* - * NB: this is public for use by the PF_KEY support. - */ -struct auth_hash * -ah_algorithm_lookup(int alg) -{ - if (alg >= AH_ALG_MAX) - return NULL; - switch (alg) { - case SADB_X_AALG_NULL: - return &auth_hash_null; - case SADB_AALG_MD5HMAC: - return &auth_hash_hmac_md5; - case SADB_AALG_SHA1HMAC: - return &auth_hash_hmac_sha1; - case SADB_X_AALG_RIPEMD160HMAC: - return &auth_hash_hmac_ripemd_160; - case SADB_X_AALG_MD5: - return &auth_hash_key_md5; - case SADB_X_AALG_SHA: - return &auth_hash_key_sha1; - case SADB_X_AALG_SHA2_256: - return &auth_hash_hmac_sha2_256; - case SADB_X_AALG_SHA2_384: - return &auth_hash_hmac_sha2_384; - case SADB_X_AALG_SHA2_512: - return &auth_hash_hmac_sha2_512; - } - return NULL; -} - -size_t -ah_hdrsiz(struct secasvar *sav) -{ - size_t size; - - if (sav != NULL) { - int authsize; - KASSERT(sav->tdb_authalgxform != NULL, - ("ah_hdrsiz: null xform")); - /*XXX not right for null algorithm--does it matter??*/ - authsize = AUTHSIZE(sav); - size = roundup(authsize, sizeof (u_int32_t)) + HDRSIZE(sav); - } else { - /* default guess */ - size = sizeof (struct ah) + sizeof (u_int32_t) + 16; - } - return size; -} - -/* - * NB: public for use by esp_init. - */ -int -ah_init0(struct secasvar *sav, struct xformsw *xsp, struct cryptoini *cria) -{ - struct auth_hash *thash; - int keylen; - - thash = ah_algorithm_lookup(sav->alg_auth); - if (thash == NULL) { - DPRINTF(("ah_init: unsupported authentication algorithm %u\n", - sav->alg_auth)); - return EINVAL; - } - /* - * Verify the replay state block allocation is consistent with - * the protocol type. We check here so we can make assumptions - * later during protocol processing. - */ - /* NB: replay state is setup elsewhere (sigh) */ - if (((sav->flags&SADB_X_EXT_OLD) == 0) ^ (sav->replay != NULL)) { - DPRINTF(("ah_init: replay state block inconsistency, " - "%s algorithm %s replay state\n", - (sav->flags & SADB_X_EXT_OLD) ? "old" : "new", - sav->replay == NULL ? "without" : "with")); - return EINVAL; - } - if (sav->key_auth == NULL) { - DPRINTF(("ah_init: no authentication key for %s " - "algorithm\n", thash->name)); - return EINVAL; - } - keylen = _KEYLEN(sav->key_auth); - if (keylen != thash->keysize && thash->keysize != 0) { - DPRINTF(("ah_init: invalid keylength %d, algorithm " - "%s requires keysize %d\n", - keylen, thash->name, thash->keysize)); - return EINVAL; - } - - sav->tdb_xform = xsp; - sav->tdb_authalgxform = thash; - - /* Initialize crypto session. */ - bzero(cria, sizeof (*cria)); - cria->cri_alg = sav->tdb_authalgxform->type; - cria->cri_klen = _KEYBITS(sav->key_auth); - cria->cri_key = _KEYBUF(sav->key_auth); - - return 0; -} - -/* - * ah_init() is called when an SPI is being set up. - */ -static int -ah_init(struct secasvar *sav, struct xformsw *xsp) -{ - struct cryptoini cria; - int error; - - error = ah_init0(sav, xsp, &cria); - return error ? error : - crypto_newsession(&sav->tdb_cryptoid, &cria, crypto_support); -} - -/* - * Paranoia. - * - * NB: public for use by esp_zeroize (XXX). - */ -int -ah_zeroize(struct secasvar *sav) -{ - int err; - - if (sav->key_auth) - bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth)); - - err = crypto_freesession(sav->tdb_cryptoid); - sav->tdb_cryptoid = 0; - sav->tdb_authalgxform = NULL; - sav->tdb_xform = NULL; - return err; -} - -/* - * Massage IPv4/IPv6 headers for AH processing. - */ -static int -ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) -{ - struct mbuf *m = *m0; - unsigned char *ptr; - int off, count; - -#ifdef INET - struct ip *ip; -#endif /* INET */ - -#ifdef INET6 - struct ip6_ext *ip6e; - struct ip6_hdr ip6; - int alloc, len, ad; -#endif /* INET6 */ - - switch (proto) { -#ifdef INET - case AF_INET: - /* - * This is the least painful way of dealing with IPv4 header - * and option processing -- just make sure they're in - * contiguous memory. - */ - *m0 = m = m_pullup(m, skip); - if (m == NULL) { - DPRINTF(("ah_massage_headers: m_pullup failed\n")); - return ENOBUFS; - } - - /* Fix the IP header */ - ip = mtod(m, struct ip *); - if (ah_cleartos) - ip->ip_tos = 0; - ip->ip_ttl = 0; - ip->ip_sum = 0; - - /* - * On input, fix ip_len which has been byte-swapped - * at ip_input(). - */ - if (!out) { - ip->ip_len = htons(ip->ip_len + skip); - - if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK) - ip->ip_off = htons(ip->ip_off & IP_DF); - else - ip->ip_off = 0; - } else { - if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK) - ip->ip_off = htons(ntohs(ip->ip_off) & IP_DF); - else - ip->ip_off = 0; - } - - ptr = mtod(m, unsigned char *) + sizeof(struct ip); - - /* IPv4 option processing */ - for (off = sizeof(struct ip); off < skip;) { - if (ptr[off] == IPOPT_EOL || ptr[off] == IPOPT_NOP || - off + 1 < skip) - ; - else { - DPRINTF(("ah_massage_headers: illegal IPv4 " - "option length for option %d\n", - ptr[off])); - - m_freem(m); - return EINVAL; - } - - switch (ptr[off]) { - case IPOPT_EOL: - off = skip; /* End the loop. */ - break; - - case IPOPT_NOP: - off++; - break; - - case IPOPT_SECURITY: /* 0x82 */ - case 0x85: /* Extended security. */ - case 0x86: /* Commercial security. */ - case 0x94: /* Router alert */ - case 0x95: /* RFC1770 */ - /* Sanity check for option length. */ - if (ptr[off + 1] < 2) { - DPRINTF(("ah_massage_headers: " - "illegal IPv4 option length for " - "option %d\n", ptr[off])); - - m_freem(m); - return EINVAL; - } - - off += ptr[off + 1]; - break; - - case IPOPT_LSRR: - case IPOPT_SSRR: - /* Sanity check for option length. */ - if (ptr[off + 1] < 2) { - DPRINTF(("ah_massage_headers: " - "illegal IPv4 option length for " - "option %d\n", ptr[off])); - - m_freem(m); - return EINVAL; - } - - /* - * On output, if we have either of the - * source routing options, we should - * swap the destination address of the - * IP header with the last address - * specified in the option, as that is - * what the destination's IP header - * will look like. - */ - if (out) - bcopy(ptr + off + ptr[off + 1] - - sizeof(struct in_addr), - &(ip->ip_dst), sizeof(struct in_addr)); - - /* Fall through */ - default: - /* Sanity check for option length. */ - if (ptr[off + 1] < 2) { - DPRINTF(("ah_massage_headers: " - "illegal IPv4 option length for " - "option %d\n", ptr[off])); - m_freem(m); - return EINVAL; - } - - /* Zeroize all other options. */ - count = ptr[off + 1]; - bcopy(ipseczeroes, ptr, count); - off += count; - break; - } - - /* Sanity check. */ - if (off > skip) { - DPRINTF(("ah_massage_headers(): malformed " - "IPv4 options header\n")); - - m_freem(m); - return EINVAL; - } - } - - break; -#endif /* INET */ - -#ifdef INET6 - case AF_INET6: /* Ugly... */ - /* Copy and "cook" the IPv6 header. */ - m_copydata(m, 0, sizeof(ip6), (caddr_t) &ip6); - - /* We don't do IPv6 Jumbograms. */ - if (ip6.ip6_plen == 0) { - DPRINTF(("ah_massage_headers: unsupported IPv6 jumbogram\n")); - m_freem(m); - return EMSGSIZE; - } - - ip6.ip6_flow = 0; - ip6.ip6_hlim = 0; - ip6.ip6_vfc &= ~IPV6_VERSION_MASK; - ip6.ip6_vfc |= IPV6_VERSION; - - /* Scoped address handling. */ - if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_src)) - ip6.ip6_src.s6_addr16[1] = 0; - if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_dst)) - ip6.ip6_dst.s6_addr16[1] = 0; - - /* Done with IPv6 header. */ - m_copyback(m, 0, sizeof(struct ip6_hdr), (caddr_t) &ip6); - - /* Let's deal with the remaining headers (if any). */ - if (skip - sizeof(struct ip6_hdr) > 0) { - if (m->m_len <= skip) { - ptr = kmalloc(skip - sizeof(struct ip6_hdr), - M_XDATA, M_INTWAIT | M_NULLOK); - if (ptr == NULL) { - DPRINTF(("ah_massage_headers: failed " - "to allocate memory for IPv6 " - "headers\n")); - m_freem(m); - return ENOBUFS; - } - - /* - * Copy all the protocol headers after - * the IPv6 header. - */ - m_copydata(m, sizeof(struct ip6_hdr), - skip - sizeof(struct ip6_hdr), ptr); - alloc = 1; - } else { - /* No need to allocate memory. */ - ptr = mtod(m, unsigned char *) + - sizeof(struct ip6_hdr); - alloc = 0; - } - } else - break; - - off = ip6.ip6_nxt & 0xff; /* Next header type. */ - - for (len = 0; len < skip - sizeof(struct ip6_hdr);) - switch (off) { - case IPPROTO_HOPOPTS: - case IPPROTO_DSTOPTS: - ip6e = (struct ip6_ext *) (ptr + len); - - /* - * Process the mutable/immutable - * options -- borrows heavily from the - * KAME code. - */ - for (count = len + sizeof(struct ip6_ext); - count < len + ((ip6e->ip6e_len + 1) << 3);) { - if (ptr[count] == IP6OPT_PAD1) { - count++; - continue; /* Skip padding. */ - } - - /* Sanity check. */ - if (count > len + - ((ip6e->ip6e_len + 1) << 3)) { - m_freem(m); - - /* Free, if we allocated. */ - if (alloc) - kfree(ptr, M_XDATA); - return EINVAL; - } - - ad = ptr[count + 1]; - - /* If mutable option, zeroize. */ - if (ptr[count] & IP6OPT_MUTABLE) - bcopy(ipseczeroes, ptr + count, - ptr[count + 1]); - - count += ad; - - /* Sanity check. */ - if (count > - skip - sizeof(struct ip6_hdr)) { - m_freem(m); - - /* Free, if we allocated. */ - if (alloc) - kfree(ptr, M_XDATA); - return EINVAL; - } - } - - /* Advance. */ - len += ((ip6e->ip6e_len + 1) << 3); - off = ip6e->ip6e_nxt; - break; - - case IPPROTO_ROUTING: - /* - * Always include routing headers in - * computation. - */ - ip6e = (struct ip6_ext *) (ptr + len); - len += ((ip6e->ip6e_len + 1) << 3); - off = ip6e->ip6e_nxt; - break; - - default: - DPRINTF(("ah_massage_headers: unexpected " - "IPv6 header type %d", off)); - if (alloc) - kfree(ptr, M_XDATA); - m_freem(m); - return EINVAL; - } - - /* Copyback and free, if we allocated. */ - if (alloc) { - m_copyback(m, sizeof(struct ip6_hdr), - skip - sizeof(struct ip6_hdr), ptr); - kfree(ptr, M_XDATA); - } - - break; -#endif /* INET6 */ - } - - return 0; -} - -/* - * ah_input() gets called to verify that an input packet - * passes authentication. - */ -static int -ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) -{ - struct auth_hash *ahx; - struct tdb_ident *tdbi; - struct tdb_crypto *tc; - struct m_tag *mtag; - struct newah *ah; - int hl, rplen, authsize; - - struct cryptodesc *crda; - struct cryptop *crp; - - KASSERT(sav != NULL, ("ah_input: null SA")); - KASSERT(sav->key_auth != NULL, - ("ah_input: null authentication key")); - KASSERT(sav->tdb_authalgxform != NULL, - ("ah_input: null authentication xform")); - - /* Figure out header size. */ - rplen = HDRSIZE(sav); - - /* XXX don't pullup, just copy header */ - IP6_EXTHDR_GET(ah, struct newah *, m, skip, rplen); - if (ah == NULL) { - DPRINTF(("ah_input: cannot pullup header\n")); - ahstat.ahs_hdrops++; /*XXX*/ - m_freem(m); - return ENOBUFS; - } - - /* Check replay window, if applicable. */ - if (sav->replay && !ipsec_chkreplay(ntohl(ah->ah_seq), sav)) { - ahstat.ahs_replay++; - DPRINTF(("ah_input: packet replay failure: %s\n", - ipsec_logsastr(sav))); - m_freem(m); - return ENOBUFS; - } - - /* Verify AH header length. */ - hl = ah->ah_len * sizeof (u_int32_t); - ahx = sav->tdb_authalgxform; - authsize = AUTHSIZE(sav); - if (hl != authsize + rplen - sizeof (struct ah)) { - DPRINTF(("ah_input: bad authenticator length %u (expecting %lu)" - " for packet in SA %s/%08lx\n", - hl, (u_long) (authsize + rplen - sizeof (struct ah)), - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - ahstat.ahs_badauthl++; - m_freem(m); - return EACCES; - } - ahstat.ahs_ibytes += m->m_pkthdr.len - skip - hl; - - /* Get crypto descriptors. */ - crp = crypto_getreq(1); - if (crp == NULL) { - DPRINTF(("ah_input: failed to acquire crypto descriptor\n")); - ahstat.ahs_crypto++; - m_freem(m); - return ENOBUFS; - } - - crda = crp->crp_desc; - KASSERT(crda != NULL, ("ah_input: null crypto descriptor")); - - crda->crd_skip = 0; - crda->crd_len = m->m_pkthdr.len; - crda->crd_inject = skip + rplen; - - /* Authentication operation. */ - crda->crd_alg = ahx->type; - crda->crd_key = _KEYBUF(sav->key_auth); - crda->crd_klen = _KEYBITS(sav->key_auth); - - /* Find out if we've already done crypto. */ - for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL); - mtag != NULL; - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) { - tdbi = (struct tdb_ident *)m_tag_data(mtag); - if (tdbi->proto == sav->sah->saidx.proto && - tdbi->spi == sav->spi && - !bcmp(&tdbi->dst, &sav->sah->saidx.dst, - sizeof (union sockaddr_union))) - break; - } - - /* Allocate IPsec-specific opaque crypto info. */ - if (mtag == NULL) { - tc = kmalloc(sizeof (struct tdb_crypto) + - skip + rplen + authsize, M_XDATA, - M_INTWAIT | M_ZERO | M_NULLOK); - } else { - /* Hash verification has already been done successfully. */ - tc = kmalloc(sizeof (struct tdb_crypto), - M_XDATA, M_INTWAIT | M_ZERO | M_NULLOK); - } - if (tc == NULL) { - DPRINTF(("ah_input: failed to allocate tdb_crypto\n")); - ahstat.ahs_crypto++; - crypto_freereq(crp); - m_freem(m); - return ENOBUFS; - } - - /* Only save information if crypto processing is needed. */ - if (mtag == NULL) { - int error; - - /* - * Save the authenticator, the skipped portion of the packet, - * and the AH header. - */ - m_copydata(m, 0, skip + rplen + authsize, (caddr_t)(tc+1)); - - /* Zeroize the authenticator on the packet. */ - m_copyback(m, skip + rplen, authsize, ipseczeroes); - - /* "Massage" the packet headers for crypto processing. */ - error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family, - skip, ahx->type, 0); - if (error != 0) { - /* NB: mbuf is free'd by ah_massage_headers */ - ahstat.ahs_hdrops++; - kfree(tc, M_XDATA); - crypto_freereq(crp); - return error; - } - } - - /* Crypto operation descriptor. */ - crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ - crp->crp_flags = CRYPTO_F_IMBUF; - crp->crp_buf = (caddr_t) m; - crp->crp_callback = ah_input_cb; - crp->crp_sid = sav->tdb_cryptoid; - crp->crp_opaque = (caddr_t) tc; - - /* These are passed as-is to the callback. */ - tc->tc_spi = sav->spi; - tc->tc_dst = sav->sah->saidx.dst; - tc->tc_proto = sav->sah->saidx.proto; - tc->tc_nxt = ah->ah_nxt; - tc->tc_protoff = protoff; - tc->tc_skip = skip; - tc->tc_ptr = (caddr_t) mtag; /* Save the mtag we've identified. */ - - if (mtag == NULL) - return crypto_dispatch(crp); - else - return ah_input_cb(crp); -} - -#ifdef INET6 -#define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) do { \ - if (saidx->dst.sa.sa_family == AF_INET6) { \ - error = ipsec6_common_input_cb(m, sav, skip, protoff, mtag); \ - } else { \ - error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag); \ - } \ -} while (0) -#else -#define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) \ - (error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag)) -#endif - -/* - * AH input callback from the crypto driver. - */ -static int -ah_input_cb(struct cryptop *crp) -{ - int rplen, error, skip, protoff; - unsigned char calc[AH_ALEN_MAX]; - struct mbuf *m; - struct cryptodesc *crd; - struct auth_hash *ahx; - struct tdb_crypto *tc; - struct m_tag *mtag; - struct secasvar *sav; - struct secasindex *saidx; - u_int8_t nxt; - caddr_t ptr; - int authsize; - - crd = crp->crp_desc; - - tc = (struct tdb_crypto *) crp->crp_opaque; - KASSERT(tc != NULL, ("ah_input_cb: null opaque crypto data area!")); - skip = tc->tc_skip; - nxt = tc->tc_nxt; - protoff = tc->tc_protoff; - mtag = (struct m_tag *) tc->tc_ptr; - m = (struct mbuf *) crp->crp_buf; - - crit_enter(); - - sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi); - if (sav == NULL) { - ahstat.ahs_notdb++; - DPRINTF(("ah_input_cb: SA expired while in crypto\n")); - error = ENOBUFS; /*XXX*/ - goto bad; - } - - saidx = &sav->sah->saidx; - KASSERT(saidx->dst.sa.sa_family == AF_INET || - saidx->dst.sa.sa_family == AF_INET6, - ("ah_input_cb: unexpected protocol family %u", - saidx->dst.sa.sa_family)); - - ahx = (struct auth_hash *) sav->tdb_authalgxform; - - /* Check for crypto errors. */ - if (crp->crp_etype) { - if (sav->tdb_cryptoid != 0) - sav->tdb_cryptoid = crp->crp_sid; - - if (crp->crp_etype == EAGAIN) { - error = crypto_dispatch(crp); - crit_exit(); - return(error); - } - - ahstat.ahs_noxform++; - DPRINTF(("ah_input_cb: crypto error %d\n", crp->crp_etype)); - error = crp->crp_etype; - goto bad; - } else { - ahstat.ahs_hist[sav->alg_auth]++; - crypto_freereq(crp); /* No longer needed. */ - crp = NULL; - } - - /* Shouldn't happen... */ - if (m == NULL) { - ahstat.ahs_crypto++; - DPRINTF(("ah_input_cb: bogus returned buffer from crypto\n")); - error = EINVAL; - goto bad; - } - - /* Figure out header size. */ - rplen = HDRSIZE(sav); - authsize = AUTHSIZE(sav); - - /* Copy authenticator off the packet. */ - m_copydata(m, skip + rplen, authsize, calc); - - /* - * If we have an mtag, we don't need to verify the authenticator -- - * it has been verified by an IPsec-aware NIC. - */ - if (mtag == NULL) { - ptr = (caddr_t) (tc + 1); - - /* Verify authenticator. */ - if (bcmp(ptr + skip + rplen, calc, authsize)) { - DPRINTF(("ah_input: authentication hash mismatch " - "for packet in SA %s/%08lx\n", - ipsec_address(&saidx->dst), - (u_long) ntohl(sav->spi))); - ahstat.ahs_badauth++; - error = EACCES; - goto bad; - } - - /* Fix the Next Protocol field. */ - ((u_int8_t *) ptr)[protoff] = nxt; - - /* Copyback the saved (uncooked) network headers. */ - m_copyback(m, 0, skip, ptr); - } else { - /* Fix the Next Protocol field. */ - m_copyback(m, protoff, sizeof(u_int8_t), &nxt); - } - - kfree(tc, M_XDATA), tc = NULL; /* No longer needed */ - - /* - * Header is now authenticated. - */ - m->m_flags |= M_AUTHIPHDR|M_AUTHIPDGM; - - /* - * Update replay sequence number, if appropriate. - */ - if (sav->replay) { - u_int32_t seq; - - m_copydata(m, skip + offsetof(struct newah, ah_seq), - sizeof (seq), (caddr_t) &seq); - if (ipsec_updatereplay(ntohl(seq), sav)) { - ahstat.ahs_replay++; - error = ENOBUFS; /*XXX as above*/ - goto bad; - } - } - - /* - * Remove the AH header and authenticator from the mbuf. - */ - error = m_striphdr(m, skip, rplen + authsize); - if (error) { - DPRINTF(("ah_input_cb: mangled mbuf chain for SA %s/%08lx\n", - ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); - - ahstat.ahs_hdrops++; - goto bad; - } - - IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag); - - KEY_FREESAV(&sav); - crit_exit(); - return error; -bad: - if (sav) - KEY_FREESAV(&sav); - crit_exit(); - if (m != NULL) - m_freem(m); - if (tc != NULL) - kfree(tc, M_XDATA); - if (crp != NULL) - crypto_freereq(crp); - return error; -} - -/* - * AH output routine, called by ipsec[46]_process_packet(). - */ -static int -ah_output( - struct mbuf *m, - struct ipsecrequest *isr, - struct mbuf **mp, - int skip, - int protoff) -{ - struct secasvar *sav; - struct auth_hash *ahx; - struct cryptodesc *crda; - struct tdb_crypto *tc; - struct mbuf *mi; - struct cryptop *crp; - u_int16_t iplen; - int error, rplen, authsize, maxpacketsize, roff; - u_int8_t prot; - struct newah *ah; - - sav = isr->sav; - KASSERT(sav != NULL, ("ah_output: null SA")); - ahx = sav->tdb_authalgxform; - KASSERT(ahx != NULL, ("ah_output: null authentication xform")); - - ahstat.ahs_output++; - - /* Figure out header size. */ - rplen = HDRSIZE(sav); - - /* Check for maximum packet size violations. */ - switch (sav->sah->saidx.dst.sa.sa_family) { -#ifdef INET - case AF_INET: - maxpacketsize = IP_MAXPACKET; - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - maxpacketsize = IPV6_MAXPACKET; - break; -#endif /* INET6 */ - default: - DPRINTF(("ah_output: unknown/unsupported protocol " - "family %u, SA %s/%08lx\n", - sav->sah->saidx.dst.sa.sa_family, - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - ahstat.ahs_nopf++; - error = EPFNOSUPPORT; - goto bad; - } - authsize = AUTHSIZE(sav); - if (rplen + authsize + m->m_pkthdr.len > maxpacketsize) { - DPRINTF(("ah_output: packet in SA %s/%08lx got too big " - "(len %u, max len %u)\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi), - rplen + authsize + m->m_pkthdr.len, maxpacketsize)); - ahstat.ahs_toobig++; - error = EMSGSIZE; - goto bad; - } - - /* Update the counters. */ - ahstat.ahs_obytes += m->m_pkthdr.len - skip; - - m = m_clone(m); - if (m == NULL) { - DPRINTF(("ah_output: cannot clone mbuf chain, SA %s/%08lx\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - ahstat.ahs_hdrops++; - error = ENOBUFS; - goto bad; - } - - /* Inject AH header. */ - mi = m_makespace(m, skip, rplen + authsize, &roff); - if (mi == NULL) { - DPRINTF(("ah_output: failed to inject %u byte AH header for SA " - "%s/%08lx\n", - rplen + authsize, - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - ahstat.ahs_hdrops++; /*XXX differs from openbsd */ - error = ENOBUFS; - goto bad; - } - - /* - * The AH header is guaranteed by m_makespace() to be in - * contiguous memory, at roff bytes offset into the returned mbuf. - */ - ah = (struct newah *)(mtod(mi, caddr_t) + roff); - - /* Initialize the AH header. */ - m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &ah->ah_nxt); - ah->ah_len = (rplen + authsize - sizeof(struct ah)) / sizeof(u_int32_t); - ah->ah_reserve = 0; - ah->ah_spi = sav->spi; - - /* Zeroize authenticator. */ - m_copyback(m, skip + rplen, authsize, ipseczeroes); - - /* Insert packet replay counter, as requested. */ - if (sav->replay) { - if (sav->replay->count == ~0 && - (sav->flags & SADB_X_EXT_CYCSEQ) == 0) { - DPRINTF(("ah_output: replay counter wrapped for SA " - "%s/%08lx\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - ahstat.ahs_wrap++; - error = EINVAL; - goto bad; - } - sav->replay->count++; - ah->ah_seq = htonl(sav->replay->count); - } - - /* Get crypto descriptors. */ - crp = crypto_getreq(1); - if (crp == NULL) { - DPRINTF(("ah_output: failed to acquire crypto descriptors\n")); - ahstat.ahs_crypto++; - error = ENOBUFS; - goto bad; - } - - crda = crp->crp_desc; - - crda->crd_skip = 0; - crda->crd_inject = skip + rplen; - crda->crd_len = m->m_pkthdr.len; - - /* Authentication operation. */ - crda->crd_alg = ahx->type; - crda->crd_key = _KEYBUF(sav->key_auth); - crda->crd_klen = _KEYBITS(sav->key_auth); - - /* Allocate IPsec-specific opaque crypto info. */ - tc = kmalloc(sizeof(struct tdb_crypto) + skip, M_XDATA, - M_INTWAIT | M_ZERO | M_NULLOK); - if (tc == NULL) { - crypto_freereq(crp); - DPRINTF(("ah_output: failed to allocate tdb_crypto\n")); - ahstat.ahs_crypto++; - error = ENOBUFS; - goto bad; - } - - /* Save the skipped portion of the packet. */ - m_copydata(m, 0, skip, (caddr_t) (tc + 1)); - - /* - * Fix IP header length on the header used for - * authentication. We don't need to fix the original - * header length as it will be fixed by our caller. - */ - switch (sav->sah->saidx.dst.sa.sa_family) { -#ifdef INET - case AF_INET: - bcopy(((caddr_t)(tc + 1)) + - offsetof(struct ip, ip_len), - (caddr_t) &iplen, sizeof(u_int16_t)); - iplen = htons(ntohs(iplen) + rplen + authsize); - m_copyback(m, offsetof(struct ip, ip_len), - sizeof(u_int16_t), (caddr_t) &iplen); - break; -#endif /* INET */ - -#ifdef INET6 - case AF_INET6: - bcopy(((caddr_t)(tc + 1)) + - offsetof(struct ip6_hdr, ip6_plen), - (caddr_t) &iplen, sizeof(u_int16_t)); - iplen = htons(ntohs(iplen) + rplen + authsize); - m_copyback(m, offsetof(struct ip6_hdr, ip6_plen), - sizeof(u_int16_t), (caddr_t) &iplen); - break; -#endif /* INET6 */ - } - - /* Fix the Next Header field in saved header. */ - ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH; - - /* Update the Next Protocol field in the IP header. */ - prot = IPPROTO_AH; - m_copyback(m, protoff, sizeof(u_int8_t), (caddr_t) &prot); - - /* "Massage" the packet headers for crypto processing. */ - error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family, - skip, ahx->type, 1); - if (error != 0) { - m = NULL; /* mbuf was free'd by ah_massage_headers. */ - kfree(tc, M_XDATA); - crypto_freereq(crp); - goto bad; - } - - /* Crypto operation descriptor. */ - crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ - crp->crp_flags = CRYPTO_F_IMBUF; - crp->crp_buf = (caddr_t) m; - crp->crp_callback = ah_output_cb; - crp->crp_sid = sav->tdb_cryptoid; - crp->crp_opaque = (caddr_t) tc; - - /* These are passed as-is to the callback. */ - tc->tc_isr = isr; - tc->tc_spi = sav->spi; - tc->tc_dst = sav->sah->saidx.dst; - tc->tc_proto = sav->sah->saidx.proto; - tc->tc_skip = skip; - tc->tc_protoff = protoff; - - return crypto_dispatch(crp); -bad: - if (m) - m_freem(m); - return (error); -} - -/* - * AH output callback from the crypto driver. - */ -static int -ah_output_cb(struct cryptop *crp) -{ - int skip, protoff, error; - struct tdb_crypto *tc; - struct ipsecrequest *isr; - struct secasvar *sav; - struct mbuf *m; - caddr_t ptr; - int err; - - tc = (struct tdb_crypto *) crp->crp_opaque; - KASSERT(tc != NULL, ("ah_output_cb: null opaque data area!")); - skip = tc->tc_skip; - protoff = tc->tc_protoff; - ptr = (caddr_t) (tc + 1); - m = (struct mbuf *) crp->crp_buf; - - crit_enter(); - - isr = tc->tc_isr; - sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi); - if (sav == NULL) { - ahstat.ahs_notdb++; - DPRINTF(("ah_output_cb: SA expired while in crypto\n")); - error = ENOBUFS; /*XXX*/ - goto bad; - } - KASSERT(isr->sav == sav, ("ah_output_cb: SA changed")); - - /* Check for crypto errors. */ - if (crp->crp_etype) { - if (sav->tdb_cryptoid != 0) - sav->tdb_cryptoid = crp->crp_sid; - - if (crp->crp_etype == EAGAIN) { - KEY_FREESAV(&sav); - crit_exit(); - return crypto_dispatch(crp); - } - - ahstat.ahs_noxform++; - DPRINTF(("ah_output_cb: crypto error %d\n", crp->crp_etype)); - error = crp->crp_etype; - goto bad; - } - - /* Shouldn't happen... */ - if (m == NULL) { - ahstat.ahs_crypto++; - DPRINTF(("ah_output_cb: bogus returned buffer from crypto\n")); - error = EINVAL; - goto bad; - } - ahstat.ahs_hist[sav->alg_auth]++; - - /* - * Copy original headers (with the new protocol number) back - * in place. - */ - m_copyback(m, 0, skip, ptr); - - /* No longer needed. */ - kfree(tc, M_XDATA); - crypto_freereq(crp); - - /* NB: m is reclaimed by ipsec_process_done. */ - err = ipsec_process_done(m, isr); - KEY_FREESAV(&sav); - crit_exit(); - return err; -bad: - if (sav) - KEY_FREESAV(&sav); - crit_exit(); - if (m) - m_freem(m); - kfree(tc, M_XDATA); - crypto_freereq(crp); - return error; -} - -static struct xformsw ah_xformsw = { - XF_AH, XFT_AUTH, "IPsec AH", - ah_init, ah_zeroize, ah_input, ah_output, -}; - -static void -ah_attach(void) -{ - xform_register(&ah_xformsw); -} -SYSINIT(ah_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ah_attach, NULL); diff --git a/sys/netproto/ipsec/xform_esp.c b/sys/netproto/ipsec/xform_esp.c deleted file mode 100644 index 66f5a8680e..0000000000 --- a/sys/netproto/ipsec/xform_esp.c +++ /dev/null @@ -1,971 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/xform_esp.c,v 1.2.2.2 2003/02/26 00:14:05 sam Exp $ */ -/* $OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */ -/* - * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). - * - * The original version of this code was written by John Ioannidis - * for BSD/OS in Athens, Greece, in November 1995. - * - * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, - * by Angelos D. Keromytis. - * - * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis - * and Niels Provos. - * - * Additional features in 1999 by Angelos D. Keromytis. - * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, - * Angelos D. Keromytis and Niels Provos. - * Copyright (c) 2001 Angelos D. Keromytis. - * - * Permission to use, copy, and modify this software with or without fee - * is hereby granted, provided that this entire notice is included in - * all copies of any software which is or includes a copy or - * modification of this software. - * You may use this code under the GNU public license if you so wish. Please - * contribute changes back to the authors under this freer than GPL license - * so that we may further the use of strong encryption without limitations to - * all. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE - * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR - * PURPOSE. - */ -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef INET6 -#include -#include -#include -#endif - -#include -#include - -#include -#include - -int esp_enable = 1; -struct espstat espstat; - -SYSCTL_DECL(_net_inet_esp); -SYSCTL_INT(_net_inet_esp, OID_AUTO, - esp_enable, CTLFLAG_RW, &esp_enable, 0, ""); -SYSCTL_STRUCT(_net_inet_esp, IPSECCTL_STATS, - stats, CTLFLAG_RD, &espstat, espstat, ""); - -static int esp_max_ivlen; /* max iv length over all algorithms */ - -static int esp_input_cb(struct cryptop *op); -static int esp_output_cb(struct cryptop *crp); - -/* - * NB: this is public for use by the PF_KEY support. - * NB: if you add support here; be sure to add code to esp_attach below! - */ -struct enc_xform * -esp_algorithm_lookup(int alg) -{ - if (alg >= ESP_ALG_MAX) - return NULL; - switch (alg) { - case SADB_EALG_DESCBC: - return &enc_xform_des; - case SADB_EALG_3DESCBC: - return &enc_xform_3des; - case SADB_X_EALG_AES: - return &enc_xform_rijndael128; - case SADB_X_EALG_BLOWFISHCBC: - return &enc_xform_blf; - case SADB_X_EALG_CAST128CBC: - return &enc_xform_cast5; - case SADB_X_EALG_SKIPJACK: - return &enc_xform_skipjack; - case SADB_EALG_NULL: - return &enc_xform_null; - } - return NULL; -} - -size_t -esp_hdrsiz(struct secasvar *sav) -{ - size_t size; - - if (sav != NULL) { - /*XXX not right for null algorithm--does it matter??*/ - KASSERT(sav->tdb_encalgxform != NULL, - ("esp_hdrsiz: SA with null xform")); - if (sav->flags & SADB_X_EXT_OLD) - size = sizeof (struct esp); - else - size = sizeof (struct newesp); - size += sav->tdb_encalgxform->blocksize + 9; - /*XXX need alg check???*/ - if (sav->tdb_authalgxform != NULL && sav->replay) - size += ah_hdrsiz(sav); - } else { - /* - * base header size - * + max iv length for CBC mode - * + max pad length - * + sizeof (pad length field) - * + sizeof (next header field) - * + max icv supported. - */ - size = sizeof (struct newesp) + esp_max_ivlen + 9 + 16; - } - return size; -} - -/* - * esp_init() is called when an SPI is being set up. - */ -static int -esp_init(struct secasvar *sav, struct xformsw *xsp) -{ - struct enc_xform *txform; - struct cryptoini cria, crie; - int keylen; - int error; - - txform = esp_algorithm_lookup(sav->alg_enc); - if (txform == NULL) { - DPRINTF(("esp_init: unsupported encryption algorithm %d\n", - sav->alg_enc)); - return EINVAL; - } - if (sav->key_enc == NULL) { - DPRINTF(("esp_init: no encoding key for %s algorithm\n", - txform->name)); - return EINVAL; - } - if ((sav->flags&(SADB_X_EXT_OLD|SADB_X_EXT_IV4B)) == SADB_X_EXT_IV4B) { - DPRINTF(("esp_init: 4-byte IV not supported with protocol\n")); - return EINVAL; - } - keylen = _KEYLEN(sav->key_enc); - if (txform->minkey > keylen || keylen > txform->maxkey) { - DPRINTF(("esp_init: invalid key length %u, must be in " - "the range [%u..%u] for algorithm %s\n", - keylen, txform->minkey, txform->maxkey, - txform->name)); - return EINVAL; - } - - /* - * NB: The null xform needs a non-zero blocksize to keep the - * crypto code happy but if we use it to set ivlen then - * the ESP header will be processed incorrectly. The - * compromise is to force it to zero here. - */ - sav->ivlen = (txform == &enc_xform_null ? 0 : txform->blocksize); - sav->iv = (caddr_t) kmalloc(sav->ivlen, M_XDATA, M_WAITOK); - key_randomfill(sav->iv, sav->ivlen); /*XXX*/ - - /* - * Setup AH-related state. - */ - if (sav->alg_auth != 0) { - error = ah_init0(sav, xsp, &cria); - if (error) - return error; - } - - /* NB: override anything set in ah_init0 */ - sav->tdb_xform = xsp; - sav->tdb_encalgxform = txform; - - /* Initialize crypto session. */ - bzero(&crie, sizeof (crie)); - crie.cri_alg = sav->tdb_encalgxform->type; - crie.cri_klen = _KEYBITS(sav->key_enc); - crie.cri_key = _KEYBUF(sav->key_enc); - /* XXX Rounds ? */ - - if (sav->tdb_authalgxform && sav->tdb_encalgxform) { - /* init both auth & enc */ - crie.cri_next = &cria; - error = crypto_newsession(&sav->tdb_cryptoid, - &crie, crypto_support); - } else if (sav->tdb_encalgxform) { - error = crypto_newsession(&sav->tdb_cryptoid, - &crie, crypto_support); - } else if (sav->tdb_authalgxform) { - error = crypto_newsession(&sav->tdb_cryptoid, - &cria, crypto_support); - } else { - /* XXX cannot happen? */ - DPRINTF(("esp_init: no encoding OR authentication xform!\n")); - error = EINVAL; - } - return error; -} - -/* - * Paranoia. - */ -static int -esp_zeroize(struct secasvar *sav) -{ - /* NB: ah_zerorize free's the crypto session state */ - int error = ah_zeroize(sav); - - if (sav->key_enc) - bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc)); - /* NB: sav->iv is freed elsewhere, even though we malloc it! */ - sav->tdb_encalgxform = NULL; - sav->tdb_xform = NULL; - return error; -} - -/* - * ESP input processing, called (eventually) through the protocol switch. - */ -static int -esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) -{ - struct auth_hash *esph; - struct enc_xform *espx; - struct tdb_ident *tdbi; - struct tdb_crypto *tc; - int plen, alen, hlen; - struct m_tag *mtag; - struct newesp *esp; - - struct cryptodesc *crde; - struct cryptop *crp; - - KASSERT(sav != NULL, ("esp_input: null SA")); - KASSERT(sav->tdb_encalgxform != NULL, - ("esp_input: null encoding xform")); - KASSERT((skip&3) == 0 && (m->m_pkthdr.len&3) == 0, - ("esp_input: misaligned packet, skip %u pkt len %u", - skip, m->m_pkthdr.len)); - - /* XXX don't pullup, just copy header */ - IP6_EXTHDR_GET(esp, struct newesp *, m, skip, sizeof (struct newesp)); - - esph = sav->tdb_authalgxform; - espx = sav->tdb_encalgxform; - - /* Determine the ESP header length */ - if (sav->flags & SADB_X_EXT_OLD) - hlen = sizeof (struct esp) + sav->ivlen; - else - hlen = sizeof (struct newesp) + sav->ivlen; - /* Authenticator hash size */ - alen = esph ? AH_HMAC_HASHLEN : 0; - - /* - * Verify payload length is multiple of encryption algorithm - * block size. - * - * NB: This works for the null algorithm because the blocksize - * is 4 and all packets must be 4-byte aligned regardless - * of the algorithm. - */ - plen = m->m_pkthdr.len - (skip + hlen + alen); - if ((plen & (espx->blocksize - 1)) || (plen <= 0)) { - DPRINTF(("esp_input: " - "payload of %d octets not a multiple of %d octets," - " SA %s/%08lx\n", - plen, espx->blocksize, - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - espstat.esps_badilen++; - m_freem(m); - return EINVAL; - } - - /* - * Check sequence number. - */ - if (esph && sav->replay && !ipsec_chkreplay(ntohl(esp->esp_seq), sav)) { - DPRINTF(("esp_input: packet replay check for %s\n", - ipsec_logsastr(sav))); /*XXX*/ - espstat.esps_replay++; - m_freem(m); - return ENOBUFS; /*XXX*/ - } - - /* Update the counters */ - espstat.esps_ibytes += m->m_pkthdr.len - skip - hlen - alen; - - /* Find out if we've already done crypto */ - for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL); - mtag != NULL; - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) { - tdbi = (struct tdb_ident *)m_tag_data(mtag); - if (tdbi->proto == sav->sah->saidx.proto && - tdbi->spi == sav->spi && - !bcmp(&tdbi->dst, &sav->sah->saidx.dst, - sizeof(union sockaddr_union))) - break; - } - - /* Get crypto descriptors */ - crp = crypto_getreq(esph && espx ? 2 : 1); - if (crp == NULL) { - DPRINTF(("esp_input: failed to acquire crypto descriptors\n")); - espstat.esps_crypto++; - m_freem(m); - return ENOBUFS; - } - - /* Get IPsec-specific opaque pointer */ - if (esph == NULL || mtag != NULL) - tc = kmalloc(sizeof(struct tdb_crypto), - M_XDATA, M_INTWAIT | M_ZERO | M_NULLOK); - else - tc = kmalloc(sizeof(struct tdb_crypto) + alen, - M_XDATA, M_INTWAIT | M_ZERO | M_NULLOK); - if (tc == NULL) { - crypto_freereq(crp); - DPRINTF(("esp_input: failed to allocate tdb_crypto\n")); - espstat.esps_crypto++; - m_freem(m); - return ENOBUFS; - } - - tc->tc_ptr = (caddr_t) mtag; - - if (esph) { - struct cryptodesc *crda = crp->crp_desc; - - KASSERT(crda != NULL, ("esp_input: null ah crypto descriptor")); - - /* Authentication descriptor */ - crda->crd_skip = skip; - crda->crd_len = m->m_pkthdr.len - (skip + alen); - crda->crd_inject = m->m_pkthdr.len - alen; - - crda->crd_alg = esph->type; - crda->crd_key = _KEYBUF(sav->key_auth); - crda->crd_klen = _KEYBITS(sav->key_auth); - - /* Copy the authenticator */ - if (mtag == NULL) - m_copydata(m, m->m_pkthdr.len - alen, alen, - (caddr_t) (tc + 1)); - - /* Chain authentication request */ - crde = crda->crd_next; - } else { - crde = crp->crp_desc; - } - - /* Crypto operation descriptor */ - crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ - crp->crp_flags = CRYPTO_F_IMBUF; - crp->crp_buf = (caddr_t) m; - crp->crp_callback = esp_input_cb; - crp->crp_sid = sav->tdb_cryptoid; - crp->crp_opaque = (caddr_t) tc; - - /* These are passed as-is to the callback */ - tc->tc_spi = sav->spi; - tc->tc_dst = sav->sah->saidx.dst; - tc->tc_proto = sav->sah->saidx.proto; - tc->tc_protoff = protoff; - tc->tc_skip = skip; - - /* Decryption descriptor */ - if (espx) { - KASSERT(crde != NULL, ("esp_input: null esp crypto descriptor")); - crde->crd_skip = skip + hlen; - crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); - crde->crd_inject = skip + hlen - sav->ivlen; - - crde->crd_alg = espx->type; - crde->crd_key = _KEYBUF(sav->key_enc); - crde->crd_klen = _KEYBITS(sav->key_enc); - /* XXX Rounds ? */ - } - - if (mtag == NULL) - return crypto_dispatch(crp); - else - return esp_input_cb(crp); -} - -#ifdef INET6 -#define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) do { \ - if (saidx->dst.sa.sa_family == AF_INET6) { \ - error = ipsec6_common_input_cb(m, sav, skip, protoff, mtag); \ - } else { \ - error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag); \ - } \ -} while (0) -#else -#define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) \ - (error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag)) -#endif - -/* - * ESP input callback from the crypto driver. - */ -static int -esp_input_cb(struct cryptop *crp) -{ - u_int8_t lastthree[3], aalg[AH_HMAC_HASHLEN]; - int hlen, skip, protoff, error; - struct mbuf *m; - struct cryptodesc *crd; - struct auth_hash *esph; - struct enc_xform *espx; - struct tdb_crypto *tc; - struct m_tag *mtag; - struct secasvar *sav; - struct secasindex *saidx; - caddr_t ptr; - - crd = crp->crp_desc; - KASSERT(crd != NULL, ("esp_input_cb: null crypto descriptor!")); - - tc = (struct tdb_crypto *) crp->crp_opaque; - KASSERT(tc != NULL, ("esp_input_cb: null opaque crypto data area!")); - skip = tc->tc_skip; - protoff = tc->tc_protoff; - mtag = (struct m_tag *) tc->tc_ptr; - m = (struct mbuf *) crp->crp_buf; - - crit_enter(); - - sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi); - if (sav == NULL) { - espstat.esps_notdb++; - DPRINTF(("esp_input_cb: SA expired while in crypto " - "(SA %s/%08lx proto %u)\n", ipsec_address(&tc->tc_dst), - (u_long) ntohl(tc->tc_spi), tc->tc_proto)); - error = ENOBUFS; /*XXX*/ - goto bad; - } - - saidx = &sav->sah->saidx; - KASSERT(saidx->dst.sa.sa_family == AF_INET || - saidx->dst.sa.sa_family == AF_INET6, - ("ah_input_cb: unexpected protocol family %u", - saidx->dst.sa.sa_family)); - - esph = sav->tdb_authalgxform; - espx = sav->tdb_encalgxform; - - /* Check for crypto errors */ - if (crp->crp_etype) { - /* Reset the session ID */ - if (sav->tdb_cryptoid != 0) - sav->tdb_cryptoid = crp->crp_sid; - - if (crp->crp_etype == EAGAIN) { - KEY_FREESAV(&sav); - crit_exit(); - return crypto_dispatch(crp); - } - - espstat.esps_noxform++; - DPRINTF(("esp_input_cb: crypto error %d\n", crp->crp_etype)); - error = crp->crp_etype; - goto bad; - } - - /* Shouldn't happen... */ - if (m == NULL) { - espstat.esps_crypto++; - DPRINTF(("esp_input_cb: bogus returned buffer from crypto\n")); - error = EINVAL; - goto bad; - } - espstat.esps_hist[sav->alg_enc]++; - - /* If authentication was performed, check now. */ - if (esph != NULL) { - /* - * If we have a tag, it means an IPsec-aware NIC did - * the verification for us. Otherwise we need to - * check the authentication calculation. - */ - ahstat.ahs_hist[sav->alg_auth]++; - if (mtag == NULL) { - /* Copy the authenticator from the packet */ - m_copydata(m, m->m_pkthdr.len - esph->blocksize, - esph->blocksize, aalg); - - ptr = (caddr_t) (tc + 1); - - /* Verify authenticator */ - if (bcmp(ptr, aalg, esph->blocksize) != 0) { - DPRINTF(("esp_input_cb: " - "authentication hash mismatch for packet in SA %s/%08lx\n", - ipsec_address(&saidx->dst), - (u_long) ntohl(sav->spi))); - espstat.esps_badauth++; - error = EACCES; - goto bad; - } - } - - /* Remove trailing authenticator */ - m_adj(m, -(esph->blocksize)); - } - - /* Release the crypto descriptors */ - kfree(tc, M_XDATA), tc = NULL; - crypto_freereq(crp), crp = NULL; - - /* - * Packet is now decrypted. - */ - m->m_flags |= M_DECRYPTED; - - /* - * Update replay sequence number, if appropriate. - */ - if (sav->replay) { - u_int32_t seq; - - m_copydata(m, skip + offsetof(struct newesp, esp_seq), - sizeof (seq), (caddr_t) &seq); - if (ipsec_updatereplay(ntohl(seq), sav)) { - DPRINTF(("%s: packet replay check for %s\n", __func__, - ipsec_logsastr(sav))); - espstat.esps_replay++; - error = ENOBUFS; - goto bad; - } - } - - /* Determine the ESP header length */ - if (sav->flags & SADB_X_EXT_OLD) - hlen = sizeof (struct esp) + sav->ivlen; - else - hlen = sizeof (struct newesp) + sav->ivlen; - - /* Remove the ESP header and IV from the mbuf. */ - error = m_striphdr(m, skip, hlen); - if (error) { - espstat.esps_hdrops++; - DPRINTF(("esp_input_cb: bad mbuf chain, SA %s/%08lx\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - goto bad; - } - - /* Save the last three bytes of decrypted data */ - m_copydata(m, m->m_pkthdr.len - 3, 3, lastthree); - - /* Verify pad length */ - if (lastthree[1] + 2 > m->m_pkthdr.len - skip) { - espstat.esps_badilen++; - DPRINTF(("esp_input_cb: invalid padding length %d " - "for %u byte packet in SA %s/%08lx\n", - lastthree[1], m->m_pkthdr.len - skip, - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - error = EINVAL; - goto bad; - } - - /* Verify correct decryption by checking the last padding bytes */ - if ((sav->flags & SADB_X_EXT_PMASK) != SADB_X_EXT_PRAND) { - if (lastthree[1] != lastthree[0] && lastthree[1] != 0) { - espstat.esps_badenc++; - DPRINTF(("esp_input_cb: decryption failed " - "for packet in SA %s/%08lx\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); -DPRINTF(("esp_input_cb: %x %x\n", lastthree[0], lastthree[1])); - error = EINVAL; - goto bad; - } - } - - /* Trim the mbuf chain to remove trailing authenticator and padding */ - m_adj(m, -(lastthree[1] + 2)); - - /* Restore the Next Protocol field */ - m_copyback(m, protoff, sizeof (u_int8_t), lastthree + 2); - - IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag); - - KEY_FREESAV(&sav); - crit_exit(); - return error; -bad: - if (sav) - KEY_FREESAV(&sav); - crit_exit(); - if (m != NULL) - m_freem(m); - if (tc != NULL) - kfree(tc, M_XDATA); - if (crp != NULL) - crypto_freereq(crp); - return error; -} - -/* - * ESP output routine, called by ipsec[46]_process_packet(). - */ -static int -esp_output( - struct mbuf *m, - struct ipsecrequest *isr, - struct mbuf **mp, - int skip, - int protoff -) -{ - struct enc_xform *espx; - struct auth_hash *esph; - int hlen, rlen, plen, padding, blks, alen, i, roff; - struct mbuf *mo = NULL; - struct tdb_crypto *tc; - struct secasvar *sav; - struct secasindex *saidx; - unsigned char *pad; - u_int8_t prot; - int error, maxpacketsize; - - struct cryptodesc *crde = NULL, *crda = NULL; - struct cryptop *crp; - - sav = isr->sav; - KASSERT(sav != NULL, ("esp_output: null SA")); - esph = sav->tdb_authalgxform; - espx = sav->tdb_encalgxform; - KASSERT(espx != NULL, ("esp_output: null encoding xform")); - - if (sav->flags & SADB_X_EXT_OLD) - hlen = sizeof (struct esp) + sav->ivlen; - else - hlen = sizeof (struct newesp) + sav->ivlen; - - rlen = m->m_pkthdr.len - skip; /* Raw payload length. */ - /* - * NB: The null encoding transform has a blocksize of 4 - * so that headers are properly aligned. - */ - blks = espx->blocksize; /* IV blocksize */ - - /* XXX clamp padding length a la KAME??? */ - padding = ((blks - ((rlen + 2) % blks)) % blks) + 2; - plen = rlen + padding; /* Padded payload length. */ - - if (esph) - alen = AH_HMAC_HASHLEN; - else - alen = 0; - - espstat.esps_output++; - - saidx = &sav->sah->saidx; - /* Check for maximum packet size violations. */ - switch (saidx->dst.sa.sa_family) { -#ifdef INET - case AF_INET: - maxpacketsize = IP_MAXPACKET; - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - maxpacketsize = IPV6_MAXPACKET; - break; -#endif /* INET6 */ - default: - DPRINTF(("esp_output: unknown/unsupported protocol " - "family %d, SA %s/%08lx\n", - saidx->dst.sa.sa_family, ipsec_address(&saidx->dst), - (u_long) ntohl(sav->spi))); - espstat.esps_nopf++; - error = EPFNOSUPPORT; - goto bad; - } - if (skip + hlen + rlen + padding + alen > maxpacketsize) { - DPRINTF(("esp_output: packet in SA %s/%08lx got too big " - "(len %u, max len %u)\n", - ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi), - skip + hlen + rlen + padding + alen, maxpacketsize)); - espstat.esps_toobig++; - error = EMSGSIZE; - goto bad; - } - - /* Update the counters. */ - espstat.esps_obytes += m->m_pkthdr.len - skip; - - m = m_clone(m); - if (m == NULL) { - DPRINTF(("esp_output: cannot clone mbuf chain, SA %s/%08lx\n", - ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); - espstat.esps_hdrops++; - error = ENOBUFS; - goto bad; - } - - /* Inject ESP header. */ - mo = m_makespace(m, skip, hlen, &roff); - if (mo == NULL) { - DPRINTF(("esp_output: failed to inject %u byte ESP hdr for SA " - "%s/%08lx\n", - hlen, ipsec_address(&saidx->dst), - (u_long) ntohl(sav->spi))); - espstat.esps_hdrops++; /* XXX diffs from openbsd */ - error = ENOBUFS; - goto bad; - } - - /* Initialize ESP header. */ - bcopy((caddr_t) &sav->spi, mtod(mo, caddr_t) + roff, sizeof(u_int32_t)); - if (sav->replay) { - u_int32_t replay = htonl(++(sav->replay->count)); - bcopy((caddr_t) &replay, - mtod(mo, caddr_t) + roff + sizeof(u_int32_t), - sizeof(u_int32_t)); - } - - /* - * Add padding -- better to do it ourselves than use the crypto engine, - * although if/when we support compression, we'd have to do that. - */ - pad = (u_char *) m_pad(m, padding + alen); - if (pad == NULL) { - DPRINTF(("esp_output: m_pad failed for SA %s/%08lx\n", - ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); - m = NULL; /* NB: free'd by m_pad */ - error = ENOBUFS; - goto bad; - } - - /* - * Add padding: random, zero, or self-describing. - * XXX catch unexpected setting - */ - switch (sav->flags & SADB_X_EXT_PMASK) { - case SADB_X_EXT_PRAND: - read_random(pad, padding - 2); - break; - case SADB_X_EXT_PZERO: - bzero(pad, padding - 2); - break; - case SADB_X_EXT_PSEQ: - for (i = 0; i < padding - 2; i++) - pad[i] = i+1; - break; - } - - /* Fix padding length and Next Protocol in padding itself. */ - pad[padding - 2] = padding - 2; - m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1); - - /* Fix Next Protocol in IPv4/IPv6 header. */ - prot = IPPROTO_ESP; - m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot); - - /* Get crypto descriptors. */ - crp = crypto_getreq(esph && espx ? 2 : 1); - if (crp == NULL) { - DPRINTF(("esp_output: failed to acquire crypto descriptors\n")); - espstat.esps_crypto++; - error = ENOBUFS; - goto bad; - } - - if (espx) { - crde = crp->crp_desc; - crda = crde->crd_next; - - /* Encryption descriptor. */ - crde->crd_skip = skip + hlen; - crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); - crde->crd_flags = CRD_F_ENCRYPT; - crde->crd_inject = skip + hlen - sav->ivlen; - - /* Encryption operation. */ - crde->crd_alg = espx->type; - crde->crd_key = _KEYBUF(sav->key_enc); - crde->crd_klen = _KEYBITS(sav->key_enc); - /* XXX Rounds ? */ - } else - crda = crp->crp_desc; - - /* IPsec-specific opaque crypto info. */ - tc = kmalloc(sizeof(struct tdb_crypto), - M_XDATA, M_INTWAIT | M_ZERO | M_NULLOK); - if (tc == NULL) { - crypto_freereq(crp); - DPRINTF(("esp_output: failed to allocate tdb_crypto\n")); - espstat.esps_crypto++; - error = ENOBUFS; - goto bad; - } - - /* Callback parameters */ - tc->tc_isr = isr; - tc->tc_spi = sav->spi; - tc->tc_dst = saidx->dst; - tc->tc_proto = saidx->proto; - - /* Crypto operation descriptor. */ - crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ - crp->crp_flags = CRYPTO_F_IMBUF; - crp->crp_buf = (caddr_t) m; - crp->crp_callback = esp_output_cb; - crp->crp_opaque = (caddr_t) tc; - crp->crp_sid = sav->tdb_cryptoid; - - if (esph) { - /* Authentication descriptor. */ - crda->crd_skip = skip; - crda->crd_len = m->m_pkthdr.len - (skip + alen); - crda->crd_inject = m->m_pkthdr.len - alen; - - /* Authentication operation. */ - crda->crd_alg = esph->type; - crda->crd_key = _KEYBUF(sav->key_auth); - crda->crd_klen = _KEYBITS(sav->key_auth); - } - - return crypto_dispatch(crp); -bad: - if (m) - m_freem(m); - return (error); -} - -/* - * ESP output callback from the crypto driver. - */ -static int -esp_output_cb(struct cryptop *crp) -{ - struct tdb_crypto *tc; - struct ipsecrequest *isr; - struct secasvar *sav; - struct mbuf *m; - int err, error; - - tc = (struct tdb_crypto *) crp->crp_opaque; - KASSERT(tc != NULL, ("esp_output_cb: null opaque data area!")); - m = (struct mbuf *) crp->crp_buf; - - crit_enter(); - - isr = tc->tc_isr; - sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi); - if (sav == NULL) { - espstat.esps_notdb++; - DPRINTF(("esp_output_cb: SA expired while in crypto " - "(SA %s/%08lx proto %u)\n", ipsec_address(&tc->tc_dst), - (u_long) ntohl(tc->tc_spi), tc->tc_proto)); - error = ENOBUFS; /*XXX*/ - goto bad; - } - KASSERT(isr->sav == sav, - ("esp_output_cb: SA changed was %p now %p\n", isr->sav, sav)); - - /* Check for crypto errors. */ - if (crp->crp_etype) { - /* Reset session ID. */ - if (sav->tdb_cryptoid != 0) - sav->tdb_cryptoid = crp->crp_sid; - - if (crp->crp_etype == EAGAIN) { - KEY_FREESAV(&sav); - crit_exit(); - return crypto_dispatch(crp); - } - - espstat.esps_noxform++; - DPRINTF(("esp_output_cb: crypto error %d\n", crp->crp_etype)); - error = crp->crp_etype; - goto bad; - } - - /* Shouldn't happen... */ - if (m == NULL) { - espstat.esps_crypto++; - DPRINTF(("esp_output_cb: bogus returned buffer from crypto\n")); - error = EINVAL; - goto bad; - } - espstat.esps_hist[sav->alg_enc]++; - if (sav->tdb_authalgxform != NULL) - ahstat.ahs_hist[sav->alg_auth]++; - - /* Release crypto descriptors. */ - kfree(tc, M_XDATA); - crypto_freereq(crp); - - /* NB: m is reclaimed by ipsec_process_done. */ - err = ipsec_process_done(m, isr); - KEY_FREESAV(&sav); - crit_exit(); - return err; -bad: - if (sav) - KEY_FREESAV(&sav); - crit_exit(); - if (m) - m_freem(m); - kfree(tc, M_XDATA); - crypto_freereq(crp); - return error; -} - -static struct xformsw esp_xformsw = { - XF_ESP, XFT_CONF|XFT_AUTH, "IPsec ESP", - esp_init, esp_zeroize, esp_input, - esp_output -}; - -static void -esp_attach(void) -{ -#define MAXIV(xform) \ - if (xform.blocksize > esp_max_ivlen) \ - esp_max_ivlen = xform.blocksize \ - - esp_max_ivlen = 0; - MAXIV(enc_xform_des); /* SADB_EALG_DESCBC */ - MAXIV(enc_xform_3des); /* SADB_EALG_3DESCBC */ - MAXIV(enc_xform_rijndael128); /* SADB_X_EALG_AES */ - MAXIV(enc_xform_blf); /* SADB_X_EALG_BLOWFISHCBC */ - MAXIV(enc_xform_cast5); /* SADB_X_EALG_CAST128CBC */ - MAXIV(enc_xform_skipjack); /* SADB_X_EALG_SKIPJACK */ - MAXIV(enc_xform_null); /* SADB_EALG_NULL */ - - xform_register(&esp_xformsw); -#undef MAXIV -} -SYSINIT(esp_xform_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, esp_attach, NULL); diff --git a/sys/netproto/ipsec/xform_ipcomp.c b/sys/netproto/ipsec/xform_ipcomp.c deleted file mode 100644 index 97cb7e4440..0000000000 --- a/sys/netproto/ipsec/xform_ipcomp.c +++ /dev/null @@ -1,618 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/xform_ipcomp.c,v 1.1.4.2 2003/02/26 00:14:06 sam Exp $ */ -/* $OpenBSD: ip_ipcomp.c,v 1.1 2001/07/05 12:08:52 jjbg Exp $ */ - -/* - * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org) - * - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -/* IP payload compression protocol (IPComp), see RFC 2393 */ -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#ifdef INET6 -#include -#include -#endif - -#include -#include - -#include -#include - -#include -#include -#include - -int ipcomp_enable = 0; -struct ipcompstat ipcompstat; - -SYSCTL_DECL(_net_inet_ipcomp); -SYSCTL_INT(_net_inet_ipcomp, OID_AUTO, - ipcomp_enable, CTLFLAG_RW, &ipcomp_enable, 0, ""); -SYSCTL_STRUCT(_net_inet_ipcomp, IPSECCTL_STATS, - stats, CTLFLAG_RD, &ipcompstat, ipcompstat, ""); - -static int ipcomp_input_cb(struct cryptop *crp); -static int ipcomp_output_cb(struct cryptop *crp); - -struct comp_algo * -ipcomp_algorithm_lookup(int alg) -{ - if (alg >= IPCOMP_ALG_MAX) - return NULL; - switch (alg) { - case SADB_X_CALG_DEFLATE: - return &comp_algo_deflate; - } - return NULL; -} - -/* - * ipcomp_init() is called when an CPI is being set up. - */ -static int -ipcomp_init(struct secasvar *sav, struct xformsw *xsp) -{ - struct comp_algo *tcomp; - struct cryptoini cric; - - /* NB: algorithm really comes in alg_enc and not alg_comp! */ - tcomp = ipcomp_algorithm_lookup(sav->alg_enc); - if (tcomp == NULL) { - DPRINTF(("ipcomp_init: unsupported compression algorithm %d\n", - sav->alg_comp)); - return EINVAL; - } - sav->alg_comp = sav->alg_enc; /* set for doing histogram */ - sav->tdb_xform = xsp; - sav->tdb_compalgxform = tcomp; - - /* Initialize crypto session */ - bzero(&cric, sizeof (cric)); - cric.cri_alg = sav->tdb_compalgxform->type; - - return crypto_newsession(&sav->tdb_cryptoid, &cric, crypto_support); -} - -/* - * ipcomp_zeroize() used when IPCA is deleted - */ -static int -ipcomp_zeroize(struct secasvar *sav) -{ - int err; - - err = crypto_freesession(sav->tdb_cryptoid); - sav->tdb_cryptoid = 0; - return err; -} - -/* - * ipcomp_input() gets called to uncompress an input packet - */ -static int -ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) -{ - struct tdb_crypto *tc; - struct cryptodesc *crdc; - struct cryptop *crp; - struct ipcomp *ipcomp; - caddr_t addr; - int hlen = IPCOMP_HLENGTH; - - /* - * Check that the next header of the IPComp is not IPComp again, before - * doing any real work. Given it is not possible to do double - * compression it means someone is playing tricks on us. - */ - if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) { - ipcompstat.ipcomps_hdrops++; /*XXX*/ - DPRINTF(("%s: m_pullup failed\n", __func__)); - return (ENOBUFS); - } - addr = (caddr_t) mtod(m, struct ip *) + skip; - ipcomp = (struct ipcomp *)addr; - if (ipcomp->comp_nxt == IPPROTO_IPCOMP) { - m_freem(m); - ipcompstat.ipcomps_pdrops++; /* XXX have our own stats? */ - DPRINTF(("%s: recursive compression detected\n", __func__)); - return (EINVAL); - } - - /* Get crypto descriptors */ - crp = crypto_getreq(1); - if (crp == NULL) { - m_freem(m); - DPRINTF(("ipcomp_input: no crypto descriptors\n")); - ipcompstat.ipcomps_crypto++; - return ENOBUFS; - } - /* Get IPsec-specific opaque pointer */ - tc = kmalloc(sizeof (*tc), M_XDATA, - M_INTWAIT | M_ZERO | M_NULLOK); - if (tc == NULL) { - m_freem(m); - crypto_freereq(crp); - DPRINTF(("ipcomp_input: cannot allocate tdb_crypto\n")); - ipcompstat.ipcomps_crypto++; - return ENOBUFS; - } - crdc = crp->crp_desc; - - crdc->crd_skip = skip + hlen; - crdc->crd_len = m->m_pkthdr.len - (skip + hlen); - crdc->crd_inject = skip; - - tc->tc_ptr = 0; - - /* Decompression operation */ - crdc->crd_alg = sav->tdb_compalgxform->type; - - /* Crypto operation descriptor */ - crp->crp_ilen = m->m_pkthdr.len - (skip + hlen); - crp->crp_flags = CRYPTO_F_IMBUF; - crp->crp_buf = (caddr_t) m; - crp->crp_callback = ipcomp_input_cb; - crp->crp_sid = sav->tdb_cryptoid; - crp->crp_opaque = (caddr_t) tc; - - /* These are passed as-is to the callback */ - tc->tc_spi = sav->spi; - tc->tc_dst = sav->sah->saidx.dst; - tc->tc_proto = sav->sah->saidx.proto; - tc->tc_protoff = protoff; - tc->tc_skip = skip; - - return crypto_dispatch(crp); -} - -#ifdef INET6 -#define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) do { \ - if (saidx->dst.sa.sa_family == AF_INET6) { \ - error = ipsec6_common_input_cb(m, sav, skip, protoff, mtag); \ - } else { \ - error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag); \ - } \ -} while (0) -#else -#define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) \ - (error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag)) -#endif - -/* - * IPComp input callback from the crypto driver. - */ -static int -ipcomp_input_cb(struct cryptop *crp) -{ - struct tdb_crypto *tc; - int skip, protoff; - struct mbuf *m; - struct secasvar *sav; - struct secasindex *saidx; - int hlen = IPCOMP_HLENGTH, error, clen; - u_int8_t nproto; - caddr_t addr; - - tc = (struct tdb_crypto *) crp->crp_opaque; - KASSERT(tc != NULL, ("ipcomp_input_cb: null opaque crypto data area!")); - skip = tc->tc_skip; - protoff = tc->tc_protoff; - m = (struct mbuf *) crp->crp_buf; - - crit_enter(); - - sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi); - if (sav == NULL) { - ipcompstat.ipcomps_notdb++; - DPRINTF(("ipcomp_input_cb: SA expired while in crypto\n")); - error = ENOBUFS; /*XXX*/ - goto bad; - } - - saidx = &sav->sah->saidx; - KASSERT(saidx->dst.sa.sa_family == AF_INET || - saidx->dst.sa.sa_family == AF_INET6, - ("ah_input_cb: unexpected protocol family %u", - saidx->dst.sa.sa_family)); - - /* Check for crypto errors */ - if (crp->crp_etype) { - /* Reset the session ID */ - if (sav->tdb_cryptoid != 0) - sav->tdb_cryptoid = crp->crp_sid; - - if (crp->crp_etype == EAGAIN) { - KEY_FREESAV(&sav); - crit_exit(); - return crypto_dispatch(crp); - } - - ipcompstat.ipcomps_noxform++; - DPRINTF(("ipcomp_input_cb: crypto error %d\n", crp->crp_etype)); - error = crp->crp_etype; - goto bad; - } - /* Shouldn't happen... */ - if (m == NULL) { - ipcompstat.ipcomps_crypto++; - DPRINTF(("ipcomp_input_cb: null mbuf returned from crypto\n")); - error = EINVAL; - goto bad; - } - ipcompstat.ipcomps_hist[sav->alg_comp]++; - - clen = crp->crp_olen; /* Length of data after processing */ - - /* Release the crypto descriptors */ - kfree(tc, M_XDATA), tc = NULL; - crypto_freereq(crp), crp = NULL; - - /* In case it's not done already, adjust the size of the mbuf chain */ - m->m_pkthdr.len = clen + hlen + skip; - - if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) { - ipcompstat.ipcomps_hdrops++; /*XXX*/ - DPRINTF(("ipcomp_input_cb: m_pullup failed\n")); - error = EINVAL; /*XXX*/ - goto bad; - } - - /* Keep the next protocol field */ - addr = (caddr_t) mtod(m, struct ip *) + skip; - nproto = ((struct ipcomp *) addr)->comp_nxt; - - /* Remove the IPCOMP header */ - error = m_striphdr(m, skip, hlen); - if (error) { - ipcompstat.ipcomps_hdrops++; - DPRINTF(("ipcomp_input_cb: bad mbuf chain, IPCA %s/%08lx\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - goto bad; - } - - /* Restore the Next Protocol field */ - m_copyback(m, protoff, sizeof (u_int8_t), &nproto); - - IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, NULL); - - KEY_FREESAV(&sav); - crit_exit(); - return error; -bad: - if (sav) - KEY_FREESAV(&sav); - crit_exit(); - if (m) - m_freem(m); - if (tc != NULL) - kfree(tc, M_XDATA); - if (crp) - crypto_freereq(crp); - return error; -} - -/* - * IPComp output routine, called by ipsec[46]_process_packet() - */ -static int -ipcomp_output( - struct mbuf *m, - struct ipsecrequest *isr, - struct mbuf **mp, - int skip, - int protoff -) -{ - struct secasvar *sav; - struct comp_algo *ipcompx; - int error, ralen, hlen, maxpacketsize, roff; - u_int8_t prot; - struct cryptodesc *crdc; - struct cryptop *crp; - struct tdb_crypto *tc; - struct mbuf *mo; - struct ipcomp *ipcomp; - - sav = isr->sav; - KASSERT(sav != NULL, ("ipcomp_output: null SA")); - ipcompx = sav->tdb_compalgxform; - KASSERT(ipcompx != NULL, ("ipcomp_output: null compression xform")); - - ralen = m->m_pkthdr.len - skip; /* Raw payload length before comp. */ - hlen = IPCOMP_HLENGTH; - - ipcompstat.ipcomps_output++; - - /* Check for maximum packet size violations. */ - switch (sav->sah->saidx.dst.sa.sa_family) { -#ifdef INET - case AF_INET: - maxpacketsize = IP_MAXPACKET; - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - maxpacketsize = IPV6_MAXPACKET; - break; -#endif /* INET6 */ - default: - ipcompstat.ipcomps_nopf++; - DPRINTF(("ipcomp_output: unknown/unsupported protocol family %d" - ", IPCA %s/%08lx\n", - sav->sah->saidx.dst.sa.sa_family, - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - error = EPFNOSUPPORT; - goto bad; - } - if (skip + hlen + ralen > maxpacketsize) { - ipcompstat.ipcomps_toobig++; - DPRINTF(("ipcomp_output: packet in IPCA %s/%08lx got too big " - "(len %u, max len %u)\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi), - skip + hlen + ralen, maxpacketsize)); - error = EMSGSIZE; - goto bad; - } - - /* Update the counters */ - ipcompstat.ipcomps_obytes += m->m_pkthdr.len - skip; - - m = m_clone(m); - if (m == NULL) { - ipcompstat.ipcomps_hdrops++; - DPRINTF(("ipcomp_output: cannot clone mbuf chain, IPCA %s/%08lx\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - error = ENOBUFS; - goto bad; - } - - /* Inject IPCOMP header */ - mo = m_makespace(m, skip, hlen, &roff); - if (mo == NULL) { - ipcompstat.ipcomps_wrap++; - DPRINTF(("ipcomp_output: failed to inject IPCOMP header for " - "IPCA %s/%08lx\n", - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - error = ENOBUFS; - goto bad; - } - ipcomp = (struct ipcomp *)(mtod(mo, caddr_t) + roff); - - /* Initialize the IPCOMP header */ - /* XXX alignment always correct? */ - switch (sav->sah->saidx.dst.sa.sa_family) { -#ifdef INET - case AF_INET: - ipcomp->comp_nxt = mtod(m, struct ip *)->ip_p; - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - ipcomp->comp_nxt = mtod(m, struct ip6_hdr *)->ip6_nxt; - break; -#endif - } - ipcomp->comp_flags = 0; - ipcomp->comp_cpi = htons((u_int16_t) ntohl(sav->spi)); - - /* Fix Next Protocol in IPv4/IPv6 header */ - prot = IPPROTO_IPCOMP; - m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot); - - /* Ok now, we can pass to the crypto processing */ - - /* Get crypto descriptors */ - crp = crypto_getreq(1); - if (crp == NULL) { - ipcompstat.ipcomps_crypto++; - DPRINTF(("ipcomp_output: failed to acquire crypto descriptor\n")); - error = ENOBUFS; - goto bad; - } - crdc = crp->crp_desc; - - /* Compression descriptor */ - crdc->crd_skip = skip + hlen; - crdc->crd_len = m->m_pkthdr.len - (skip + hlen); - crdc->crd_flags = CRD_F_COMP; - crdc->crd_inject = skip + hlen; - - /* Compression operation */ - crdc->crd_alg = ipcompx->type; - - /* IPsec-specific opaque crypto info */ - tc = kmalloc(sizeof(struct tdb_crypto), - M_XDATA, M_INTWAIT | M_ZERO | M_NULLOK); - if (tc == NULL) { - ipcompstat.ipcomps_crypto++; - DPRINTF(("ipcomp_output: failed to allocate tdb_crypto\n")); - crypto_freereq(crp); - error = ENOBUFS; - goto bad; - } - - tc->tc_isr = isr; - tc->tc_spi = sav->spi; - tc->tc_dst = sav->sah->saidx.dst; - tc->tc_proto = sav->sah->saidx.proto; - tc->tc_skip = skip + hlen; - - /* Crypto operation descriptor */ - crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ - crp->crp_flags = CRYPTO_F_IMBUF; - crp->crp_buf = (caddr_t) m; - crp->crp_callback = ipcomp_output_cb; - crp->crp_opaque = (caddr_t) tc; - crp->crp_sid = sav->tdb_cryptoid; - - return crypto_dispatch(crp); -bad: - if (m) - m_freem(m); - return (error); -} - -/* - * IPComp output callback from the crypto driver. - */ -static int -ipcomp_output_cb(struct cryptop *crp) -{ - struct tdb_crypto *tc; - struct ipsecrequest *isr; - struct secasvar *sav; - struct mbuf *m; - int error, skip, rlen; - - tc = (struct tdb_crypto *) crp->crp_opaque; - KASSERT(tc != NULL, ("ipcomp_output_cb: null opaque data area!")); - m = (struct mbuf *) crp->crp_buf; - skip = tc->tc_skip; - rlen = crp->crp_ilen - skip; - - crit_enter(); - - isr = tc->tc_isr; - sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi); - if (sav == NULL) { - ipcompstat.ipcomps_notdb++; - DPRINTF(("ipcomp_output_cb: SA expired while in crypto\n")); - error = ENOBUFS; /*XXX*/ - goto bad; - } - KASSERT(isr->sav == sav, ("ipcomp_output_cb: SA changed")); - - /* Check for crypto errors */ - if (crp->crp_etype) { - /* Reset session ID */ - if (sav->tdb_cryptoid != 0) - sav->tdb_cryptoid = crp->crp_sid; - - if (crp->crp_etype == EAGAIN) { - KEY_FREESAV(&sav); - crit_exit(); - return crypto_dispatch(crp); - } - ipcompstat.ipcomps_noxform++; - DPRINTF(("ipcomp_output_cb: crypto error %d\n", crp->crp_etype)); - error = crp->crp_etype; - goto bad; - } - /* Shouldn't happen... */ - if (m == NULL) { - ipcompstat.ipcomps_crypto++; - DPRINTF(("ipcomp_output_cb: bogus return buffer from crypto\n")); - error = EINVAL; - goto bad; - } - ipcompstat.ipcomps_hist[sav->alg_comp]++; - - if (rlen > crp->crp_olen) { - /* Adjust the length in the IP header */ - switch (sav->sah->saidx.dst.sa.sa_family) { -#ifdef INET - case AF_INET: - mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - mtod(m, struct ip6_hdr *)->ip6_plen = - htons(m->m_pkthdr.len) - sizeof(struct ip6_hdr); - break; -#endif /* INET6 */ - default: - ipcompstat.ipcomps_nopf++; - DPRINTF(("ipcomp_output: unknown/unsupported protocol " - "family %d, IPCA %s/%08lx\n", - sav->sah->saidx.dst.sa.sa_family, - ipsec_address(&sav->sah->saidx.dst), - (u_long) ntohl(sav->spi))); - error = EPFNOSUPPORT; - goto bad; - } - } else { - /* compression was useless, we have lost time */ - /* XXX add statistic */ - } - - /* Release the crypto descriptor */ - kfree(tc, M_XDATA); - crypto_freereq(crp); - - /* NB: m is reclaimed by ipsec_process_done. */ - error = ipsec_process_done(m, isr); - KEY_FREESAV(&sav); - crit_exit(); - return error; -bad: - if (sav) - KEY_FREESAV(&sav); - crit_exit(); - if (m) - m_freem(m); - kfree(tc, M_XDATA); - crypto_freereq(crp); - return error; -} - -static struct xformsw ipcomp_xformsw = { - XF_IPCOMP, XFT_COMP, "IPcomp", - ipcomp_init, ipcomp_zeroize, ipcomp_input, - ipcomp_output -}; - -static void -ipcomp_attach(void) -{ - xform_register(&ipcomp_xformsw); -} -SYSINIT(ipcomp_xform_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, ipcomp_attach, NULL); diff --git a/sys/netproto/ipsec/xform_ipip.c b/sys/netproto/ipsec/xform_ipip.c deleted file mode 100644 index 204b77a744..0000000000 --- a/sys/netproto/ipsec/xform_ipip.c +++ /dev/null @@ -1,707 +0,0 @@ -/* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */ -/* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */ -/* - * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). - * - * The original version of this code was written by John Ioannidis - * for BSD/OS in Athens, Greece, in November 1995. - * - * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, - * by Angelos D. Keromytis. - * - * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis - * and Niels Provos. - * - * Additional features in 1999 by Angelos D. Keromytis. - * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, - * Angelos D. Keromytis and Niels Provos. - * Copyright (c) 2001, Angelos D. Keromytis. - * - * Permission to use, copy, and modify this software with or without fee - * is hereby granted, provided that this entire notice is included in - * all copies of any software which is or includes a copy or - * modification of this software. - * You may use this code under the GNU public license if you so wish. Please - * contribute changes back to the authors under this freer than GPL license - * so that we may further the use of strong encryption without limitations to - * all. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE - * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR - * PURPOSE. - */ - -/* - * IP-inside-IP processing - */ -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#ifdef MROUTING -#include -#endif - -#ifdef INET6 -#include -#include -#include -#include -#include -#endif - -#include -#include - -#include - -typedef void pr_in_input_t (struct mbuf *, int, int); /* XXX FIX THIS */ - -/* - * We can control the acceptance of IP4 packets by altering the sysctl - * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. - */ -int ipip_allow = 0; -struct ipipstat ipipstat; - -SYSCTL_DECL(_net_inet_ipip); -SYSCTL_INT(_net_inet_ipip, OID_AUTO, - ipip_allow, CTLFLAG_RW, &ipip_allow, 0, ""); -SYSCTL_STRUCT(_net_inet_ipip, IPSECCTL_STATS, - stats, CTLFLAG_RD, &ipipstat, ipipstat, ""); - -/* XXX IPCOMP */ -#define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED) - -static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp); - -#ifdef INET6 -/* - * Really only a wrapper for ipip_input(), for use with IPv6. - */ -int -ip4_input6(struct mbuf **mp, int *offp, int proto) -{ -#if 0 - /* If we do not accept IP-in-IP explicitly, drop. */ - if (!ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) { - DPRINTF(("ip4_input6: dropped due to policy\n")); - ipipstat.ipips_pdrops++; - m_freem(*m); - return IPPROTO_DONE; - } -#endif - _ipip_input(*mp, *offp, NULL); - return IPPROTO_DONE; -} -#endif /* INET6 */ - -#ifdef INET -/* - * Really only a wrapper for ipip_input(), for use with IPv4. - */ -int -ip4_input(struct mbuf **mp, int *offp, int proto) -{ -#if 0 - /* If we do not accept IP-in-IP explicitly, drop. */ - if (!ipip_allow && (m->m_flags & M_IPSEC) == 0) { - DPRINTF(("ip4_input: dropped due to policy\n")); - ipipstat.ipips_pdrops++; - m_freem(m); - return; - } -#endif - _ipip_input(*mp, *offp, NULL); - return IPPROTO_DONE; -} -#endif /* INET */ - -/* - * ipip_input gets called when we receive an IP{46} encapsulated packet, - * either because we got it at a real interface, or because AH or ESP - * were being used in tunnel mode (in which case the rcvif element will - * contain the address of the encX interface associated with the tunnel. - */ - -static void -_ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) -{ - struct sockaddr_in *sin; - struct ifaddr *ifa; - struct ip *ipo; -#ifdef INET6 - struct sockaddr_in6 *sin6; - struct ip6_hdr *ip6 = NULL; - u_int8_t itos; -#endif - u_int8_t nxt; - int isr; - u_int8_t otos; - u_int8_t v; - int hlen; - - ipipstat.ipips_ipackets++; - - m_copydata(m, 0, 1, &v); - - switch (v >> 4) { -#ifdef INET - case 4: - hlen = sizeof(struct ip); - break; -#endif /* INET */ -#ifdef INET6 - case 6: - hlen = sizeof(struct ip6_hdr); - break; -#endif - default: - DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) " - "for outer header\n", v, v>>4)); - ipipstat.ipips_family++; - m_freem(m); - return /* EAFNOSUPPORT */; - } - - /* Bring the IP header in the first mbuf, if not there already */ - if (m->m_len < hlen) { - if ((m = m_pullup(m, hlen)) == NULL) { - DPRINTF(("ipip_input: m_pullup (1) failed\n")); - ipipstat.ipips_hdrops++; - return; - } - } - - ipo = mtod(m, struct ip *); - -#ifdef MROUTING - if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) { - if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) { - ipip_mroute_input (m, iphlen); - return; - } - } -#endif /* MROUTING */ - - /* Keep outer ecn field. */ - switch (v >> 4) { -#ifdef INET - case 4: - otos = ipo->ip_tos; - break; -#endif /* INET */ -#ifdef INET6 - case 6: - otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff; - break; -#endif - default: - panic("ipip_input: unknown ip version %u (outer)", v>>4); - } - - /* Remove outer IP header */ - m_adj(m, iphlen); - - /* Sanity check */ - if (m->m_pkthdr.len < sizeof(struct ip)) { - ipipstat.ipips_hdrops++; - m_freem(m); - return; - } - - m_copydata(m, 0, 1, &v); - - switch (v >> 4) { -#ifdef INET - case 4: - hlen = sizeof(struct ip); - break; -#endif /* INET */ - -#ifdef INET6 - case 6: - hlen = sizeof(struct ip6_hdr); - break; -#endif - default: - DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) " - "for inner header\n", v, v>>4)); - ipipstat.ipips_family++; - m_freem(m); - return; /* EAFNOSUPPORT */ - } - - /* - * Bring the inner IP header in the first mbuf, if not there already. - */ - if (m->m_len < hlen) { - if ((m = m_pullup(m, hlen)) == NULL) { - DPRINTF(("ipip_input: m_pullup (2) failed\n")); - ipipstat.ipips_hdrops++; - return; - } - } - - /* - * RFC 1853 specifies that the inner TTL should not be touched on - * decapsulation. There's no reason this comment should be here, but - * this is as good as any a position. - */ - - /* Some sanity checks in the inner IP header */ - switch (v >> 4) { -#ifdef INET - case 4: - ipo = mtod(m, struct ip *); - nxt = ipo->ip_p; - ip_ecn_egress(ip4_ipsec_ecn, &otos, &ipo->ip_tos); - break; -#endif /* INET */ -#ifdef INET6 - case 6: - ip6 = (struct ip6_hdr *) ipo; - nxt = ip6->ip6_nxt; - itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; - ip_ecn_egress(ip6_ipsec_ecn, &otos, &itos); - ip6->ip6_flow &= ~htonl(0xff << 20); - ip6->ip6_flow |= htonl((u_int32_t) itos << 20); - break; -#endif - default: - panic("ipip_input: unknown ip version %u (inner)", v>>4); - } - - /* Check for local address spoofing. */ - if ((m->m_pkthdr.rcvif == NULL || - !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) && - ipip_allow != 2) { - struct ifnet_array *arr; - int i; - - arr = ifnet_array_get(); - for (i = 0; i < arr->ifnet_count; ++i) { - struct ifnet *ifp = arr->ifnet_arr[i]; - struct ifaddr_container *ifac; - - TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) { - ifa = ifac->ifa; -#ifdef INET - if (ipo) { - if (ifa->ifa_addr->sa_family != - AF_INET) - continue; - - sin = (struct sockaddr_in *) ifa->ifa_addr; - - if (sin->sin_addr.s_addr == - ipo->ip_src.s_addr) { - ipipstat.ipips_spoof++; - m_freem(m); - return; - } - } -#endif /* INET */ - -#ifdef INET6 - if (ip6) { - if (ifa->ifa_addr->sa_family != - AF_INET6) - continue; - - sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; - - if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) { - ipipstat.ipips_spoof++; - m_freem(m); - return; - } - - } -#endif /* INET6 */ - } - } - } - - /* Statistics */ - ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen; - - /* - * Interface pointer stays the same; if no IPsec processing has - * been done (or will be done), this will point to a normal - * interface. Otherwise, it'll point to an enc interface, which - * will allow a packet filter to distinguish between secure and - * untrusted packets. - */ - - switch (v >> 4) { -#ifdef INET - case 4: - isr = NETISR_IP; - break; -#endif -#ifdef INET6 - case 6: - isr = NETISR_IPV6; - break; -#endif - default: - panic("ipip_input: should never reach here"); - } - - if (netisr_queue(isr, m)) { - ipipstat.ipips_qfull++; - - DPRINTF(("ipip_input: packet dropped because of full queue\n")); - } -} - -int -ipip_output( - struct mbuf *m, - struct ipsecrequest *isr, - struct mbuf **mp, - int skip, - int protoff -) -{ - struct secasvar *sav; - u_int8_t tp, otos; - struct secasindex *saidx; - int error; -#ifdef INET - u_int8_t itos; - struct ip *ipo; -#endif /* INET */ -#ifdef INET6 - struct ip6_hdr *ip6, *ip6o; -#endif /* INET6 */ - - sav = isr->sav; - KASSERT(sav != NULL, ("ipip_output: null SA")); - KASSERT(sav->sah != NULL, ("ipip_output: null SAH")); - - /* XXX Deal with empty TDB source/destination addresses. */ - - m_copydata(m, 0, 1, &tp); - tp = (tp >> 4) & 0xff; /* Get the IP version number. */ - - saidx = &sav->sah->saidx; - switch (saidx->dst.sa.sa_family) { -#ifdef INET - case AF_INET: - if (saidx->src.sa.sa_family != AF_INET || - saidx->src.sin.sin_addr.s_addr == INADDR_ANY || - saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) { - DPRINTF(("ipip_output: unspecified tunnel endpoint " - "address in SA %s/%08lx\n", - ipsec_address(&saidx->dst), - (u_long) ntohl(sav->spi))); - ipipstat.ipips_unspec++; - error = EINVAL; - goto bad; - } - - M_PREPEND(m, sizeof(struct ip), M_NOWAIT); - if (m == NULL) { - DPRINTF(("ipip_output: M_PREPEND failed\n")); - ipipstat.ipips_hdrops++; - error = ENOBUFS; - goto bad; - } - - ipo = mtod(m, struct ip *); - - ipo->ip_v = IPVERSION; - ipo->ip_hl = 5; - ipo->ip_len = htons(m->m_pkthdr.len); - ipo->ip_ttl = ip_defttl; - ipo->ip_sum = 0; - ipo->ip_src = saidx->src.sin.sin_addr; - ipo->ip_dst = saidx->dst.sin.sin_addr; - - ipo->ip_id = ip_newid(); - - /* If the inner protocol is IP... */ - if (tp == IPVERSION) { - /* Save ECN notification */ - m_copydata(m, sizeof(struct ip) + - offsetof(struct ip, ip_tos), - sizeof(u_int8_t), (caddr_t) &itos); - - ipo->ip_p = IPPROTO_IPIP; - - /* - * We should be keeping tunnel soft-state and - * send back ICMPs if needed. - */ - m_copydata(m, sizeof(struct ip) + - offsetof(struct ip, ip_off), - sizeof(u_int16_t), (caddr_t) &ipo->ip_off); - ipo->ip_off = ntohs(ipo->ip_off); - ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK); - ipo->ip_off = htons(ipo->ip_off); - } -#ifdef INET6 - else if (tp == (IPV6_VERSION >> 4)) { - u_int32_t itos32; - - /* Save ECN notification. */ - m_copydata(m, sizeof(struct ip) + - offsetof(struct ip6_hdr, ip6_flow), - sizeof(u_int32_t), (caddr_t) &itos32); - itos = ntohl(itos32) >> 20; - ipo->ip_p = IPPROTO_IPV6; - ipo->ip_off = 0; - } -#endif /* INET6 */ - else { - goto nofamily; - } - - otos = 0; - ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); - ipo->ip_tos = otos; - break; -#endif /* INET */ - -#ifdef INET6 - case AF_INET6: - if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) || - saidx->src.sa.sa_family != AF_INET6 || - IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) { - DPRINTF(("ipip_output: unspecified tunnel endpoint " - "address in SA %s/%08lx\n", - ipsec_address(&saidx->dst), - (u_long) ntohl(sav->spi))); - ipipstat.ipips_unspec++; - error = ENOBUFS; - goto bad; - } - - /* scoped address handling */ - ip6 = mtod(m, struct ip6_hdr *); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) - ip6->ip6_src.s6_addr16[1] = 0; - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) - ip6->ip6_dst.s6_addr16[1] = 0; - - M_PREPEND(m, sizeof(struct ip6_hdr), M_NOWAIT); - if (m == NULL) { - DPRINTF(("ipip_output: M_PREPEND failed\n")); - ipipstat.ipips_hdrops++; - *mp = NULL; - error = ENOBUFS; - goto bad; - } - - /* Initialize IPv6 header */ - ip6o = mtod(m, struct ip6_hdr *); - ip6o->ip6_flow = 0; - ip6o->ip6_vfc &= ~IPV6_VERSION_MASK; - ip6o->ip6_vfc |= IPV6_VERSION; - ip6o->ip6_plen = htons(m->m_pkthdr.len); - ip6o->ip6_hlim = ip_defttl; - ip6o->ip6_dst = saidx->dst.sin6.sin6_addr; - ip6o->ip6_src = saidx->src.sin6.sin6_addr; - -#ifdef INET - if (tp == IPVERSION) { - /* Save ECN notification */ - m_copydata(m, sizeof(struct ip6_hdr) + - offsetof(struct ip, ip_tos), sizeof(u_int8_t), - (caddr_t) &itos); - - /* This is really IPVERSION. */ - ip6o->ip6_nxt = IPPROTO_IPIP; - } else -#endif /* INET */ - if (tp == (IPV6_VERSION >> 4)) { - u_int32_t itos32; - - /* Save ECN notification. */ - m_copydata(m, sizeof(struct ip6_hdr) + - offsetof(struct ip6_hdr, ip6_flow), - sizeof(u_int32_t), (caddr_t) &itos32); - itos = ntohl(itos32) >> 20; - - ip6o->ip6_nxt = IPPROTO_IPV6; - } else { - goto nofamily; - } - - otos = 0; - ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); - ip6o->ip6_flow |= htonl((u_int32_t) otos << 20); - break; -#endif /* INET6 */ - - default: -nofamily: - DPRINTF(("ipip_output: unsupported protocol family %u\n", - saidx->dst.sa.sa_family)); - ipipstat.ipips_family++; - error = EAFNOSUPPORT; /* XXX diffs from openbsd */ - goto bad; - } - - ipipstat.ipips_opackets++; - *mp = m; - -#ifdef INET - if (saidx->dst.sa.sa_family == AF_INET) { -#if 0 - if (sav->tdb_xform->xf_type == XF_IP4) - tdb->tdb_cur_bytes += - m->m_pkthdr.len - sizeof(struct ip); -#endif - ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip); - } -#endif /* INET */ - -#ifdef INET6 - if (saidx->dst.sa.sa_family == AF_INET6) { -#if 0 - if (sav->tdb_xform->xf_type == XF_IP4) - tdb->tdb_cur_bytes += - m->m_pkthdr.len - sizeof(struct ip6_hdr); -#endif - ipipstat.ipips_obytes += - m->m_pkthdr.len - sizeof(struct ip6_hdr); - } -#endif /* INET6 */ - - return 0; -bad: - if (m) - m_freem(m), *mp = NULL; - return (error); -} - -#ifdef FAST_IPSEC -static int -ipe4_init(struct secasvar *sav, struct xformsw *xsp) -{ - sav->tdb_xform = xsp; - return 0; -} - -static int -ipe4_zeroize(struct secasvar *sav) -{ - sav->tdb_xform = NULL; - return 0; -} - -static int -ipe4_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) -{ - /* This is a rather serious mistake, so no conditional printing. */ - kprintf("ipe4_input: should never be called\n"); - if (m) - m_freem(m); - return EOPNOTSUPP; -} - -static struct xformsw ipe4_xformsw = { - XF_IP4, 0, "IPv4 Simple Encapsulation", - ipe4_init, ipe4_zeroize, ipe4_input, ipip_output, -}; - -extern struct domain inetdomain; - -static struct protosw ipe4_protosw[] = { - { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_IPV4, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = ip4_input, - .pr_output = NULL, - .pr_ctlinput = NULL, - .pr_ctloutput = rip_ctloutput, - - .pr_ctlport = cpu0_ctlport, - .pr_init = raw_init, - .pr_usrreqs = &rip_usrreqs - }, -#ifdef INET6 - { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_IPV6, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = ip4_input6, - .pr_output = NULL, - .pr_ctlinput = NULL, - .pr_ctloutput = rip_ctloutput, - - .pr_ctlport = cpu0_ctlport, - .pr_init = raw_init, - .pr_usrreqs = &rip_usrreqs - } -#endif -}; - -/* - * Check the encapsulated packet to see if we want it - */ -static int -ipe4_encapcheck(const struct mbuf *m, int off, int proto, void *arg) -{ - /* - * Only take packets coming from IPSEC tunnels; the rest - * must be handled by the gif tunnel code. Note that we - * also return a minimum priority when we want the packet - * so any explicit gif tunnels take precedence. - */ - return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0); -} - -static void -ipe4_attach(void) -{ - xform_register(&ipe4_xformsw); - /* attach to encapsulation framework */ - /* XXX save return cookie for detach on module remove */ - encap_attach_func(AF_INET, -1, - ipe4_encapcheck, &ipe4_protosw[0], NULL); -#ifdef INET6 - encap_attach_func(AF_INET6, -1, - ipe4_encapcheck, &ipe4_protosw[1], NULL); -#endif -} -SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL); -#endif /* FAST_IPSEC */ diff --git a/sys/netproto/key/key.c b/sys/netproto/key/key.c deleted file mode 100644 index e023e9177a..0000000000 --- a/sys/netproto/key/key.c +++ /dev/null @@ -1,7366 +0,0 @@ -/* $FreeBSD: src/sys/netkey/key.c,v 1.16.2.13 2002/07/24 18:17:40 ume Exp $ */ -/* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ - -/* - * 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. - */ - -/* - * This code is referd to RFC 2367 - */ - -#include "opt_inet.h" -#include "opt_inet6.h" -#include "opt_ipsec.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#ifdef INET6 -#include -#include -#include -#endif /* INET6 */ - -#ifdef INET -#include -#endif -#ifdef INET6 -#include -#endif /* INET6 */ - -#include -#include "keydb.h" -#include "key.h" -#include "keysock.h" -#include "key_debug.h" - -#include -#ifdef INET6 -#include -#endif -#include -#ifdef INET6 -#include -#endif -#ifdef IPSEC_ESP -#include -#ifdef INET6 -#include -#endif -#endif -#include -#ifdef INET6 -#include -#endif - -#include - -/* randomness */ -#include - -#include - -#ifndef satosin -#define satosin(s) ((struct sockaddr_in *)s) -#endif - -#define FULLMASK 0xff - -/* - * Note on SA reference counting: - * - SAs that are not in DEAD state will have (total external reference + 1) - * following value in reference count field. they cannot be freed and are - * referenced from SA header. - * - SAs that are in DEAD state will have (total external reference) - * in reference count field. they are ready to be freed. reference from - * SA header will be removed in key_delsav(), when the reference count - * field hits 0 (= no external reference other than from SA header. - */ - -#ifndef IPSEC_DEBUG2 -static struct callout key_timehandler_ch; -#endif -u_int32_t key_debug_level = 0; -static u_int key_spi_trycnt = 1000; -static u_int32_t key_spi_minval = 0x100; -static u_int32_t key_spi_maxval = 0x0fffffff; /* XXX */ -static u_int32_t policy_id = 0; -static u_int key_int_random = 60; /*interval to initialize randseed,1(m)*/ -static u_int key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/ -static int key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/ -static int key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/ -static int key_preferred_oldsa = 1; /* preferred old sa rather than new sa.*/ - -static u_int32_t acq_seq = 0; -static int key_tick_init_random = 0; - -static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */ -static LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */ -static LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1]; - /* registed list */ -#ifndef IPSEC_NONBLOCK_ACQUIRE -static LIST_HEAD(_acqtree, secacq) acqtree; /* acquiring list */ -#endif -static LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */ - -struct lwkt_token key_token = LWKT_TOKEN_INITIALIZER(key_token); - -struct key_cb key_cb; - -/* search order for SAs */ -static const u_int saorder_state_valid_prefer_old[] = { - SADB_SASTATE_DYING, SADB_SASTATE_MATURE, -}; -static const u_int saorder_state_valid_prefer_new[] = { - SADB_SASTATE_MATURE, SADB_SASTATE_DYING, -}; -static const u_int saorder_state_alive[] = { - /* except DEAD */ - SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL -}; -static const u_int saorder_state_any[] = { - SADB_SASTATE_MATURE, SADB_SASTATE_DYING, - SADB_SASTATE_LARVAL, SADB_SASTATE_DEAD -}; - -static const int minsize[] = { - sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ - sizeof(struct sadb_sa), /* SADB_EXT_SA */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ - sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_SRC */ - sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_DST */ - sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_PROXY */ - sizeof(struct sadb_key), /* SADB_EXT_KEY_AUTH */ - sizeof(struct sadb_key), /* SADB_EXT_KEY_ENCRYPT */ - sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_SRC */ - sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_DST */ - sizeof(struct sadb_sens), /* SADB_EXT_SENSITIVITY */ - sizeof(struct sadb_prop), /* SADB_EXT_PROPOSAL */ - sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_AUTH */ - sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_ENCRYPT */ - sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ - 0, /* SADB_X_EXT_KMPRIVATE */ - sizeof(struct sadb_x_policy), /* SADB_X_EXT_POLICY */ - sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */ -}; -static const int maxsize[] = { - sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ - sizeof(struct sadb_sa), /* SADB_EXT_SA */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ - sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ - 0, /* SADB_EXT_ADDRESS_SRC */ - 0, /* SADB_EXT_ADDRESS_DST */ - 0, /* SADB_EXT_ADDRESS_PROXY */ - 0, /* SADB_EXT_KEY_AUTH */ - 0, /* SADB_EXT_KEY_ENCRYPT */ - 0, /* SADB_EXT_IDENTITY_SRC */ - 0, /* SADB_EXT_IDENTITY_DST */ - 0, /* SADB_EXT_SENSITIVITY */ - 0, /* SADB_EXT_PROPOSAL */ - 0, /* SADB_EXT_SUPPORTED_AUTH */ - 0, /* SADB_EXT_SUPPORTED_ENCRYPT */ - sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ - 0, /* SADB_X_EXT_KMPRIVATE */ - 0, /* SADB_X_EXT_POLICY */ - sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */ -}; - -static int ipsec_esp_keymin = 256; -static int ipsec_esp_auth = 0; -static int ipsec_ah_keymin = 128; - -#ifdef SYSCTL_DECL -SYSCTL_DECL(_net_key); -#endif - -SYSCTL_INT(_net_key, KEYCTL_DEBUG_LEVEL, debug, CTLFLAG_RW, \ - &key_debug_level, 0, ""); - -/* max count of trial for the decision of spi value */ -SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ - &key_spi_trycnt, 0, ""); - -/* minimum spi value to allocate automatically. */ -SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ - &key_spi_minval, 0, ""); - -/* maximun spi value to allocate automatically. */ -SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ - &key_spi_maxval, 0, ""); - -/* interval to initialize randseed */ -SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ - &key_int_random, 0, ""); - -/* lifetime for larval SA */ -SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ - &key_larval_lifetime, 0, ""); - -/* counter for blocking to send SADB_ACQUIRE to IKEd */ -SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \ - &key_blockacq_count, 0, ""); - -/* lifetime for blocking to send SADB_ACQUIRE to IKEd */ -SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ - &key_blockacq_lifetime, 0, ""); - -/* ESP auth */ -SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \ - &ipsec_esp_auth, 0, ""); - -/* minimum ESP key length */ -SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \ - &ipsec_esp_keymin, 0, ""); - -/* minimum AH key length */ -SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \ - &ipsec_ah_keymin, 0, ""); - -/* perfered old SA rather than new SA */ -SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW,\ - &key_preferred_oldsa, 0, ""); - -#ifndef LIST_FOREACH -#define LIST_FOREACH(elm, head, field) \ - for (elm = LIST_FIRST(head); elm; elm = LIST_NEXT(elm, field)) -#endif -#define __LIST_CHAINED(elm) \ - (!((elm)->chain.le_next == NULL && (elm)->chain.le_prev == NULL)) -#define LIST_INSERT_TAIL(head, elm, type, field) \ -do {\ - struct type *curelm = LIST_FIRST(head); \ - if (curelm == NULL) {\ - LIST_INSERT_HEAD(head, elm, field); \ - } else { \ - while (LIST_NEXT(curelm, field)) \ - curelm = LIST_NEXT(curelm, field);\ - LIST_INSERT_AFTER(curelm, elm, field);\ - }\ -} while (0) - -#define KEY_CHKSASTATE(head, sav, name) \ -do { \ - if ((head) != (sav)) { \ - ipseclog((LOG_DEBUG, "%s: state mismatched (TREE=%d SA=%d)\n", \ - (name), (head), (sav))); \ - continue; \ - } \ -} while (0) - -#define KEY_CHKSPDIR(head, sp, name) \ -do { \ - if ((head) != (sp)) { \ - ipseclog((LOG_DEBUG, "%s: direction mismatched (TREE=%d SP=%d), " \ - "anyway continue.\n", \ - (name), (head), (sp))); \ - } \ -} while (0) - -#if 1 -#define KMALLOC(p, t, n) \ - ((p) = (t) kmalloc((unsigned long)(n), M_SECA, M_INTWAIT | M_NULLOK)) -#define KFREE(p) \ - kfree((caddr_t)(p), M_SECA); -#else -#define KMALLOC(p, t, n) \ -do { \ - ((p) = (t)kmalloc((unsigned long)(n), M_SECA, M_INTWAIT | M_NULLOK)); \ - kprintf("%s %d: %p <- KMALLOC(%s, %d)\n", \ - __FILE__, __LINE__, (p), #t, n); \ -} while (0) - -#define KFREE(p) \ - do { \ - kprintf("%s %d: %p -> KFREE()\n", __FILE__, __LINE__, (p)); \ - kfree((caddr_t)(p), M_SECA); \ - } while (0) -#endif - -/* - * set parameters into secpolicyindex buffer. - * Must allocate secpolicyindex buffer passed to this function. - */ -#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, idx) \ -do { \ - bzero((idx), sizeof(struct secpolicyindex)); \ - (idx)->dir = (_dir); \ - (idx)->prefs = (ps); \ - (idx)->prefd = (pd); \ - (idx)->ul_proto = (ulp); \ - bcopy((s), &(idx)->src, ((struct sockaddr *)(s))->sa_len); \ - bcopy((d), &(idx)->dst, ((struct sockaddr *)(d))->sa_len); \ -} while (0) - -/* - * set parameters into secasindex buffer. - * Must allocate secasindex buffer before calling this function. - */ -#define KEY_SETSECASIDX(p, m, r, s, d, idx) \ -do { \ - bzero((idx), sizeof(struct secasindex)); \ - (idx)->proto = (p); \ - (idx)->mode = (m); \ - (idx)->reqid = (r); \ - bcopy((s), &(idx)->src, ((struct sockaddr *)(s))->sa_len); \ - bcopy((d), &(idx)->dst, ((struct sockaddr *)(d))->sa_len); \ -} while (0) - -/* key statistics */ -struct _keystat { - u_long getspi_count; /* the avarage of count to try to get new SPI */ -} keystat; - -struct sadb_msghdr { - struct sadb_msg *msg; - struct sadb_ext *ext[SADB_EXT_MAX + 1]; - int extoff[SADB_EXT_MAX + 1]; - int extlen[SADB_EXT_MAX + 1]; -}; - -static struct secasvar *key_allocsa_policy (struct secasindex *); -static void key_freesp_so (struct secpolicy **); -static struct secasvar *key_do_allocsa_policy (struct secashead *, u_int); -static void key_delsp (struct secpolicy *); -static struct secpolicy *key_getsp (struct secpolicyindex *); -static struct secpolicy *key_getspbyid (u_int32_t); -static u_int32_t key_newreqid (void); -static struct mbuf *key_gather_mbuf (struct mbuf *, - const struct sadb_msghdr *, int, int, ...); -static int key_spdadd (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static u_int32_t key_getnewspid (void); -static int key_spddelete (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_spddelete2 (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_spdget (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_spdflush (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_spddump (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static struct mbuf *key_setdumpsp (struct secpolicy *, - u_int8_t, u_int32_t, u_int32_t); -static u_int key_getspreqmsglen (struct secpolicy *); -static int key_spdexpire (struct secpolicy *); -static struct secashead *key_newsah (struct secasindex *); -static void key_delsah (struct secashead *); -static struct secasvar *key_newsav (struct mbuf *, - const struct sadb_msghdr *, struct secashead *, int *); -static void key_delsav (struct secasvar *); -static struct secashead *key_getsah (struct secasindex *); -static struct secasvar *key_checkspidup (struct secasindex *, u_int32_t); -static struct secasvar *key_getsavbyspi (struct secashead *, u_int32_t); -static int key_setsaval (struct secasvar *, struct mbuf *, - const struct sadb_msghdr *); -static int key_mature (struct secasvar *); -static struct mbuf *key_setdumpsa (struct secasvar *, u_int8_t, - u_int8_t, u_int32_t, u_int32_t); -static struct mbuf *key_setsadbmsg (u_int8_t, u_int16_t, u_int8_t, - u_int32_t, pid_t, u_int16_t); -static struct mbuf *key_setsadbsa (struct secasvar *); -static struct mbuf *key_setsadbaddr (u_int16_t, - struct sockaddr *, u_int8_t, u_int16_t); -#if 0 -static struct mbuf *key_setsadbident (u_int16_t, u_int16_t, caddr_t, - int, u_int64_t); -#endif -static struct mbuf *key_setsadbxsa2 (u_int8_t, u_int32_t, u_int32_t); -static struct mbuf *key_setsadbxpolicy (u_int16_t, u_int8_t, - u_int32_t); -static void *key_newbuf (const void *, u_int); -#ifdef INET6 -static int key_ismyaddr6 (struct sockaddr_in6 *); -#endif - -/* flags for key_cmpsaidx() */ -#define CMP_HEAD 1 /* protocol, addresses. */ -#define CMP_MODE_REQID 2 /* additionally HEAD, reqid, mode. */ -#define CMP_REQID 3 /* additionally HEAD, reaid. */ -#define CMP_EXACTLY 4 /* all elements. */ -static int key_cmpsaidx - (struct secasindex *, struct secasindex *, int); - -static int key_cmpspidx_exactly - (struct secpolicyindex *, struct secpolicyindex *); -static int key_cmpspidx_withmask - (struct secpolicyindex *, struct secpolicyindex *); -static int key_sockaddrcmp (struct sockaddr *, struct sockaddr *, int); -static int key_bbcmp (caddr_t, caddr_t, u_int); -static void key_srandom (void); -static u_int16_t key_satype2proto (u_int8_t); -static u_int8_t key_proto2satype (u_int16_t); - -static int key_getspi (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static u_int32_t key_do_getnewspi (struct sadb_spirange *, - struct secasindex *); -static int key_update (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -#ifdef IPSEC_DOSEQCHECK -static struct secasvar *key_getsavbyseq (struct secashead *, u_int32_t); -#endif -static int key_add (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_setident (struct secashead *, struct mbuf *, - const struct sadb_msghdr *); -static struct mbuf *key_getmsgbuf_x1 (struct mbuf *, - const struct sadb_msghdr *); -static int key_delete (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_get (struct socket *, struct mbuf *, - const struct sadb_msghdr *); - -static void key_getcomb_setlifetime (struct sadb_comb *); -#ifdef IPSEC_ESP -static struct mbuf *key_getcomb_esp (void); -#endif -static struct mbuf *key_getcomb_ah (void); -static struct mbuf *key_getcomb_ipcomp (void); -static struct mbuf *key_getprop (const struct secasindex *); - -static int key_acquire (struct secasindex *, struct secpolicy *); -#ifndef IPSEC_NONBLOCK_ACQUIRE -static struct secacq *key_newacq (struct secasindex *); -static struct secacq *key_getacq (struct secasindex *); -static struct secacq *key_getacqbyseq (u_int32_t); -#endif -static struct secspacq *key_newspacq (struct secpolicyindex *); -static struct secspacq *key_getspacq (struct secpolicyindex *); -static int key_acquire2 (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_register (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_expire (struct secasvar *); -static int key_flush (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_dump (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_promisc (struct socket *, struct mbuf *, - const struct sadb_msghdr *); -static int key_senderror (struct socket *, struct mbuf *, int); -static int key_validate_ext (const struct sadb_ext *, int); -static int key_align (struct mbuf *, struct sadb_msghdr *); -#if 0 -static const char *key_getfqdn (void); -static const char *key_getuserfqdn (void); -#endif -static void key_sa_chgstate (struct secasvar *, u_int8_t); -static struct mbuf *key_alloc_mbuf (int); - -/* %%% IPsec policy management */ -/* - * allocating a SP for OUTBOUND or INBOUND packet. - * Must call key_freesp() later. - * OUT: NULL: not found - * others: found and return the pointer. - */ -struct secpolicy * -key_allocsp(struct secpolicyindex *spidx, u_int dir) -{ - struct secpolicy *sp; - struct timeval tv; - - /* sanity check */ - if (spidx == NULL) - panic("key_allocsp: NULL pointer is passed."); - - /* check direction */ - switch (dir) { - case IPSEC_DIR_INBOUND: - case IPSEC_DIR_OUTBOUND: - break; - default: - panic("key_allocsp: Invalid direction is passed."); - } - - /* get a SP entry */ - lwkt_gettoken(&key_token); - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("*** objects\n"); - kdebug_secpolicyindex(spidx)); - - LIST_FOREACH(sp, &sptree[dir], chain) { - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - kprintf("*** in SPD\n"); - kdebug_secpolicyindex(&sp->spidx)); - - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (key_cmpspidx_withmask(&sp->spidx, spidx)) - goto found; - } - - lwkt_reltoken(&key_token); - return NULL; - -found: - /* sanity check */ - KEY_CHKSPDIR(sp->spidx.dir, dir, "key_allocsp"); - - /* found a SPD entry */ - sp->refcnt++; - microtime(&tv); - sp->lastused = tv.tv_sec; - lwkt_reltoken(&key_token); - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_allocsp cause refcnt++:%d SP:%p\n", - sp->refcnt, sp)); - - return sp; -} - -/* - * return a policy that matches this particular inbound packet. - * XXX slow - */ -struct secpolicy * -key_gettunnel(struct sockaddr *osrc, struct sockaddr *odst, - struct sockaddr *isrc, struct sockaddr *idst) -{ - struct secpolicy *sp; - const int dir = IPSEC_DIR_INBOUND; - struct timeval tv; - struct ipsecrequest *r1, *r2, *p; - struct sockaddr *os, *od, *is, *id; - struct secpolicyindex spidx; - - if (isrc->sa_family != idst->sa_family) { - ipseclog((LOG_ERR, "protocol family mismatched %d != %d\n.", - isrc->sa_family, idst->sa_family)); - return NULL; - } - - lwkt_gettoken(&key_token); - LIST_FOREACH(sp, &sptree[dir], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - - r1 = r2 = NULL; - for (p = sp->req; p; p = p->next) { - if (p->saidx.mode != IPSEC_MODE_TUNNEL) - continue; - - r1 = r2; - r2 = p; - - if (!r1) { - /* here we look at address matches only */ - spidx = sp->spidx; - if (isrc->sa_len > sizeof(spidx.src) || - idst->sa_len > sizeof(spidx.dst)) - continue; - bcopy(isrc, &spidx.src, isrc->sa_len); - bcopy(idst, &spidx.dst, idst->sa_len); - if (!key_cmpspidx_withmask(&sp->spidx, &spidx)) - continue; - } else { - is = (struct sockaddr *)&r1->saidx.src; - id = (struct sockaddr *)&r1->saidx.dst; - if (key_sockaddrcmp(is, isrc, 0) || - key_sockaddrcmp(id, idst, 0)) - continue; - } - - os = (struct sockaddr *)&r2->saidx.src; - od = (struct sockaddr *)&r2->saidx.dst; - if (key_sockaddrcmp(os, osrc, 0) || - key_sockaddrcmp(od, odst, 0)) - continue; - - goto found; - } - } - lwkt_reltoken(&key_token); - return NULL; - -found: - sp->refcnt++; - microtime(&tv); - sp->lastused = tv.tv_sec; - lwkt_reltoken(&key_token); - return sp; -} - -/* - * allocating an SA entry for an *OUTBOUND* packet. - * checking each request entries in SP, and acquire an SA if need. - * OUT: 0: there are valid requests. - * ENOENT: policy may be valid, but SA with REQUIRE is on acquiring. - */ -int -key_checkrequest(struct ipsecrequest *isr, struct secasindex *saidx) -{ - u_int level; - int error; - - /* sanity check */ - if (isr == NULL || saidx == NULL) - panic("key_checkrequest: NULL pointer is passed."); - - /* check mode */ - switch (saidx->mode) { - case IPSEC_MODE_TRANSPORT: - case IPSEC_MODE_TUNNEL: - break; - case IPSEC_MODE_ANY: - default: - panic("key_checkrequest: Invalid policy defined."); - } - - lwkt_gettoken(&key_token); - - /* get current level */ - level = ipsec_get_reqlevel(isr); - -#if 0 - /* - * We do allocate new SA only if the state of SA in the holder is - * SADB_SASTATE_DEAD. The SA for outbound must be the oldest. - */ - if (isr->sav != NULL) { - if (isr->sav->sah == NULL) - panic("key_checkrequest: sah is null."); - if (isr->sav == (struct secasvar *)LIST_FIRST( - &isr->sav->sah->savtree[SADB_SASTATE_DEAD])) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP checkrequest calls free SA:%p\n", - isr->sav)); - key_freesav(isr->sav); - isr->sav = NULL; - } - } -#else - /* - * we free any SA stashed in the IPsec request because a different - * SA may be involved each time this request is checked, either - * because new SAs are being configured, or this request is - * associated with an unconnected datagram socket, or this request - * is associated with a system default policy. - * - * The operation may have negative impact to performance. We may - * want to check cached SA carefully, rather than picking new SA - * every time. - */ - if (isr->sav != NULL) { - key_freesav(isr->sav); - isr->sav = NULL; - } -#endif - - /* - * new SA allocation if no SA found. - * key_allocsa_policy should allocate the oldest SA available. - * See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt. - */ - if (isr->sav == NULL) - isr->sav = key_allocsa_policy(saidx); - - /* When there is SA. */ - if (isr->sav != NULL) { - lwkt_reltoken(&key_token); - return 0; - } - - /* there is no SA */ - if ((error = key_acquire(saidx, isr->sp)) != 0) { - /* XXX What should I do ? */ - ipseclog((LOG_DEBUG, "key_checkrequest: error %d returned " - "from key_acquire.\n", error)); - lwkt_reltoken(&key_token); - return error; - } - - lwkt_reltoken(&key_token); - return level == IPSEC_LEVEL_REQUIRE ? ENOENT : 0; -} - -/* - * allocating a SA for policy entry from SAD. - * NOTE: searching SAD of aliving state. - * OUT: NULL: not found. - * others: found and return the pointer. - */ -static struct secasvar * -key_allocsa_policy(struct secasindex *saidx) -{ - struct secashead *sah; - struct secasvar *sav; - u_int stateidx, state; - const u_int *saorder_state_valid; - int arraysize; - - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) - goto found; - } - - return NULL; - - found: - - /* - * search a valid state list for outbound packet. - * This search order is important. - */ - if (key_preferred_oldsa) { - saorder_state_valid = saorder_state_valid_prefer_old; - arraysize = NELEM(saorder_state_valid_prefer_old); - } else { - saorder_state_valid = saorder_state_valid_prefer_new; - arraysize = NELEM(saorder_state_valid_prefer_new); - } - - for (stateidx = 0; stateidx < arraysize; stateidx++) { - - state = saorder_state_valid[stateidx]; - - sav = key_do_allocsa_policy(sah, state); - if (sav != NULL) - return sav; - } - - return NULL; -} - -/* - * searching SAD with direction, protocol, mode and state. - * called by key_allocsa_policy(). - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -static struct secasvar * -key_do_allocsa_policy(struct secashead *sah, u_int state) -{ - struct secasvar *sav, *nextsav, *candidate, *d; - - /* initilize */ - candidate = NULL; - - for (sav = LIST_FIRST(&sah->savtree[state]); - sav != NULL; - sav = nextsav) { - - nextsav = LIST_NEXT(sav, chain); - - /* sanity check */ - KEY_CHKSASTATE(sav->state, state, "key_do_allocsa_policy"); - - /* initialize */ - if (candidate == NULL) { - candidate = sav; - continue; - } - - /* Which SA is the better ? */ - - /* sanity check 2 */ - if (candidate->lft_c == NULL || sav->lft_c == NULL) - panic("key_do_allocsa_policy: " - "lifetime_current is NULL.\n"); - - /* What the best method is to compare ? */ - if (key_preferred_oldsa) { - if (candidate->lft_c->sadb_lifetime_addtime > - sav->lft_c->sadb_lifetime_addtime) { - candidate = sav; - } - continue; - /*NOTREACHED*/ - } - - /* prefered new sa rather than old sa */ - if (candidate->lft_c->sadb_lifetime_addtime < - sav->lft_c->sadb_lifetime_addtime) { - d = candidate; - candidate = sav; - } else - d = sav; - - /* - * prepared to delete the SA when there is more - * suitable candidate and the lifetime of the SA is not - * permanent. - */ - if (d->lft_c->sadb_lifetime_addtime != 0) { - struct mbuf *m, *result; - - key_sa_chgstate(d, SADB_SASTATE_DEAD); - - m = key_setsadbmsg(SADB_DELETE, 0, - d->sah->saidx.proto, 0, 0, d->refcnt - 1); - if (!m) - goto msgfail; - result = m; - - /* set sadb_address for saidx's. */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - (struct sockaddr *)&d->sah->saidx.src, - d->sah->saidx.src.ss_len << 3, - IPSEC_ULPROTO_ANY); - if (!m) - goto msgfail; - m_cat(result, m); - - /* set sadb_address for saidx's. */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - (struct sockaddr *)&d->sah->saidx.src, - d->sah->saidx.src.ss_len << 3, - IPSEC_ULPROTO_ANY); - if (!m) - goto msgfail; - m_cat(result, m); - - /* create SA extension */ - m = key_setsadbsa(d); - if (!m) - goto msgfail; - m_cat(result, m); - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, - sizeof(struct sadb_msg)); - if (result == NULL) - goto msgfail; - } - - result->m_pkthdr.len = 0; - for (m = result; m; m = m->m_next) - result->m_pkthdr.len += m->m_len; - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - if (key_sendup_mbuf(NULL, result, - KEY_SENDUP_REGISTERED)) - goto msgfail; - msgfail: - key_freesav(d); - } - } - - if (candidate) { - candidate->refcnt++; - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP allocsa_policy cause " - "refcnt++:%d SA:%p\n", - candidate->refcnt, candidate)); - } - return candidate; -} - -/* - * allocating a SA entry for a *INBOUND* packet. - * Must call key_freesav() later. - * OUT: positive: pointer to a sav. - * NULL: not found, or error occured. - * - * In the comparison, source address will be ignored for RFC2401 conformance. - * To quote, from section 4.1: - * A security association is uniquely identified by a triple consisting - * of a Security Parameter Index (SPI), an IP Destination Address, and a - * security protocol (AH or ESP) identifier. - * Note that, however, we do need to keep source address in IPsec SA. - * IKE specification and PF_KEY specification do assume that we - * keep source address in IPsec SA. We see a tricky situation here. - */ -struct secasvar * -key_allocsa(u_int family, caddr_t src, caddr_t dst, u_int proto, - u_int32_t spi) -{ - struct secashead *sah; - struct secasvar *sav; - u_int stateidx, state; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - const u_int *saorder_state_valid; - int arraysize; - - /* sanity check */ - if (src == NULL || dst == NULL) - panic("key_allocsa: NULL pointer is passed."); - - /* - * when both systems employ similar strategy to use a SA. - * the search order is important even in the inbound case. - */ - if (key_preferred_oldsa) { - saorder_state_valid = saorder_state_valid_prefer_old; - arraysize = NELEM(saorder_state_valid_prefer_old); - } else { - saorder_state_valid = saorder_state_valid_prefer_new; - arraysize = NELEM(saorder_state_valid_prefer_new); - } - - /* - * searching SAD. - * XXX: to be checked internal IP header somewhere. Also when - * IPsec tunnel packet is received. But ESP tunnel mode is - * encrypted so we can't check internal IP header. - */ - lwkt_gettoken(&key_token); - LIST_FOREACH(sah, &sahtree, chain) { - /* - * search a valid state list for inbound packet. - * the search order is not important. - */ - for (stateidx = 0; stateidx < arraysize; stateidx++) { - state = saorder_state_valid[stateidx]; - LIST_FOREACH(sav, &sah->savtree[state], chain) { - /* sanity check */ - KEY_CHKSASTATE(sav->state, state, "key_allocsav"); - if (proto != sav->sah->saidx.proto) - continue; - if (spi != sav->spi) - continue; - if (family != sav->sah->saidx.src.ss_family || - family != sav->sah->saidx.dst.ss_family) - continue; - -#if 0 /* don't check src */ - /* check src address */ - switch (family) { - case AF_INET: - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(sin); - bcopy(src, &sin.sin_addr, - sizeof(sin.sin_addr)); - if (key_sockaddrcmp((struct sockaddr*)&sin, - (struct sockaddr *)&sav->sah->saidx.src, 0) != 0) - continue; - - break; - case AF_INET6: - bzero(&sin6, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_len = sizeof(sin6); - bcopy(src, &sin6.sin6_addr, - sizeof(sin6.sin6_addr)); - if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) { - /* kame fake scopeid */ - sin6.sin6_scope_id = - ntohs(sin6.sin6_addr.s6_addr16[1]); - sin6.sin6_addr.s6_addr16[1] = 0; - } - if (key_sockaddrcmp((struct sockaddr*)&sin6, - (struct sockaddr *)&sav->sah->saidx.src, 0) != 0) - continue; - break; - default: - ipseclog((LOG_DEBUG, "key_allocsa: " - "unknown address family=%d.\n", - family)); - continue; - } - -#endif - /* check dst address */ - switch (family) { - case AF_INET: - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(sin); - bcopy(dst, &sin.sin_addr, - sizeof(sin.sin_addr)); - if (key_sockaddrcmp((struct sockaddr*)&sin, - (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0) - continue; - - break; - case AF_INET6: - bzero(&sin6, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_len = sizeof(sin6); - bcopy(dst, &sin6.sin6_addr, - sizeof(sin6.sin6_addr)); - if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) { - /* kame fake scopeid */ - sin6.sin6_scope_id = - ntohs(sin6.sin6_addr.s6_addr16[1]); - sin6.sin6_addr.s6_addr16[1] = 0; - } - if (key_sockaddrcmp((struct sockaddr*)&sin6, - (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0) - continue; - break; - default: - ipseclog((LOG_DEBUG, "key_allocsa: " - "unknown address family=%d.\n", - family)); - continue; - } - - goto found; - } - } - } - - /* not found */ - lwkt_reltoken(&key_token); - return NULL; - -found: - sav->refcnt++; - lwkt_reltoken(&key_token); - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP allocsa cause refcnt++:%d SA:%p\n", - sav->refcnt, sav)); - return sav; -} - -/* - * Must be called after calling key_allocsp(). - * For both the packet without socket and key_freeso(). - */ -void -key_freesp(struct secpolicy *sp) -{ - /* sanity check */ - if (sp == NULL) - panic("key_freesp: NULL pointer is passed."); - - lwkt_gettoken(&key_token); - sp->refcnt--; - if (sp->refcnt == 0) - key_delsp(sp); - lwkt_reltoken(&key_token); -} - -/* - * Must be called after calling key_allocsp(). - * For the packet with socket. - */ -void -key_freeso(struct socket *so) -{ - /* sanity check */ - if (so == NULL) - panic("key_freeso: NULL pointer is passed."); - - lwkt_gettoken(&key_token); - switch (so->so_proto->pr_domain->dom_family) { -#ifdef INET - case PF_INET: - { - struct inpcb *pcb = so->so_pcb; - - /* Does it have a PCB ? */ - if (pcb == NULL) - break; - key_freesp_so(&pcb->inp_sp->sp_in); - key_freesp_so(&pcb->inp_sp->sp_out); - } - break; -#endif -#ifdef INET6 - case PF_INET6: - { -#ifdef HAVE_NRL_INPCB - struct inpcb *pcb = so->so_pcb; - - /* Does it have a PCB ? */ - if (pcb == NULL) - break; - key_freesp_so(&pcb->inp_sp->sp_in); - key_freesp_so(&pcb->inp_sp->sp_out); -#else - struct in6pcb *pcb = so->so_pcb; - - /* Does it have a PCB ? */ - if (pcb == NULL) - break; - key_freesp_so(&pcb->in6p_sp->sp_in); - key_freesp_so(&pcb->in6p_sp->sp_out); -#endif - } - break; -#endif /* INET6 */ - default: - ipseclog((LOG_DEBUG, "key_freeso: unknown address family=%d.\n", - so->so_proto->pr_domain->dom_family)); - break; - } - lwkt_reltoken(&key_token); -} - -static void -key_freesp_so(struct secpolicy **sp) -{ - /* sanity check */ - if (sp == NULL || *sp == NULL) - panic("key_freesp_so: sp == NULL"); - - switch ((*sp)->policy) { - case IPSEC_POLICY_IPSEC: - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP freeso calls free SP:%p\n", *sp)); - key_freesp(*sp); - *sp = NULL; - break; - case IPSEC_POLICY_ENTRUST: - case IPSEC_POLICY_BYPASS: - return; - default: - panic("key_freesp_so: Invalid policy found %d", (*sp)->policy); - } - - return; -} - -/* - * Must be called after calling key_allocsa(). - * This function is called by key_freesp() to free some SA allocated - * for a policy. - */ -void -key_freesav(struct secasvar *sav) -{ - /* sanity check */ - if (sav == NULL) - panic("key_freesav: NULL pointer is passed."); - - lwkt_gettoken(&key_token); - sav->refcnt--; - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP freesav cause refcnt--:%d SA:%p SPI %u\n", - sav->refcnt, sav, (u_int32_t)ntohl(sav->spi))); - - if (sav->refcnt == 0) - key_delsav(sav); - - lwkt_reltoken(&key_token); -} - -/* %%% SPD management */ -/* - * free security policy entry. - */ -static void -key_delsp(struct secpolicy *sp) -{ - /* sanity check */ - if (sp == NULL) - panic("key_delsp: NULL pointer is passed."); - - sp->state = IPSEC_SPSTATE_DEAD; - - if (sp->refcnt > 0) - return; /* can't free */ - - /* remove from SP index */ - if (__LIST_CHAINED(sp)) - LIST_REMOVE(sp, chain); - - { - struct ipsecrequest *isr = sp->req, *nextisr; - - while (isr != NULL) { - if (isr->sav != NULL) { - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP delsp calls free SA:%p\n", - isr->sav)); - key_freesav(isr->sav); - isr->sav = NULL; - } - - nextisr = isr->next; - KFREE(isr); - isr = nextisr; - } - } - keydb_delsecpolicy(sp); -} - -/* - * search SPD - * OUT: NULL : not found - * others : found, pointer to a SP. - */ -static struct secpolicy * -key_getsp(struct secpolicyindex *spidx) -{ - struct secpolicy *sp; - - /* sanity check */ - if (spidx == NULL) - panic("key_getsp: NULL pointer is passed."); - - LIST_FOREACH(sp, &sptree[spidx->dir], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (key_cmpspidx_exactly(spidx, &sp->spidx)) { - sp->refcnt++; - return sp; - } - } - - return NULL; -} - -/* - * get SP by index. - * OUT: NULL : not found - * others : found, pointer to a SP. - */ -static struct secpolicy * -key_getspbyid(u_int32_t id) -{ - struct secpolicy *sp; - - LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (sp->id == id) { - sp->refcnt++; - return sp; - } - } - - LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (sp->id == id) { - sp->refcnt++; - return sp; - } - } - - return NULL; -} - -struct secpolicy * -key_newsp(void) -{ - struct secpolicy *newsp = NULL; - - lwkt_gettoken(&key_token); - newsp = keydb_newsecpolicy(); - if (newsp) { - newsp->refcnt = 1; - newsp->req = NULL; - } - lwkt_reltoken(&key_token); - - return newsp; -} - -/* - * create secpolicy structure from sadb_x_policy structure. - * NOTE: `state', `secpolicyindex' in secpolicy structure are not set, - * so must be set properly later. - */ -struct secpolicy * -key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error) -{ - struct secpolicy *newsp; - - /* sanity check */ - if (xpl0 == NULL) - panic("key_msg2sp: NULL pointer was passed."); - if (len < sizeof(*xpl0)) - panic("key_msg2sp: invalid length."); - if (len != PFKEY_EXTLEN(xpl0)) { - ipseclog((LOG_DEBUG, "key_msg2sp: Invalid msg length.\n")); - *error = EINVAL; - return NULL; - } - - lwkt_gettoken(&key_token); - if ((newsp = key_newsp()) == NULL) { - lwkt_reltoken(&key_token); - *error = ENOBUFS; - return NULL; - } - - newsp->spidx.dir = xpl0->sadb_x_policy_dir; - newsp->policy = xpl0->sadb_x_policy_type; - - /* check policy */ - switch (xpl0->sadb_x_policy_type) { - case IPSEC_POLICY_DISCARD: - case IPSEC_POLICY_NONE: - case IPSEC_POLICY_ENTRUST: - case IPSEC_POLICY_BYPASS: - newsp->req = NULL; - break; - - case IPSEC_POLICY_IPSEC: - { - int tlen; - struct sadb_x_ipsecrequest *xisr; - struct ipsecrequest **p_isr = &newsp->req; - - /* validity check */ - if (PFKEY_EXTLEN(xpl0) < sizeof(*xpl0)) { - ipseclog((LOG_DEBUG, - "key_msg2sp: Invalid msg length.\n")); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = EINVAL; - return NULL; - } - - tlen = PFKEY_EXTLEN(xpl0) - sizeof(*xpl0); - xisr = (struct sadb_x_ipsecrequest *)(xpl0 + 1); - - while (tlen > 0) { - - /* length check */ - if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) { - ipseclog((LOG_DEBUG, "key_msg2sp: " - "invalid ipsecrequest length.\n")); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = EINVAL; - return NULL; - } - - /* allocate request buffer */ - KMALLOC(*p_isr, struct ipsecrequest *, sizeof(**p_isr)); - if ((*p_isr) == NULL) { - ipseclog((LOG_DEBUG, - "key_msg2sp: No more memory.\n")); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = ENOBUFS; - return NULL; - } - bzero(*p_isr, sizeof(**p_isr)); - - /* set values */ - (*p_isr)->next = NULL; - - switch (xisr->sadb_x_ipsecrequest_proto) { - case IPPROTO_ESP: - case IPPROTO_AH: - case IPPROTO_IPCOMP: - break; - default: - ipseclog((LOG_DEBUG, - "key_msg2sp: invalid proto type=%u\n", - xisr->sadb_x_ipsecrequest_proto)); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = EPROTONOSUPPORT; - return NULL; - } - (*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto; - - switch (xisr->sadb_x_ipsecrequest_mode) { - case IPSEC_MODE_TRANSPORT: - case IPSEC_MODE_TUNNEL: - break; - case IPSEC_MODE_ANY: - default: - ipseclog((LOG_DEBUG, - "key_msg2sp: invalid mode=%u\n", - xisr->sadb_x_ipsecrequest_mode)); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = EINVAL; - return NULL; - } - (*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode; - - switch (xisr->sadb_x_ipsecrequest_level) { - case IPSEC_LEVEL_DEFAULT: - case IPSEC_LEVEL_USE: - case IPSEC_LEVEL_REQUIRE: - break; - case IPSEC_LEVEL_UNIQUE: - /* validity check */ - /* - * If range violation of reqid, kernel will - * update it, don't refuse it. - */ - if (xisr->sadb_x_ipsecrequest_reqid - > IPSEC_MANUAL_REQID_MAX) { - ipseclog((LOG_DEBUG, - "key_msg2sp: reqid=%d range " - "violation, updated by kernel.\n", - xisr->sadb_x_ipsecrequest_reqid)); - xisr->sadb_x_ipsecrequest_reqid = 0; - } - - /* allocate new reqid id if reqid is zero. */ - if (xisr->sadb_x_ipsecrequest_reqid == 0) { - u_int32_t reqid; - if ((reqid = key_newreqid()) == 0) { - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = ENOBUFS; - return NULL; - } - (*p_isr)->saidx.reqid = reqid; - xisr->sadb_x_ipsecrequest_reqid = reqid; - } else { - /* set it for manual keying. */ - (*p_isr)->saidx.reqid = - xisr->sadb_x_ipsecrequest_reqid; - } - break; - - default: - ipseclog((LOG_DEBUG, "key_msg2sp: invalid level=%u\n", - xisr->sadb_x_ipsecrequest_level)); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = EINVAL; - return NULL; - } - (*p_isr)->level = xisr->sadb_x_ipsecrequest_level; - - /* set IP addresses if there */ - if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) { - struct sockaddr *paddr; - - paddr = (struct sockaddr *)(xisr + 1); - - /* validity check */ - if (paddr->sa_len - > sizeof((*p_isr)->saidx.src)) { - ipseclog((LOG_DEBUG, "key_msg2sp: invalid request " - "address length.\n")); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = EINVAL; - return NULL; - } - bcopy(paddr, &(*p_isr)->saidx.src, - paddr->sa_len); - - paddr = (struct sockaddr *)((caddr_t)paddr - + paddr->sa_len); - - /* validity check */ - if (paddr->sa_len - > sizeof((*p_isr)->saidx.dst)) { - ipseclog((LOG_DEBUG, "key_msg2sp: invalid request " - "address length.\n")); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = EINVAL; - return NULL; - } - bcopy(paddr, &(*p_isr)->saidx.dst, - paddr->sa_len); - } - - (*p_isr)->sav = NULL; - (*p_isr)->sp = newsp; - - /* initialization for the next. */ - p_isr = &(*p_isr)->next; - tlen -= xisr->sadb_x_ipsecrequest_len; - - /* validity check */ - if (tlen < 0) { - ipseclog((LOG_DEBUG, "key_msg2sp: becoming tlen < 0.\n")); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = EINVAL; - return NULL; - } - - xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr - + xisr->sadb_x_ipsecrequest_len); - } - } - break; - default: - ipseclog((LOG_DEBUG, "key_msg2sp: invalid policy type.\n")); - key_freesp(newsp); - lwkt_reltoken(&key_token); - *error = EINVAL; - return NULL; - } - lwkt_reltoken(&key_token); - *error = 0; - return newsp; -} - -static u_int32_t -key_newreqid(void) -{ - static u_int32_t auto_reqid = IPSEC_MANUAL_REQID_MAX + 1; - - auto_reqid = (auto_reqid == ~0 - ? IPSEC_MANUAL_REQID_MAX + 1 : auto_reqid + 1); - - /* XXX should be unique check */ - - return auto_reqid; -} - -/* - * copy secpolicy struct to sadb_x_policy structure indicated. - */ -struct mbuf * -key_sp2msg(struct secpolicy *sp) -{ - struct sadb_x_policy *xpl; - int tlen; - caddr_t p; - struct mbuf *m; - - /* sanity check. */ - if (sp == NULL) - panic("key_sp2msg: NULL pointer was passed."); - - lwkt_gettoken(&key_token); - tlen = key_getspreqmsglen(sp); - - m = key_alloc_mbuf(tlen); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - lwkt_reltoken(&key_token); - return NULL; - } - - m->m_len = tlen; - m->m_next = NULL; - xpl = mtod(m, struct sadb_x_policy *); - bzero(xpl, tlen); - - xpl->sadb_x_policy_len = PFKEY_UNIT64(tlen); - xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY; - xpl->sadb_x_policy_type = sp->policy; - xpl->sadb_x_policy_dir = sp->spidx.dir; - xpl->sadb_x_policy_id = sp->id; - p = (caddr_t)xpl + sizeof(*xpl); - - /* if is the policy for ipsec ? */ - if (sp->policy == IPSEC_POLICY_IPSEC) { - struct sadb_x_ipsecrequest *xisr; - struct ipsecrequest *isr; - - for (isr = sp->req; isr != NULL; isr = isr->next) { - - xisr = (struct sadb_x_ipsecrequest *)p; - - xisr->sadb_x_ipsecrequest_proto = isr->saidx.proto; - xisr->sadb_x_ipsecrequest_mode = isr->saidx.mode; - xisr->sadb_x_ipsecrequest_level = isr->level; - xisr->sadb_x_ipsecrequest_reqid = isr->saidx.reqid; - - p += sizeof(*xisr); - bcopy(&isr->saidx.src, p, isr->saidx.src.ss_len); - p += isr->saidx.src.ss_len; - bcopy(&isr->saidx.dst, p, isr->saidx.dst.ss_len); - p += isr->saidx.src.ss_len; - - xisr->sadb_x_ipsecrequest_len = - PFKEY_ALIGN8(sizeof(*xisr) - + isr->saidx.src.ss_len - + isr->saidx.dst.ss_len); - } - } - lwkt_reltoken(&key_token); - return m; -} - -/* m will not be freed nor modified */ -static struct mbuf * -key_gather_mbuf(struct mbuf *m, const struct sadb_msghdr *mhp, - int ndeep, int nitem, ...) -{ - __va_list ap; - int idx; - int i; - struct mbuf *result = NULL, *n; - int len; - - if (m == NULL || mhp == NULL) - panic("null pointer passed to key_gather"); - - __va_start(ap, nitem); - for (i = 0; i < nitem; i++) { - idx = __va_arg(ap, int); - if (idx < 0 || idx > SADB_EXT_MAX) - goto fail; - /* don't attempt to pull empty extension */ - if (idx == SADB_EXT_RESERVED && mhp->msg == NULL) - continue; - if (idx != SADB_EXT_RESERVED && - (mhp->ext[idx] == NULL || mhp->extlen[idx] == 0)) - continue; - - if (idx == SADB_EXT_RESERVED) { - len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); -#ifdef DIAGNOSTIC - if (len > MHLEN) - panic("assumption failed"); -#endif - MGETHDR(n, M_NOWAIT, MT_DATA); - if (!n) - goto fail; - n->m_len = len; - n->m_next = NULL; - m_copydata(m, 0, sizeof(struct sadb_msg), - mtod(n, caddr_t)); - } else if (i < ndeep) { - len = mhp->extlen[idx]; - n = key_alloc_mbuf(len); - if (!n || n->m_next) { /*XXX*/ - if (n) - m_freem(n); - goto fail; - } - m_copydata(m, mhp->extoff[idx], mhp->extlen[idx], - mtod(n, caddr_t)); - } else { - n = m_copym(m, mhp->extoff[idx], mhp->extlen[idx], - M_NOWAIT); - } - if (n == NULL) - goto fail; - - if (result) - m_cat(result, n); - else - result = n; - } - __va_end(ap); - - if ((result->m_flags & M_PKTHDR) != 0) { - result->m_pkthdr.len = 0; - for (n = result; n; n = n->m_next) - result->m_pkthdr.len += n->m_len; - } - - return result; - -fail: - m_freem(result); - return NULL; -} - -/* - * SADB_X_SPDADD, SADB_X_SPDSETIDX or SADB_X_SPDUPDATE processing - * add a entry to SP database, when received - * - * from the user(?). - * Adding to SP database, - * and send - * - * to the socket which was send. - * - * SPDADD set a unique policy entry. - * SPDSETIDX like SPDADD without a part of policy requests. - * SPDUPDATE replace a unique policy entry. - * - * m will always be freed. - */ -static int -key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_address *src0, *dst0; - struct sadb_x_policy *xpl0, *xpl; - struct sadb_lifetime *lft = NULL; - struct secpolicyindex spidx; - struct secpolicy *newsp; - struct timeval tv; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spdadd: NULL pointer is passed."); - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - mhp->ext[SADB_X_EXT_POLICY] == NULL) { - ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { - ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL) { - if (mhp->extlen[SADB_EXT_LIFETIME_HARD] - < sizeof(struct sadb_lifetime)) { - ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - lft = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD]; - } - - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY]; - - /* make secindex */ - /* XXX boundary check against sa_len */ - KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, - src0 + 1, - dst0 + 1, - src0->sadb_address_prefixlen, - dst0->sadb_address_prefixlen, - src0->sadb_address_proto, - &spidx); - - /* checking the direciton. */ - switch (xpl0->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - case IPSEC_DIR_OUTBOUND: - break; - default: - ipseclog((LOG_DEBUG, "key_spdadd: Invalid SP direction.\n")); - mhp->msg->sadb_msg_errno = EINVAL; - return 0; - } - - /* check policy */ - /* key_spdadd() accepts DISCARD, NONE and IPSEC. */ - if (xpl0->sadb_x_policy_type == IPSEC_POLICY_ENTRUST - || xpl0->sadb_x_policy_type == IPSEC_POLICY_BYPASS) { - ipseclog((LOG_DEBUG, "key_spdadd: Invalid policy type.\n")); - return key_senderror(so, m, EINVAL); - } - - /* policy requests are mandatory when action is ipsec. */ - if (mhp->msg->sadb_msg_type != SADB_X_SPDSETIDX - && xpl0->sadb_x_policy_type == IPSEC_POLICY_IPSEC - && mhp->extlen[SADB_X_EXT_POLICY] <= sizeof(*xpl0)) { - ipseclog((LOG_DEBUG, "key_spdadd: some policy requests part required.\n")); - return key_senderror(so, m, EINVAL); - } - - /* - * checking there is SP already or not. - * SPDUPDATE doesn't depend on whether there is a SP or not. - * If the type is either SPDADD or SPDSETIDX AND a SP is found, - * then error. - */ - newsp = key_getsp(&spidx); - if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { - if (newsp) { - newsp->state = IPSEC_SPSTATE_DEAD; - key_freesp(newsp); - } - } else { - if (newsp != NULL) { - key_freesp(newsp); - ipseclog((LOG_DEBUG, "key_spdadd: a SP entry exists already.\n")); - return key_senderror(so, m, EEXIST); - } - } - - /* allocation new SP entry */ - if ((newsp = key_msg2sp(xpl0, PFKEY_EXTLEN(xpl0), &error)) == NULL) { - return key_senderror(so, m, error); - } - - if ((newsp->id = key_getnewspid()) == 0) { - keydb_delsecpolicy(newsp); - return key_senderror(so, m, ENOBUFS); - } - - /* XXX boundary check against sa_len */ - KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, - src0 + 1, - dst0 + 1, - src0->sadb_address_prefixlen, - dst0->sadb_address_prefixlen, - src0->sadb_address_proto, - &newsp->spidx); - - /* sanity check on addr pair */ - if (((struct sockaddr *)(src0 + 1))->sa_family != - ((struct sockaddr *)(dst0+ 1))->sa_family) { - keydb_delsecpolicy(newsp); - return key_senderror(so, m, EINVAL); - } - if (((struct sockaddr *)(src0 + 1))->sa_len != - ((struct sockaddr *)(dst0+ 1))->sa_len) { - keydb_delsecpolicy(newsp); - return key_senderror(so, m, EINVAL); - } -#if 1 - if (newsp->req && newsp->req->saidx.src.ss_family) { - struct sockaddr *sa; - sa = (struct sockaddr *)(src0 + 1); - if (sa->sa_family != newsp->req->saidx.src.ss_family) { - keydb_delsecpolicy(newsp); - return key_senderror(so, m, EINVAL); - } - } - if (newsp->req && newsp->req->saidx.dst.ss_family) { - struct sockaddr *sa; - sa = (struct sockaddr *)(dst0 + 1); - if (sa->sa_family != newsp->req->saidx.dst.ss_family) { - keydb_delsecpolicy(newsp); - return key_senderror(so, m, EINVAL); - } - } -#endif - - microtime(&tv); - newsp->created = tv.tv_sec; - newsp->lastused = tv.tv_sec; - newsp->lifetime = lft ? lft->sadb_lifetime_addtime : 0; - newsp->validtime = lft ? lft->sadb_lifetime_usetime : 0; - - newsp->refcnt = 1; /* do not reclaim until I say I do */ - newsp->state = IPSEC_SPSTATE_ALIVE; - LIST_INSERT_TAIL(&sptree[newsp->spidx.dir], newsp, secpolicy, chain); - - /* delete the entry in spacqtree */ - if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { - struct secspacq *spacq; - if ((spacq = key_getspacq(&spidx)) != NULL) { - /* reset counter in order to deletion by timehandler. */ - microtime(&tv); - spacq->created = tv.tv_sec; - spacq->count = 0; - } - } - - { - struct mbuf *n, *mpolicy; - struct sadb_msg *newmsg; - int off; - - /* create new sadb_msg to reply. */ - if (lft) { - n = key_gather_mbuf(m, mhp, 2, 5, SADB_EXT_RESERVED, - SADB_X_EXT_POLICY, SADB_EXT_LIFETIME_HARD, - SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - } else { - n = key_gather_mbuf(m, mhp, 2, 4, SADB_EXT_RESERVED, - SADB_X_EXT_POLICY, - SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - } - if (!n) - return key_senderror(so, m, ENOBUFS); - - if (n->m_len < sizeof(*newmsg)) { - n = m_pullup(n, sizeof(*newmsg)); - if (!n) - return key_senderror(so, m, ENOBUFS); - } - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - off = 0; - mpolicy = m_pulldown(n, PFKEY_ALIGN8(sizeof(struct sadb_msg)), - sizeof(*xpl), &off); - if (mpolicy == NULL) { - /* n is already freed */ - return key_senderror(so, m, ENOBUFS); - } - xpl = (struct sadb_x_policy *)(mtod(mpolicy, caddr_t) + off); - if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) { - m_freem(n); - return key_senderror(so, m, EINVAL); - } - xpl->sadb_x_policy_id = newsp->id; - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * get new policy id. - * OUT: - * 0: failure. - * others: success. - */ -static u_int32_t -key_getnewspid(void) -{ - u_int32_t newid = 0; - int count = key_spi_trycnt; /* XXX */ - struct secpolicy *sp; - - /* when requesting to allocate spi ranged */ - while (count--) { - newid = (policy_id = (policy_id == ~0 ? 1 : policy_id + 1)); - - if ((sp = key_getspbyid(newid)) == NULL) - break; - - key_freesp(sp); - } - - if (count == 0 || newid == 0) { - ipseclog((LOG_DEBUG, "key_getnewspid: to allocate policy id is failed.\n")); - return 0; - } - - return newid; -} - -/* - * SADB_SPDDELETE processing - * receive - * - * from the user(?), and set SADB_SASTATE_DEAD, - * and send, - * - * to the ikmpd. - * policy(*) including direction of policy. - * - * m will always be freed. - */ -static int -key_spddelete(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct sadb_address *src0, *dst0; - struct sadb_x_policy *xpl0; - struct secpolicyindex spidx; - struct secpolicy *sp; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spddelete: NULL pointer is passed."); - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - mhp->ext[SADB_X_EXT_POLICY] == NULL) { - ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { - ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY]; - - /* make secindex */ - /* XXX boundary check against sa_len */ - KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, - src0 + 1, - dst0 + 1, - src0->sadb_address_prefixlen, - dst0->sadb_address_prefixlen, - src0->sadb_address_proto, - &spidx); - - /* checking the direciton. */ - switch (xpl0->sadb_x_policy_dir) { - case IPSEC_DIR_INBOUND: - case IPSEC_DIR_OUTBOUND: - break; - default: - ipseclog((LOG_DEBUG, "key_spddelete: Invalid SP direction.\n")); - return key_senderror(so, m, EINVAL); - } - - /* Is there SP in SPD ? */ - if ((sp = key_getsp(&spidx)) == NULL) { - ipseclog((LOG_DEBUG, "key_spddelete: no SP found.\n")); - return key_senderror(so, m, EINVAL); - } - - /* save policy id to buffer to be returned. */ - xpl0->sadb_x_policy_id = sp->id; - - sp->state = IPSEC_SPSTATE_DEAD; - key_freesp(sp); - - { - struct mbuf *n; - struct sadb_msg *newmsg; - - /* create new sadb_msg to reply. */ - n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED, - SADB_X_EXT_POLICY, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - if (!n) - return key_senderror(so, m, ENOBUFS); - - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * SADB_SPDDELETE2 processing - * receive - * - * from the user(?), and set SADB_SASTATE_DEAD, - * and send, - * - * to the ikmpd. - * policy(*) including direction of policy. - * - * m will always be freed. - */ -static int -key_spddelete2(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - u_int32_t id; - struct secpolicy *sp; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spddelete2: NULL pointer is passed."); - - if (mhp->ext[SADB_X_EXT_POLICY] == NULL || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { - ipseclog((LOG_DEBUG, "key_spddelete2: invalid message is passed.\n")); - key_senderror(so, m, EINVAL); - return 0; - } - - id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; - - /* Is there SP in SPD ? */ - if ((sp = key_getspbyid(id)) == NULL) { - ipseclog((LOG_DEBUG, "key_spddelete2: no SP found id:%u.\n", id)); - key_senderror(so, m, EINVAL); - } - - sp->state = IPSEC_SPSTATE_DEAD; - key_freesp(sp); - - { - struct mbuf *n, *nn; - struct sadb_msg *newmsg; - int off, len; - - /* create new sadb_msg to reply. */ - len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); - - if (len > MCLBYTES) - return key_senderror(so, m, ENOBUFS); - MGETHDR(n, M_NOWAIT, MT_DATA); - if (n && len > MHLEN) { - MCLGET(n, M_NOWAIT); - if ((n->m_flags & M_EXT) == 0) { - m_freem(n); - n = NULL; - } - } - if (!n) - return key_senderror(so, m, ENOBUFS); - - n->m_len = len; - n->m_next = NULL; - off = 0; - - m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off); - off += PFKEY_ALIGN8(sizeof(struct sadb_msg)); - -#ifdef DIAGNOSTIC - if (off != len) - panic("length inconsistency in key_spddelete2"); -#endif - - n->m_next = m_copym(m, mhp->extoff[SADB_X_EXT_POLICY], - mhp->extlen[SADB_X_EXT_POLICY], M_NOWAIT); - if (!n->m_next) { - m_freem(n); - return key_senderror(so, m, ENOBUFS); - } - - n->m_pkthdr.len = 0; - for (nn = n; nn; nn = nn->m_next) - n->m_pkthdr.len += nn->m_len; - - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * SADB_X_GET processing - * receive - * - * from the user(?), - * and send, - * - * to the ikmpd. - * policy(*) including direction of policy. - * - * m will always be freed. - */ -static int -key_spdget(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - u_int32_t id; - struct secpolicy *sp; - struct mbuf *n; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spdget: NULL pointer is passed."); - - if (mhp->ext[SADB_X_EXT_POLICY] == NULL || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { - ipseclog((LOG_DEBUG, "key_spdget: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; - - /* Is there SP in SPD ? */ - if ((sp = key_getspbyid(id)) == NULL) { - ipseclog((LOG_DEBUG, "key_spdget: no SP found id:%u.\n", id)); - return key_senderror(so, m, ENOENT); - } - - n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid); - if (n != NULL) { - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } else - return key_senderror(so, m, ENOBUFS); -} - -/* - * SADB_X_SPDACQUIRE processing. - * Acquire policy and SA(s) for a *OUTBOUND* packet. - * send - * - * to KMD, and expect to receive - * with SADB_X_SPDACQUIRE if error occured, - * or - * - * with SADB_X_SPDUPDATE from KMD by PF_KEY. - * policy(*) is without policy requests. - * - * 0 : succeed - * others: error number - */ -int -key_spdacquire(struct secpolicy *sp) -{ - struct mbuf *result = NULL, *m; - struct secspacq *newspacq; - int error; - - /* sanity check */ - if (sp == NULL) - panic("key_spdacquire: NULL pointer is passed."); - if (sp->req != NULL) - panic("key_spdacquire: called but there is request."); - if (sp->policy != IPSEC_POLICY_IPSEC) - panic("key_spdacquire: policy mismatched. IPsec is expected."); - - lwkt_gettoken(&key_token); - /* get a entry to check whether sent message or not. */ - if ((newspacq = key_getspacq(&sp->spidx)) != NULL) { - if (key_blockacq_count < newspacq->count) { - /* reset counter and do send message. */ - newspacq->count = 0; - } else { - /* increment counter and do nothing. */ - newspacq->count++; - lwkt_reltoken(&key_token); - return 0; - } - } else { - /* make new entry for blocking to send SADB_ACQUIRE. */ - if ((newspacq = key_newspacq(&sp->spidx)) == NULL) { - lwkt_reltoken(&key_token); - return ENOBUFS; - } - - /* add to acqtree */ - LIST_INSERT_HEAD(&spacqtree, newspacq, chain); - } - - /* create new sadb_msg to reply. */ - m = key_setsadbmsg(SADB_X_SPDACQUIRE, 0, 0, 0, 0, 0); - if (!m) { - error = ENOBUFS; - goto fail; - } - result = m; - - result->m_pkthdr.len = 0; - for (m = result; m; m = m->m_next) - result->m_pkthdr.len += m->m_len; - - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - error = key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED); - lwkt_reltoken(&key_token); - return error; - -fail: - lwkt_reltoken(&key_token); - if (result) - m_freem(result); - return error; -} - -/* - * SADB_SPDFLUSH processing - * receive - * - * from the user, and free all entries in secpctree. - * and send, - * - * to the user. - * NOTE: what to do is only marking SADB_SASTATE_DEAD. - * - * m will always be freed. - */ -static int -key_spdflush(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct sadb_msg *newmsg; - struct secpolicy *sp; - u_int dir; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spdflush: NULL pointer is passed."); - - if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg))) - return key_senderror(so, m, EINVAL); - - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH(sp, &sptree[dir], chain) { - sp->state = IPSEC_SPSTATE_DEAD; - } - } - - if (sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) { - ipseclog((LOG_DEBUG, "key_spdflush: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - - if (m->m_next) - m_freem(m->m_next); - m->m_next = NULL; - m->m_pkthdr.len = m->m_len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); - newmsg = mtod(m, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); -} - -/* - * SADB_SPDDUMP processing - * receive - * - * from the user, and dump all SP leaves - * and send, - * ..... - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_spddump(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct secpolicy *sp; - int cnt; - u_int dir; - struct mbuf *n; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spddump: NULL pointer is passed."); - - /* search SPD entry and get buffer size. */ - cnt = 0; - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH(sp, &sptree[dir], chain) { - cnt++; - } - } - - if (cnt == 0) - return key_senderror(so, m, ENOENT); - - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - LIST_FOREACH(sp, &sptree[dir], chain) { - --cnt; - n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, - mhp->msg->sadb_msg_pid); - - if (n) - key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } - } - - m_freem(m); - return 0; -} - -static struct mbuf * -key_setdumpsp(struct secpolicy *sp, u_int8_t type, u_int32_t seq, - u_int32_t pid) -{ - struct mbuf *result = NULL, *m; - - m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt); - if (!m) - goto fail; - result = m; - - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - (struct sockaddr *)&sp->spidx.src, sp->spidx.prefs, - sp->spidx.ul_proto); - if (!m) - goto fail; - m_cat(result, m); - - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - (struct sockaddr *)&sp->spidx.dst, sp->spidx.prefd, - sp->spidx.ul_proto); - if (!m) - goto fail; - m_cat(result, m); - - m = key_sp2msg(sp); - if (!m) - goto fail; - m_cat(result, m); - - if ((result->m_flags & M_PKTHDR) == 0) - goto fail; - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) - goto fail; - } - - result->m_pkthdr.len = 0; - for (m = result; m; m = m->m_next) - result->m_pkthdr.len += m->m_len; - - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - return result; - -fail: - m_freem(result); - return NULL; -} - -/* - * get PFKEY message length for security policy and request. - */ -static u_int -key_getspreqmsglen(struct secpolicy *sp) -{ - u_int tlen; - - tlen = sizeof(struct sadb_x_policy); - - /* if is the policy for ipsec ? */ - if (sp->policy != IPSEC_POLICY_IPSEC) - return tlen; - - /* get length of ipsec requests */ - { - struct ipsecrequest *isr; - int len; - - for (isr = sp->req; isr != NULL; isr = isr->next) { - len = sizeof(struct sadb_x_ipsecrequest) - + isr->saidx.src.ss_len - + isr->saidx.dst.ss_len; - - tlen += PFKEY_ALIGN8(len); - } - } - - return tlen; -} - -/* - * SADB_SPDEXPIRE processing - * send - * - * to KMD by PF_KEY. - * - * OUT: 0 : succeed - * others : error number - */ -static int -key_spdexpire(struct secpolicy *sp) -{ - struct mbuf *result = NULL, *m; - int len; - int error = -1; - struct sadb_lifetime *lt; - - /* XXX: Why do we lock ? */ - - /* sanity check */ - if (sp == NULL) - panic("key_spdexpire: NULL pointer is passed."); - - /* set msg header */ - m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0); - if (!m) { - error = ENOBUFS; - goto fail; - } - result = m; - - /* create lifetime extension (current and hard) */ - len = PFKEY_ALIGN8(sizeof(*lt)) * 2; - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - error = ENOBUFS; - goto fail; - } - bzero(mtod(m, caddr_t), len); - lt = mtod(m, struct sadb_lifetime *); - lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); - lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; - lt->sadb_lifetime_allocations = 0; - lt->sadb_lifetime_bytes = 0; - lt->sadb_lifetime_addtime = sp->created; - lt->sadb_lifetime_usetime = sp->lastused; - lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2); - lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); - lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; - lt->sadb_lifetime_allocations = 0; - lt->sadb_lifetime_bytes = 0; - lt->sadb_lifetime_addtime = sp->lifetime; - lt->sadb_lifetime_usetime = sp->validtime; - m_cat(result, m); - - /* set sadb_address for source */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - (struct sockaddr *)&sp->spidx.src, - sp->spidx.prefs, sp->spidx.ul_proto); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* set sadb_address for destination */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - (struct sockaddr *)&sp->spidx.dst, - sp->spidx.prefd, sp->spidx.ul_proto); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* set secpolicy */ - m = key_sp2msg(sp); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - if ((result->m_flags & M_PKTHDR) == 0) { - error = EINVAL; - goto fail; - } - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) { - error = ENOBUFS; - goto fail; - } - } - - result->m_pkthdr.len = 0; - for (m = result; m; m = m->m_next) - result->m_pkthdr.len += m->m_len; - - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); - - fail: - if (result) - m_freem(result); - return error; -} - -/* %%% SAD management */ -/* - * allocating a memory for new SA head, and copy from the values of mhp. - * OUT: NULL : failure due to the lack of memory. - * others : pointer to new SA head. - */ -static struct secashead * -key_newsah(struct secasindex *saidx) -{ - struct secashead *newsah; - - /* sanity check */ - if (saidx == NULL) - panic("key_newsaidx: NULL pointer is passed."); - - newsah = keydb_newsecashead(); - if (newsah == NULL) - return NULL; - - bcopy(saidx, &newsah->saidx, sizeof(newsah->saidx)); - - /* add to saidxtree */ - newsah->state = SADB_SASTATE_MATURE; - LIST_INSERT_HEAD(&sahtree, newsah, chain); - - return(newsah); -} - -/* - * delete SA index and all SA registerd. - */ -static void -key_delsah(struct secashead *sah) -{ - struct secasvar *sav, *nextsav; - u_int stateidx, state; - int zombie = 0; - - /* sanity check */ - if (sah == NULL) - panic("key_delsah: NULL pointer is passed."); - - /* searching all SA registerd in the secindex. */ - for (stateidx = 0; - stateidx < NELEM(saorder_state_any); - stateidx++) { - - state = saorder_state_any[stateidx]; - for (sav = (struct secasvar *)LIST_FIRST(&sah->savtree[state]); - sav != NULL; - sav = nextsav) { - - nextsav = LIST_NEXT(sav, chain); - - if (sav->refcnt > 0) { - /* give up to delete this sa */ - zombie++; - continue; - } - - /* sanity check */ - KEY_CHKSASTATE(state, sav->state, "key_delsah"); - - key_freesav(sav); - - /* remove back pointer */ - sav->sah = NULL; - sav = NULL; - } - } - - /* don't delete sah only if there are savs. */ - if (zombie) - return; - - if (sah->sa_route.ro_rt) { - RTFREE(sah->sa_route.ro_rt); - sah->sa_route.ro_rt = NULL; - } - - /* remove from tree of SA index */ - if (__LIST_CHAINED(sah)) - LIST_REMOVE(sah, chain); - - KFREE(sah); - - return; -} - -/* - * allocating a new SA with LARVAL state. key_add() and key_getspi() call, - * and copy the values of mhp into new buffer. - * When SAD message type is GETSPI: - * to set sequence number from acq_seq++, - * to set zero to SPI. - * not to call key_setsava(). - * OUT: NULL : fail - * others : pointer to new secasvar. - * - * does not modify mbuf. does not free mbuf on error. - */ -static struct secasvar * -key_newsav(struct mbuf *m, const struct sadb_msghdr *mhp, - struct secashead *sah, int *errp) -{ - struct secasvar *newsav; - const struct sadb_sa *xsa; - - /* sanity check */ - if (m == NULL || mhp == NULL || mhp->msg == NULL || sah == NULL) - panic("key_newsa: NULL pointer is passed."); - - KMALLOC(newsav, struct secasvar *, sizeof(struct secasvar)); - if (newsav == NULL) { - ipseclog((LOG_DEBUG, "key_newsa: No more memory.\n")); - *errp = ENOBUFS; - return NULL; - } - bzero((caddr_t)newsav, sizeof(struct secasvar)); - - switch (mhp->msg->sadb_msg_type) { - case SADB_GETSPI: - newsav->spi = 0; - -#ifdef IPSEC_DOSEQCHECK - /* sync sequence number */ - if (mhp->msg->sadb_msg_seq == 0) - newsav->seq = - (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq)); - else -#endif - newsav->seq = mhp->msg->sadb_msg_seq; - break; - - case SADB_ADD: - /* sanity check */ - if (mhp->ext[SADB_EXT_SA] == NULL) { - KFREE(newsav); - ipseclog((LOG_DEBUG, "key_newsa: invalid message is passed.\n")); - *errp = EINVAL; - return NULL; - } - xsa = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - newsav->spi = xsa->sadb_sa_spi; - newsav->seq = mhp->msg->sadb_msg_seq; - break; - default: - KFREE(newsav); - *errp = EINVAL; - return NULL; - } - - /* copy sav values */ - if (mhp->msg->sadb_msg_type != SADB_GETSPI) { - *errp = key_setsaval(newsav, m, mhp); - if (*errp) { - KFREE(newsav); - return NULL; - } - } - - /* reset created */ - { - struct timeval tv; - microtime(&tv); - newsav->created = tv.tv_sec; - } - - newsav->pid = mhp->msg->sadb_msg_pid; - - /* add to satree */ - newsav->sah = sah; - newsav->refcnt = 1; - newsav->state = SADB_SASTATE_LARVAL; - LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav, - secasvar, chain); - - return newsav; -} - -/* - * free() SA variable entry. - */ -static void -key_delsav(struct secasvar *sav) -{ - /* sanity check */ - if (sav == NULL) - panic("key_delsav: NULL pointer is passed."); - - if (sav->refcnt > 0) - return; /* can't free */ - - /* remove from SA header */ - if (__LIST_CHAINED(sav)) - LIST_REMOVE(sav, chain); - - if (sav->key_auth != NULL) { - bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth)); - KFREE(sav->key_auth); - sav->key_auth = NULL; - } - if (sav->key_enc != NULL) { - bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc)); - KFREE(sav->key_enc); - sav->key_enc = NULL; - } - if (sav->sched) { - bzero(sav->sched, sav->schedlen); - KFREE(sav->sched); - sav->sched = NULL; - } - if (sav->replay != NULL) { - keydb_delsecreplay(sav->replay); - sav->replay = NULL; - } - if (sav->lft_c != NULL) { - KFREE(sav->lft_c); - sav->lft_c = NULL; - } - if (sav->lft_h != NULL) { - KFREE(sav->lft_h); - sav->lft_h = NULL; - } - if (sav->lft_s != NULL) { - KFREE(sav->lft_s); - sav->lft_s = NULL; - } - if (sav->iv != NULL) { - KFREE(sav->iv); - sav->iv = NULL; - } - - KFREE(sav); - - return; -} - -/* - * search SAD. - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -static struct secashead * -key_getsah(struct secasindex *saidx) -{ - struct secashead *sah; - - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID)) - return sah; - } - - return NULL; -} - -/* - * check not to be duplicated SPI. - * NOTE: this function is too slow due to searching all SAD. - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -static struct secasvar * -key_checkspidup(struct secasindex *saidx, u_int32_t spi) -{ - struct secashead *sah; - struct secasvar *sav; - - /* check address family */ - if (saidx->src.ss_family != saidx->dst.ss_family) { - ipseclog((LOG_DEBUG, "key_checkspidup: address family mismatched.\n")); - return NULL; - } - - /* check all SAD */ - LIST_FOREACH(sah, &sahtree, chain) { - if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst)) - continue; - sav = key_getsavbyspi(sah, spi); - if (sav != NULL) - return sav; - } - - return NULL; -} - -/* - * search SAD litmited alive SA, protocol, SPI. - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -static struct secasvar * -key_getsavbyspi(struct secashead *sah, u_int32_t spi) -{ - struct secasvar *sav; - u_int stateidx, state; - - /* search all status */ - for (stateidx = 0; - stateidx < NELEM(saorder_state_alive); - stateidx++) { - - state = saorder_state_alive[stateidx]; - LIST_FOREACH(sav, &sah->savtree[state], chain) { - - /* sanity check */ - if (sav->state != state) { - ipseclog((LOG_DEBUG, "key_getsavbyspi: " - "invalid sav->state (queue: %d SA: %d)\n", - state, sav->state)); - continue; - } - - if (sav->spi == spi) - return sav; - } - } - - return NULL; -} - -/* - * copy SA values from PF_KEY message except *SPI, SEQ, PID, STATE and TYPE*. - * You must update these if need. - * OUT: 0: success. - * !0: failure. - * - * does not modify mbuf. does not free mbuf on error. - */ -static int -key_setsaval(struct secasvar *sav, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ -#ifdef IPSEC_ESP - const struct esp_algorithm *algo; -#endif - int error = 0; - struct timeval tv; - - /* sanity check */ - if (m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_setsaval: NULL pointer is passed."); - - /* initialization */ - sav->replay = NULL; - sav->key_auth = NULL; - sav->key_enc = NULL; - sav->sched = NULL; - sav->schedlen = 0; - sav->iv = NULL; - sav->lft_c = NULL; - sav->lft_h = NULL; - sav->lft_s = NULL; - - /* SA */ - if (mhp->ext[SADB_EXT_SA] != NULL) { - const struct sadb_sa *sa0; - - sa0 = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - if (mhp->extlen[SADB_EXT_SA] < sizeof(*sa0)) { - error = EINVAL; - goto fail; - } - - sav->alg_auth = sa0->sadb_sa_auth; - sav->alg_enc = sa0->sadb_sa_encrypt; - sav->flags = sa0->sadb_sa_flags; - - /* replay window */ - if ((sa0->sadb_sa_flags & SADB_X_EXT_OLD) == 0) { - sav->replay = keydb_newsecreplay(sa0->sadb_sa_replay); - if (sav->replay == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - } - } - - /* Authentication keys */ - if (mhp->ext[SADB_EXT_KEY_AUTH] != NULL) { - const struct sadb_key *key0; - int len; - - key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_AUTH]; - len = mhp->extlen[SADB_EXT_KEY_AUTH]; - - error = 0; - if (len < sizeof(*key0)) { - error = EINVAL; - goto fail; - } - switch (mhp->msg->sadb_msg_satype) { - case SADB_SATYPE_AH: - case SADB_SATYPE_ESP: - case SADB_X_SATYPE_TCPSIGNATURE: - if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) && - sav->alg_auth != SADB_X_AALG_NULL) - error = EINVAL; - break; - case SADB_X_SATYPE_IPCOMP: - default: - error = EINVAL; - break; - } - if (error) { - ipseclog((LOG_DEBUG, "key_setsaval: invalid key_auth values.\n")); - goto fail; - } - - sav->key_auth = (struct sadb_key *)key_newbuf(key0, len); - if (sav->key_auth == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - } - - /* Encryption key */ - if (mhp->ext[SADB_EXT_KEY_ENCRYPT] != NULL) { - const struct sadb_key *key0; - int len; - - key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_ENCRYPT]; - len = mhp->extlen[SADB_EXT_KEY_ENCRYPT]; - - error = 0; - if (len < sizeof(*key0)) { - error = EINVAL; - goto fail; - } - switch (mhp->msg->sadb_msg_satype) { - case SADB_SATYPE_ESP: - if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) && - sav->alg_enc != SADB_EALG_NULL) { - error = EINVAL; - break; - } - sav->key_enc = (struct sadb_key *)key_newbuf(key0, len); - if (sav->key_enc == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - break; - case SADB_X_SATYPE_IPCOMP: - if (len != PFKEY_ALIGN8(sizeof(struct sadb_key))) - error = EINVAL; - sav->key_enc = NULL; /*just in case*/ - break; - case SADB_SATYPE_AH: - case SADB_X_SATYPE_TCPSIGNATURE: - default: - error = EINVAL; - break; - } - if (error) { - ipseclog((LOG_DEBUG, "key_setsatval: invalid key_enc value.\n")); - goto fail; - } - } - - /* set iv */ - sav->ivlen = 0; - - switch (mhp->msg->sadb_msg_satype) { - case SADB_SATYPE_ESP: -#ifdef IPSEC_ESP - algo = esp_algorithm_lookup(sav->alg_enc); - if (algo && algo->ivlen) - sav->ivlen = (*algo->ivlen)(algo, sav); - if (sav->ivlen == 0) - break; - KMALLOC(sav->iv, caddr_t, sav->ivlen); - if (sav->iv == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - - /* initialize */ - key_randomfill(sav->iv, sav->ivlen); -#endif - break; - case SADB_SATYPE_AH: - case SADB_X_SATYPE_IPCOMP: - case SADB_X_SATYPE_TCPSIGNATURE: - break; - default: - ipseclog((LOG_DEBUG, "key_setsaval: invalid SA type.\n")); - error = EINVAL; - goto fail; - } - - /* reset created */ - microtime(&tv); - sav->created = tv.tv_sec; - - /* make lifetime for CURRENT */ - KMALLOC(sav->lft_c, struct sadb_lifetime *, - sizeof(struct sadb_lifetime)); - if (sav->lft_c == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - - microtime(&tv); - - sav->lft_c->sadb_lifetime_len = - PFKEY_UNIT64(sizeof(struct sadb_lifetime)); - sav->lft_c->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; - sav->lft_c->sadb_lifetime_allocations = 0; - sav->lft_c->sadb_lifetime_bytes = 0; - sav->lft_c->sadb_lifetime_addtime = tv.tv_sec; - sav->lft_c->sadb_lifetime_usetime = 0; - - /* lifetimes for HARD and SOFT */ - { - const struct sadb_lifetime *lft0; - - lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD]; - if (lft0 != NULL) { - if (mhp->extlen[SADB_EXT_LIFETIME_HARD] < sizeof(*lft0)) { - error = EINVAL; - goto fail; - } - sav->lft_h = (struct sadb_lifetime *)key_newbuf(lft0, - sizeof(*lft0)); - if (sav->lft_h == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - /* to be initialize ? */ - } - - lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_SOFT]; - if (lft0 != NULL) { - if (mhp->extlen[SADB_EXT_LIFETIME_SOFT] < sizeof(*lft0)) { - error = EINVAL; - goto fail; - } - sav->lft_s = (struct sadb_lifetime *)key_newbuf(lft0, - sizeof(*lft0)); - if (sav->lft_s == NULL) { - ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n")); - error = ENOBUFS; - goto fail; - } - /* to be initialize ? */ - } - } - - return 0; - - fail: - /* initialization */ - if (sav->replay != NULL) { - keydb_delsecreplay(sav->replay); - sav->replay = NULL; - } - if (sav->key_auth != NULL) { - KFREE(sav->key_auth); - sav->key_auth = NULL; - } - if (sav->key_enc != NULL) { - KFREE(sav->key_enc); - sav->key_enc = NULL; - } - if (sav->sched) { - KFREE(sav->sched); - sav->sched = NULL; - } - if (sav->iv != NULL) { - KFREE(sav->iv); - sav->iv = NULL; - } - if (sav->lft_c != NULL) { - KFREE(sav->lft_c); - sav->lft_c = NULL; - } - if (sav->lft_h != NULL) { - KFREE(sav->lft_h); - sav->lft_h = NULL; - } - if (sav->lft_s != NULL) { - KFREE(sav->lft_s); - sav->lft_s = NULL; - } - - return error; -} - -/* - * validation with a secasvar entry, and set SADB_SATYPE_MATURE. - * OUT: 0: valid - * other: errno - */ -static int -key_mature(struct secasvar *sav) -{ - int mature; - int checkmask = 0; /* 2^0: ealg 2^1: aalg 2^2: calg */ - int mustmask = 0; /* 2^0: ealg 2^1: aalg 2^2: calg */ - - mature = 0; - - /* check SPI value */ - switch (sav->sah->saidx.proto) { - case IPPROTO_ESP: - case IPPROTO_AH: - if (ntohl(sav->spi) >= 0 && ntohl(sav->spi) <= 255) { - ipseclog((LOG_DEBUG, - "key_mature: illegal range of SPI %u.\n", - (u_int32_t)ntohl(sav->spi))); - return EINVAL; - } - break; - } - - /* check satype */ - switch (sav->sah->saidx.proto) { - case IPPROTO_ESP: - /* check flags */ - if ((sav->flags & SADB_X_EXT_OLD) - && (sav->flags & SADB_X_EXT_DERIV)) { - ipseclog((LOG_DEBUG, "key_mature: " - "invalid flag (derived) given to old-esp.\n")); - return EINVAL; - } - if (sav->alg_auth == SADB_AALG_NONE) - checkmask = 1; - else - checkmask = 3; - mustmask = 1; - break; - case IPPROTO_AH: - /* check flags */ - if (sav->flags & SADB_X_EXT_DERIV) { - ipseclog((LOG_DEBUG, "key_mature: " - "invalid flag (derived) given to AH SA.\n")); - return EINVAL; - } - if (sav->alg_enc != SADB_EALG_NONE) { - ipseclog((LOG_DEBUG, "key_mature: " - "protocol and algorithm mismated.\n")); - return(EINVAL); - } - checkmask = 2; - mustmask = 2; - break; - case IPPROTO_IPCOMP: - if (sav->alg_auth != SADB_AALG_NONE) { - ipseclog((LOG_DEBUG, "key_mature: " - "protocol and algorithm mismated.\n")); - return(EINVAL); - } - if ((sav->flags & SADB_X_EXT_RAWCPI) == 0 - && ntohl(sav->spi) >= 0x10000) { - ipseclog((LOG_DEBUG, "key_mature: invalid cpi for IPComp.\n")); - return(EINVAL); - } - checkmask = 4; - mustmask = 4; - break; - case IPPROTO_TCP: - if (sav->alg_auth != SADB_X_AALG_TCP_MD5) { - ipseclog((LOG_DEBUG, "key_mature: " - "protocol and algorithm mismated.\n")); - return(EINVAL); - } - checkmask = 0; - mustmask = 0; - break; - default: - ipseclog((LOG_DEBUG, "key_mature: Invalid satype.\n")); - return EPROTONOSUPPORT; - } - - /* check authentication algorithm */ - if ((checkmask & 2) != 0) { - const struct ah_algorithm *algo; - int keylen; - - algo = ah_algorithm_lookup(sav->alg_auth); - if (!algo) { - ipseclog((LOG_DEBUG,"key_mature: " - "unknown authentication algorithm.\n")); - return EINVAL; - } - - /* algorithm-dependent check */ - if (sav->key_auth) - keylen = sav->key_auth->sadb_key_bits; - else - keylen = 0; - if (keylen < algo->keymin || algo->keymax < keylen) { - ipseclog((LOG_DEBUG, - "key_mature: invalid AH key length %d " - "(%d-%d allowed)\n", - keylen, algo->keymin, algo->keymax)); - return EINVAL; - } - - if (algo->mature) { - if ((*algo->mature)(sav)) { - /* message generated in per-algorithm function*/ - return EINVAL; - } else - mature = SADB_SATYPE_AH; - } - - if ((mustmask & 2) != 0 && mature != SADB_SATYPE_AH) { - ipseclog((LOG_DEBUG, "key_mature: no satisfy algorithm for AH\n")); - return EINVAL; - } - } - - /* check encryption algorithm */ - if ((checkmask & 1) != 0) { -#ifdef IPSEC_ESP - const struct esp_algorithm *algo; - int keylen; - - algo = esp_algorithm_lookup(sav->alg_enc); - if (!algo) { - ipseclog((LOG_DEBUG, "key_mature: unknown encryption algorithm.\n")); - return EINVAL; - } - - /* algorithm-dependent check */ - if (sav->key_enc) - keylen = sav->key_enc->sadb_key_bits; - else - keylen = 0; - if (keylen < algo->keymin || algo->keymax < keylen) { - ipseclog((LOG_DEBUG, - "key_mature: invalid ESP key length %d " - "(%d-%d allowed)\n", - keylen, algo->keymin, algo->keymax)); - return EINVAL; - } - - if (algo->mature) { - if ((*algo->mature)(sav)) { - /* message generated in per-algorithm function*/ - return EINVAL; - } else - mature = SADB_SATYPE_ESP; - } - - if ((mustmask & 1) != 0 && mature != SADB_SATYPE_ESP) { - ipseclog((LOG_DEBUG, "key_mature: no satisfy algorithm for ESP\n")); - return EINVAL; - } -#else /*IPSEC_ESP*/ - ipseclog((LOG_DEBUG, "key_mature: ESP not supported in this configuration\n")); - return EINVAL; -#endif - } - - /* check compression algorithm */ - if ((checkmask & 4) != 0) { - const struct ipcomp_algorithm *algo; - - /* algorithm-dependent check */ - algo = ipcomp_algorithm_lookup(sav->alg_enc); - if (!algo) { - ipseclog((LOG_DEBUG, "key_mature: unknown compression algorithm.\n")); - return EINVAL; - } - } - - key_sa_chgstate(sav, SADB_SASTATE_MATURE); - - return 0; -} - -/* - * subroutine for SADB_GET and SADB_DUMP. - */ -static struct mbuf * -key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype, - u_int32_t seq, u_int32_t pid) -{ - struct mbuf *result = NULL, *tres = NULL, *m; - int l = 0; - int i; - void *p; - int dumporder[] = { - SADB_EXT_SA, SADB_X_EXT_SA2, - SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT, - SADB_EXT_LIFETIME_CURRENT, SADB_EXT_ADDRESS_SRC, - SADB_EXT_ADDRESS_DST, SADB_EXT_ADDRESS_PROXY, SADB_EXT_KEY_AUTH, - SADB_EXT_KEY_ENCRYPT, SADB_EXT_IDENTITY_SRC, - SADB_EXT_IDENTITY_DST, SADB_EXT_SENSITIVITY, - }; - - m = key_setsadbmsg(type, 0, satype, seq, pid, sav->refcnt); - if (m == NULL) - goto fail; - result = m; - - for (i = NELEM(dumporder) - 1; i >= 0; i--) { - m = NULL; - p = NULL; - switch (dumporder[i]) { - case SADB_EXT_SA: - m = key_setsadbsa(sav); - if (!m) - goto fail; - break; - - case SADB_X_EXT_SA2: - m = key_setsadbxsa2(sav->sah->saidx.mode, - sav->replay ? sav->replay->count : 0, - sav->sah->saidx.reqid); - if (!m) - goto fail; - break; - - case SADB_EXT_ADDRESS_SRC: - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - (struct sockaddr *)&sav->sah->saidx.src, - FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) - goto fail; - break; - - case SADB_EXT_ADDRESS_DST: - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - (struct sockaddr *)&sav->sah->saidx.dst, - FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) - goto fail; - break; - - case SADB_EXT_KEY_AUTH: - if (!sav->key_auth) - continue; - l = PFKEY_UNUNIT64(sav->key_auth->sadb_key_len); - p = sav->key_auth; - break; - - case SADB_EXT_KEY_ENCRYPT: - if (!sav->key_enc) - continue; - l = PFKEY_UNUNIT64(sav->key_enc->sadb_key_len); - p = sav->key_enc; - break; - - case SADB_EXT_LIFETIME_CURRENT: - if (!sav->lft_c) - continue; - l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_c)->sadb_ext_len); - p = sav->lft_c; - break; - - case SADB_EXT_LIFETIME_HARD: - if (!sav->lft_h) - continue; - l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_h)->sadb_ext_len); - p = sav->lft_h; - break; - - case SADB_EXT_LIFETIME_SOFT: - if (!sav->lft_s) - continue; - l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_s)->sadb_ext_len); - p = sav->lft_s; - break; - - case SADB_EXT_ADDRESS_PROXY: - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - /* XXX: should we brought from SPD ? */ - case SADB_EXT_SENSITIVITY: - default: - continue; - } - - if ((!m && !p) || (m && p)) - goto fail; - if (p && tres) { - M_PREPEND(tres, l, M_NOWAIT); - if (!tres) - goto fail; - bcopy(p, mtod(tres, caddr_t), l); - continue; - } - if (p) { - m = key_alloc_mbuf(l); - if (!m) - goto fail; - m_copyback(m, 0, l, p); - } - - if (tres) - m_cat(m, tres); - tres = m; - } - - m_cat(result, tres); - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) - goto fail; - } - - result->m_pkthdr.len = 0; - for (m = result; m; m = m->m_next) - result->m_pkthdr.len += m->m_len; - - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - return result; - -fail: - m_freem(result); - m_freem(tres); - return NULL; -} - -/* - * set data into sadb_msg. - */ -static struct mbuf * -key_setsadbmsg(u_int8_t type, u_int16_t tlen, u_int8_t satype, - u_int32_t seq, pid_t pid, u_int16_t reserved) -{ - struct mbuf *m; - struct sadb_msg *p; - int len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); - if (len > MCLBYTES) - return NULL; - MGETHDR(m, M_NOWAIT, MT_DATA); - if (m && len > MHLEN) { - MCLGET(m, M_NOWAIT); - if ((m->m_flags & M_EXT) == 0) { - m_freem(m); - m = NULL; - } - } - if (!m) - return NULL; - m->m_pkthdr.len = m->m_len = len; - m->m_next = NULL; - - p = mtod(m, struct sadb_msg *); - - bzero(p, len); - p->sadb_msg_version = PF_KEY_V2; - p->sadb_msg_type = type; - p->sadb_msg_errno = 0; - p->sadb_msg_satype = satype; - p->sadb_msg_len = PFKEY_UNIT64(tlen); - p->sadb_msg_reserved = reserved; - p->sadb_msg_seq = seq; - p->sadb_msg_pid = (u_int32_t)pid; - - return m; -} - -/* - * copy secasvar data into sadb_address. - */ -static struct mbuf * -key_setsadbsa(struct secasvar *sav) -{ - struct mbuf *m; - struct sadb_sa *p; - int len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_sa)); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_sa *); - - bzero(p, len); - p->sadb_sa_len = PFKEY_UNIT64(len); - p->sadb_sa_exttype = SADB_EXT_SA; - p->sadb_sa_spi = sav->spi; - p->sadb_sa_replay = (sav->replay != NULL ? sav->replay->wsize : 0); - p->sadb_sa_state = sav->state; - p->sadb_sa_auth = sav->alg_auth; - p->sadb_sa_encrypt = sav->alg_enc; - p->sadb_sa_flags = sav->flags; - - return m; -} - -/* - * set data into sadb_address. - */ -static struct mbuf * -key_setsadbaddr(u_int16_t exttype, struct sockaddr *saddr, - u_int8_t prefixlen, u_int16_t ul_proto) -{ - struct mbuf *m; - struct sadb_address *p; - size_t len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_address)) + - PFKEY_ALIGN8(saddr->sa_len); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_address *); - - bzero(p, len); - p->sadb_address_len = PFKEY_UNIT64(len); - p->sadb_address_exttype = exttype; - p->sadb_address_proto = ul_proto; - if (prefixlen == FULLMASK) { - switch (saddr->sa_family) { - case AF_INET: - prefixlen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - prefixlen = sizeof(struct in6_addr) << 3; - break; - default: - ; /*XXX*/ - } - } - p->sadb_address_prefixlen = prefixlen; - p->sadb_address_reserved = 0; - - bcopy(saddr, - mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_address)), - saddr->sa_len); - - return m; -} - -#if 0 -/* - * set data into sadb_ident. - */ -static struct mbuf * -key_setsadbident(u_int16_t exttype, u_int16_t idtype, caddr_t string, - int stringlen, u_int64_t id) -{ - struct mbuf *m; - struct sadb_ident *p; - size_t len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_ident)) + PFKEY_ALIGN8(stringlen); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_ident *); - - bzero(p, len); - p->sadb_ident_len = PFKEY_UNIT64(len); - p->sadb_ident_exttype = exttype; - p->sadb_ident_type = idtype; - p->sadb_ident_reserved = 0; - p->sadb_ident_id = id; - - bcopy(string, - mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_ident)), - stringlen); - - return m; -} -#endif - -/* - * set data into sadb_x_sa2. - */ -static struct mbuf * -key_setsadbxsa2(u_int8_t mode, u_int32_t seq, u_int32_t reqid) -{ - struct mbuf *m; - struct sadb_x_sa2 *p; - size_t len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_x_sa2)); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_x_sa2 *); - - bzero(p, len); - p->sadb_x_sa2_len = PFKEY_UNIT64(len); - p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; - p->sadb_x_sa2_mode = mode; - p->sadb_x_sa2_reserved1 = 0; - p->sadb_x_sa2_reserved2 = 0; - p->sadb_x_sa2_sequence = seq; - p->sadb_x_sa2_reqid = reqid; - - return m; -} - -/* - * set data into sadb_x_policy - */ -static struct mbuf * -key_setsadbxpolicy(u_int16_t type, u_int8_t dir, u_int32_t id) -{ - struct mbuf *m; - struct sadb_x_policy *p; - size_t len; - - len = PFKEY_ALIGN8(sizeof(struct sadb_x_policy)); - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - return NULL; - } - - p = mtod(m, struct sadb_x_policy *); - - bzero(p, len); - p->sadb_x_policy_len = PFKEY_UNIT64(len); - p->sadb_x_policy_exttype = SADB_X_EXT_POLICY; - p->sadb_x_policy_type = type; - p->sadb_x_policy_dir = dir; - p->sadb_x_policy_id = id; - - return m; -} - -/* %%% utilities */ -/* - * copy a buffer into the new buffer allocated. - */ -static void * -key_newbuf(const void *src, u_int len) -{ - caddr_t new; - - KMALLOC(new, caddr_t, len); - if (new == NULL) { - ipseclog((LOG_DEBUG, "key_newbuf: No more memory.\n")); - return NULL; - } - bcopy(src, new, len); - - return new; -} - -/* compare my own address - * OUT: 1: true, i.e. my address. - * 0: false - */ -int -key_ismyaddr(struct sockaddr *sa) -{ -#ifdef INET - struct sockaddr_in *sin; - struct in_ifaddr_container *iac; -#endif - int res; - - /* sanity check */ - if (sa == NULL) - panic("key_ismyaddr: NULL pointer is passed."); - - lwkt_gettoken(&key_token); - switch (sa->sa_family) { -#ifdef INET - case AF_INET: - sin = (struct sockaddr_in *)sa; - TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { - struct in_ifaddr *ia = iac->ia; - - if (sin->sin_family == ia->ia_addr.sin_family && - sin->sin_len == ia->ia_addr.sin_len && - sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr) - { - lwkt_reltoken(&key_token); - return 1; - } - } - res = 0; - break; -#endif -#ifdef INET6 - case AF_INET6: - res = key_ismyaddr6((struct sockaddr_in6 *)sa); - break; -#endif - default: - res = 0; - break; - } - lwkt_reltoken(&key_token); - return res; -} - -#ifdef INET6 -/* - * compare my own address for IPv6. - * 1: ours - * 0: other - * NOTE: derived ip6_input() in KAME. This is necessary to modify more. - */ -static int -key_ismyaddr6(struct sockaddr_in6 *sin6) -{ - struct in6_ifaddr *ia; - struct in6_multi *in6m; - - for (ia = in6_ifaddr; ia; ia = ia->ia_next) { - if (key_sockaddrcmp((struct sockaddr *)&sin6, - (struct sockaddr *)&ia->ia_addr, 0) == 0) - return 1; - - /* - * XXX Multicast - * XXX why do we care about multlicast here while we don't care - * about IPv4 multicast?? - * XXX scope - */ - in6m = IN6_LOOKUP_MULTI(&sin6->sin6_addr, ia->ia_ifp); - if (in6m) - return 1; - } - - /* loopback, just for safety */ - if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) - return 1; - - return 0; -} -#endif /*INET6*/ - -/* - * compare two secasindex structure. - * flag can specify to compare 2 saidxes. - * compare two secasindex structure without both mode and reqid. - * don't compare port. - * IN: - * saidx0: source, it can be in SAD. - * saidx1: object. - * OUT: - * 1 : equal - * 0 : not equal - */ -static int -key_cmpsaidx(struct secasindex *saidx0, struct secasindex *saidx1, - int flag) -{ - /* sanity */ - if (saidx0 == NULL && saidx1 == NULL) - return 1; - - if (saidx0 == NULL || saidx1 == NULL) - return 0; - - if (saidx0->proto != saidx1->proto) - return 0; - - if (flag == CMP_EXACTLY) { - if (saidx0->mode != saidx1->mode) - return 0; - if (saidx0->reqid != saidx1->reqid) - return 0; - if (bcmp(&saidx0->src, &saidx1->src, saidx0->src.ss_len) != 0 || - bcmp(&saidx0->dst, &saidx1->dst, saidx0->dst.ss_len) != 0) - return 0; - } else { - - /* CMP_MODE_REQID, CMP_REQID, CMP_HEAD */ - if (flag == CMP_MODE_REQID - ||flag == CMP_REQID) { - /* - * If reqid of SPD is non-zero, unique SA is required. - * The result must be of same reqid in this case. - */ - if (saidx1->reqid != 0 && saidx0->reqid != saidx1->reqid) - return 0; - } - - if (flag == CMP_MODE_REQID) { - if (saidx0->mode != IPSEC_MODE_ANY - && saidx0->mode != saidx1->mode) - return 0; - } - - if (key_sockaddrcmp((struct sockaddr *)&saidx0->src, - (struct sockaddr *)&saidx1->src, 0) != 0) { - return 0; - } - if (key_sockaddrcmp((struct sockaddr *)&saidx0->dst, - (struct sockaddr *)&saidx1->dst, 0) != 0) { - return 0; - } - } - - return 1; -} - -/* - * compare two secindex structure exactly. - * IN: - * spidx0: source, it is often in SPD. - * spidx1: object, it is often from PFKEY message. - * OUT: - * 1 : equal - * 0 : not equal - */ -static int -key_cmpspidx_exactly(struct secpolicyindex *spidx0, - struct secpolicyindex *spidx1) -{ - /* sanity */ - if (spidx0 == NULL && spidx1 == NULL) - return 1; - - if (spidx0 == NULL || spidx1 == NULL) - return 0; - - if (spidx0->prefs != spidx1->prefs - || spidx0->prefd != spidx1->prefd - || spidx0->ul_proto != spidx1->ul_proto) - return 0; - - if (key_sockaddrcmp((struct sockaddr *)&spidx0->src, - (struct sockaddr *)&spidx1->src, 1) != 0) { - return 0; - } - if (key_sockaddrcmp((struct sockaddr *)&spidx0->dst, - (struct sockaddr *)&spidx1->dst, 1) != 0) { - return 0; - } - - return 1; -} - -/* - * compare two secindex structure with mask. - * IN: - * spidx0: source, it is often in SPD. - * spidx1: object, it is often from IP header. - * OUT: - * 1 : equal - * 0 : not equal - */ -static int -key_cmpspidx_withmask(struct secpolicyindex *spidx0, - struct secpolicyindex *spidx1) -{ - /* sanity */ - if (spidx0 == NULL && spidx1 == NULL) - return 1; - - if (spidx0 == NULL || spidx1 == NULL) - return 0; - - if (spidx0->src.ss_family != spidx1->src.ss_family || - spidx0->dst.ss_family != spidx1->dst.ss_family || - spidx0->src.ss_len != spidx1->src.ss_len || - spidx0->dst.ss_len != spidx1->dst.ss_len) - return 0; - - /* if spidx.ul_proto == IPSEC_ULPROTO_ANY, ignore. */ - if (spidx0->ul_proto != (u_int16_t)IPSEC_ULPROTO_ANY - && spidx0->ul_proto != spidx1->ul_proto) - return 0; - - switch (spidx0->src.ss_family) { - case AF_INET: - if (satosin(&spidx0->src)->sin_port != IPSEC_PORT_ANY - && satosin(&spidx0->src)->sin_port != - satosin(&spidx1->src)->sin_port) - return 0; - if (!key_bbcmp((caddr_t)&satosin(&spidx0->src)->sin_addr, - (caddr_t)&satosin(&spidx1->src)->sin_addr, spidx0->prefs)) - return 0; - break; - case AF_INET6: - if (satosin6(&spidx0->src)->sin6_port != IPSEC_PORT_ANY - && satosin6(&spidx0->src)->sin6_port != - satosin6(&spidx1->src)->sin6_port) - return 0; - /* - * scope_id check. if sin6_scope_id is 0, we regard it - * as a wildcard scope, which matches any scope zone ID. - */ - if (satosin6(&spidx0->src)->sin6_scope_id && - satosin6(&spidx1->src)->sin6_scope_id && - satosin6(&spidx0->src)->sin6_scope_id != - satosin6(&spidx1->src)->sin6_scope_id) - return 0; - if (!key_bbcmp((caddr_t)&satosin6(&spidx0->src)->sin6_addr, - (caddr_t)&satosin6(&spidx1->src)->sin6_addr, spidx0->prefs)) - return 0; - break; - default: - /* XXX */ - if (bcmp(&spidx0->src, &spidx1->src, spidx0->src.ss_len) != 0) - return 0; - break; - } - - switch (spidx0->dst.ss_family) { - case AF_INET: - if (satosin(&spidx0->dst)->sin_port != IPSEC_PORT_ANY - && satosin(&spidx0->dst)->sin_port != - satosin(&spidx1->dst)->sin_port) - return 0; - if (!key_bbcmp((caddr_t)&satosin(&spidx0->dst)->sin_addr, - (caddr_t)&satosin(&spidx1->dst)->sin_addr, spidx0->prefd)) - return 0; - break; - case AF_INET6: - if (satosin6(&spidx0->dst)->sin6_port != IPSEC_PORT_ANY - && satosin6(&spidx0->dst)->sin6_port != - satosin6(&spidx1->dst)->sin6_port) - return 0; - /* - * scope_id check. if sin6_scope_id is 0, we regard it - * as a wildcard scope, which matches any scope zone ID. - */ - if (satosin6(&spidx0->src)->sin6_scope_id && - satosin6(&spidx1->src)->sin6_scope_id && - satosin6(&spidx0->dst)->sin6_scope_id != - satosin6(&spidx1->dst)->sin6_scope_id) - return 0; - if (!key_bbcmp((caddr_t)&satosin6(&spidx0->dst)->sin6_addr, - (caddr_t)&satosin6(&spidx1->dst)->sin6_addr, spidx0->prefd)) - return 0; - break; - default: - /* XXX */ - if (bcmp(&spidx0->dst, &spidx1->dst, spidx0->dst.ss_len) != 0) - return 0; - break; - } - - /* XXX Do we check other field ? e.g. flowinfo */ - - return 1; -} - -/* returns 0 on match */ -static int -key_sockaddrcmp(struct sockaddr *sa1, struct sockaddr *sa2, int port) -{ - if (sa1->sa_family != sa2->sa_family || sa1->sa_len != sa2->sa_len) - return 1; - - switch (sa1->sa_family) { - case AF_INET: - if (sa1->sa_len != sizeof(struct sockaddr_in)) - return 1; - if (satosin(sa1)->sin_addr.s_addr != - satosin(sa2)->sin_addr.s_addr) { - return 1; - } - if (port && satosin(sa1)->sin_port != satosin(sa2)->sin_port) - return 1; - break; - case AF_INET6: - if (sa1->sa_len != sizeof(struct sockaddr_in6)) - return 1; /*EINVAL*/ - if (satosin6(sa1)->sin6_scope_id != - satosin6(sa2)->sin6_scope_id) { - return 1; - } - if (!IN6_ARE_ADDR_EQUAL(&satosin6(sa1)->sin6_addr, - &satosin6(sa2)->sin6_addr)) { - return 1; - } - if (port && - satosin6(sa1)->sin6_port != satosin6(sa2)->sin6_port) { - return 1; - } - default: - if (bcmp(sa1, sa2, sa1->sa_len) != 0) - return 1; - break; - } - - return 0; -} - -/* - * compare two buffers with mask. - * IN: - * addr1: source - * addr2: object - * bits: Number of bits to compare - * OUT: - * 1 : equal - * 0 : not equal - */ -static int -key_bbcmp(caddr_t p1, caddr_t p2, u_int bits) -{ - u_int8_t mask; - - /* XXX: This could be considerably faster if we compare a word - * at a time, but it is complicated on LSB Endian machines */ - - /* Handle null pointers */ - if (p1 == NULL || p2 == NULL) - return (p1 == p2); - - while (bits >= 8) { - if (*p1++ != *p2++) - return 0; - bits -= 8; - } - - if (bits > 0) { - mask = ~((1<<(8-bits))-1); - if ((*p1 & mask) != (*p2 & mask)) - return 0; - } - return 1; /* Match! */ -} - -/* - * time handler. - * scanning SPD and SAD to check status for each entries, - * and do to remove or to expire. - * XXX: year 2038 problem may remain. - */ -void -key_timehandler(void *__dummy) -{ - u_int dir; - struct timeval tv; - - microtime(&tv); - - lwkt_gettoken(&key_token); - - /* SPD */ - { - struct secpolicy *sp, *nextsp; - - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { - for (sp = LIST_FIRST(&sptree[dir]); - sp != NULL; - sp = nextsp) { - - nextsp = LIST_NEXT(sp, chain); - - if (sp->state == IPSEC_SPSTATE_DEAD) { - key_freesp(sp); - continue; - } - - if (sp->lifetime == 0 && sp->validtime == 0) - continue; - - /* the deletion will occur next time */ - if ((sp->lifetime - && tv.tv_sec - sp->created > sp->lifetime) - || (sp->validtime - && tv.tv_sec - sp->lastused > sp->validtime)) { - sp->state = IPSEC_SPSTATE_DEAD; - key_spdexpire(sp); - continue; - } - } - } - } - - /* SAD */ - { - struct secashead *sah, *nextsah; - struct secasvar *sav, *nextsav; - - for (sah = LIST_FIRST(&sahtree); - sah != NULL; - sah = nextsah) { - - nextsah = LIST_NEXT(sah, chain); - - /* if sah has been dead, then delete it and process next sah. */ - if (sah->state == SADB_SASTATE_DEAD) { - key_delsah(sah); - continue; - } - - /* if LARVAL entry doesn't become MATURE, delete it. */ - for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_LARVAL]); - sav != NULL; - sav = nextsav) { - - nextsav = LIST_NEXT(sav, chain); - - if (tv.tv_sec - sav->created > key_larval_lifetime) { - key_freesav(sav); - } - } - - /* - * check MATURE entry to start to send expire message - * whether or not. - */ - for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_MATURE]); - sav != NULL; - sav = nextsav) { - - nextsav = LIST_NEXT(sav, chain); - - /* we don't need to check. */ - if (sav->lft_s == NULL) - continue; - - /* sanity check */ - if (sav->lft_c == NULL) { - ipseclog((LOG_DEBUG,"key_timehandler: " - "There is no CURRENT time, why?\n")); - continue; - } - - /* check SOFT lifetime */ - if (sav->lft_s->sadb_lifetime_addtime != 0 - && tv.tv_sec - sav->created > sav->lft_s->sadb_lifetime_addtime) { - /* - * check the SA if it has been used. - * when it hasn't been used, delete it. - * i don't think such SA will be used. - */ - if (sav->lft_c->sadb_lifetime_usetime == 0) { - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - key_freesav(sav); - sav = NULL; - } else { - key_sa_chgstate(sav, SADB_SASTATE_DYING); - /* - * XXX If we keep to send expire - * message in the status of - * DYING. Do remove below code. - */ - key_expire(sav); - } - } - - /* check SOFT lifetime by bytes */ - /* - * XXX I don't know the way to delete this SA - * when new SA is installed. Caution when it's - * installed too big lifetime by time. - */ - else if (sav->lft_s->sadb_lifetime_bytes != 0 - && sav->lft_s->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) { - - key_sa_chgstate(sav, SADB_SASTATE_DYING); - /* - * XXX If we keep to send expire - * message in the status of - * DYING. Do remove below code. - */ - key_expire(sav); - } - } - - /* check DYING entry to change status to DEAD. */ - for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_DYING]); - sav != NULL; - sav = nextsav) { - - nextsav = LIST_NEXT(sav, chain); - - /* we don't need to check. */ - if (sav->lft_h == NULL) - continue; - - /* sanity check */ - if (sav->lft_c == NULL) { - ipseclog((LOG_DEBUG, "key_timehandler: " - "There is no CURRENT time, why?\n")); - continue; - } - - if (sav->lft_h->sadb_lifetime_addtime != 0 - && tv.tv_sec - sav->created > sav->lft_h->sadb_lifetime_addtime) { - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - key_freesav(sav); - sav = NULL; - } -#if 0 /* XXX Should we keep to send expire message until HARD lifetime ? */ - else if (sav->lft_s != NULL - && sav->lft_s->sadb_lifetime_addtime != 0 - && tv.tv_sec - sav->created > sav->lft_s->sadb_lifetime_addtime) { - /* - * XXX: should be checked to be - * installed the valid SA. - */ - - /* - * If there is no SA then sending - * expire message. - */ - key_expire(sav); - } -#endif - /* check HARD lifetime by bytes */ - else if (sav->lft_h->sadb_lifetime_bytes != 0 - && sav->lft_h->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) { - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - key_freesav(sav); - sav = NULL; - } - } - - /* delete entry in DEAD */ - for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_DEAD]); - sav != NULL; - sav = nextsav) { - - nextsav = LIST_NEXT(sav, chain); - - /* sanity check */ - if (sav->state != SADB_SASTATE_DEAD) { - ipseclog((LOG_DEBUG, "key_timehandler: " - "invalid sav->state " - "(queue: %d SA: %d): " - "kill it anyway\n", - SADB_SASTATE_DEAD, sav->state)); - } - - /* - * do not call key_freesav() here. - * sav should already be freed, and sav->refcnt - * shows other references to sav - * (such as from SPD). - */ - } - } - } - -#ifndef IPSEC_NONBLOCK_ACQUIRE - /* ACQ tree */ - { - struct secacq *acq, *nextacq; - - for (acq = LIST_FIRST(&acqtree); - acq != NULL; - acq = nextacq) { - - nextacq = LIST_NEXT(acq, chain); - - if (tv.tv_sec - acq->created > key_blockacq_lifetime - && __LIST_CHAINED(acq)) { - LIST_REMOVE(acq, chain); - KFREE(acq); - } - } - } -#endif - - /* SP ACQ tree */ - { - struct secspacq *acq, *nextacq; - - for (acq = LIST_FIRST(&spacqtree); - acq != NULL; - acq = nextacq) { - - nextacq = LIST_NEXT(acq, chain); - - if (tv.tv_sec - acq->created > key_blockacq_lifetime - && __LIST_CHAINED(acq)) { - LIST_REMOVE(acq, chain); - KFREE(acq); - } - } - } - - /* initialize random seed */ - if (key_tick_init_random++ > key_int_random) { - key_tick_init_random = 0; - key_srandom(); - } - -#ifndef IPSEC_DEBUG2 - /* do exchange to tick time !! */ - callout_reset(&key_timehandler_ch, hz, key_timehandler, NULL); -#endif /* IPSEC_DEBUG2 */ - - lwkt_reltoken(&key_token); - return; -} - -/* - * to initialize a seed for random() - */ -static void -key_srandom(void) -{ - struct timeval tv; - - microtime(&tv); - - skrandom(tv.tv_usec); - - return; -} - -u_long -key_random(void) -{ - u_long value; - - key_randomfill(&value, sizeof(value)); - return value; -} - -void -key_randomfill(void *p, size_t l) -{ - size_t n; - u_long v; - static int warn = 1; - - n = 0; - n = (size_t)read_random(p, (u_int)l); - /* last resort */ - while (n < l) { - v = krandom(); - bcopy(&v, (u_int8_t *)p + n, - l - n < sizeof(v) ? l - n : sizeof(v)); - n += sizeof(v); - - if (warn) { - kprintf("WARNING: pseudo-random number generator " - "used for IPsec processing\n"); - warn = 0; - } - } -} - -/* - * map SADB_SATYPE_* to IPPROTO_*. - * if satype == SADB_SATYPE then satype is mapped to ~0. - * OUT: - * 0: invalid satype. - */ -static u_int16_t -key_satype2proto(u_int8_t satype) -{ - switch (satype) { - case SADB_SATYPE_UNSPEC: - return IPSEC_PROTO_ANY; - case SADB_SATYPE_AH: - return IPPROTO_AH; - case SADB_SATYPE_ESP: - return IPPROTO_ESP; - case SADB_X_SATYPE_IPCOMP: - return IPPROTO_IPCOMP; - case SADB_X_SATYPE_TCPSIGNATURE: - return IPPROTO_TCP; - break; - default: - return 0; - } - /* NOTREACHED */ -} - -/* - * map IPPROTO_* to SADB_SATYPE_* - * OUT: - * 0: invalid protocol type. - */ -static u_int8_t -key_proto2satype(u_int16_t proto) -{ - switch (proto) { - case IPPROTO_AH: - return SADB_SATYPE_AH; - case IPPROTO_ESP: - return SADB_SATYPE_ESP; - case IPPROTO_IPCOMP: - return SADB_X_SATYPE_IPCOMP; - case IPPROTO_TCP: - return SADB_X_SATYPE_TCPSIGNATURE; - break; - default: - return 0; - } - /* NOTREACHED */ -} - -/* %%% PF_KEY */ -/* - * SADB_GETSPI processing is to receive - * - * from the IKMPd, to assign a unique spi value, to hang on the INBOUND - * tree with the status of LARVAL, and send - * - * to the IKMPd. - * - * IN: mhp: pointer to the pointer to each header. - * OUT: NULL if fail. - * other if success, return pointer to the message to send. - */ -static int -key_getspi(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *newsah; - struct secasvar *newsav; - u_int8_t proto; - u_int32_t spi; - u_int8_t mode; - u_int32_t reqid; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_getspi: NULL pointer is passed."); - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { - ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->ext[SADB_X_EXT_SA2] != NULL) { - mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; - reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; - } else { - mode = IPSEC_MODE_ANY; - reqid = 0; - } - - src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_getspi: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - /* make sure if port number is zero. */ - switch (((struct sockaddr *)(src0 + 1))->sa_family) { - case AF_INET: - if (((struct sockaddr *)(src0 + 1))->sa_len != - sizeof(struct sockaddr_in)) - return key_senderror(so, m, EINVAL); - ((struct sockaddr_in *)(src0 + 1))->sin_port = 0; - break; - case AF_INET6: - if (((struct sockaddr *)(src0 + 1))->sa_len != - sizeof(struct sockaddr_in6)) - return key_senderror(so, m, EINVAL); - ((struct sockaddr_in6 *)(src0 + 1))->sin6_port = 0; - break; - default: - ; /*???*/ - } - switch (((struct sockaddr *)(dst0 + 1))->sa_family) { - case AF_INET: - if (((struct sockaddr *)(dst0 + 1))->sa_len != - sizeof(struct sockaddr_in)) - return key_senderror(so, m, EINVAL); - ((struct sockaddr_in *)(dst0 + 1))->sin_port = 0; - break; - case AF_INET6: - if (((struct sockaddr *)(dst0 + 1))->sa_len != - sizeof(struct sockaddr_in6)) - return key_senderror(so, m, EINVAL); - ((struct sockaddr_in6 *)(dst0 + 1))->sin6_port = 0; - break; - default: - ; /*???*/ - } - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - - /* SPI allocation */ - spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE], - &saidx); - if (spi == 0) - return key_senderror(so, m, EINVAL); - - /* get a SA index */ - if ((newsah = key_getsah(&saidx)) == NULL) { - /* create a new SA index */ - if ((newsah = key_newsah(&saidx)) == NULL) { - ipseclog((LOG_DEBUG, "key_getspi: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - } - - /* get a new SA */ - /* XXX rewrite */ - newsav = key_newsav(m, mhp, newsah, &error); - if (newsav == NULL) { - /* XXX don't free new SA index allocated in above. */ - return key_senderror(so, m, error); - } - - /* set spi */ - newsav->spi = htonl(spi); - -#ifndef IPSEC_NONBLOCK_ACQUIRE - /* delete the entry in acqtree */ - if (mhp->msg->sadb_msg_seq != 0) { - struct secacq *acq; - if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) != NULL) { - /* reset counter in order to deletion by timehandler. */ - struct timeval tv; - microtime(&tv); - acq->created = tv.tv_sec; - acq->count = 0; - } - } -#endif - - { - struct mbuf *n, *nn; - struct sadb_sa *m_sa; - struct sadb_msg *newmsg; - int off, len; - - /* create new sadb_msg to reply. */ - len = PFKEY_ALIGN8(sizeof(struct sadb_msg)) + - PFKEY_ALIGN8(sizeof(struct sadb_sa)); - if (len > MCLBYTES) - return key_senderror(so, m, ENOBUFS); - - MGETHDR(n, M_NOWAIT, MT_DATA); - if (len > MHLEN) { - MCLGET(n, M_NOWAIT); - if ((n->m_flags & M_EXT) == 0) { - m_freem(n); - n = NULL; - } - } - if (!n) - return key_senderror(so, m, ENOBUFS); - - n->m_len = len; - n->m_next = NULL; - off = 0; - - m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off); - off += PFKEY_ALIGN8(sizeof(struct sadb_msg)); - - m_sa = (struct sadb_sa *)(mtod(n, caddr_t) + off); - m_sa->sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa)); - m_sa->sadb_sa_exttype = SADB_EXT_SA; - m_sa->sadb_sa_spi = htonl(spi); - off += PFKEY_ALIGN8(sizeof(struct sadb_sa)); - -#ifdef DIAGNOSTIC - if (off != len) - panic("length inconsistency in key_getspi"); -#endif - - n->m_next = key_gather_mbuf(m, mhp, 0, 2, SADB_EXT_ADDRESS_SRC, - SADB_EXT_ADDRESS_DST); - if (!n->m_next) { - m_freem(n); - return key_senderror(so, m, ENOBUFS); - } - - if (n->m_len < sizeof(struct sadb_msg)) { - n = m_pullup(n, sizeof(struct sadb_msg)); - if (n == NULL) - return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); - } - - n->m_pkthdr.len = 0; - for (nn = n; nn; nn = nn->m_next) - n->m_pkthdr.len += nn->m_len; - - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_seq = newsav->seq; - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } -} - -/* - * allocating new SPI - * called by key_getspi(). - * OUT: - * 0: failure. - * others: success. - */ -static u_int32_t -key_do_getnewspi(struct sadb_spirange *spirange, - struct secasindex *saidx) -{ - u_int32_t newspi; - u_int32_t min, max; - int count = key_spi_trycnt; - - /* set spi range to allocate */ - if (spirange != NULL) { - min = spirange->sadb_spirange_min; - max = spirange->sadb_spirange_max; - } else { - min = key_spi_minval; - max = key_spi_maxval; - } - /* IPCOMP needs 2-byte SPI */ - if (saidx->proto == IPPROTO_IPCOMP) { - u_int32_t t; - if (min >= 0x10000) - min = 0xffff; - if (max >= 0x10000) - max = 0xffff; - if (min > max) { - t = min; min = max; max = t; - } - } - - if (min == max) { - if (key_checkspidup(saidx, min) != NULL) { - ipseclog((LOG_DEBUG, "key_do_getnewspi: SPI %u exists already.\n", min)); - return 0; - } - - count--; /* taking one cost. */ - newspi = min; - - } else { - - /* init SPI */ - newspi = 0; - - /* when requesting to allocate spi ranged */ - while (count--) { - /* generate pseudo-random SPI value ranged. */ - newspi = min + (key_random() % (max - min + 1)); - - if (key_checkspidup(saidx, newspi) == NULL) - break; - } - - if (count == 0 || newspi == 0) { - ipseclog((LOG_DEBUG, "key_do_getnewspi: to allocate spi is failed.\n")); - return 0; - } - } - - /* statistics */ - keystat.getspi_count = - (keystat.getspi_count + key_spi_trycnt - count) / 2; - - return newspi; -} - -/* - * SADB_UPDATE processing - * receive - * - * from the ikmpd, and update a secasvar entry whose status is SADB_SASTATE_LARVAL. - * and send - * - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_update(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct sadb_sa *sa0; - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - struct secasvar *sav; - u_int16_t proto; - u_int8_t mode; - u_int32_t reqid; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_update: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_update: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_SA] == NULL || - mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP && - mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) || - (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH && - mhp->ext[SADB_EXT_KEY_AUTH] == NULL) || - (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL && - mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) || - (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL && - mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) { - ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || - mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->ext[SADB_X_EXT_SA2] != NULL) { - mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; - reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; - } else { - mode = IPSEC_MODE_ANY; - reqid = 0; - } - /* XXX boundary checking for other extensions */ - - sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ - if ((sah = key_getsah(&saidx)) == NULL) { - ipseclog((LOG_DEBUG, "key_update: no SA index found.\n")); - return key_senderror(so, m, ENOENT); - } - - /* set spidx if there */ - /* XXX rewrite */ - error = key_setident(sah, m, mhp); - if (error) - return key_senderror(so, m, error); - - /* find a SA with sequence number. */ -#ifdef IPSEC_DOSEQCHECK - if (mhp->msg->sadb_msg_seq != 0 - && (sav = key_getsavbyseq(sah, mhp->msg->sadb_msg_seq)) == NULL) { - ipseclog((LOG_DEBUG, - "key_update: no larval SA with sequence %u exists.\n", - mhp->msg->sadb_msg_seq)); - return key_senderror(so, m, ENOENT); - } -#else - if ((sav = key_getsavbyspi(sah, sa0->sadb_sa_spi)) == NULL) { - ipseclog((LOG_DEBUG, - "key_update: no such a SA found (spi:%u)\n", - (u_int32_t)ntohl(sa0->sadb_sa_spi))); - return key_senderror(so, m, EINVAL); - } -#endif - - /* validity check */ - if (sav->sah->saidx.proto != proto) { - ipseclog((LOG_DEBUG, - "key_update: protocol mismatched (DB=%u param=%u)\n", - sav->sah->saidx.proto, proto)); - return key_senderror(so, m, EINVAL); - } -#ifdef IPSEC_DOSEQCHECK - if (sav->spi != sa0->sadb_sa_spi) { - ipseclog((LOG_DEBUG, - "key_update: SPI mismatched (DB:%u param:%u)\n", - (u_int32_t)ntohl(sav->spi), - (u_int32_t)ntohl(sa0->sadb_sa_spi))); - return key_senderror(so, m, EINVAL); - } -#endif - if (sav->pid != mhp->msg->sadb_msg_pid) { - ipseclog((LOG_DEBUG, - "key_update: pid mismatched (DB:%u param:%u)\n", - sav->pid, mhp->msg->sadb_msg_pid)); - return key_senderror(so, m, EINVAL); - } - - /* copy sav values */ - error = key_setsaval(sav, m, mhp); - if (error) { - key_freesav(sav); - return key_senderror(so, m, error); - } - - /* check SA values to be mature. */ - if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) { - key_freesav(sav); - return key_senderror(so, m, 0); - } - - { - struct mbuf *n; - - /* set msg buf from mhp */ - n = key_getmsgbuf_x1(m, mhp); - if (n == NULL) { - ipseclog((LOG_DEBUG, "key_update: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * search SAD with sequence for a SA which state is SADB_SASTATE_LARVAL. - * only called by key_update(). - * OUT: - * NULL : not found - * others : found, pointer to a SA. - */ -#ifdef IPSEC_DOSEQCHECK -static struct secasvar * -key_getsavbyseq(struct secashead *sah, u_int32_t seq) -{ - struct secasvar *sav; - u_int state; - - state = SADB_SASTATE_LARVAL; - - /* search SAD with sequence number ? */ - LIST_FOREACH(sav, &sah->savtree[state], chain) { - - KEY_CHKSASTATE(state, sav->state, "key_getsabyseq"); - - if (sav->seq == seq) { - sav->refcnt++; - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, - kprintf("DP key_getsavbyseq cause " - "refcnt++:%d SA:%p\n", - sav->refcnt, sav)); - return sav; - } - } - - return NULL; -} -#endif - -/* - * SADB_ADD processing - * add a entry to SA database, when received - * - * from the ikmpd, - * and send - * - * to the ikmpd. - * - * IGNORE identity and sensitivity messages. - * - * m will always be freed. - */ -static int -key_add(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct sadb_sa *sa0; - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *newsah; - struct secasvar *newsav; - u_int16_t proto; - u_int8_t mode; - u_int32_t reqid; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_add: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_add: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_SA] == NULL || - mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP && - mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) || - (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH && - mhp->ext[SADB_EXT_KEY_AUTH] == NULL) || - (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL && - mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) || - (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL && - mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) { - ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || - mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - /* XXX need more */ - ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->ext[SADB_X_EXT_SA2] != NULL) { - mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; - reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; - } else { - mode = IPSEC_MODE_ANY; - reqid = 0; - } - - sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ - if ((newsah = key_getsah(&saidx)) == NULL) { - /* create a new SA header */ - if ((newsah = key_newsah(&saidx)) == NULL) { - ipseclog((LOG_DEBUG, "key_add: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - } - - /* set spidx if there */ - /* XXX rewrite */ - error = key_setident(newsah, m, mhp); - if (error) { - return key_senderror(so, m, error); - } - - /* create new SA entry. */ - /* We can create new SA only if SPI is differenct. */ - if (key_getsavbyspi(newsah, sa0->sadb_sa_spi)) { - ipseclog((LOG_DEBUG, "key_add: SA already exists.\n")); - return key_senderror(so, m, EEXIST); - } - newsav = key_newsav(m, mhp, newsah, &error); - if (newsav == NULL) { - return key_senderror(so, m, error); - } - - /* check SA values to be mature. */ - if ((error = key_mature(newsav)) != 0) { - key_freesav(newsav); - return key_senderror(so, m, error); - } - - /* - * don't call key_freesav() here, as we would like to keep the SA - * in the database on success. - */ - - { - struct mbuf *n; - - /* set msg buf from mhp */ - n = key_getmsgbuf_x1(m, mhp); - if (n == NULL) { - ipseclog((LOG_DEBUG, "key_update: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* m is retained */ -static int -key_setident(struct secashead *sah, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - const struct sadb_ident *idsrc, *iddst; - int idsrclen, iddstlen; - - /* sanity check */ - if (sah == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_setident: NULL pointer is passed."); - - /* don't make buffer if not there */ - if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL && - mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) { - sah->idents = NULL; - sah->identd = NULL; - return 0; - } - - if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL || - mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) { - ipseclog((LOG_DEBUG, "key_setident: invalid identity.\n")); - return EINVAL; - } - - idsrc = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_SRC]; - iddst = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_DST]; - idsrclen = mhp->extlen[SADB_EXT_IDENTITY_SRC]; - iddstlen = mhp->extlen[SADB_EXT_IDENTITY_DST]; - - /* validity check */ - if (idsrc->sadb_ident_type != iddst->sadb_ident_type) { - ipseclog((LOG_DEBUG, "key_setident: ident type mismatch.\n")); - return EINVAL; - } - - switch (idsrc->sadb_ident_type) { - case SADB_IDENTTYPE_PREFIX: - case SADB_IDENTTYPE_FQDN: - case SADB_IDENTTYPE_USERFQDN: - default: - /* XXX do nothing */ - sah->idents = NULL; - sah->identd = NULL; - return 0; - } - - /* make structure */ - KMALLOC(sah->idents, struct sadb_ident *, idsrclen); - if (sah->idents == NULL) { - ipseclog((LOG_DEBUG, "key_setident: No more memory.\n")); - return ENOBUFS; - } - KMALLOC(sah->identd, struct sadb_ident *, iddstlen); - if (sah->identd == NULL) { - KFREE(sah->idents); - sah->idents = NULL; - ipseclog((LOG_DEBUG, "key_setident: No more memory.\n")); - return ENOBUFS; - } - bcopy(idsrc, sah->idents, idsrclen); - bcopy(iddst, sah->identd, iddstlen); - - return 0; -} - -/* - * m will not be freed on return. - * it is caller's responsibility to free the result. - */ -static struct mbuf * -key_getmsgbuf_x1(struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct mbuf *n; - - /* sanity check */ - if (m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_getmsgbuf_x1: NULL pointer is passed."); - - /* create new sadb_msg to reply. */ - n = key_gather_mbuf(m, mhp, 1, 9, SADB_EXT_RESERVED, - SADB_EXT_SA, SADB_X_EXT_SA2, - SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST, - SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT, - SADB_EXT_IDENTITY_SRC, SADB_EXT_IDENTITY_DST); - if (!n) - return NULL; - - if (n->m_len < sizeof(struct sadb_msg)) { - n = m_pullup(n, sizeof(struct sadb_msg)); - if (n == NULL) - return NULL; - } - mtod(n, struct sadb_msg *)->sadb_msg_errno = 0; - mtod(n, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(n->m_pkthdr.len); - - return n; -} - -static int key_delete_all (struct socket *, struct mbuf *, - const struct sadb_msghdr *, u_int16_t); - -/* - * SADB_DELETE processing - * receive - * - * from the ikmpd, and set SADB_SASTATE_DEAD, - * and send, - * - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_delete(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct sadb_sa *sa0; - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - struct secasvar *sav = NULL; - u_int16_t proto; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_delete: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_delete: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { - ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_SA] == NULL) { - /* - * Caller wants us to delete all non-LARVAL SAs - * that match the src/dst. This is used during - * IKE INITIAL-CONTACT. - */ - ipseclog((LOG_DEBUG, "key_delete: doing delete all.\n")); - return key_delete_all(so, m, mhp, proto); - } else if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa)) { - ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) - continue; - - /* get a SA with SPI. */ - sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); - if (sav) - break; - } - if (sah == NULL) { - ipseclog((LOG_DEBUG, "key_delete: no SA found.\n")); - return key_senderror(so, m, ENOENT); - } - - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - key_freesav(sav); - sav = NULL; - - { - struct mbuf *n; - struct sadb_msg *newmsg; - - /* create new sadb_msg to reply. */ - n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED, - SADB_EXT_SA, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - if (!n) - return key_senderror(so, m, ENOBUFS); - - if (n->m_len < sizeof(struct sadb_msg)) { - n = m_pullup(n, sizeof(struct sadb_msg)); - if (n == NULL) - return key_senderror(so, m, ENOBUFS); - } - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * delete all SAs for src/dst. Called from key_delete(). - */ -static int -key_delete_all(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp, u_int16_t proto) -{ - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - struct secasvar *sav, *nextsav; - u_int stateidx, state; - - src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) - continue; - - /* Delete all non-LARVAL SAs. */ - for (stateidx = 0; - stateidx < NELEM(saorder_state_alive); - stateidx++) { - state = saorder_state_alive[stateidx]; - if (state == SADB_SASTATE_LARVAL) - continue; - for (sav = LIST_FIRST(&sah->savtree[state]); - sav != NULL; sav = nextsav) { - nextsav = LIST_NEXT(sav, chain); - /* sanity check */ - if (sav->state != state) { - ipseclog((LOG_DEBUG, "key_delete_all: " - "invalid sav->state " - "(queue: %d SA: %d)\n", - state, sav->state)); - continue; - } - - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - key_freesav(sav); - } - } - } - { - struct mbuf *n; - struct sadb_msg *newmsg; - - /* create new sadb_msg to reply. */ - n = key_gather_mbuf(m, mhp, 1, 3, SADB_EXT_RESERVED, - SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); - if (!n) - return key_senderror(so, m, ENOBUFS); - - if (n->m_len < sizeof(struct sadb_msg)) { - n = m_pullup(n, sizeof(struct sadb_msg)); - if (n == NULL) - return key_senderror(so, m, ENOBUFS); - } - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); - } -} - -/* - * SADB_GET processing - * receive - * - * from the ikmpd, and get a SP and a SA to respond, - * and send, - * - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_get(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) -{ - struct sadb_sa *sa0; - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - struct secasvar *sav = NULL; - u_int16_t proto; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_get: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_get: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_SA] == NULL || - mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { - ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || - mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { - ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) - continue; - - /* get a SA with SPI. */ - sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); - if (sav) - break; - } - if (sah == NULL) { - ipseclog((LOG_DEBUG, "key_get: no SA found.\n")); - return key_senderror(so, m, ENOENT); - } - - { - struct mbuf *n; - u_int8_t satype; - - /* map proto to satype */ - if ((satype = key_proto2satype(sah->saidx.proto)) == 0) { - ipseclog((LOG_DEBUG, "key_get: there was invalid proto in SAD.\n")); - return key_senderror(so, m, EINVAL); - } - - /* create new sadb_msg to reply. */ - n = key_setdumpsa(sav, SADB_GET, satype, mhp->msg->sadb_msg_seq, - mhp->msg->sadb_msg_pid); - if (!n) - return key_senderror(so, m, ENOBUFS); - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } -} - -/* XXX make it sysctl-configurable? */ -static void -key_getcomb_setlifetime(struct sadb_comb *comb) -{ - - comb->sadb_comb_soft_allocations = 1; - comb->sadb_comb_hard_allocations = 1; - comb->sadb_comb_soft_bytes = 0; - comb->sadb_comb_hard_bytes = 0; - comb->sadb_comb_hard_addtime = 86400; /* 1 day */ - comb->sadb_comb_soft_addtime = comb->sadb_comb_soft_addtime * 80 / 100; - comb->sadb_comb_soft_usetime = 28800; /* 8 hours */ - comb->sadb_comb_hard_usetime = comb->sadb_comb_hard_usetime * 80 / 100; -} - -#ifdef IPSEC_ESP -/* - * XXX reorder combinations by preference - * XXX no idea if the user wants ESP authentication or not - */ -static struct mbuf * -key_getcomb_esp(void) -{ - struct sadb_comb *comb; - const struct esp_algorithm *algo; - struct mbuf *result = NULL, *m, *n; - int encmin; - int i, off, o; - int totlen; - const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); - - m = NULL; - for (i = 1; i <= SADB_EALG_MAX; i++) { - algo = esp_algorithm_lookup(i); - if (!algo) - continue; - - if (algo->keymax < ipsec_esp_keymin) - continue; - if (algo->keymin < ipsec_esp_keymin) - encmin = ipsec_esp_keymin; - else - encmin = algo->keymin; - - if (ipsec_esp_auth) - m = key_getcomb_ah(); - else { -#ifdef DIAGNOSTIC - if (l > MLEN) - panic("assumption failed in key_getcomb_esp"); -#endif - MGET(m, M_NOWAIT, MT_DATA); - if (m) { - M_ALIGN(m, l); - m->m_len = l; - m->m_next = NULL; - bzero(mtod(m, caddr_t), m->m_len); - } - } - if (!m) - goto fail; - - totlen = 0; - for (n = m; n; n = n->m_next) - totlen += n->m_len; -#ifdef DIAGNOSTIC - if (totlen % l) - panic("assumption failed in key_getcomb_esp"); -#endif - - for (off = 0; off < totlen; off += l) { - n = m_pulldown(m, off, l, &o); - if (!n) { - /* m is already freed */ - goto fail; - } - comb = (struct sadb_comb *)(mtod(n, caddr_t) + o); - bzero(comb, sizeof(*comb)); - key_getcomb_setlifetime(comb); - comb->sadb_comb_encrypt = i; - comb->sadb_comb_encrypt_minbits = encmin; - comb->sadb_comb_encrypt_maxbits = algo->keymax; - } - - if (!result) - result = m; - else - m_cat(result, m); - } - - return result; - - fail: - if (result) - m_freem(result); - return NULL; -} -#endif - -/* - * XXX reorder combinations by preference - */ -static struct mbuf * -key_getcomb_ah(void) -{ - struct sadb_comb *comb; - const struct ah_algorithm *algo; - struct mbuf *m; - int min; - int i; - const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); - - m = NULL; - for (i = 1; i <= SADB_AALG_MAX; i++) { -#if 1 - /* we prefer HMAC algorithms, not old algorithms */ - if (i != SADB_AALG_SHA1HMAC && i != SADB_AALG_MD5HMAC) - continue; -#endif - algo = ah_algorithm_lookup(i); - if (!algo) - continue; - - if (algo->keymax < ipsec_ah_keymin) - continue; - if (algo->keymin < ipsec_ah_keymin) - min = ipsec_ah_keymin; - else - min = algo->keymin; - - if (!m) { -#ifdef DIAGNOSTIC - if (l > MLEN) - panic("assumption failed in key_getcomb_ah"); -#endif - MGET(m, M_NOWAIT, MT_DATA); - if (m) { - M_ALIGN(m, l); - m->m_len = l; - m->m_next = NULL; - } - } else - M_PREPEND(m, l, M_NOWAIT); - if (!m) - return NULL; - - comb = mtod(m, struct sadb_comb *); - bzero(comb, sizeof(*comb)); - key_getcomb_setlifetime(comb); - comb->sadb_comb_auth = i; - comb->sadb_comb_auth_minbits = min; - comb->sadb_comb_auth_maxbits = algo->keymax; - } - - return m; -} - -/* - * not really an official behavior. discussed in pf_key@inner.net in Sep2000. - * XXX reorder combinations by preference - */ -static struct mbuf * -key_getcomb_ipcomp(void) -{ - struct sadb_comb *comb; - const struct ipcomp_algorithm *algo; - struct mbuf *m; - int i; - const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); - - m = NULL; - for (i = 1; i <= SADB_X_CALG_MAX; i++) { - algo = ipcomp_algorithm_lookup(i); - if (!algo) - continue; - - if (!m) { -#ifdef DIAGNOSTIC - if (l > MLEN) - panic("assumption failed in key_getcomb_ipcomp"); -#endif - MGET(m, M_NOWAIT, MT_DATA); - if (m) { - M_ALIGN(m, l); - m->m_len = l; - m->m_next = NULL; - } - } else - M_PREPEND(m, l, M_NOWAIT); - if (!m) - return NULL; - - comb = mtod(m, struct sadb_comb *); - bzero(comb, sizeof(*comb)); - key_getcomb_setlifetime(comb); - comb->sadb_comb_encrypt = i; - /* what should we set into sadb_comb_*_{min,max}bits? */ - } - - return m; -} - -/* - * XXX no way to pass mode (transport/tunnel) to userland - * XXX replay checking? - * XXX sysctl interface to ipsec_{ah,esp}_keymin - */ -static struct mbuf * -key_getprop(const struct secasindex *saidx) -{ - struct sadb_prop *prop; - struct mbuf *m, *n; - const int l = PFKEY_ALIGN8(sizeof(struct sadb_prop)); - int totlen; - - switch (saidx->proto) { -#ifdef IPSEC_ESP - case IPPROTO_ESP: - m = key_getcomb_esp(); - break; -#endif - case IPPROTO_AH: - m = key_getcomb_ah(); - break; - case IPPROTO_IPCOMP: - m = key_getcomb_ipcomp(); - break; - default: - return NULL; - } - - if (!m) - return NULL; - M_PREPEND(m, l, M_NOWAIT); - if (!m) - return NULL; - - totlen = 0; - for (n = m; n; n = n->m_next) - totlen += n->m_len; - - prop = mtod(m, struct sadb_prop *); - bzero(prop, sizeof(*prop)); - prop->sadb_prop_len = PFKEY_UNIT64(totlen); - prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; - prop->sadb_prop_replay = 32; /* XXX */ - - return m; -} - -/* - * SADB_ACQUIRE processing called by key_checkrequest() and key_acquire2(). - * send - * - * to KMD, and expect to receive - * with SADB_ACQUIRE if error occured, - * or - * with SADB_GETSPI - * from KMD by PF_KEY. - * - * XXX x_policy is outside of RFC2367 (KAME extension). - * XXX sensitivity is not supported. - * XXX for ipcomp, RFC2367 does not define how to fill in proposal. - * see comment for key_getcomb_ipcomp(). - * - * OUT: - * 0 : succeed - * others: error number - */ -static int -key_acquire(struct secasindex *saidx, struct secpolicy *sp) -{ - struct mbuf *result = NULL, *m; -#ifndef IPSEC_NONBLOCK_ACQUIRE - struct secacq *newacq; -#endif - u_int8_t satype; - int error = -1; - u_int32_t seq; - - /* sanity check */ - if (saidx == NULL) - panic("key_acquire: NULL pointer is passed."); - if ((satype = key_proto2satype(saidx->proto)) == 0) - panic("key_acquire: invalid proto is passed."); - -#ifndef IPSEC_NONBLOCK_ACQUIRE - /* - * We never do anything about acquirng SA. There is anather - * solution that kernel blocks to send SADB_ACQUIRE message until - * getting something message from IKEd. In later case, to be - * managed with ACQUIRING list. - */ - /* get a entry to check whether sending message or not. */ - if ((newacq = key_getacq(saidx)) != NULL) { - if (key_blockacq_count < newacq->count) { - /* reset counter and do send message. */ - newacq->count = 0; - } else { - /* increment counter and do nothing. */ - newacq->count++; - return 0; - } - } else { - /* make new entry for blocking to send SADB_ACQUIRE. */ - if ((newacq = key_newacq(saidx)) == NULL) - return ENOBUFS; - - /* add to acqtree */ - LIST_INSERT_HEAD(&acqtree, newacq, chain); - } -#endif - - -#ifndef IPSEC_NONBLOCK_ACQUIRE - seq = newacq->seq; -#else - seq = (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq)); -#endif - m = key_setsadbmsg(SADB_ACQUIRE, 0, satype, seq, 0, 0); - if (!m) { - error = ENOBUFS; - goto fail; - } - result = m; - - /* set sadb_address for saidx's. */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - (struct sockaddr *)&saidx->src, FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - (struct sockaddr *)&saidx->dst, FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* XXX proxy address (optional) */ - - /* set sadb_x_policy */ - if (sp) { - m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - } - - /* XXX identity (optional) */ -#if 0 - if (idexttype && fqdn) { - /* create identity extension (FQDN) */ - struct sadb_ident *id; - int fqdnlen; - - fqdnlen = strlen(fqdn) + 1; /* +1 for terminating-NUL */ - id = (struct sadb_ident *)p; - bzero(id, sizeof(*id) + PFKEY_ALIGN8(fqdnlen)); - id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(fqdnlen)); - id->sadb_ident_exttype = idexttype; - id->sadb_ident_type = SADB_IDENTTYPE_FQDN; - bcopy(fqdn, id + 1, fqdnlen); - p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(fqdnlen); - } - - if (idexttype) { - /* create identity extension (USERFQDN) */ - struct sadb_ident *id; - int userfqdnlen; - - if (userfqdn) { - /* +1 for terminating-NUL */ - userfqdnlen = strlen(userfqdn) + 1; - } else - userfqdnlen = 0; - id = (struct sadb_ident *)p; - bzero(id, sizeof(*id) + PFKEY_ALIGN8(userfqdnlen)); - id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(userfqdnlen)); - id->sadb_ident_exttype = idexttype; - id->sadb_ident_type = SADB_IDENTTYPE_USERFQDN; - /* XXX is it correct? */ - if (curproc && curproc->p_cred) - id->sadb_ident_id = curproc->p_cred->p_ruid; - if (userfqdn && userfqdnlen) - bcopy(userfqdn, id + 1, userfqdnlen); - p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(userfqdnlen); - } -#endif - - /* XXX sensitivity (optional) */ - - /* create proposal/combination extension */ - m = key_getprop(saidx); -#if 0 - /* - * spec conformant: always attach proposal/combination extension, - * the problem is that we have no way to attach it for ipcomp, - * due to the way sadb_comb is declared in RFC2367. - */ - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); -#else - /* - * outside of spec; make proposal/combination extension optional. - */ - if (m) - m_cat(result, m); -#endif - - if ((result->m_flags & M_PKTHDR) == 0) { - error = EINVAL; - goto fail; - } - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) { - error = ENOBUFS; - goto fail; - } - } - - result->m_pkthdr.len = 0; - for (m = result; m; m = m->m_next) - result->m_pkthdr.len += m->m_len; - - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); - - fail: - if (result) - m_freem(result); - return error; -} - -#ifndef IPSEC_NONBLOCK_ACQUIRE -static struct secacq * -key_newacq(struct secasindex *saidx) -{ - struct secacq *newacq; - struct timeval tv; - - /* get new entry */ - KMALLOC(newacq, struct secacq *, sizeof(struct secacq)); - if (newacq == NULL) { - ipseclog((LOG_DEBUG, "key_newacq: No more memory.\n")); - return NULL; - } - bzero(newacq, sizeof(*newacq)); - - /* copy secindex */ - bcopy(saidx, &newacq->saidx, sizeof(newacq->saidx)); - newacq->seq = (acq_seq == ~0 ? 1 : ++acq_seq); - microtime(&tv); - newacq->created = tv.tv_sec; - newacq->count = 0; - - return newacq; -} - -static struct secacq * -key_getacq(struct secasindex *saidx) -{ - struct secacq *acq; - - LIST_FOREACH(acq, &acqtree, chain) { - if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY)) - return acq; - } - - return NULL; -} - -static struct secacq * -key_getacqbyseq(u_int32_t seq) -{ - struct secacq *acq; - - LIST_FOREACH(acq, &acqtree, chain) { - if (acq->seq == seq) - return acq; - } - - return NULL; -} -#endif - -static struct secspacq * -key_newspacq(struct secpolicyindex *spidx) -{ - struct secspacq *acq; - struct timeval tv; - - /* get new entry */ - KMALLOC(acq, struct secspacq *, sizeof(struct secspacq)); - if (acq == NULL) { - ipseclog((LOG_DEBUG, "key_newspacq: No more memory.\n")); - return NULL; - } - bzero(acq, sizeof(*acq)); - - /* copy secindex */ - bcopy(spidx, &acq->spidx, sizeof(acq->spidx)); - microtime(&tv); - acq->created = tv.tv_sec; - acq->count = 0; - - return acq; -} - -static struct secspacq * -key_getspacq(struct secpolicyindex *spidx) -{ - struct secspacq *acq; - - LIST_FOREACH(acq, &spacqtree, chain) { - if (key_cmpspidx_exactly(spidx, &acq->spidx)) - return acq; - } - - return NULL; -} - -/* - * SADB_ACQUIRE processing, - * in first situation, is receiving - * - * from the ikmpd, and clear sequence of its secasvar entry. - * - * In second situation, is receiving - * - * from a user land process, and return - * - * to the socket. - * - * m will always be freed. - */ -static int -key_acquire2(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct sadb_address *src0, *dst0; - struct secasindex saidx; - struct secashead *sah; - u_int16_t proto; - int error; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_acquire2: NULL pointer is passed."); - - /* - * Error message from KMd. - * We assume that if error was occured in IKEd, the length of PFKEY - * message is equal to the size of sadb_msg structure. - * We do not raise error even if error occured in this function. - */ - if (mhp->msg->sadb_msg_len == PFKEY_UNIT64(sizeof(struct sadb_msg))) { -#ifndef IPSEC_NONBLOCK_ACQUIRE - struct secacq *acq; - struct timeval tv; - - /* check sequence number */ - if (mhp->msg->sadb_msg_seq == 0) { - ipseclog((LOG_DEBUG, "key_acquire2: must specify sequence number.\n")); - m_freem(m); - return 0; - } - - if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) == NULL) { - /* - * the specified larval SA is already gone, or we got - * a bogus sequence number. we can silently ignore it. - */ - m_freem(m); - return 0; - } - - /* reset acq counter in order to deletion by timehander. */ - microtime(&tv); - acq->created = tv.tv_sec; - acq->count = 0; -#endif - m_freem(m); - return 0; - } - - /* - * This message is from user land. - */ - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_acquire2: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || - mhp->ext[SADB_EXT_PROPOSAL] == NULL) { - /* error */ - ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || - mhp->extlen[SADB_EXT_PROPOSAL] < sizeof(struct sadb_prop)) { - /* error */ - ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; - dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; - - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - /* get a SA index */ - LIST_FOREACH(sah, &sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE_REQID)) - break; - } - if (sah != NULL) { - ipseclog((LOG_DEBUG, "key_acquire2: a SA exists already.\n")); - return key_senderror(so, m, EEXIST); - } - - error = key_acquire(&saidx, NULL); - if (error != 0) { - ipseclog((LOG_DEBUG, "key_acquire2: error %d returned " - "from key_acquire.\n", mhp->msg->sadb_msg_errno)); - return key_senderror(so, m, error); - } - - return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED); -} - -/* - * SADB_REGISTER processing. - * If SATYPE_UNSPEC has been passed as satype, only return sabd_supported. - * receive - * - * from the ikmpd, and register a socket to send PF_KEY messages, - * and send - * - * to KMD by PF_KEY. - * If socket is detached, must free from regnode. - * - * m will always be freed. - */ -static int -key_register(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct secreg *reg, *newreg = NULL; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_register: NULL pointer is passed."); - - /* check for invalid register message */ - if (mhp->msg->sadb_msg_satype >= NELEM(regtree)) - return key_senderror(so, m, EINVAL); - - /* When SATYPE_UNSPEC is specified, only return sabd_supported. */ - if (mhp->msg->sadb_msg_satype == SADB_SATYPE_UNSPEC) - goto setmsg; - - /* check whether existing or not */ - LIST_FOREACH(reg, ®tree[mhp->msg->sadb_msg_satype], chain) { - if (reg->so == so) { - ipseclog((LOG_DEBUG, "key_register: socket exists already.\n")); - return key_senderror(so, m, EEXIST); - } - } - - /* create regnode */ - KMALLOC(newreg, struct secreg *, sizeof(*newreg)); - if (newreg == NULL) { - ipseclog((LOG_DEBUG, "key_register: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - bzero((caddr_t)newreg, sizeof(*newreg)); - - newreg->so = so; - ((struct keycb *)sotorawcb(so))->kp_registered++; - - /* add regnode to regtree. */ - LIST_INSERT_HEAD(®tree[mhp->msg->sadb_msg_satype], newreg, chain); - - setmsg: - { - struct mbuf *n; - struct sadb_msg *newmsg; - struct sadb_supported *sup; - u_int len, alen, elen; - int off; - int i; - struct sadb_alg *alg; - - /* create new sadb_msg to reply. */ - alen = 0; - for (i = 1; i <= SADB_AALG_MAX; i++) { - if (ah_algorithm_lookup(i)) - alen += sizeof(struct sadb_alg); - } - if (alen) - alen += sizeof(struct sadb_supported); - elen = 0; -#ifdef IPSEC_ESP - for (i = 1; i <= SADB_EALG_MAX; i++) { - if (esp_algorithm_lookup(i)) - elen += sizeof(struct sadb_alg); - } - if (elen) - elen += sizeof(struct sadb_supported); -#endif - - len = sizeof(struct sadb_msg) + alen + elen; - - if (len > MCLBYTES) - return key_senderror(so, m, ENOBUFS); - - MGETHDR(n, M_NOWAIT, MT_DATA); - if (len > MHLEN) { - MCLGET(n, M_NOWAIT); - if ((n->m_flags & M_EXT) == 0) { - m_freem(n); - n = NULL; - } - } - if (!n) - return key_senderror(so, m, ENOBUFS); - - n->m_pkthdr.len = n->m_len = len; - n->m_next = NULL; - off = 0; - - m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off); - newmsg = mtod(n, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(len); - off += PFKEY_ALIGN8(sizeof(struct sadb_msg)); - - /* for authentication algorithm */ - if (alen) { - sup = (struct sadb_supported *)(mtod(n, caddr_t) + off); - sup->sadb_supported_len = PFKEY_UNIT64(alen); - sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH; - off += PFKEY_ALIGN8(sizeof(*sup)); - - for (i = 1; i <= SADB_AALG_MAX; i++) { - const struct ah_algorithm *aalgo; - - aalgo = ah_algorithm_lookup(i); - if (!aalgo) - continue; - alg = (struct sadb_alg *)(mtod(n, caddr_t) + off); - alg->sadb_alg_id = i; - alg->sadb_alg_ivlen = 0; - alg->sadb_alg_minbits = aalgo->keymin; - alg->sadb_alg_maxbits = aalgo->keymax; - off += PFKEY_ALIGN8(sizeof(*alg)); - } - } - -#ifdef IPSEC_ESP - /* for encryption algorithm */ - if (elen) { - sup = (struct sadb_supported *)(mtod(n, caddr_t) + off); - sup->sadb_supported_len = PFKEY_UNIT64(elen); - sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT; - off += PFKEY_ALIGN8(sizeof(*sup)); - - for (i = 1; i <= SADB_EALG_MAX; i++) { - const struct esp_algorithm *ealgo; - - ealgo = esp_algorithm_lookup(i); - if (!ealgo) - continue; - alg = (struct sadb_alg *)(mtod(n, caddr_t) + off); - alg->sadb_alg_id = i; - if (ealgo && ealgo->ivlen) { - /* - * give NULL to get the value preferred by - * algorithm XXX SADB_X_EXT_DERIV ? - */ - alg->sadb_alg_ivlen = - (*ealgo->ivlen)(ealgo, NULL); - } else - alg->sadb_alg_ivlen = 0; - alg->sadb_alg_minbits = ealgo->keymin; - alg->sadb_alg_maxbits = ealgo->keymax; - off += PFKEY_ALIGN8(sizeof(struct sadb_alg)); - } - } -#endif - -#ifdef DIGAGNOSTIC - if (off != len) - panic("length assumption failed in key_register"); -#endif - - m_freem(m); - return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED); - } -} - -/* - * free secreg entry registered. - * XXX: I want to do free a socket marked done SADB_RESIGER to socket. - */ -void -key_freereg(struct socket *so) -{ - struct secreg *reg; - int i; - - /* sanity check */ - if (so == NULL) - panic("key_freereg: NULL pointer is passed."); - - /* - * check whether existing or not. - * check all type of SA, because there is a potential that - * one socket is registered to multiple type of SA. - */ - lwkt_gettoken(&key_token); - for (i = 0; i <= SADB_SATYPE_MAX; i++) { - LIST_FOREACH(reg, ®tree[i], chain) { - if (reg->so == so - && __LIST_CHAINED(reg)) { - LIST_REMOVE(reg, chain); - KFREE(reg); - break; - } - } - } - lwkt_reltoken(&key_token); -} - -/* - * SADB_EXPIRE processing - * send - * - * to KMD by PF_KEY. - * NOTE: We send only soft lifetime extension. - * - * OUT: 0 : succeed - * others : error number - */ -static int -key_expire(struct secasvar *sav) -{ - int satype; - struct mbuf *result = NULL, *m; - int len; - int error = -1; - struct sadb_lifetime *lt; - - /* sanity check */ - if (sav == NULL) - panic("key_expire: NULL pointer is passed."); - if (sav->sah == NULL) - panic("key_expire: Why was SA index in SA NULL."); - if ((satype = key_proto2satype(sav->sah->saidx.proto)) == 0) - panic("key_expire: invalid proto is passed."); - - /* set msg header */ - m = key_setsadbmsg(SADB_EXPIRE, 0, satype, sav->seq, 0, sav->refcnt); - if (!m) { - error = ENOBUFS; - goto fail; - } - result = m; - - /* create SA extension */ - m = key_setsadbsa(sav); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* create SA extension */ - m = key_setsadbxsa2(sav->sah->saidx.mode, - sav->replay ? sav->replay->count : 0, - sav->sah->saidx.reqid); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* create lifetime extension (current and soft) */ - len = PFKEY_ALIGN8(sizeof(*lt)) * 2; - m = key_alloc_mbuf(len); - if (!m || m->m_next) { /*XXX*/ - if (m) - m_freem(m); - error = ENOBUFS; - goto fail; - } - bzero(mtod(m, caddr_t), len); - lt = mtod(m, struct sadb_lifetime *); - lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); - lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; - lt->sadb_lifetime_allocations = sav->lft_c->sadb_lifetime_allocations; - lt->sadb_lifetime_bytes = sav->lft_c->sadb_lifetime_bytes; - lt->sadb_lifetime_addtime = sav->lft_c->sadb_lifetime_addtime; - lt->sadb_lifetime_usetime = sav->lft_c->sadb_lifetime_usetime; - lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2); - bcopy(sav->lft_s, lt, sizeof(*lt)); - m_cat(result, m); - - /* set sadb_address for source */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, - (struct sockaddr *)&sav->sah->saidx.src, - FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - /* set sadb_address for destination */ - m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, - (struct sockaddr *)&sav->sah->saidx.dst, - FULLMASK, IPSEC_ULPROTO_ANY); - if (!m) { - error = ENOBUFS; - goto fail; - } - m_cat(result, m); - - if ((result->m_flags & M_PKTHDR) == 0) { - error = EINVAL; - goto fail; - } - - if (result->m_len < sizeof(struct sadb_msg)) { - result = m_pullup(result, sizeof(struct sadb_msg)); - if (result == NULL) { - error = ENOBUFS; - goto fail; - } - } - - result->m_pkthdr.len = 0; - for (m = result; m; m = m->m_next) - result->m_pkthdr.len += m->m_len; - - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - - return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); - - fail: - if (result) - m_freem(result); - return error; -} - -/* - * SADB_FLUSH processing - * receive - * - * from the ikmpd, and free all entries in secastree. - * and send, - * - * to the ikmpd. - * NOTE: to do is only marking SADB_SASTATE_DEAD. - * - * m will always be freed. - */ -static int -key_flush(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct sadb_msg *newmsg; - struct secashead *sah, *nextsah; - struct secasvar *sav, *nextsav; - u_int16_t proto; - u_int8_t state; - u_int stateidx; - - /* sanity check */ - if (so == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_flush: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_flush: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - /* no SATYPE specified, i.e. flushing all SA. */ - for (sah = LIST_FIRST(&sahtree); - sah != NULL; - sah = nextsah) { - nextsah = LIST_NEXT(sah, chain); - - if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC - && proto != sah->saidx.proto) - continue; - - for (stateidx = 0; - stateidx < NELEM(saorder_state_alive); - stateidx++) { - state = saorder_state_any[stateidx]; - for (sav = LIST_FIRST(&sah->savtree[state]); - sav != NULL; - sav = nextsav) { - - nextsav = LIST_NEXT(sav, chain); - - key_sa_chgstate(sav, SADB_SASTATE_DEAD); - key_freesav(sav); - } - } - - sah->state = SADB_SASTATE_DEAD; - } - - if (m->m_len < sizeof(struct sadb_msg) || - sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) { - ipseclog((LOG_DEBUG, "key_flush: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } - - if (m->m_next) - m_freem(m->m_next); - m->m_next = NULL; - m->m_pkthdr.len = m->m_len = sizeof(struct sadb_msg); - newmsg = mtod(m, struct sadb_msg *); - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); -} - -/* - * SADB_DUMP processing - * dump all entries including status of DEAD in SAD. - * receive - * - * from the ikmpd, and dump all secasvar leaves - * and send, - * ..... - * to the ikmpd. - * - * m will always be freed. - */ -static int -key_dump(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - struct secashead *sah; - struct secasvar *sav; - u_int16_t proto; - u_int stateidx; - u_int8_t satype; - u_int8_t state; - int cnt; - struct mbuf *n; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_dump: NULL pointer is passed."); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { - ipseclog((LOG_DEBUG, "key_dump: invalid satype is passed.\n")); - return key_senderror(so, m, EINVAL); - } - - /* count sav entries to be sent to the userland. */ - cnt = 0; - LIST_FOREACH(sah, &sahtree, chain) { - if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC - && proto != sah->saidx.proto) - continue; - - for (stateidx = 0; - stateidx < NELEM(saorder_state_any); - stateidx++) { - state = saorder_state_any[stateidx]; - LIST_FOREACH(sav, &sah->savtree[state], chain) { - cnt++; - } - } - } - - if (cnt == 0) - return key_senderror(so, m, ENOENT); - - /* send this to the userland, one at a time. */ - LIST_FOREACH(sah, &sahtree, chain) { - if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC - && proto != sah->saidx.proto) - continue; - - /* map proto to satype */ - if ((satype = key_proto2satype(sah->saidx.proto)) == 0) { - ipseclog((LOG_DEBUG, "key_dump: there was invalid proto in SAD.\n")); - return key_senderror(so, m, EINVAL); - } - - for (stateidx = 0; - stateidx < NELEM(saorder_state_any); - stateidx++) { - state = saorder_state_any[stateidx]; - LIST_FOREACH(sav, &sah->savtree[state], chain) { - n = key_setdumpsa(sav, SADB_DUMP, satype, - --cnt, mhp->msg->sadb_msg_pid); - if (!n) - return key_senderror(so, m, ENOBUFS); - - key_sendup_mbuf(so, n, KEY_SENDUP_ONE); - } - } - } - - m_freem(m); - return 0; -} - -/* - * SADB_X_PROMISC processing - * - * m will always be freed. - */ -static int -key_promisc(struct socket *so, struct mbuf *m, - const struct sadb_msghdr *mhp) -{ - int olen; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_promisc: NULL pointer is passed."); - - olen = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); - - if (olen < sizeof(struct sadb_msg)) { -#if 1 - return key_senderror(so, m, EINVAL); -#else - m_freem(m); - return 0; -#endif - } else if (olen == sizeof(struct sadb_msg)) { - /* enable/disable promisc mode */ - struct keycb *kp; - - if ((kp = (struct keycb *)sotorawcb(so)) == NULL) - return key_senderror(so, m, EINVAL); - mhp->msg->sadb_msg_errno = 0; - switch (mhp->msg->sadb_msg_satype) { - case 0: - case 1: - kp->kp_promisc = mhp->msg->sadb_msg_satype; - break; - default: - return key_senderror(so, m, EINVAL); - } - - /* send the original message back to everyone */ - mhp->msg->sadb_msg_errno = 0; - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); - } else { - /* send packet as is */ - - m_adj(m, PFKEY_ALIGN8(sizeof(struct sadb_msg))); - - /* TODO: if sadb_msg_seq is specified, send to specific pid */ - return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); - } -} - -static int (*key_typesw[]) (struct socket *, struct mbuf *, - const struct sadb_msghdr *) = { - NULL, /* SADB_RESERVED */ - key_getspi, /* SADB_GETSPI */ - key_update, /* SADB_UPDATE */ - key_add, /* SADB_ADD */ - key_delete, /* SADB_DELETE */ - key_get, /* SADB_GET */ - key_acquire2, /* SADB_ACQUIRE */ - key_register, /* SADB_REGISTER */ - NULL, /* SADB_EXPIRE */ - key_flush, /* SADB_FLUSH */ - key_dump, /* SADB_DUMP */ - key_promisc, /* SADB_X_PROMISC */ - NULL, /* SADB_X_PCHANGE */ - key_spdadd, /* SADB_X_SPDUPDATE */ - key_spdadd, /* SADB_X_SPDADD */ - key_spddelete, /* SADB_X_SPDDELETE */ - key_spdget, /* SADB_X_SPDGET */ - NULL, /* SADB_X_SPDACQUIRE */ - key_spddump, /* SADB_X_SPDDUMP */ - key_spdflush, /* SADB_X_SPDFLUSH */ - key_spdadd, /* SADB_X_SPDSETIDX */ - NULL, /* SADB_X_SPDEXPIRE */ - key_spddelete2, /* SADB_X_SPDDELETE2 */ -}; - -/* - * parse sadb_msg buffer to process PFKEYv2, - * and create a data to response if needed. - * I think to be dealed with mbuf directly. - * IN: - * msgp : pointer to pointer to a received buffer pulluped. - * This is rewrited to response. - * so : pointer to socket. - * OUT: - * length for buffer to send to user process. - */ -int -key_parse(struct mbuf *m, struct socket *so) -{ - struct sadb_msg *msg; - struct sadb_msghdr mh; - u_int orglen; - int error; - int target; - - /* sanity check */ - if (m == NULL || so == NULL) - panic("key_parse: NULL pointer is passed."); - -#if 0 /*kdebug_sadb assumes msg in linear buffer*/ - KEYDEBUG(KEYDEBUG_KEY_DUMP, - ipseclog((LOG_DEBUG, "key_parse: passed sadb_msg\n")); - kdebug_sadb(msg)); -#endif - - if (m->m_len < sizeof(struct sadb_msg)) { - m = m_pullup(m, sizeof(struct sadb_msg)); - if (!m) - return ENOBUFS; - } - msg = mtod(m, struct sadb_msg *); - orglen = PFKEY_UNUNIT64(msg->sadb_msg_len); - target = KEY_SENDUP_ONE; - - if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len != orglen) { - ipseclog((LOG_DEBUG, "key_parse: invalid message length.\n")); - pfkeystat.out_invlen++; - error = EINVAL; - goto senderror; - } - - if (msg->sadb_msg_version != PF_KEY_V2) { - ipseclog((LOG_DEBUG, - "key_parse: PF_KEY version %u is mismatched.\n", - msg->sadb_msg_version)); - pfkeystat.out_invver++; - error = EINVAL; - goto senderror; - } - - if (msg->sadb_msg_type > SADB_MAX) { - ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n", - msg->sadb_msg_type)); - pfkeystat.out_invmsgtype++; - error = EINVAL; - goto senderror; - } - - /* for old-fashioned code - should be nuked */ - if (m->m_pkthdr.len > MCLBYTES) { - m_freem(m); - return ENOBUFS; - } - if (m->m_next) { - struct mbuf *n; - - MGETHDR(n, M_NOWAIT, MT_DATA); - if (n && m->m_pkthdr.len > MHLEN) { - MCLGET(n, M_NOWAIT); - if ((n->m_flags & M_EXT) == 0) { - m_free(n); - n = NULL; - } - } - if (!n) { - m_freem(m); - return ENOBUFS; - } - m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t)); - n->m_pkthdr.len = n->m_len = m->m_pkthdr.len; - n->m_next = NULL; - m_freem(m); - m = n; - } - - /* align the mbuf chain so that extensions are in contiguous region. */ - error = key_align(m, &mh); - if (error) - return error; - - if (m->m_next) { /*XXX*/ - m_freem(m); - return ENOBUFS; - } - - msg = mh.msg; - - /* check SA type */ - switch (msg->sadb_msg_satype) { - case SADB_SATYPE_UNSPEC: - switch (msg->sadb_msg_type) { - case SADB_GETSPI: - case SADB_UPDATE: - case SADB_ADD: - case SADB_DELETE: - case SADB_GET: - case SADB_ACQUIRE: - case SADB_EXPIRE: - ipseclog((LOG_DEBUG, "key_parse: must specify satype " - "when msg type=%u.\n", msg->sadb_msg_type)); - pfkeystat.out_invsatype++; - error = EINVAL; - goto senderror; - } - break; - case SADB_SATYPE_AH: - case SADB_SATYPE_ESP: - case SADB_X_SATYPE_IPCOMP: - case SADB_X_SATYPE_TCPSIGNATURE: - switch (msg->sadb_msg_type) { - case SADB_X_SPDADD: - case SADB_X_SPDDELETE: - case SADB_X_SPDGET: - case SADB_X_SPDDUMP: - case SADB_X_SPDFLUSH: - case SADB_X_SPDSETIDX: - case SADB_X_SPDUPDATE: - case SADB_X_SPDDELETE2: - ipseclog((LOG_DEBUG, "key_parse: illegal satype=%u\n", - msg->sadb_msg_type)); - pfkeystat.out_invsatype++; - error = EINVAL; - goto senderror; - } - break; - case SADB_SATYPE_RSVP: - case SADB_SATYPE_OSPFV2: - case SADB_SATYPE_RIPV2: - case SADB_SATYPE_MIP: - ipseclog((LOG_DEBUG, "key_parse: type %u isn't supported.\n", - msg->sadb_msg_satype)); - pfkeystat.out_invsatype++; - error = EOPNOTSUPP; - goto senderror; - case 1: /* XXX: What does it do? */ - if (msg->sadb_msg_type == SADB_X_PROMISC) - break; - /*FALLTHROUGH*/ - default: - ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n", - msg->sadb_msg_satype)); - pfkeystat.out_invsatype++; - error = EINVAL; - goto senderror; - } - - /* check field of upper layer protocol and address family */ - if (mh.ext[SADB_EXT_ADDRESS_SRC] != NULL - && mh.ext[SADB_EXT_ADDRESS_DST] != NULL) { - struct sadb_address *src0, *dst0; - u_int plen; - - src0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_DST]); - - /* check upper layer protocol */ - if (src0->sadb_address_proto != dst0->sadb_address_proto) { - ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n")); - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - - /* check family */ - if (PFKEY_ADDR_SADDR(src0)->sa_family != - PFKEY_ADDR_SADDR(dst0)->sa_family) { - ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n")); - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - if (PFKEY_ADDR_SADDR(src0)->sa_len != - PFKEY_ADDR_SADDR(dst0)->sa_len) { - ipseclog((LOG_DEBUG, - "key_parse: address struct size mismatched.\n")); - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - - switch (PFKEY_ADDR_SADDR(src0)->sa_family) { - case AF_INET: - if (PFKEY_ADDR_SADDR(src0)->sa_len != - sizeof(struct sockaddr_in)) { - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - break; - case AF_INET6: - if (PFKEY_ADDR_SADDR(src0)->sa_len != - sizeof(struct sockaddr_in6)) { - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - break; - default: - ipseclog((LOG_DEBUG, - "key_parse: unsupported address family.\n")); - pfkeystat.out_invaddr++; - error = EAFNOSUPPORT; - goto senderror; - } - - switch (PFKEY_ADDR_SADDR(src0)->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - plen = 0; /*fool gcc*/ - break; - } - - /* check max prefix length */ - if (src0->sadb_address_prefixlen > plen || - dst0->sadb_address_prefixlen > plen) { - ipseclog((LOG_DEBUG, - "key_parse: illegal prefixlen.\n")); - pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } - - /* - * prefixlen == 0 is valid because there can be a case when - * all addresses are matched. - */ - } - - if (msg->sadb_msg_type >= NELEM(key_typesw) || - key_typesw[msg->sadb_msg_type] == NULL) { - pfkeystat.out_invmsgtype++; - error = EINVAL; - goto senderror; - } - - lwkt_gettoken(&key_token); - error = (*key_typesw[msg->sadb_msg_type])(so, m, &mh); - lwkt_reltoken(&key_token); - return error; - -senderror: - msg->sadb_msg_errno = error; - lwkt_gettoken(&key_token); - error = key_sendup_mbuf(so, m, target); - lwkt_reltoken(&key_token); - return error; -} - -static int -key_senderror(struct socket *so, struct mbuf *m, int code) -{ - struct sadb_msg *msg; - - if (m->m_len < sizeof(struct sadb_msg)) - panic("invalid mbuf passed to key_senderror"); - - msg = mtod(m, struct sadb_msg *); - msg->sadb_msg_errno = code; - return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); -} - -/* - * set the pointer to each header into message buffer. - * m will be freed on error. - * XXX larger-than-MCLBYTES extension? - */ -static int -key_align(struct mbuf *m, struct sadb_msghdr *mhp) -{ - struct mbuf *n; - struct sadb_ext *ext; - size_t off, end; - int extlen; - int toff; - - /* sanity check */ - if (m == NULL || mhp == NULL) - panic("key_align: NULL pointer is passed."); - if (m->m_len < sizeof(struct sadb_msg)) - panic("invalid mbuf passed to key_align"); - - /* initialize */ - bzero(mhp, sizeof(*mhp)); - - mhp->msg = mtod(m, struct sadb_msg *); - mhp->ext[0] = (struct sadb_ext *)mhp->msg; /*XXX backward compat */ - - end = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); - extlen = end; /*just in case extlen is not updated*/ - for (off = sizeof(struct sadb_msg); off < end; off += extlen) { - n = m_pulldown(m, off, sizeof(struct sadb_ext), &toff); - if (!n) { - /* m is already freed */ - return ENOBUFS; - } - ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff); - - /* set pointer */ - switch (ext->sadb_ext_type) { - case SADB_EXT_SA: - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - case SADB_EXT_LIFETIME_CURRENT: - case SADB_EXT_LIFETIME_HARD: - case SADB_EXT_LIFETIME_SOFT: - case SADB_EXT_KEY_AUTH: - case SADB_EXT_KEY_ENCRYPT: - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - case SADB_EXT_SENSITIVITY: - case SADB_EXT_PROPOSAL: - case SADB_EXT_SUPPORTED_AUTH: - case SADB_EXT_SUPPORTED_ENCRYPT: - case SADB_EXT_SPIRANGE: - case SADB_X_EXT_POLICY: - case SADB_X_EXT_SA2: - /* duplicate check */ - /* - * XXX Are there duplication payloads of either - * KEY_AUTH or KEY_ENCRYPT ? - */ - if (mhp->ext[ext->sadb_ext_type] != NULL) { - ipseclog((LOG_DEBUG, - "key_align: duplicate ext_type %u " - "is passed.\n", ext->sadb_ext_type)); - m_freem(m); - pfkeystat.out_dupext++; - return EINVAL; - } - break; - default: - ipseclog((LOG_DEBUG, - "key_align: invalid ext_type %u is passed.\n", - ext->sadb_ext_type)); - m_freem(m); - pfkeystat.out_invexttype++; - return EINVAL; - } - - extlen = PFKEY_UNUNIT64(ext->sadb_ext_len); - - if (key_validate_ext(ext, extlen)) { - m_freem(m); - pfkeystat.out_invlen++; - return EINVAL; - } - - n = m_pulldown(m, off, extlen, &toff); - if (!n) { - /* m is already freed */ - return ENOBUFS; - } - ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff); - - mhp->ext[ext->sadb_ext_type] = ext; - mhp->extoff[ext->sadb_ext_type] = off; - mhp->extlen[ext->sadb_ext_type] = extlen; - } - - if (off != end) { - m_freem(m); - pfkeystat.out_invlen++; - return EINVAL; - } - - return 0; -} - -static int -key_validate_ext(const struct sadb_ext *ext, int len) -{ - const struct sockaddr *sa; - enum { NONE, ADDR } checktype = NONE; - int baselen = 0; - const int sal = offsetof(struct sockaddr, sa_len) + sizeof(sa->sa_len); - - if (len != PFKEY_UNUNIT64(ext->sadb_ext_len)) - return EINVAL; - - /* if it does not match minimum/maximum length, bail */ - if (ext->sadb_ext_type >= NELEM(minsize) || - ext->sadb_ext_type >= NELEM(maxsize)) - return EINVAL; - if (!minsize[ext->sadb_ext_type] || len < minsize[ext->sadb_ext_type]) - return EINVAL; - if (maxsize[ext->sadb_ext_type] && len > maxsize[ext->sadb_ext_type]) - return EINVAL; - - /* more checks based on sadb_ext_type XXX need more */ - switch (ext->sadb_ext_type) { - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - baselen = PFKEY_ALIGN8(sizeof(struct sadb_address)); - checktype = ADDR; - break; - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - if (((const struct sadb_ident *)ext)->sadb_ident_type == - SADB_X_IDENTTYPE_ADDR) { - baselen = PFKEY_ALIGN8(sizeof(struct sadb_ident)); - checktype = ADDR; - } else - checktype = NONE; - break; - default: - checktype = NONE; - break; - } - - switch (checktype) { - case NONE: - break; - case ADDR: - sa = (const struct sockaddr *)((c_caddr_t)ext + baselen); - if (len < baselen + sal) - return EINVAL; - if (baselen + PFKEY_ALIGN8(sa->sa_len) != len) - return EINVAL; - break; - } - - return 0; -} - -void -key_init(void) -{ - int i; - - bzero((caddr_t)&key_cb, sizeof(key_cb)); - - for (i = 0; i < IPSEC_DIR_MAX; i++) { - LIST_INIT(&sptree[i]); - } - - LIST_INIT(&sahtree); - - for (i = 0; i <= SADB_SATYPE_MAX; i++) { - LIST_INIT(®tree[i]); - } - -#ifndef IPSEC_NONBLOCK_ACQUIRE - LIST_INIT(&acqtree); -#endif - LIST_INIT(&spacqtree); - - /* system default */ -#ifdef INET - ip4_def_policy.policy = IPSEC_POLICY_NONE; - ip4_def_policy.refcnt++; /*never reclaim this*/ -#endif -#ifdef INET6 - ip6_def_policy.policy = IPSEC_POLICY_NONE; - ip6_def_policy.refcnt++; /*never reclaim this*/ -#endif - -#ifndef IPSEC_DEBUG2 - callout_init(&key_timehandler_ch); - callout_reset(&key_timehandler_ch, hz, key_timehandler, NULL); -#endif /*IPSEC_DEBUG2*/ - - /* initialize key statistics */ - keystat.getspi_count = 1; - - kprintf("IPsec: Initialized Security Association Processing.\n"); - - return; -} - -/* - * XXX: maybe This function is called after INBOUND IPsec processing. - * - * Special check for tunnel-mode packets. - * We must make some checks for consistency between inner and outer IP header. - * - * xxx more checks to be provided - */ -int -key_checktunnelsanity(struct secasvar *sav, u_int family, - caddr_t src, caddr_t dst) -{ - /* sanity check */ - if (sav->sah == NULL) - panic("sav->sah == NULL at key_checktunnelsanity"); - - /* XXX: check inner IP header */ - - return 1; -} - -#if 0 -#define hostnamelen strlen(hostname) - -/* - * Get FQDN for the host. - * If the administrator configured hostname (by hostname(1)) without - * domain name, returns nothing. - */ -static const char * -key_getfqdn(void) -{ - int i; - int hasdot; - static char fqdn[MAXHOSTNAMELEN + 1]; - - if (!hostnamelen) - return NULL; - - /* check if it comes with domain name. */ - hasdot = 0; - for (i = 0; i < hostnamelen; i++) { - if (hostname[i] == '.') - hasdot++; - } - if (!hasdot) - return NULL; - - /* NOTE: hostname may not be NUL-terminated. */ - bzero(fqdn, sizeof(fqdn)); - bcopy(hostname, fqdn, hostnamelen); - fqdn[hostnamelen] = '\0'; - return fqdn; -} - -/* - * get username@FQDN for the host/user. - */ -static const char * -key_getuserfqdn(void) -{ - const char *host; - static char userfqdn[MAXHOSTNAMELEN + MAXLOGNAME + 2]; - struct proc *p = curproc; - char *q; - - if (!p || !p->p_pgrp || !p->p_pgrp->pg_session) - return NULL; - if (!(host = key_getfqdn())) - return NULL; - - /* NOTE: s_login may not be-NUL terminated. */ - bzero(userfqdn, sizeof(userfqdn)); - bcopy(p->p_pgrp->pg_session->s_login, userfqdn, MAXLOGNAME); - userfqdn[MAXLOGNAME] = '\0'; /* safeguard */ - q = userfqdn + strlen(userfqdn); - *q++ = '@'; - bcopy(host, q, strlen(host)); - q += strlen(host); - *q++ = '\0'; - - return userfqdn; -} -#endif - -/* record data transfer on SA, and update timestamps */ -void -key_sa_recordxfer(struct secasvar *sav, struct mbuf *m) -{ - if (!sav) - panic("key_sa_recordxfer called with sav == NULL"); - if (!m) - panic("key_sa_recordxfer called with m == NULL"); - if (!sav->lft_c) - return; - - /* - * XXX Currently, there is a difference of bytes size - * between inbound and outbound processing. - */ - sav->lft_c->sadb_lifetime_bytes += m->m_pkthdr.len; - /* to check bytes lifetime is done in key_timehandler(). */ - - /* - * We use the number of packets as the unit of - * sadb_lifetime_allocations. We increment the variable - * whenever {esp,ah}_{in,out}put is called. - */ - sav->lft_c->sadb_lifetime_allocations++; - /* XXX check for expires? */ - - /* - * NOTE: We record CURRENT sadb_lifetime_usetime by using wall clock, - * in seconds. HARD and SOFT lifetime are measured by the time - * difference (again in seconds) from sadb_lifetime_usetime. - * - * usetime - * v expire expire - * -----+-----+--------+---> t - * <--------------> HARD - * <-----> SOFT - */ - { - struct timeval tv; - microtime(&tv); - sav->lft_c->sadb_lifetime_usetime = tv.tv_sec; - /* XXX check for expires? */ - } - - return; -} - -/* dumb version */ -void -key_sa_routechange(struct sockaddr *dst) -{ - struct secashead *sah; - struct route *ro; - - lwkt_gettoken(&key_token); - LIST_FOREACH(sah, &sahtree, chain) { - ro = &sah->sa_route; - if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len - && bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) { - RTFREE(ro->ro_rt); - ro->ro_rt = NULL; - } - } - lwkt_reltoken(&key_token); -} - -static void -key_sa_chgstate(struct secasvar *sav, u_int8_t state) -{ - if (sav == NULL) - panic("key_sa_chgstate called with sav == NULL"); - - if (sav->state == state) - return; - - if (__LIST_CHAINED(sav)) - LIST_REMOVE(sav, chain); - - sav->state = state; - LIST_INSERT_HEAD(&sav->sah->savtree[state], sav, chain); -} - -void -key_sa_stir_iv(struct secasvar *sav) -{ - if (!sav->iv) - panic("key_sa_stir_iv called with sav == NULL"); - key_randomfill(sav->iv, sav->ivlen); -} - -/* XXX too much? */ -static struct mbuf * -key_alloc_mbuf(int l) -{ - struct mbuf *m = NULL, *n; - int len, t; - - len = l; - while (len > 0) { - MGET(n, M_NOWAIT, MT_DATA); - if (n && len > MLEN) - MCLGET(n, M_NOWAIT); - if (!n) { - m_freem(m); - return NULL; - } - - n->m_next = NULL; - n->m_len = 0; - n->m_len = M_TRAILINGSPACE(n); - /* use the bottom of mbuf, hoping we can prepend afterwards */ - if (n->m_len > len) { - t = (n->m_len - len) & ~(sizeof(long) - 1); - n->m_data += t; - n->m_len = len; - } - - len -= n->m_len; - - if (m) - m_cat(m, n); - else - m = n; - } - - return m; -} diff --git a/sys/netproto/key/key.h b/sys/netproto/key/key.h deleted file mode 100644 index 2c904122f7..0000000000 --- a/sys/netproto/key/key.h +++ /dev/null @@ -1,84 +0,0 @@ -/* $FreeBSD: src/sys/netkey/key.h,v 1.5.2.3 2002/04/28 05:40:28 suz Exp $ */ -/* $DragonFly: src/sys/netproto/key/key.h,v 1.4 2004/09/16 23:01:34 joerg Exp $ */ -/* $KAME: key.h,v 1.21 2001/07/27 03:51:30 itojun Exp $ */ - -/* - * 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. - */ - -#ifndef _NETKEY_KEY_H_ -#define _NETKEY_KEY_H_ - -#ifdef _KERNEL - -extern struct key_cb key_cb; -extern struct lwkt_token key_token; - -struct secpolicy; -struct secpolicyindex; -struct ipsecrequest; -struct secasvar; -struct sockaddr; -struct socket; -struct sadb_msg; -struct sadb_x_policy; - -extern struct secpolicy *key_allocsp (struct secpolicyindex *, u_int); -extern struct secpolicy *key_gettunnel (struct sockaddr *, - struct sockaddr *, struct sockaddr *, struct sockaddr *); -extern int key_checkrequest - (struct ipsecrequest *isr, struct secasindex *); -extern struct secasvar *key_allocsa (u_int, caddr_t, caddr_t, - u_int, u_int32_t); -extern void key_freesp (struct secpolicy *); -extern void key_freeso (struct socket *); -extern void key_freesav (struct secasvar *); -extern struct secpolicy *key_newsp (void); -extern struct secpolicy *key_msg2sp (struct sadb_x_policy *, - size_t, int *); -extern struct mbuf *key_sp2msg (struct secpolicy *); -extern int key_ismyaddr (struct sockaddr *); -extern int key_spdacquire (struct secpolicy *); -extern void key_timehandler(void *); -extern u_long key_random (void); -extern void key_randomfill (void *, size_t); -extern void key_freereg (struct socket *); -extern int key_parse (struct mbuf *, struct socket *); -extern void key_init (void); -extern int key_checktunnelsanity (struct secasvar *, u_int, - caddr_t, caddr_t); -extern void key_sa_recordxfer (struct secasvar *, struct mbuf *); -extern void key_sa_routechange (struct sockaddr *); -extern void key_sa_stir_iv (struct secasvar *); - -#ifdef MALLOC_DECLARE -MALLOC_DECLARE(M_SECA); -#endif /* MALLOC_DECLARE */ - -#endif /* defined(_KERNEL) */ -#endif /* _NETKEY_KEY_H_ */ diff --git a/sys/netproto/key/key_debug.c b/sys/netproto/key/key_debug.c deleted file mode 100644 index 7b8f56c975..0000000000 --- a/sys/netproto/key/key_debug.c +++ /dev/null @@ -1,726 +0,0 @@ -/* $FreeBSD: src/sys/netkey/key_debug.c,v 1.10.2.5 2002/04/28 05:40:28 suz Exp $ */ -/* $KAME: key_debug.c,v 1.26 2001/06/27 10:46:50 sakane Exp $ */ - -/* - * 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. - */ - -#ifdef _KERNEL -#include "opt_inet.h" -#include "opt_inet6.h" -#include "opt_ipsec.h" -#endif - -#include -#include -#ifdef _KERNEL -#include -#include -#include -#endif -#include - -#include - -#include "key_var.h" -#include "key_debug.h" - -#include -#include - -#ifndef _KERNEL -#include -#include -#include -#endif /* !_KERNEL */ - -static void kdebug_sadb_prop (struct sadb_ext *); -static void kdebug_sadb_identity (struct sadb_ext *); -static void kdebug_sadb_supported (struct sadb_ext *); -static void kdebug_sadb_lifetime (struct sadb_ext *); -static void kdebug_sadb_sa (struct sadb_ext *); -static void kdebug_sadb_address (struct sadb_ext *); -static void kdebug_sadb_key (struct sadb_ext *); -static void kdebug_sadb_x_sa2 (struct sadb_ext *); - -#ifdef _KERNEL -static void kdebug_secreplay (struct secreplay *); -#endif - -#ifndef _KERNEL -#define kprintf printf -#define panic(param) { printf(param); exit(-1); } -#endif - -/* NOTE: host byte order */ - -/* %%%: about struct sadb_msg */ -void -kdebug_sadb(struct sadb_msg *base) -{ - struct sadb_ext *ext; - int tlen, extlen; - - /* sanity check */ - if (base == NULL) - panic("kdebug_sadb: NULL pointer was passed."); - - kprintf("sadb_msg{ version=%u type=%u errno=%u satype=%u\n", - base->sadb_msg_version, base->sadb_msg_type, - base->sadb_msg_errno, base->sadb_msg_satype); - kprintf(" len=%u reserved=%u seq=%u pid=%u\n", - base->sadb_msg_len, base->sadb_msg_reserved, - base->sadb_msg_seq, base->sadb_msg_pid); - - tlen = PFKEY_UNUNIT64(base->sadb_msg_len) - sizeof(struct sadb_msg); - ext = (struct sadb_ext *)((caddr_t)base + sizeof(struct sadb_msg)); - - while (tlen > 0) { - kprintf("sadb_ext{ len=%u type=%u }\n", - ext->sadb_ext_len, ext->sadb_ext_type); - - if (ext->sadb_ext_len == 0) { - kprintf("kdebug_sadb: invalid ext_len=0 was passed.\n"); - return; - } - if (ext->sadb_ext_len > tlen) { - kprintf("kdebug_sadb: ext_len exceeds end of buffer.\n"); - return; - } - - switch (ext->sadb_ext_type) { - case SADB_EXT_SA: - kdebug_sadb_sa(ext); - break; - case SADB_EXT_LIFETIME_CURRENT: - case SADB_EXT_LIFETIME_HARD: - case SADB_EXT_LIFETIME_SOFT: - kdebug_sadb_lifetime(ext); - break; - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - kdebug_sadb_address(ext); - break; - case SADB_EXT_KEY_AUTH: - case SADB_EXT_KEY_ENCRYPT: - kdebug_sadb_key(ext); - break; - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - kdebug_sadb_identity(ext); - break; - case SADB_EXT_SENSITIVITY: - break; - case SADB_EXT_PROPOSAL: - kdebug_sadb_prop(ext); - break; - case SADB_EXT_SUPPORTED_AUTH: - case SADB_EXT_SUPPORTED_ENCRYPT: - kdebug_sadb_supported(ext); - break; - case SADB_EXT_SPIRANGE: - case SADB_X_EXT_KMPRIVATE: - break; - case SADB_X_EXT_POLICY: - kdebug_sadb_x_policy(ext); - break; - case SADB_X_EXT_SA2: - kdebug_sadb_x_sa2(ext); - break; - default: - kprintf("kdebug_sadb: invalid ext_type %u was passed.\n", - ext->sadb_ext_type); - return; - } - - extlen = PFKEY_UNUNIT64(ext->sadb_ext_len); - tlen -= extlen; - ext = (struct sadb_ext *)((caddr_t)ext + extlen); - } - - return; -} - -static void -kdebug_sadb_prop(struct sadb_ext *ext) -{ - struct sadb_prop *prop = (struct sadb_prop *)ext; - struct sadb_comb *comb; - int len; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_prop: NULL pointer was passed."); - - len = (PFKEY_UNUNIT64(prop->sadb_prop_len) - sizeof(*prop)) - / sizeof(*comb); - comb = (struct sadb_comb *)(prop + 1); - kprintf("sadb_prop{ replay=%u\n", prop->sadb_prop_replay); - - while (len--) { - kprintf("sadb_comb{ auth=%u encrypt=%u " - "flags=0x%04x reserved=0x%08x\n", - comb->sadb_comb_auth, comb->sadb_comb_encrypt, - comb->sadb_comb_flags, comb->sadb_comb_reserved); - - kprintf(" auth_minbits=%u auth_maxbits=%u " - "encrypt_minbits=%u encrypt_maxbits=%u\n", - comb->sadb_comb_auth_minbits, - comb->sadb_comb_auth_maxbits, - comb->sadb_comb_encrypt_minbits, - comb->sadb_comb_encrypt_maxbits); - - kprintf(" soft_alloc=%u hard_alloc=%u " - "soft_bytes=%lu hard_bytes=%lu\n", - comb->sadb_comb_soft_allocations, - comb->sadb_comb_hard_allocations, - (unsigned long)comb->sadb_comb_soft_bytes, - (unsigned long)comb->sadb_comb_hard_bytes); - - kprintf(" soft_alloc=%lu hard_alloc=%lu " - "soft_bytes=%lu hard_bytes=%lu }\n", - (unsigned long)comb->sadb_comb_soft_addtime, - (unsigned long)comb->sadb_comb_hard_addtime, - (unsigned long)comb->sadb_comb_soft_usetime, - (unsigned long)comb->sadb_comb_hard_usetime); - comb++; - } - kprintf("}\n"); - - return; -} - -static void -kdebug_sadb_identity(struct sadb_ext *ext) -{ - struct sadb_ident *id = (struct sadb_ident *)ext; - int len; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_identity: NULL pointer was passed."); - - len = PFKEY_UNUNIT64(id->sadb_ident_len) - sizeof(*id); - kprintf("sadb_ident_%s{", - id->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC ? "src" : "dst"); - switch (id->sadb_ident_type) { - default: - kprintf(" type=%d id=%lu", - id->sadb_ident_type, (u_long)id->sadb_ident_id); - if (len) { -#ifdef _KERNEL - ipsec_hexdump((caddr_t)(id + 1), len); /*XXX cast ?*/ -#else - char *p, *ep; - kprintf("\n str=\""); - p = (char *)(id + 1); - ep = p + len; - for (/*nothing*/; *p && p < ep; p++) { - if (isprint(*p)) - kprintf("%c", *p & 0xff); - else - kprintf("\\%03o", *p & 0xff); - } -#endif - kprintf("\""); - } - break; - } - - kprintf(" }\n"); - - return; -} - -static void -kdebug_sadb_supported(struct sadb_ext *ext) -{ - struct sadb_supported *sup = (struct sadb_supported *)ext; - struct sadb_alg *alg; - int len; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_supported: NULL pointer was passed."); - - len = (PFKEY_UNUNIT64(sup->sadb_supported_len) - sizeof(*sup)) - / sizeof(*alg); - alg = (struct sadb_alg *)(sup + 1); - kprintf("sadb_sup{\n"); - while (len--) { - kprintf(" { id=%d ivlen=%d min=%d max=%d }\n", - alg->sadb_alg_id, alg->sadb_alg_ivlen, - alg->sadb_alg_minbits, alg->sadb_alg_maxbits); - alg++; - } - kprintf("}\n"); - - return; -} - -static void -kdebug_sadb_lifetime(struct sadb_ext *ext) -{ - struct sadb_lifetime *lft = (struct sadb_lifetime *)ext; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_lifetime: NULL pointer was passed."); - - kprintf("sadb_lifetime{ alloc=%u, bytes=%u\n", - lft->sadb_lifetime_allocations, - (u_int32_t)lft->sadb_lifetime_bytes); - kprintf(" addtime=%u, usetime=%u }\n", - (u_int32_t)lft->sadb_lifetime_addtime, - (u_int32_t)lft->sadb_lifetime_usetime); - - return; -} - -static void -kdebug_sadb_sa(struct sadb_ext *ext) -{ - struct sadb_sa *sa = (struct sadb_sa *)ext; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_sa: NULL pointer was passed."); - - kprintf("sadb_sa{ spi=%u replay=%u state=%u\n", - (u_int32_t)ntohl(sa->sadb_sa_spi), sa->sadb_sa_replay, - sa->sadb_sa_state); - kprintf(" auth=%u encrypt=%u flags=0x%08x }\n", - sa->sadb_sa_auth, sa->sadb_sa_encrypt, sa->sadb_sa_flags); - - return; -} - -static void -kdebug_sadb_address(struct sadb_ext *ext) -{ - struct sadb_address *addr = (struct sadb_address *)ext; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_address: NULL pointer was passed."); - - kprintf("sadb_address{ proto=%u prefixlen=%u reserved=0x%02x%02x }\n", - addr->sadb_address_proto, addr->sadb_address_prefixlen, - ((u_char *)&addr->sadb_address_reserved)[0], - ((u_char *)&addr->sadb_address_reserved)[1]); - - kdebug_sockaddr((struct sockaddr *)((caddr_t)ext + sizeof(*addr))); - - return; -} - -static void -kdebug_sadb_key(struct sadb_ext *ext) -{ - struct sadb_key *key = (struct sadb_key *)ext; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_key: NULL pointer was passed."); - - kprintf("sadb_key{ bits=%u reserved=%u\n", - key->sadb_key_bits, key->sadb_key_reserved); - kprintf(" key="); - - /* sanity check 2 */ - if ((key->sadb_key_bits >> 3) > - (PFKEY_UNUNIT64(key->sadb_key_len) - sizeof(struct sadb_key))) { - kprintf("kdebug_sadb_key: key length mismatch, bit:%d len:%ld.\n", - key->sadb_key_bits >> 3, - (long)PFKEY_UNUNIT64(key->sadb_key_len) - sizeof(struct sadb_key)); - } - - ipsec_hexdump((caddr_t)key + sizeof(struct sadb_key), - key->sadb_key_bits >> 3); - kprintf(" }\n"); - return; -} - -static void -kdebug_sadb_x_sa2(struct sadb_ext *ext) -{ - struct sadb_x_sa2 *sa2 = (struct sadb_x_sa2 *)ext; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_x_sa2: NULL pointer was passed."); - - kprintf("sadb_x_sa2{ mode=%u reqid=%u\n", - sa2->sadb_x_sa2_mode, sa2->sadb_x_sa2_reqid); - kprintf(" reserved1=%u reserved2=%u sequence=%u }\n", - sa2->sadb_x_sa2_reserved1, sa2->sadb_x_sa2_reserved2, - sa2->sadb_x_sa2_sequence); - - return; -} - -void -kdebug_sadb_x_policy(struct sadb_ext *ext) -{ - struct sadb_x_policy *xpl = (struct sadb_x_policy *)ext; - struct sockaddr *addr; - - /* sanity check */ - if (ext == NULL) - panic("kdebug_sadb_x_policy: NULL pointer was passed."); - - kprintf("sadb_x_policy{ type=%u dir=%u id=%x }\n", - xpl->sadb_x_policy_type, xpl->sadb_x_policy_dir, - xpl->sadb_x_policy_id); - - if (xpl->sadb_x_policy_type == IPSEC_POLICY_IPSEC) { - int tlen; - struct sadb_x_ipsecrequest *xisr; - - tlen = PFKEY_UNUNIT64(xpl->sadb_x_policy_len) - sizeof(*xpl); - xisr = (struct sadb_x_ipsecrequest *)(xpl + 1); - - while (tlen > 0) { - kprintf(" { len=%u proto=%u mode=%u level=%u reqid=%u\n", - xisr->sadb_x_ipsecrequest_len, - xisr->sadb_x_ipsecrequest_proto, - xisr->sadb_x_ipsecrequest_mode, - xisr->sadb_x_ipsecrequest_level, - xisr->sadb_x_ipsecrequest_reqid); - - if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) { - addr = (struct sockaddr *)(xisr + 1); - kdebug_sockaddr(addr); - addr = (struct sockaddr *)((caddr_t)addr - + addr->sa_len); - kdebug_sockaddr(addr); - } - - kprintf(" }\n"); - - /* prevent infinite loop */ - if (xisr->sadb_x_ipsecrequest_len <= 0) { - kprintf("kdebug_sadb_x_policy: wrong policy struct.\n"); - return; - } - /* prevent overflow */ - if (xisr->sadb_x_ipsecrequest_len > tlen) { - kprintf("invalid ipsec policy length\n"); - return; - } - - tlen -= xisr->sadb_x_ipsecrequest_len; - - xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr - + xisr->sadb_x_ipsecrequest_len); - } - - if (tlen != 0) - panic("kdebug_sadb_x_policy: wrong policy struct."); - } - - return; -} - -#ifdef _KERNEL -/* %%%: about SPD and SAD */ -void -kdebug_secpolicy(struct secpolicy *sp) -{ - /* sanity check */ - if (sp == NULL) - panic("kdebug_secpolicy: NULL pointer was passed."); - - kprintf("secpolicy{ refcnt=%u state=%u policy=%u\n", - sp->refcnt, sp->state, sp->policy); - - kdebug_secpolicyindex(&sp->spidx); - - switch (sp->policy) { - case IPSEC_POLICY_DISCARD: - kprintf(" type=discard }\n"); - break; - case IPSEC_POLICY_NONE: - kprintf(" type=none }\n"); - break; - case IPSEC_POLICY_IPSEC: - { - struct ipsecrequest *isr; - for (isr = sp->req; isr != NULL; isr = isr->next) { - - kprintf(" level=%u\n", isr->level); - kdebug_secasindex(&isr->saidx); - - if (isr->sav != NULL) - kdebug_secasv(isr->sav); - } - kprintf(" }\n"); - } - break; - case IPSEC_POLICY_BYPASS: - kprintf(" type=bypass }\n"); - break; - case IPSEC_POLICY_ENTRUST: - kprintf(" type=entrust }\n"); - break; - default: - kprintf("kdebug_secpolicy: Invalid policy found. %d\n", - sp->policy); - break; - } - - return; -} - -void -kdebug_secpolicyindex(struct secpolicyindex *spidx) -{ - /* sanity check */ - if (spidx == NULL) - panic("kdebug_secpolicyindex: NULL pointer was passed."); - - kprintf("secpolicyindex{ dir=%u prefs=%u prefd=%u ul_proto=%u\n", - spidx->dir, spidx->prefs, spidx->prefd, spidx->ul_proto); - - ipsec_hexdump((caddr_t)&spidx->src, - ((struct sockaddr *)&spidx->src)->sa_len); - kprintf("\n"); - ipsec_hexdump((caddr_t)&spidx->dst, - ((struct sockaddr *)&spidx->dst)->sa_len); - kprintf("}\n"); - - return; -} - -void -kdebug_secasindex(struct secasindex *saidx) -{ - /* sanity check */ - if (saidx == NULL) - panic("kdebug_secpolicyindex: NULL pointer was passed."); - - kprintf("secasindex{ mode=%u proto=%u\n", - saidx->mode, saidx->proto); - - ipsec_hexdump((caddr_t)&saidx->src, - ((struct sockaddr *)&saidx->src)->sa_len); - kprintf("\n"); - ipsec_hexdump((caddr_t)&saidx->dst, - ((struct sockaddr *)&saidx->dst)->sa_len); - kprintf("\n"); - - return; -} - -void -kdebug_secasv(struct secasvar *sav) -{ - /* sanity check */ - if (sav == NULL) - panic("kdebug_secasv: NULL pointer was passed."); - - kprintf("secas{"); - kdebug_secasindex(&sav->sah->saidx); - - kprintf(" refcnt=%u state=%u auth=%u enc=%u\n", - sav->refcnt, sav->state, sav->alg_auth, sav->alg_enc); - kprintf(" spi=%u flags=%u\n", - (u_int32_t)ntohl(sav->spi), sav->flags); - - if (sav->key_auth != NULL) - kdebug_sadb_key((struct sadb_ext *)sav->key_auth); - if (sav->key_enc != NULL) - kdebug_sadb_key((struct sadb_ext *)sav->key_enc); - if (sav->iv != NULL) { - kprintf(" iv="); - ipsec_hexdump(sav->iv, sav->ivlen ? sav->ivlen : 8); - kprintf("\n"); - } - - if (sav->replay != NULL) - kdebug_secreplay(sav->replay); - if (sav->lft_c != NULL) - kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_c); - if (sav->lft_h != NULL) - kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_h); - if (sav->lft_s != NULL) - kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_s); - -#if 0 /* notyet */ - /* XXX: misc[123] ? */ -#endif - - return; -} - -static void -kdebug_secreplay(struct secreplay *rpl) -{ - int len, l; - - /* sanity check */ - if (rpl == NULL) - panic("kdebug_secreplay: NULL pointer was passed."); - - kprintf(" secreplay{ count=%u wsize=%u seq=%u lastseq=%u", - rpl->count, rpl->wsize, rpl->seq, rpl->lastseq); - - if (rpl->bitmap == NULL) { - kprintf(" }\n"); - return; - } - - kprintf("\n bitmap { "); - - for (len = 0; len < rpl->wsize; len++) { - for (l = 7; l >= 0; l--) - kprintf("%u", (((rpl->bitmap)[len] >> l) & 1) ? 1 : 0); - } - kprintf(" }\n"); - - return; -} - -void -kdebug_mbufhdr(struct mbuf *m) -{ - /* sanity check */ - if (m == NULL) - return; - - kprintf("mbuf(%p){ m_next:%p m_nextpkt:%p m_data:%p " - "m_len:%d m_type:0x%02x m_flags:0x%02x }\n", - m, m->m_next, m->m_nextpkt, m->m_data, - m->m_len, m->m_type, m->m_flags); - - if (m->m_flags & M_PKTHDR) { - kprintf(" m_pkthdr{ len:%d rcvif:%p }\n", - m->m_pkthdr.len, m->m_pkthdr.rcvif); - } - - if (m->m_flags & M_EXT) { - kprintf(" m_ext{ ext_buf:%p ext_free:%p " - "ext_size:%u ext_ref:%p }\n", - m->m_ext.ext_buf, m->m_ext.ext_free, - m->m_ext.ext_size, m->m_ext.ext_ref); - } - - return; -} - -void -kdebug_mbuf(struct mbuf *m0) -{ - struct mbuf *m = m0; - int i, j; - - for (j = 0; m; m = m->m_next) { - kdebug_mbufhdr(m); - kprintf(" m_data:\n"); - for (i = 0; i < m->m_len; i++) { - if (i && i % 32 == 0) - kprintf("\n"); - if (i % 4 == 0) - kprintf(" "); - kprintf("%02x", mtod(m, u_char *)[i]); - j++; - } - kprintf("\n"); - } - - return; -} -#endif /* _KERNEL */ - -void -kdebug_sockaddr(struct sockaddr *addr) -{ - struct sockaddr_in *sin4; -#ifdef INET6 - struct sockaddr_in6 *sin6; -#endif - - /* sanity check */ - if (addr == NULL) - panic("kdebug_sockaddr: NULL pointer was passed."); - - /* NOTE: We deal with port number as host byte order. */ - kprintf("sockaddr{ len=%u family=%u", addr->sa_len, addr->sa_family); - - switch (addr->sa_family) { - case AF_INET: - sin4 = (struct sockaddr_in *)addr; - kprintf(" port=%u\n", ntohs(sin4->sin_port)); - ipsec_hexdump((caddr_t)&sin4->sin_addr, sizeof(sin4->sin_addr)); - break; -#ifdef INET6 - case AF_INET6: - sin6 = (struct sockaddr_in6 *)addr; - kprintf(" port=%u\n", ntohs(sin6->sin6_port)); - kprintf(" flowinfo=0x%08x, scope_id=0x%08x\n", - sin6->sin6_flowinfo, sin6->sin6_scope_id); - ipsec_hexdump((caddr_t)&sin6->sin6_addr, - sizeof(sin6->sin6_addr)); - break; -#endif - } - - kprintf(" }\n"); - - return; -} - -void -ipsec_bindump(caddr_t buf, int len) -{ - int i; - - for (i = 0; i < len; i++) - kprintf("%c", (unsigned char)buf[i]); - - return; -} - - -void -ipsec_hexdump(caddr_t buf, int len) -{ - int i; - - for (i = 0; i < len; i++) { - if (i != 0 && i % 32 == 0) kprintf("\n"); - if (i % 4 == 0) kprintf(" "); - kprintf("%02x", (unsigned char)buf[i]); - } -#if 0 - if (i % 32 != 0) kprintf("\n"); -#endif - - return; -} diff --git a/sys/netproto/key/key_debug.h b/sys/netproto/key/key_debug.h deleted file mode 100644 index 4706a47195..0000000000 --- a/sys/netproto/key/key_debug.h +++ /dev/null @@ -1,89 +0,0 @@ -/* $FreeBSD: src/sys/netkey/key_debug.h,v 1.5.2.3 2001/11/20 12:26:13 ume Exp $ */ -/* $DragonFly: src/sys/netproto/key/key_debug.h,v 1.3 2003/08/23 10:06:24 rob Exp $ */ -/* $KAME: key_debug.h,v 1.10 2001/08/05 08:37:52 itojun Exp $ */ - -/* - * 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. - */ - -#ifndef _NETKEY_KEY_DEBUG_H_ -#define _NETKEY_KEY_DEBUG_H_ - -#ifdef _KERNEL -/* debug flags */ -#define KEYDEBUG_STAMP 0x00000001 /* path */ -#define KEYDEBUG_DATA 0x00000002 /* data */ -#define KEYDEBUG_DUMP 0x00000004 /* dump */ - -#define KEYDEBUG_KEY 0x00000010 /* key processing */ -#define KEYDEBUG_ALG 0x00000020 /* ciph & auth algorithm */ -#define KEYDEBUG_IPSEC 0x00000040 /* ipsec processing */ - -#define KEYDEBUG_KEY_STAMP (KEYDEBUG_KEY | KEYDEBUG_STAMP) -#define KEYDEBUG_KEY_DATA (KEYDEBUG_KEY | KEYDEBUG_DATA) -#define KEYDEBUG_KEY_DUMP (KEYDEBUG_KEY | KEYDEBUG_DUMP) -#define KEYDEBUG_ALG_STAMP (KEYDEBUG_ALG | KEYDEBUG_STAMP) -#define KEYDEBUG_ALG_DATA (KEYDEBUG_ALG | KEYDEBUG_DATA) -#define KEYDEBUG_ALG_DUMP (KEYDEBUG_ALG | KEYDEBUG_DUMP) -#define KEYDEBUG_IPSEC_STAMP (KEYDEBUG_IPSEC | KEYDEBUG_STAMP) -#define KEYDEBUG_IPSEC_DATA (KEYDEBUG_IPSEC | KEYDEBUG_DATA) -#define KEYDEBUG_IPSEC_DUMP (KEYDEBUG_IPSEC | KEYDEBUG_DUMP) - -#define KEYDEBUG(lev,arg) \ - do { if ((key_debug_level & (lev)) == (lev)) { arg; } } while (0) - -extern u_int32_t key_debug_level; -#endif /*_KERNEL*/ - -struct sadb_msg; -struct sadb_ext; -extern void kdebug_sadb (struct sadb_msg *); -extern void kdebug_sadb_x_policy (struct sadb_ext *); - -#ifdef _KERNEL -struct secpolicy; -struct secpolicyindex; -struct secasindex; -struct secasvar; -struct secreplay; -struct mbuf; -extern void kdebug_secpolicy (struct secpolicy *); -extern void kdebug_secpolicyindex (struct secpolicyindex *); -extern void kdebug_secasindex (struct secasindex *); -extern void kdebug_secasv (struct secasvar *); -extern void kdebug_mbufhdr (struct mbuf *); -extern void kdebug_mbuf (struct mbuf *); -#endif /*_KERNEL*/ - -struct sockaddr; -extern void kdebug_sockaddr (struct sockaddr *); - -extern void ipsec_hexdump (caddr_t, int); -extern void ipsec_bindump (caddr_t, int); - -#endif /* _NETKEY_KEY_DEBUG_H_ */ diff --git a/sys/netproto/key/key_var.h b/sys/netproto/key/key_var.h deleted file mode 100644 index f2a4e252cc..0000000000 --- a/sys/netproto/key/key_var.h +++ /dev/null @@ -1,73 +0,0 @@ -/* $FreeBSD: src/sys/netkey/key_var.h,v 1.2.2.4 2001/12/12 15:27:45 ume Exp $ */ -/* $KAME: key_var.h,v 1.11 2001/09/12 23:05:07 sakane Exp $ */ - -/* - * 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. - */ - -#ifndef _NETKEY_KEY_VAR_H_ -#define _NETKEY_KEY_VAR_H_ - -/* sysctl */ -#define KEYCTL_DEBUG_LEVEL 1 -#define KEYCTL_SPI_TRY 2 -#define KEYCTL_SPI_MIN_VALUE 3 -#define KEYCTL_SPI_MAX_VALUE 4 -#define KEYCTL_RANDOM_INT 5 -#define KEYCTL_LARVAL_LIFETIME 6 -#define KEYCTL_BLOCKACQ_COUNT 7 -#define KEYCTL_BLOCKACQ_LIFETIME 8 -#define KEYCTL_ESP_KEYMIN 9 -#define KEYCTL_ESP_AUTH 10 -#define KEYCTL_AH_KEYMIN 11 -#define KEYCTL_PREFERED_OLDSA 12 -#define KEYCTL_MAXID 13 - -#define KEYCTL_NAMES { \ - { 0, 0 }, \ - { "debug", CTLTYPE_INT }, \ - { "spi_try", CTLTYPE_INT }, \ - { "spi_min_value", CTLTYPE_INT }, \ - { "spi_max_value", CTLTYPE_INT }, \ - { "random_int", CTLTYPE_INT }, \ - { "larval_lifetime", CTLTYPE_INT }, \ - { "blockacq_count", CTLTYPE_INT }, \ - { "blockacq_lifetime", CTLTYPE_INT }, \ - { "esp_keymin", CTLTYPE_INT }, \ - { "esp_auth", CTLTYPE_INT }, \ - { "ah_keymin", CTLTYPE_INT }, \ - { "prefered_oldsa", CTLTYPE_INT }, \ -} - -#ifdef _KERNEL -#define _KEYLEN(key) ((u_int)((key)->sadb_key_bits >> 3)) -#define _KEYBITS(key) ((u_int)((key)->sadb_key_bits)) -#define _KEYBUF(key) ((caddr_t)((caddr_t)(key) + sizeof(struct sadb_key))) -#endif /*_KERNEL*/ - -#endif /* _NETKEY_KEY_VAR_H_ */ diff --git a/sys/netproto/key/keydb.c b/sys/netproto/key/keydb.c deleted file mode 100644 index daac155a7e..0000000000 --- a/sys/netproto/key/keydb.c +++ /dev/null @@ -1,195 +0,0 @@ -/* $FreeBSD: src/sys/netkey/keydb.c,v 1.1.2.1 2000/07/15 07:14:42 kris Exp $ */ -/* $KAME: keydb.c,v 1.64 2000/05/11 17:02:30 itojun Exp $ */ - -/* - * 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. - */ - -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include "keydb.h" -#include "key.h" -#include - -#include - -MALLOC_DEFINE(M_SECA, "key mgmt", "security associations, key management"); - -static void keydb_delsecasvar (struct secasvar *); - -/* - * secpolicy management - */ -struct secpolicy * -keydb_newsecpolicy(void) -{ - return(kmalloc(sizeof(struct secpolicy), M_SECA, - M_INTWAIT | M_NULLOK | M_ZERO)); -} - -void -keydb_delsecpolicy(struct secpolicy *p) -{ - kfree(p, M_SECA); -} - -/* - * secashead management - */ -struct secashead * -keydb_newsecashead(void) -{ - struct secashead *p; - int i; - - p = kmalloc(sizeof(*p), M_SECA, M_INTWAIT | M_NULLOK | M_ZERO); - if (!p) - return p; - for (i = 0; i < NELEM(p->savtree); i++) - LIST_INIT(&p->savtree[i]); - return p; -} - -void -keydb_delsecashead(struct secashead *p) -{ - - kfree(p, M_SECA); -} - -/* - * secasvar management (reference counted) - */ -struct secasvar * -keydb_newsecasvar(void) -{ - struct secasvar *p; - - p = kmalloc(sizeof(*p), M_SECA, M_INTWAIT | M_NULLOK | M_ZERO); - if (!p) - return p; - p->refcnt = 1; - return p; -} - -void -keydb_refsecasvar(struct secasvar *p) -{ - lwkt_gettoken(&key_token); - p->refcnt++; - lwkt_reltoken(&key_token); -} - -void -keydb_freesecasvar(struct secasvar *p) -{ - lwkt_gettoken(&key_token); - p->refcnt--; - /* negative refcnt will cause panic intentionally */ - if (p->refcnt <= 0) - keydb_delsecasvar(p); - lwkt_reltoken(&key_token); -} - -static void -keydb_delsecasvar(struct secasvar *p) -{ - - if (p->refcnt) - panic("keydb_delsecasvar called with refcnt != 0"); - - kfree(p, M_SECA); -} - -/* - * secreplay management - */ -struct secreplay * -keydb_newsecreplay(size_t wsize) -{ - struct secreplay *p; - - p = kmalloc(sizeof(*p), M_SECA, M_INTWAIT | M_NULLOK | M_ZERO); - if (!p) - return p; - - if (wsize != 0) { - p->bitmap = (caddr_t)kmalloc(wsize, M_SECA, M_INTWAIT | M_NULLOK | M_ZERO); - if (!p->bitmap) { - kfree(p, M_SECA); - return NULL; - } - } - p->wsize = wsize; - return p; -} - -void -keydb_delsecreplay(struct secreplay *p) -{ - - if (p->bitmap) - kfree(p->bitmap, M_SECA); - kfree(p, M_SECA); -} - -/* - * secreg management - */ -struct secreg * -keydb_newsecreg(void) -{ - struct secreg *p; - - p = kmalloc(sizeof(*p), M_SECA, M_INTWAIT | M_ZERO | M_NULLOK); - return p; -} - -void -keydb_delsecreg(struct secreg *p) -{ - - kfree(p, M_SECA); -} diff --git a/sys/netproto/key/keydb.h b/sys/netproto/key/keydb.h deleted file mode 100644 index 8701dcdf99..0000000000 --- a/sys/netproto/key/keydb.h +++ /dev/null @@ -1,181 +0,0 @@ -/* $FreeBSD: src/sys/netkey/keydb.h,v 1.2.2.3 2003/01/11 19:10:59 ume Exp $ */ -/* $DragonFly: src/sys/netproto/key/keydb.h,v 1.5 2006/05/20 02:42:13 dillon Exp $ */ -/* $KAME: keydb.h,v 1.14 2000/08/02 17:58:26 sakane Exp $ */ - -/* - * 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. - */ - -#ifndef _NETKEY_KEYDB_H_ -#define _NETKEY_KEYDB_H_ - -#ifdef _KERNEL - -#ifndef _SYS_TYPES_H_ -#include -#endif -#ifndef _SYS_QUEUE_H_ -#include -#endif -#ifndef _SYS_SOCKET_H_ -#include -#endif -#ifndef _NET_ROUTE_H_ -#include -#endif -#ifndef _NETINET_IN_H_ -#include -#endif - -#include "key_var.h" - -/* Security Assocciation Index */ -/* NOTE: Ensure to be same address family */ -struct secasindex { - struct sockaddr_storage src; /* srouce address for SA */ - struct sockaddr_storage dst; /* destination address for SA */ - u_int16_t proto; /* IPPROTO_ESP or IPPROTO_AH */ - u_int8_t mode; /* mode of protocol, see ipsec.h */ - u_int32_t reqid; /* reqid id who owned this SA */ - /* see IPSEC_MANUAL_REQID_MAX. */ -}; - -/* Security Association Data Base */ -struct secashead { - LIST_ENTRY(secashead) chain; - - struct secasindex saidx; - - struct sadb_ident *idents; /* source identity */ - struct sadb_ident *identd; /* destination identity */ - /* XXX I don't know how to use them. */ - - u_int8_t state; /* MATURE or DEAD. */ - LIST_HEAD(_satree, secasvar) savtree[SADB_SASTATE_MAX+1]; - /* SA chain */ - /* The first of this list is newer SA */ - - union { - struct route sau_route; - struct route_in6 sau_route6; - } sa_u; -#define sa_route sa_u.sau_route -}; - -/* Security Association */ -struct secasvar { - LIST_ENTRY(secasvar) chain; - - int refcnt; /* reference count */ - u_int8_t state; /* Status of this Association */ - - u_int8_t alg_auth; /* Authentication Algorithm Identifier*/ - u_int8_t alg_enc; /* Cipher Algorithm Identifier */ - u_int32_t spi; /* SPI Value, network byte order */ - u_int32_t flags; /* holder for SADB_KEY_FLAGS */ - - struct sadb_key *key_auth; /* Key for Authentication */ - struct sadb_key *key_enc; /* Key for Encryption */ - caddr_t iv; /* Initilization Vector */ - u_int ivlen; /* length of IV */ - void *sched; /* intermediate encryption key */ - size_t schedlen; - - struct secreplay *replay; /* replay prevention */ - long created; /* for lifetime */ - - struct sadb_lifetime *lft_c; /* CURRENT lifetime, it's constant. */ - struct sadb_lifetime *lft_h; /* HARD lifetime */ - struct sadb_lifetime *lft_s; /* SOFT lifetime */ - - u_int32_t seq; /* sequence number */ - pid_t pid; /* message's pid */ - - struct secashead *sah; /* back pointer to the secashead */ -}; - -/* replay prevention */ -struct secreplay { - u_int32_t count; - u_int wsize; /* window size, i.g. 4 bytes */ - u_int32_t seq; /* used by sender */ - u_int32_t lastseq; /* used by receiver */ - caddr_t bitmap; /* used by receiver */ - int overflow; /* overflow flag */ -}; - -/* socket table due to send PF_KEY messages. */ -struct secreg { - LIST_ENTRY(secreg) chain; - - struct socket *so; -}; - -#ifndef IPSEC_NONBLOCK_ACQUIRE -/* acquiring list table. */ -struct secacq { - LIST_ENTRY(secacq) chain; - - struct secasindex saidx; - - u_int32_t seq; /* sequence number */ - long created; /* for lifetime */ - int count; /* for lifetime */ -}; -#endif - -/* Sensitivity Level Specification */ -/* nothing */ - -#define SADB_KILL_INTERVAL 600 /* six seconds */ - -struct key_cb { - int key_count; - int any_count; -}; - -/* secpolicy */ -extern struct secpolicy *keydb_newsecpolicy (void); -extern void keydb_delsecpolicy (struct secpolicy *); -/* secashead */ -extern struct secashead *keydb_newsecashead (void); -extern void keydb_delsecashead (struct secashead *); -/* secasvar */ -extern struct secasvar *keydb_newsecasvar (void); -extern void keydb_refsecasvar (struct secasvar *); -extern void keydb_freesecasvar (struct secasvar *); -/* secreplay */ -extern struct secreplay *keydb_newsecreplay (size_t); -extern void keydb_delsecreplay (struct secreplay *); -/* secreg */ -extern struct secreg *keydb_newsecreg (void); -extern void keydb_delsecreg (struct secreg *); - -#endif /* _KERNEL */ - -#endif /* _NETKEY_KEYDB_H_ */ diff --git a/sys/netproto/key/keysock.c b/sys/netproto/key/keysock.c deleted file mode 100644 index 7573d5b632..0000000000 --- a/sys/netproto/key/keysock.c +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/netkey/keysock.c,v 1.1.2.4 2003/01/11 19:10:59 ume Exp $ - * $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $ - */ - -#include "opt_ipsec.h" - -/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "keydb.h" -#include "key.h" -#include "keysock.h" -#include "key_debug.h" - -#include - -struct sockaddr key_dst = { 2, PF_KEY, }; -struct sockaddr key_src = { 2, PF_KEY, }; - -static int key_sendup0 (struct rawcb *, struct mbuf *, int); - -struct pfkeystat pfkeystat; - -/* - * key_output() - */ -int -key_output(struct mbuf *m, struct socket *so, ...) -{ - struct sadb_msg *msg; - int len, error = 0; - - if (m == NULL) - panic("key_output: NULL pointer was passed."); - - pfkeystat.out_total++; - pfkeystat.out_bytes += m->m_pkthdr.len; - - len = m->m_pkthdr.len; - if (len < sizeof(struct sadb_msg)) { - pfkeystat.out_tooshort++; - error = EINVAL; - goto end; - } - - if (m->m_len < sizeof(struct sadb_msg)) { - if ((m = m_pullup(m, sizeof(struct sadb_msg))) == NULL) { - pfkeystat.out_nomem++; - error = ENOBUFS; - goto end; - } - } - - if ((m->m_flags & M_PKTHDR) == 0) - panic("key_output: not M_PKTHDR ??"); - - KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); - - msg = mtod(m, struct sadb_msg *); - pfkeystat.out_msgtype[msg->sadb_msg_type]++; - if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { - pfkeystat.out_invlen++; - error = EINVAL; - goto end; - } - - /*XXX giant lock*/ - lwkt_gettoken(&key_token); - error = key_parse(m, so); - m = NULL; - lwkt_reltoken(&key_token); -end: - if (m) - m_freem(m); - return error; -} - -/* - * send message to the socket. - */ -static int -key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc) -{ - int error; - - if (promisc) { - struct sadb_msg *pmsg; - - M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT); - if (m && m->m_len < sizeof(struct sadb_msg)) - m = m_pullup(m, sizeof(struct sadb_msg)); - if (!m) { - pfkeystat.in_nomem++; - m_freem(m); - return ENOBUFS; - } - m->m_pkthdr.len += sizeof(*pmsg); - - pmsg = mtod(m, struct sadb_msg *); - bzero(pmsg, sizeof(*pmsg)); - pmsg->sadb_msg_version = PF_KEY_V2; - pmsg->sadb_msg_type = SADB_X_PROMISC; - pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - /* pid and seq? */ - - pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; - } - - lwkt_gettoken(&key_token); - if (!ssb_appendaddr(&rp->rcb_socket->so_rcv, &key_src, m, NULL)) { - pfkeystat.in_nomem++; - m_freem(m); - error = ENOBUFS; - } else { - error = 0; - } - lwkt_reltoken(&key_token); - sorwakeup(rp->rcb_socket); - return error; -} - -/* - * XXX this interface should be obsoleted. - * - * Parameters: - * target: target of the resulting message - */ -int -key_sendup(struct socket *so, struct sadb_msg *msg, u_int len, - int target) -{ - struct mbuf *m, *n, *mprev; - int tlen; - - /* sanity check */ - if (so == NULL || msg == NULL) - panic("key_sendup: NULL pointer was passed."); - - KEYDEBUG(KEYDEBUG_KEY_DUMP, - kprintf("key_sendup: \n"); - kdebug_sadb(msg)); - - /* - * we increment statistics here, just in case we have ENOBUFS - * in this function. - */ - pfkeystat.in_total++; - pfkeystat.in_bytes += len; - pfkeystat.in_msgtype[msg->sadb_msg_type]++; - - /* - * Get mbuf chain whenever possible (not clusters), - * to save socket buffer. We'll be generating many SADB_ACQUIRE - * messages to listening key sockets. If we simply allocate clusters, - * ssb_appendaddr() will raise ENOBUFS due to too little ssb_space(). - * ssb_space() computes # of actual data bytes AND mbuf region. - * - * TODO: SADB_ACQUIRE filters should be implemented. - */ - tlen = len; - m = mprev = NULL; - while (tlen > 0) { - if (tlen == len) { - MGETHDR(n, M_NOWAIT, MT_DATA); - n->m_len = MHLEN; - } else { - MGET(n, M_NOWAIT, MT_DATA); - n->m_len = MLEN; - } - if (!n) { - pfkeystat.in_nomem++; - return ENOBUFS; - } - if (tlen >= MCLBYTES) { /*XXX better threshold? */ - MCLGET(n, M_NOWAIT); - if ((n->m_flags & M_EXT) == 0) { - m_free(n); - m_freem(m); - pfkeystat.in_nomem++; - return ENOBUFS; - } - n->m_len = MCLBYTES; - } - - if (tlen < n->m_len) - n->m_len = tlen; - n->m_next = NULL; - if (m == NULL) - m = mprev = n; - else { - mprev->m_next = n; - mprev = n; - } - tlen -= n->m_len; - n = NULL; - } - m->m_pkthdr.len = len; - m->m_pkthdr.rcvif = NULL; - m_copyback(m, 0, len, (caddr_t)msg); - - /* avoid duplicated statistics */ - pfkeystat.in_total--; - pfkeystat.in_bytes -= len; - pfkeystat.in_msgtype[msg->sadb_msg_type]--; - - return key_sendup_mbuf(so, m, target); -} - -/* so can be NULL if target != KEY_SENDUP_ONE */ -int -key_sendup_mbuf(struct socket *so, struct mbuf *m, int target) -{ - struct mbuf *n; - struct keycb *kp; - int sendup; - struct rawcb *rp; - int error = 0; - - if (m == NULL) - panic("key_sendup_mbuf: NULL pointer was passed."); - if (so == NULL && target == KEY_SENDUP_ONE) - panic("key_sendup_mbuf: NULL pointer was passed."); - - pfkeystat.in_total++; - pfkeystat.in_bytes += m->m_pkthdr.len; - if (m->m_len < sizeof(struct sadb_msg)) { -#if 1 - m = m_pullup(m, sizeof(struct sadb_msg)); - if (m == NULL) { - pfkeystat.in_nomem++; - return ENOBUFS; - } -#else - /* don't bother pulling it up just for stats */ -#endif - } - if (m->m_len >= sizeof(struct sadb_msg)) { - struct sadb_msg *msg; - msg = mtod(m, struct sadb_msg *); - pfkeystat.in_msgtype[msg->sadb_msg_type]++; - } - - lwkt_gettoken(&key_token); - - LIST_FOREACH(rp, &rawcb_list, list) - { - if (rp->rcb_proto.sp_family != PF_KEY) - continue; - if (rp->rcb_proto.sp_protocol - && rp->rcb_proto.sp_protocol != PF_KEY_V2) { - continue; - } - - kp = (struct keycb *)rp; - - /* - * If you are in promiscuous mode, and when you get broadcasted - * reply, you'll get two PF_KEY messages. - * (based on pf_key@inner.net message on 14 Oct 1998) - */ - if (((struct keycb *)rp)->kp_promisc) { - if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { - key_sendup0(rp, n, 1); - n = NULL; - } - } - - /* the exact target will be processed later */ - if (so && sotorawcb(so) == rp) - continue; - - sendup = 0; - switch (target) { - case KEY_SENDUP_ONE: - /* the statement has no effect */ - if (so && sotorawcb(so) == rp) - sendup++; - break; - case KEY_SENDUP_ALL: - sendup++; - break; - case KEY_SENDUP_REGISTERED: - if (kp->kp_registered) - sendup++; - break; - default: - panic("Unknown KEY_SENDUP=%d", target); - } - pfkeystat.in_msgtarget[target]++; - - if (!sendup) - continue; - - if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { - m_freem(m); - pfkeystat.in_nomem++; - lwkt_reltoken(&key_token); - return ENOBUFS; - } - - if ((error = key_sendup0(rp, n, 0)) != 0) { - lwkt_reltoken(&key_token); - m_freem(m); - return error; - } - - n = NULL; - } - lwkt_reltoken(&key_token); - - if (so) { - error = key_sendup0(sotorawcb(so), m, 0); - m = NULL; - } else { - error = 0; - m_freem(m); - } - return error; -} - -/* - * key_abort() - * derived from net/rtsock.c:rts_abort() - */ -static void -key_abort(netmsg_t msg) -{ - lwkt_gettoken(&key_token); - - raw_usrreqs.pru_abort(msg); - /* msg invalid now */ - - lwkt_reltoken(&key_token); -} - -/* - * key_attach() - * derived from net/rtsock.c:rts_attach() - */ -static void -key_attach(netmsg_t msg) -{ - struct socket *so = msg->attach.base.nm_so; - int proto = msg->attach.nm_proto; - struct pru_attach_info *ai = msg->attach.nm_ai; - struct keycb *kp; - struct netmsg_pru_attach smsg; - int error; - - if (sotorawcb(so) != NULL) { - error = EISCONN; /* XXX panic? */ - goto out; - } - - /* XXX */ - kp = kmalloc(sizeof *kp, M_PCB, M_WAITOK | M_ZERO); - - /* - * The critical section is necessary to block protocols from sending - * error notifications (like RTM_REDIRECT or RTM_LOSING) while - * this PCB is extant but incompletely initialized. - * Probably we should try to do more of this work beforehand and - * eliminate the critical section. - */ - lwkt_gettoken(&key_token); - so->so_pcb = (caddr_t)kp; - soreference(so); /* so_pcb assignment */ - - netmsg_init(&smsg.base, so, &netisr_adone_rport, 0, - raw_usrreqs.pru_attach); - smsg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); - smsg.base.lmsg.ms_flags |= MSGF_SYNC; - smsg.nm_proto = proto; - smsg.nm_ai = ai; - raw_usrreqs.pru_attach((netmsg_t)&smsg); - error = smsg.base.lmsg.ms_error; - - kp = (struct keycb *)sotorawcb(so); - if (error) { - kfree(kp, M_PCB); - atomic_add_int(&so->so_refs, -1); - so->so_pcb = (caddr_t) 0; - lwkt_reltoken(&key_token); - goto out; - } - - kp->kp_promisc = kp->kp_registered = 0; - - if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ - key_cb.key_count++; - key_cb.any_count++; - kp->kp_raw.rcb_laddr = &key_src; - kp->kp_raw.rcb_faddr = &key_dst; - soisconnected(so); - so->so_options |= SO_USELOOPBACK; - - lwkt_reltoken(&key_token); - error = 0; -out: - lwkt_replymsg(&msg->attach.base.lmsg, error); -} - -/* - * key_bind() - * derived from net/rtsock.c:rts_bind() - */ -static void -key_bind(netmsg_t msg) -{ - lwkt_gettoken(&key_token); - - raw_usrreqs.pru_bind(msg); /* xxx just EINVAL */ - /* msg invalid now */ - - lwkt_reltoken(&key_token); -} - -/* - * key_connect() - * derived from net/rtsock.c:rts_connect() - */ -static void -key_connect(netmsg_t msg) -{ - lwkt_gettoken(&key_token); - - raw_usrreqs.pru_connect(msg); /* XXX just EINVAL */ - /* msg invalid now */ - - lwkt_reltoken(&key_token); -} - -/* - * key_detach() - * derived from net/rtsock.c:rts_detach() - */ -static void -key_detach(netmsg_t msg) -{ - struct socket *so = msg->detach.base.nm_so; - struct keycb *kp = (struct keycb *)sotorawcb(so); - - lwkt_gettoken(&key_token); - - if (kp != NULL) { - if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) { - /* XXX: AF_KEY */ - key_cb.key_count--; - } - key_cb.any_count--; - - key_freereg(so); - } - raw_usrreqs.pru_detach(msg); - /* msg invalid now */ - - lwkt_reltoken(&key_token); -} - -/* - * key_disconnect() - * derived from net/rtsock.c:key_disconnect() - */ -static void -key_disconnect(netmsg_t msg) -{ - lwkt_gettoken(&key_token); - - raw_usrreqs.pru_disconnect(msg); - /* msg invalid now */ - - lwkt_reltoken(&key_token); -} - -/* - * key_peeraddr() - * derived from net/rtsock.c:rts_peeraddr() - */ -static void -key_peeraddr(netmsg_t msg) -{ - lwkt_gettoken(&key_token); - - raw_usrreqs.pru_peeraddr(msg); - /* msg invalid now */ - - lwkt_reltoken(&key_token); -} - -/* - * key_send() - * derived from net/rtsock.c:rts_send() - */ -static void -key_send(netmsg_t msg) -{ - lwkt_gettoken(&key_token); - - raw_usrreqs.pru_send(msg); - /* msg invalid now */ - - lwkt_reltoken(&key_token); -} - -/* - * key_shutdown() - * derived from net/rtsock.c:rts_shutdown() - */ -static void -key_shutdown(netmsg_t msg) -{ - lwkt_gettoken(&key_token); - - raw_usrreqs.pru_shutdown(msg); - /* msg invalid now */ - - lwkt_reltoken(&key_token); -} - -/* - * key_sockaddr() - * derived from net/rtsock.c:rts_sockaddr() - */ -static void -key_sockaddr(netmsg_t msg) -{ - lwkt_gettoken(&key_token); - - raw_usrreqs.pru_sockaddr(msg); - /* msg invalid now */ - - lwkt_reltoken(&key_token); -} - -struct pr_usrreqs key_usrreqs = { - .pru_abort = key_abort, - .pru_accept = pr_generic_notsupp, - .pru_attach = key_attach, - .pru_bind = key_bind, - .pru_connect = key_connect, - .pru_connect2 = pr_generic_notsupp, - .pru_control = pr_generic_notsupp, - .pru_detach = key_detach, - .pru_disconnect = key_disconnect, - .pru_listen = pr_generic_notsupp, - .pru_peeraddr = key_peeraddr, - .pru_rcvd = pr_generic_notsupp, - .pru_rcvoob = pr_generic_notsupp, - .pru_send = key_send, - .pru_sense = pru_sense_null, - .pru_shutdown = key_shutdown, - .pru_sockaddr = key_sockaddr, - .pru_sosend = sosend, - .pru_soreceive = soreceive -}; - -/* sysctl */ -SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family"); - -/* - * Definitions of protocols supported in the KEY domain. - */ - -extern struct domain keydomain; - -struct protosw keysw[] = { - { - .pr_type = SOCK_RAW, - .pr_domain = &keydomain, - .pr_protocol = PF_KEY_V2, - .pr_flags = PR_ATOMIC|PR_ADDR, - - .pr_input = NULL, - .pr_output = key_output, - .pr_ctlinput = raw_ctlinput, - .pr_ctloutput = NULL, - - .pr_ctlport = cpu0_ctlport, - .pr_init = raw_init, - .pr_usrreqs = &key_usrreqs - } -}; - -struct domain keydomain = { - PF_KEY, "key", key_init, NULL, NULL, - keysw, &keysw[NELEM(keysw)], -}; - -DOMAIN_SET(key); diff --git a/sys/netproto/key/keysock.h b/sys/netproto/key/keysock.h deleted file mode 100644 index 19d79bd3c8..0000000000 --- a/sys/netproto/key/keysock.h +++ /dev/null @@ -1,83 +0,0 @@ -/* $FreeBSD: src/sys/netkey/keysock.h,v 1.4.2.1 2000/07/15 07:14:42 kris Exp $ */ -/* $DragonFly: src/sys/netproto/key/keysock.h,v 1.4 2004/06/03 15:04:51 joerg Exp $ */ -/* $KAME: keysock.h,v 1.8 2000/03/27 05:11:06 sumikawa Exp $ */ - -/* - * 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. - */ - -#ifndef _NETKEY_KEYSOCK_H_ -#define _NETKEY_KEYSOCK_H_ - -/* statistics for pfkey socket */ -struct pfkeystat { - /* kernel -> userland */ - u_quad_t out_total; /* # of total calls */ - u_quad_t out_bytes; /* total bytecount */ - u_quad_t out_msgtype[256]; /* message type histogram */ - u_quad_t out_invlen; /* invalid length field */ - u_quad_t out_invver; /* invalid version field */ - u_quad_t out_invmsgtype; /* invalid message type field */ - u_quad_t out_tooshort; /* msg too short */ - u_quad_t out_nomem; /* memory allocation failure */ - u_quad_t out_dupext; /* duplicate extension */ - u_quad_t out_invexttype; /* invalid extension type */ - u_quad_t out_invsatype; /* invalid sa type */ - u_quad_t out_invaddr; /* invalid address extension */ - /* userland -> kernel */ - u_quad_t in_total; /* # of total calls */ - u_quad_t in_bytes; /* total bytecount */ - u_quad_t in_msgtype[256]; /* message type histogram */ - u_quad_t in_msgtarget[3]; /* one/all/registered */ - u_quad_t in_nomem; /* memory allocation failure */ - /* others */ - u_quad_t sockerr; /* # of socket related errors */ -}; - -#define KEY_SENDUP_ONE 0 -#define KEY_SENDUP_ALL 1 -#define KEY_SENDUP_REGISTERED 2 - -#ifdef _KERNEL -struct keycb { - struct rawcb kp_raw; /* rawcb */ - int kp_promisc; /* promiscuous mode */ - int kp_registered; /* registered socket */ -}; - -extern struct pfkeystat pfkeystat; - -extern int key_output (struct mbuf *, struct socket *so, ...); -extern int key_usrreq (struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *); - -extern int key_sendup(struct socket *, struct sadb_msg *, u_int, int); -extern int key_sendup_mbuf (struct socket *, struct mbuf *, int); -#endif /* _KERNEL */ - -#endif /*_NETKEY_KEYSOCK_H_*/ diff --git a/sys/platform/pc64/conf/files b/sys/platform/pc64/conf/files index b53f576ed5..0a14fa7a44 100644 --- a/sys/platform/pc64/conf/files +++ b/sys/platform/pc64/conf/files @@ -41,8 +41,6 @@ emulation/ndis/subr_u4bd.c optional ndisapi pci emulation/ndis/winx64_wrap.S optional ndisapi pci # XXX use assembler versions of bf_enc -crypto/blowfish/bf_enc.c optional ipsec ipsec_esp -crypto/des/des_enc.c optional ipsec ipsec_esp crypto/blowfish/bf_enc.c optional crypto crypto/des/des_enc.c optional crypto crypto/des/des_ecb.c optional crypto diff --git a/sys/platform/vkernel64/conf/files b/sys/platform/vkernel64/conf/files index 2b85426d8a..46e5b2199d 100644 --- a/sys/platform/vkernel64/conf/files +++ b/sys/platform/vkernel64/conf/files @@ -1,8 +1,6 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -crypto/blowfish/bf_enc.c optional ipsec ipsec_esp -crypto/des/des_enc.c optional ipsec ipsec_esp crypto/blowfish/bf_enc.c optional crypto crypto/des/des_enc.c optional crypto crypto/des/des_ecb.c optional crypto diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 086b2570a1..c55792a3e6 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -668,21 +668,8 @@ m_getb(int len, int how, int type, int flags) #define PACKET_TAG_NONE 0 /* Nadda */ -/* Packet tag for use with PACKET_ABI_COMPAT */ -#define PACKET_TAG_IPSEC_IN_DONE 1 /* IPsec applied, in */ -/* struct tdb_indent */ -#define PACKET_TAG_IPSEC_OUT_DONE 2 /* IPsec applied, out */ -/* struct tdb_indent */ -#define PACKET_TAG_IPSEC_IN_CRYPTO_DONE 3 /* NIC IPsec crypto done */ -/* struct tdb_indent, never added */ -#define PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED 4 /* NIC IPsec crypto req'ed */ -/* struct tdb_indent, never added */ -#define PACKET_TAG_IPSEC_PENDING_TDB 5 /* Reminder to do IPsec */ -/* struct tdb_indent, never added */ #define PACKET_TAG_ENCAP 6 /* Encap. processing */ /* struct ifnet *, the GIF interface */ -#define PACKET_TAG_IPSEC_HISTORY 7 /* IPSEC history */ -/* struct ipsec_history */ #define PACKET_TAG_IPV6_INPUT 8 /* IPV6 input processing */ /* struct ip6aux */ #define PACKET_TAG_IPFW_DIVERT 9 /* divert info */ diff --git a/sys/sys/param.h b/sys/sys/param.h index d50d78694c..d79e5e21ff 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -174,9 +174,10 @@ * 500301 - rename some public UFS constants * 500302 - move IOCTLTRIM to a better header and rename it to DAIOCTRIM * 500303 - get rid of sgtty (superseded by termios) + * 500304 - remove IPSEC/FAST_IPSEC */ #undef __DragonFly_version -#define __DragonFly_version 500303 /* propagated to newvers */ +#define __DragonFly_version 500304 /* propagated to newvers */ #include diff --git a/sys/sys/priv.h b/sys/sys/priv.h index ee3471d75d..ad2192b5fc 100644 --- a/sys/sys/priv.h +++ b/sys/sys/priv.h @@ -380,7 +380,12 @@ #define PRIV_NETINET_ND6 500 /* Administer IPv6 neighbor disc. */ #define PRIV_NETINET_SCOPE6 501 /* Administer IPv6 address scopes. */ #define PRIV_NETINET_ALIFETIME6 502 /* Administer IPv6 address lifetimes. */ -#define PRIV_NETINET_IPSEC 503 /* Administer IPSEC. */ + +/* + * Placeholder for IPSec privilege, not supported any more. + */ +#define _PRIV_NETINET_IPSEC 503 /* Administer IPSEC. */ + #define PRIV_NETINET_REUSEPORT 504 /* Allow [rapid] port/address reuse. */ #define PRIV_NETINET_SETHDROPTS 505 /* Set certain IPv4/6 header options. */ diff --git a/tools/tools/crypto/Makefile b/tools/tools/crypto/Makefile index 75cd7991d8..5af648474c 100644 --- a/tools/tools/crypto/Makefile +++ b/tools/tools/crypto/Makefile @@ -26,7 +26,7 @@ # ALL= cryptotest cryptokeytest cryptostats \ - ubsecstats hifnstats ipsecstats + ubsecstats hifnstats BINDIR= /usr/local/bin PRIVATELIB_LDFLAGS?= -rpath /lib/priv:/usr/lib/priv -L /usr/lib/priv @@ -54,10 +54,6 @@ hifnstats: hifnstats.c #safestats: safestats.c # ${CC} -o safestats safestats.c # -# program to print statistics kept by fast ipsec -ipsecstats: ipsecstats.c - ${CC} -o ipsecstats ipsecstats.c - clean: rm -f ${ALL} core a.out diff --git a/tools/tools/crypto/ipsecstats.c b/tools/tools/crypto/ipsecstats.c deleted file mode 100644 index d643fab827..0000000000 --- a/tools/tools/crypto/ipsecstats.c +++ /dev/null @@ -1,180 +0,0 @@ -/*- - * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/tools/tools/crypto/ipsecstats.c,v 1.1.4.1 2003/06/03 00:13:13 sam Exp $ - * $DragonFly: src/tools/tools/crypto/ipsecstats.c,v 1.2 2003/06/17 04:29:11 dillon Exp $ - */ -#include -#include -#include -#include -#include - -struct alg { - int a; - const char *name; -}; -static const struct alg aalgs[] = { - { SADB_AALG_NONE, "none", }, - { SADB_AALG_MD5HMAC, "hmac-md5", }, - { SADB_AALG_SHA1HMAC, "hmac-sha1", }, - { SADB_X_AALG_MD5, "md5", }, - { SADB_X_AALG_SHA, "sha", }, - { SADB_X_AALG_NULL, "null", }, - { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, - { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, - { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, -}; -static const struct alg espalgs[] = { - { SADB_EALG_NONE, "none", }, - { SADB_EALG_DESCBC, "des-cbc", }, - { SADB_EALG_3DESCBC, "3des-cbc", }, - { SADB_EALG_NULL, "null", }, - { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, - { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, - { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, -}; -static const struct alg ipcompalgs[] = { - { SADB_X_CALG_NONE, "none", }, - { SADB_X_CALG_OUI, "oui", }, - { SADB_X_CALG_DEFLATE, "deflate", }, - { SADB_X_CALG_LZS, "lzs", }, -}; -#define N(a) (sizeof(a)/sizeof(a[0])) - -static const char* -algname(int a, const struct alg algs[], int nalgs) -{ - static char buf[80]; - int i; - - for (i = 0; i < nalgs; i++) - if (algs[i].a == a) - return algs[i].name; - snprintf(buf, sizeof(buf), "alg#%u", a); - return buf; -} - -/* - * Little program to dump the statistics block for fast ipsec. - */ -int -main(int argc, char *argv[]) -{ -#define STAT(x,fmt) if (x) printf(fmt "\n", x) - struct newipsecstat ips; - struct ahstat ahs; - struct espstat esps; - size_t slen; - int i; - - slen = sizeof (ips); - if (sysctlbyname("net.inet.ipsec.ipsecstats", &ips, &slen, NULL, NULL) < 0) - err(1, "net.inet.ipsec.ipsecstats"); - slen = sizeof (ahs); - if (sysctlbyname("net.inet.ah.stats", &ahs, &slen, NULL, NULL) < 0) - err(1, "net.inet.ah.stats"); - slen = sizeof (esps); - if (sysctlbyname("net.inet.esp.stats", &esps, &slen, NULL, NULL) < 0) - err(1, "net.inet.esp.stats"); - -#define AHSTAT(x,fmt) if (x) printf("ah " fmt ": %u\n", x) -#define AHSTAT64(x,fmt) if (x) printf("ah " fmt ": %llu\n", x) - AHSTAT(ahs.ahs_input, "input packets processed"); - AHSTAT(ahs.ahs_output, "output packets processed"); - AHSTAT(ahs.ahs_hdrops, "headers too short"); - AHSTAT(ahs.ahs_nopf, "headers for unsupported address family"); - AHSTAT(ahs.ahs_notdb, "packets with no SA"); - AHSTAT(ahs.ahs_badkcr, "packets with bad kcr"); - AHSTAT(ahs.ahs_badauth, "packets with bad authentication"); - AHSTAT(ahs.ahs_noxform, "packets with no xform"); - AHSTAT(ahs.ahs_qfull, "packets dropped packet 'cuz queue full"); - AHSTAT(ahs.ahs_wrap, "packets dropped for replace counter wrap"); - AHSTAT(ahs.ahs_replay, "packets dropped for possible replay"); - AHSTAT(ahs.ahs_badauthl, "packets dropped for bad authenticator length"); - AHSTAT(ahs.ahs_invalid, "packets with an invalid SA"); - AHSTAT(ahs.ahs_toobig, "packets too big"); - AHSTAT(ahs.ahs_pdrops, "packets dropped due to policy"); - AHSTAT(ahs.ahs_crypto, "failed crypto requests"); - AHSTAT(ahs.ahs_tunnel, "tunnel sanity check failures"); - for (i = 0; i < AH_ALG_MAX; i++) - if (ahs.ahs_hist[i]) - printf("ah packets with %s: %u\n" - , algname(i, aalgs, N(aalgs)) - , ahs.ahs_hist[i] - ); - AHSTAT64(ahs.ahs_ibytes, "bytes received"); - AHSTAT64(ahs.ahs_obytes, "bytes transmitted"); -#undef AHSTAT64 -#undef AHSTAT - -#define ESPSTAT(x,fmt) if (x) printf("esp " fmt ": %u\n", x) -#define ESPSTAT64(x,fmt) if (x) printf("esp " fmt ": %llu\n", x) - ESPSTAT(esps.esps_input, "input packets processed"); - ESPSTAT(esps.esps_output, "output packets processed"); - ESPSTAT(esps.esps_hdrops, "headers too short"); - ESPSTAT(esps.esps_nopf, "headers for unsupported address family"); - ESPSTAT(esps.esps_notdb, "packets with no SA"); - ESPSTAT(esps.esps_badkcr, "packets with bad kcr"); - ESPSTAT(esps.esps_qfull, "packets dropped packet 'cuz queue full"); - ESPSTAT(esps.esps_noxform, "packets with no xform"); - ESPSTAT(esps.esps_badilen, "packets with bad ilen"); - ESPSTAT(esps.esps_badenc, "packets with bad encryption"); - ESPSTAT(esps.esps_badauth, "packets with bad authentication"); - ESPSTAT(esps.esps_wrap, "packets dropped for replay counter wrap"); - ESPSTAT(esps.esps_replay, "packets dropped for possible replay"); - ESPSTAT(esps.esps_invalid, "packets with an invalid SA"); - ESPSTAT(esps.esps_toobig, "packets too big"); - ESPSTAT(esps.esps_pdrops, "packets dropped due to policy"); - ESPSTAT(esps.esps_crypto, "failed crypto requests"); - ESPSTAT(esps.esps_tunnel, "tunnel sanity check failures"); - for (i = 0; i < ESP_ALG_MAX; i++) - if (esps.esps_hist[i]) - printf("esp packets with %s: %u\n" - , algname(i, espalgs, N(espalgs)) - , esps.esps_hist[i] - ); - ESPSTAT64(esps.esps_ibytes, "bytes received"); - ESPSTAT64(esps.esps_obytes, "bytes transmitted"); -#undef ESPSTAT64 -#undef ESPSTAT - - printf("\n"); - if (ips.ips_in_polvio+ips.ips_out_polvio) - printf("policy violations: input %u output %u\n", - ips.ips_in_polvio, ips.ips_out_polvio); - STAT(ips.ips_out_nosa, "no SA found %u (output)"); - STAT(ips.ips_out_nomem, "no memory available %u (output)"); - STAT(ips.ips_out_noroute, "no route available %u (output)"); - STAT(ips.ips_out_inval, "generic error %u (output)"); - STAT(ips.ips_out_bundlesa, "bundled SA processed %u (output)"); - printf("m_clone processing: %u mbufs + %u clusters coalesced\n", - ips.ips_mbcoalesced, ips.ips_clcoalesced); - printf("m_clone processing: %u clusters copied\n", ips.ips_clcopied); - printf("m_makespace: %u mbufs inserted\n", ips.ips_mbinserted); - printf("header position [front/middle/end]: %u/%u/%u\n", - ips.ips_input_front, ips.ips_input_middle, ips.ips_input_end); - return 0; -} diff --git a/usr.bin/kdump/mkioctls b/usr.bin/kdump/mkioctls index 120adfa11c..992410546f 100644 --- a/usr.bin/kdump/mkioctls +++ b/usr.bin/kdump/mkioctls @@ -23,7 +23,7 @@ LC_ALL=C; export LC_ALL ioctl_includes=` cd $1 find -s * -name '*.h' -follow | - egrep -v '^(cam/)|^(compat/)|^(fs/)|^(isofs/)|^(mfs/)|^(msdosfs/)|^(netipsec/)|^(netkey/)|^(netsmb/)|^(nfs/)|^(ntfs/)|^(pccard/)|^(ufs/)' | + egrep -v '^(cam/)|^(compat/)|^(fs/)|^(isofs/)|^(mfs/)|^(msdosfs/)|^(netkey/)|^(netsmb/)|^(nfs/)|^(ntfs/)|^(pccard/)|^(ufs/)' | xargs egrep -l \ '^#[ ]*define[ ]+[A-Za-z_][A-Za-z0-9_]*[ ]+_IO[^a-z0-9_]' | awk '{printf("#include <%s>\\\\n", $1)}' diff --git a/usr.bin/netstat/Makefile b/usr.bin/netstat/Makefile index ebc03f1a1d..4633b299b1 100644 --- a/usr.bin/netstat/Makefile +++ b/usr.bin/netstat/Makefile @@ -3,8 +3,7 @@ PROG= netstat SRCS= if.c inet.c inet6.c main.c mbuf.c mroute.c route.c \ - unix.c netgraph.c mroute6.c ipsec.c -CFLAGS+=-DIPSEC + unix.c netgraph.c mroute6.c CFLAGS+=-DINET6 NO_STRICT_ALIASING= diff --git a/usr.bin/netstat/ipsec.c b/usr.bin/netstat/ipsec.c deleted file mode 100644 index b2570df5b7..0000000000 --- a/usr.bin/netstat/ipsec.c +++ /dev/null @@ -1,314 +0,0 @@ -/* $FreeBSD: src/usr.bin/netstat/ipsec.c,v 1.1.2.3 2001/08/10 09:07:09 ru Exp $ */ -/* $NetBSD: inet.c,v 1.35.2.1 1999/04/29 14:57:08 perry Exp $ */ -/* $KAME: ipsec.c,v 1.25 2001/03/12 09:04:39 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - * - * @(#)inet.c 8.5 (Berkeley) 5/24/95 - * $FreeBSD: src/usr.bin/netstat/ipsec.c,v 1.1.2.3 2001/08/10 09:07:09 ru Exp $ - */ - -/* - * Copyright (c) 1983, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include - -#include - -#ifdef IPSEC -#include -#include -#endif - -#include -#include -#include -#include "netstat.h" - -/* - * portability issues: - * - bsdi[34] uses PLURAL(), not plural(). - * - freebsd2 can't print "unsigned long long" properly. - */ -/* - * XXX see PORTABILITY for the twist - */ -#define LLU "%llu" -#define CAST unsigned long long - -#ifdef IPSEC -struct val2str { - int val; - const char *str; -}; - -static struct val2str ipsec_ahnames[] = { - { SADB_AALG_NONE, "none", }, - { SADB_AALG_MD5HMAC, "hmac-md5", }, - { SADB_AALG_SHA1HMAC, "hmac-sha1", }, - { SADB_X_AALG_MD5, "md5", }, - { SADB_X_AALG_SHA, "sha", }, - { SADB_X_AALG_NULL, "null", }, -#ifdef SADB_X_AALG_SHA2_256 - { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, -#endif -#ifdef SADB_X_AALG_SHA2_384 - { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, -#endif -#ifdef SADB_X_AALG_SHA2_512 - { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, -#endif - { -1, NULL }, -}; - -static struct val2str ipsec_espnames[] = { - { SADB_EALG_NONE, "none", }, - { SADB_EALG_DESCBC, "des-cbc", }, - { SADB_EALG_3DESCBC, "3des-cbc", }, - { SADB_EALG_NULL, "null", }, -#ifdef SADB_X_EALG_RC5CBC - { SADB_X_EALG_RC5CBC, "rc5-cbc", }, -#endif - { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, - { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, -#ifdef SADB_X_EALG_RIJNDAELCBC - { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, -#endif - { -1, NULL }, -}; - -static struct val2str ipsec_compnames[] = { - { SADB_X_CALG_NONE, "none", }, - { SADB_X_CALG_OUI, "oui", }, - { SADB_X_CALG_DEFLATE, "deflate", }, - { SADB_X_CALG_LZS, "lzs", }, - { -1, NULL }, -}; - -static const char *pfkey_msgtypenames[] = { - "reserved", "getspi", "update", "add", "delete", - "get", "acquire", "register", "expire", "flush", - "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd", - "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush", - "x_spdsetidx", "x_spdexpire", "x_spddelete2" -}; - -static struct ipsecstat ipsecstat; - -static void print_ipsecstats (void); -static const char *pfkey_msgtype_names (int); -static void ipsec_hist (const u_quad_t *, size_t, const struct val2str *, - const char *); - -/* - * Dump IPSEC statistics structure. - */ -static void -ipsec_hist(const u_quad_t *hist, - size_t histmax, - const struct val2str *name, - const char *title) -{ - int first; - size_t proto; - const struct val2str *p; - - first = 1; - for (proto = 0; proto < histmax; proto++) { - if (hist[proto] <= 0) - continue; - if (first) { - printf("\t%s histogram:\n", title); - first = 0; - } - for (p = name; p && p->str; p++) { - if (p->val == (int)proto) - break; - } - if (p && p->str) { - printf("\t\t%s: " LLU "\n", p->str, (CAST)hist[proto]); - } else { - printf("\t\t#%ld: " LLU "\n", (long)proto, - (CAST)hist[proto]); - } - } -} - -static void -print_ipsecstats(void) -{ -#define p(f, m) if (ipsecstat.f || sflag <= 1) \ - printf(m, (CAST)ipsecstat.f, plural(ipsecstat.f)) -#define hist(f, n, t) \ - ipsec_hist((f), sizeof(f)/sizeof(f[0]), (n), (t)); - - p(in_success, "\t" LLU " inbound packet%s processed successfully\n"); - p(in_polvio, "\t" LLU " inbound packet%s violated process security " - "policy\n"); - p(in_nosa, "\t" LLU " inbound packet%s with no SA available\n"); - p(in_inval, "\t" LLU " invalid inbound packet%s\n"); - p(in_nomem, "\t" LLU " inbound packet%s failed due to insufficient memory\n"); - p(in_badspi, "\t" LLU " inbound packet%s failed getting SPI\n"); - p(in_ahreplay, "\t" LLU " inbound packet%s failed on AH replay check\n"); - p(in_espreplay, "\t" LLU " inbound packet%s failed on ESP replay check\n"); - p(in_ahauthsucc, "\t" LLU " inbound packet%s considered authentic\n"); - p(in_ahauthfail, "\t" LLU " inbound packet%s failed on authentication\n"); - hist(ipsecstat.in_ahhist, ipsec_ahnames, "AH input"); - hist(ipsecstat.in_esphist, ipsec_espnames, "ESP input"); - hist(ipsecstat.in_comphist, ipsec_compnames, "IPComp input"); - - p(out_success, "\t" LLU " outbound packet%s processed successfully\n"); - p(out_polvio, "\t" LLU " outbound packet%s violated process security " - "policy\n"); - p(out_nosa, "\t" LLU " outbound packet%s with no SA available\n"); - p(out_inval, "\t" LLU " invalid outbound packet%s\n"); - p(out_nomem, "\t" LLU " outbound packet%s failed due to insufficient memory\n"); - p(out_noroute, "\t" LLU " outbound packet%s with no route\n"); - hist(ipsecstat.out_ahhist, ipsec_ahnames, "AH output"); - hist(ipsecstat.out_esphist, ipsec_espnames, "ESP output"); - hist(ipsecstat.out_comphist, ipsec_compnames, "IPComp output"); -#undef p -#undef hist -} - -void -ipsec_stats(u_long off __unused, const char *name, int af1 __unused) -{ - if (off == 0) - return; - printf ("%s:\n", name); - kread(off, (char *)&ipsecstat, sizeof (ipsecstat)); - - print_ipsecstats(); -} - -static const char * -pfkey_msgtype_names(int x) -{ - const int max = NELEM(pfkey_msgtypenames); - static char buf[10]; - - if (x < max && pfkey_msgtypenames[x]) - return pfkey_msgtypenames[x]; - snprintf(buf, sizeof(buf), "#%d", x); - return buf; -} - -void -pfkey_stats(u_long off __unused, const char *name, int af1 __unused) -{ - struct pfkeystat pfkeystat; - unsigned first, type; - - if (off == 0) - return; - printf ("%s:\n", name); - kread(off, (char *)&pfkeystat, sizeof(pfkeystat)); - -#define p(f, m) if (pfkeystat.f || sflag <= 1) \ - printf(m, (CAST)pfkeystat.f, plural(pfkeystat.f)) - - /* kernel -> userland */ - p(out_total, "\t" LLU " request%s sent to userland\n"); - p(out_bytes, "\t" LLU " byte%s sent to userland\n"); - for (first = 1, type = 0; - type < sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]); - type++) { - if (pfkeystat.out_msgtype[type] <= 0) - continue; - if (first) { - printf("\thistogram by message type:\n"); - first = 0; - } - printf("\t\t%s: " LLU "\n", pfkey_msgtype_names(type), - (CAST)pfkeystat.out_msgtype[type]); - } - p(out_invlen, "\t" LLU " message%s with invalid length field\n"); - p(out_invver, "\t" LLU " message%s with invalid version field\n"); - p(out_invmsgtype, "\t" LLU " message%s with invalid message type field\n"); - p(out_tooshort, "\t" LLU " message%s too short\n"); - p(out_nomem, "\t" LLU " message%s with memory allocation failure\n"); - p(out_dupext, "\t" LLU " message%s with duplicate extension\n"); - p(out_invexttype, "\t" LLU " message%s with invalid extension type\n"); - p(out_invsatype, "\t" LLU " message%s with invalid sa type\n"); - p(out_invaddr, "\t" LLU " message%s with invalid address extension\n"); - - /* userland -> kernel */ - p(in_total, "\t" LLU " request%s sent from userland\n"); - p(in_bytes, "\t" LLU " byte%s sent from userland\n"); - for (first = 1, type = 0; - type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]); - type++) { - if (pfkeystat.in_msgtype[type] <= 0) - continue; - if (first) { - printf("\thistogram by message type:\n"); - first = 0; - } - printf("\t\t%s: " LLU "\n", pfkey_msgtype_names(type), - (CAST)pfkeystat.in_msgtype[type]); - } - p(in_msgtarget[KEY_SENDUP_ONE], - "\t" LLU " message%s toward single socket\n"); - p(in_msgtarget[KEY_SENDUP_ALL], - "\t" LLU " message%s toward all sockets\n"); - p(in_msgtarget[KEY_SENDUP_REGISTERED], - "\t" LLU " message%s toward registered sockets\n"); - p(in_nomem, "\t" LLU " message%s with memory allocation failure\n"); -#undef p -} -#endif /*IPSEC*/ diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c index 0d33e85450..1a9a56933f 100644 --- a/usr.bin/netstat/main.c +++ b/usr.bin/netstat/main.c @@ -106,37 +106,31 @@ static struct nlist nl[] = { { .n_name = "_ip6stat" }, #define N_ICMP6STAT 24 { .n_name = "_icmp6stat" }, -#define N_IPSECSTAT 25 - { .n_name = "_ipsecstat" }, -#define N_IPSEC6STAT 26 - { .n_name = "_ipsec6stat" }, -#define N_PIM6STAT 27 +#define N_PIM6STAT 25 { .n_name = "_pim6stat" }, -#define N_MRT6PROTO 28 +#define N_MRT6PROTO 26 { .n_name = "_ip6_mrtproto" }, -#define N_MRT6STAT 29 +#define N_MRT6STAT 27 { .n_name = "_mrt6stat" }, -#define N_MF6CTABLE 30 +#define N_MF6CTABLE 28 { .n_name = "_mf6ctable" }, -#define N_MIF6TABLE 31 +#define N_MIF6TABLE 29 { .n_name = "_mif6table" }, -#define N_PFKEYSTAT 32 - { .n_name = "_pfkeystat" }, -#define N_MBSTAT 33 +#define N_MBSTAT 30 { .n_name = "_mbstat" }, -#define N_MBTYPES 34 +#define N_MBTYPES 31 { .n_name = "_mbtypes" }, -#define N_NMBCLUSTERS 35 +#define N_NMBCLUSTERS 32 { .n_name = "_nmbclusters" }, -#define N_NMBUFS 36 +#define N_NMBUFS 33 { .n_name = "_nmbufs" }, -#define N_RTTRASH 37 +#define N_RTTRASH 34 { .n_name = "_rttrash" }, -#define N_NCPUS 38 +#define N_NCPUS 35 { .n_name = "_ncpus" }, -#define N_CARPSTAT 39 +#define N_CARPSTAT 36 { .n_name = "_carpstats" }, -#define N_NMBJCLUSTERS 40 +#define N_NMBJCLUSTERS 37 { .n_name = "_nmbjclusters" }, { .n_name = NULL }, }; @@ -165,10 +159,6 @@ struct protox { icmp_stats, NULL, "icmp", IPPROTO_ICMP }, { -1, -1, 1, protopr, igmp_stats, NULL, "igmp", IPPROTO_IGMP }, -#ifdef IPSEC - { -1, N_IPSECSTAT, 1, 0, - ipsec_stats, NULL, "ipsec", 0}, -#endif { -1, N_CARPSTAT, 1, 0, carp_stats, NULL, "carp", 0}, { -1, -1, 0, 0, @@ -185,10 +175,6 @@ struct protox ip6protox[] = { ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW }, { -1, N_ICMP6STAT, 1, protopr, icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 }, -#ifdef IPSEC - { -1, N_IPSEC6STAT, 1, 0, - ipsec_stats, NULL, "ipsec6",0 }, -#endif #ifdef notyet { -1, N_PIM6STAT, 1, 0, pim6_stats, NULL, "pim6", 0 }, @@ -202,15 +188,6 @@ struct protox ip6protox[] = { }; #endif /*INET6*/ -#ifdef IPSEC -struct protox pfkeyprotox[] = { - { -1, N_PFKEYSTAT, 1, 0, - pfkey_stats, NULL, "pfkey", 0 }, - { -1, -1, 0, 0, - 0, NULL, 0, 0 } -}; -#endif - struct protox netgraphprotox[] = { { N_NGSOCKS, -1, 1, netgraphprotopr, NULL, NULL, "ctrl", 0 }, @@ -224,9 +201,6 @@ struct protox *protoprotox[] = { protox, #ifdef INET6 ip6protox, -#endif -#ifdef IPSEC - pfkeyprotox, #endif NULL }; @@ -305,10 +279,6 @@ main(int argc, char **argv) #ifdef INET6 else if (strcmp(optarg, "inet6") == 0) af = AF_INET6; -#endif /*INET6*/ -#ifdef INET6 - else if (strcmp(optarg, "pfkey") == 0) - af = PF_KEY; #endif /*INET6*/ else if (strcmp(optarg, "unix") == 0) af = AF_UNIX; @@ -504,11 +474,6 @@ main(int argc, char **argv) for (tp = ip6protox; tp->pr_name; tp++) printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); #endif /*INET6*/ -#ifdef IPSEC - if (af == PF_KEY || af == AF_UNSPEC) - for (tp = pfkeyprotox; tp->pr_name; tp++) - printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); -#endif /*IPSEC*/ if (af == AF_NETGRAPH || af == AF_UNSPEC) for (tp = netgraphprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); diff --git a/usr.bin/netstat/netstat.1 b/usr.bin/netstat/netstat.1 index d18783a911..2a34cc4041 100644 --- a/usr.bin/netstat/netstat.1 +++ b/usr.bin/netstat/netstat.1 @@ -28,7 +28,7 @@ .\" @(#)netstat.1 8.8 (Berkeley) 4/18/94 .\" $FreeBSD: src/usr.bin/netstat/netstat.1,v 1.22.2.13 2003/05/03 22:10:02 keramida Exp $ .\" -.Dd August 8, 2015 +.Dd April 21, 2018 .Dt NETSTAT 1 .Os .Sh NAME @@ -288,11 +288,9 @@ The following address families, protocol families and protocols are recognized: .It Em Family .Em Protocols .It Cm inet Pq Dv AF_INET PF_INET -.Cm carp , divert , icmp , igmp , ip , ipsec , pim , tcp , udp +.Cm carp , divert , icmp , igmp , ip , pim , tcp , udp .It Cm inet6 Pq Dv AF_INET6 PF_INET6 -.Cm carp , icmp6 , ip6 , ipsec6 , rip6 , tcp , udp -.It Cm pfkey Pq Dv AF_KEY PF_KEY -.Cm pfkey +.Cm carp , icmp6 , ip6 , rip6 , tcp , udp .It Cm netgraph , ng Pq Dv AF_NETGRAPH PF_NETGRAPH .Cm ctrl , data .It Cm unix Pq Dv AF_UNIX PF_UNIX diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h index 80aa468d68..4f4650f372 100644 --- a/usr.bin/netstat/netstat.h +++ b/usr.bin/netstat/netstat.h @@ -70,9 +70,6 @@ void icmp_stats (u_long, const char *, int); void igmp_stats (u_long, const char *, int); void pim_stats (u_long, const char *, int); void carp_stats (u_long, const char *, int); -#ifdef IPSEC -void ipsec_stats (u_long, const char *, int); -#endif #ifdef INET6 void ip6_stats (u_long, const char *, int); @@ -90,10 +87,6 @@ char *routename6 (struct sockaddr_in6 *); const char *netname6 (struct sockaddr_in6 *, struct in6_addr *); #endif /*INET6*/ -#ifdef IPSEC -void pfkey_stats (u_long, const char *, int); -#endif - void mbpr (u_long, u_long, u_long, u_long, u_long, u_long); void hostpr (u_long, u_long); diff --git a/usr.bin/telnet/Makefile b/usr.bin/telnet/Makefile index 1d5e9d1307..b82424a00f 100644 --- a/usr.bin/telnet/Makefile +++ b/usr.bin/telnet/Makefile @@ -21,10 +21,6 @@ LDADD= -lprivate_ncurses ${LIBTELNET} CFLAGS+= -I${_SHLIBDIRPREFIX}/usr/include/priv/ncurses LDFLAGS+= ${PRIVATELIB_LDFLAGS} -CFLAGS+= -DIPSEC -DPADD+= ${LIBIPSEC} -LDADD+= -lipsec - CFLAGS+= -DENCRYPTION -DAUTHENTICATION DPADD+= ${LIBCRYPTO} ${LIBCRYPT} ${LIBPAM} LDADD+= -lprivate_crypto -lcrypt ${MINUSLPAM} diff --git a/usr.bin/telnet/commands.c b/usr.bin/telnet/commands.c index 967eeb0ccd..a41bfc74f5 100644 --- a/usr.bin/telnet/commands.c +++ b/usr.bin/telnet/commands.c @@ -2104,34 +2104,6 @@ sockaddr_ntop(struct sockaddr *sa) return addrbuf; } -#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) -static int -setpolicy(int lnet, struct addrinfo *res, char *policy) -{ - char *buf; - int level; - int optname; - - if (policy == NULL) - return 0; - - buf = ipsec_set_policy(policy, strlen(policy)); - if (buf == NULL) { - printf("%s\n", ipsec_strerror()); - return -1; - } - level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; - optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; - if (setsockopt(lnet, level, optname, buf, ipsec_get_policylen(buf)) < 0){ - perror("setsockopt"); - return -1; - } - - free(buf); - return 0; -} -#endif - #ifdef INET6 /* * When an Address Family related error happend, check if retry with @@ -2419,16 +2391,6 @@ tn(int argc, char *argv[]) goto fail; } } -#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) - if (setpolicy(net, res, ipsec_policy_in) < 0) { - (void) NetClose(net); - goto fail; - } - if (setpolicy(net, res, ipsec_policy_out) < 0) { - (void) NetClose(net); - goto fail; - } -#endif if (connect(net, res->ai_addr, res->ai_addrlen) < 0) { struct addrinfo *next; diff --git a/usr.bin/telnet/externs.h b/usr.bin/telnet/externs.h index 3aad36131b..03bfab5c39 100644 --- a/usr.bin/telnet/externs.h +++ b/usr.bin/telnet/externs.h @@ -67,14 +67,6 @@ typedef unsigned char cc_t; #include -#if defined(IPSEC) -#include -#if defined(IPSEC_POLICY_IPSEC) -extern char *ipsec_policy_in; -extern char *ipsec_policy_out; -#endif -#endif - #ifndef _POSIX_VDISABLE # ifdef sun # include /* pick up VDISABLE definition, mayby */ diff --git a/usr.bin/telnet/main.c b/usr.bin/telnet/main.c index fca22383e1..cbccbe2192 100644 --- a/usr.bin/telnet/main.c +++ b/usr.bin/telnet/main.c @@ -56,11 +56,6 @@ #define FORWARD #endif -#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) -char *ipsec_policy_in = NULL; -char *ipsec_policy_out = NULL; -#endif - int family = AF_UNSPEC; /* @@ -91,9 +86,6 @@ usage(void) "\n\t[-e char] [-l user] [-n tracefile] ", #endif "[-r] [-s src_addr] [-u] ", -#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) - "[-P policy] " -#endif #ifdef ENCRYPTION "[-y] [host-name [port]]" #else /* ENCRYPTION */ @@ -140,15 +132,7 @@ main(int argc, char *argv[]) decrypt_auto(1); #endif -#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) -#define IPSECOPT "P:" -#else -#define IPSECOPT -#endif - while ((ch = getopt(argc, argv, - "468EKLNS:X:acde:fFk:l:n:rs:t:uxy" IPSECOPT)) != -1) -#undef IPSECOPT - { + while ((ch = getopt(argc, argv, "468EKLNS:X:acde:fFk:l:n:rs:t:uxy")) != -1) { switch(ch) { case '4': family = AF_INET; @@ -308,16 +292,6 @@ main(int argc, char *argv[]) prompt); #endif /* ENCRYPTION */ break; -#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) - case 'P': - if (!strncmp("in", optarg, 2)) - ipsec_policy_in = strdup(optarg); - else if (!strncmp("out", optarg, 3)) - ipsec_policy_out = strdup(optarg); - else - usage(); - break; -#endif case '?': default: usage(); diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index fb5f6ec31a..d211b48365 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -111,7 +111,6 @@ SUBDIR= 802_11 \ sdpd \ sensorsd \ service \ - setkey \ sshd \ sshlockout \ sliplogin \ diff --git a/usr.sbin/authpf/authpf.8 b/usr.sbin/authpf/authpf.8 index 36798c1a73..31af50b67f 100644 --- a/usr.sbin/authpf/authpf.8 +++ b/usr.sbin/authpf/authpf.8 @@ -1,5 +1,4 @@ .\" $OpenBSD: authpf.8,v 1.31 2003/12/10 04:10:37 beck Exp $ -.\" $DragonFly: src/usr.sbin/authpf/authpf.8,v 1.3 2007/07/29 17:27:45 swildner Exp $ .\" .\" Copyright (c) 2002 Bob Beck (beck@openbsd.org>. All rights reserved. .\" @@ -25,7 +24,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 10, 2002 +.Dd April 21, 2018 .Dt AUTHPF 8 .Os .Sh NAME @@ -384,10 +383,9 @@ an email to remove@bulkmailerz.net. wireless network (a hub with several hundred ports), the default rule set as well as the per-user rules should probably allow very few things beyond encrypted protocols like -.Xr ssh 1 , -.Xr ssl 8 , +.Xr ssh 1 or -.Xr ipsec 4 . +.Xr ssl 8 . On a securely switched network, with plug-in jacks for visitors who are given authentication accounts, you might want to allow out everything. In this context, a secure switch is one that tries to prevent address table @@ -424,30 +422,30 @@ pass in log quick on $internal_if proto tcp from $user_ip to any \e keep state pass in quick on $internal_if from $user_ip to any .Ed -.Pp -.Sy For a wireless or shared net -\- This example -.Pa /etc/authpf/authpf.rules -could be used for an insecure network (such as a public wireless network) where -we might need to be a bit more restrictive. -.Bd -literal -internal_if="fxp1" -ipsec_gw="10.2.3.4" - -# rdr ftp for proxying by ftp-proxy(8) -rdr on $internal_if proto tcp from $user_ip to any port 21 \e - -> 127.0.0.1 port 8081 - -# allow out ftp, ssh, www and https only, and allow user to negotiate -# ipsec with the ipsec server. -pass in log quick on $internal_if proto tcp from $user_ip to any \e - port { 21, 22, 80, 443 } flags S/SA -pass in quick on $internal_if proto tcp from $user_ip to any \e - port { 21, 22, 80, 443 } -pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp \e - keep state -pass in quick proto esp from $user_ip to $ipsec_gw -.Ed +.\".Pp +.\".Sy For a wireless or shared net +.\"\- This example +.\".Pa /etc/authpf/authpf.rules +.\"could be used for an insecure network (such as a public wireless network) where +.\"we might need to be a bit more restrictive. +.\".Bd -literal +.\"internal_if="fxp1" +.\"ipsec_gw="10.2.3.4" +.\" +.\"# rdr ftp for proxying by ftp-proxy(8) +.\"rdr on $internal_if proto tcp from $user_ip to any port 21 \e +.\" -> 127.0.0.1 port 8081 +.\" +.\"# allow out ftp, ssh, www and https only, and allow user to negotiate +.\"# ipsec with the ipsec server. +.\"pass in log quick on $internal_if proto tcp from $user_ip to any \e +.\" port { 21, 22, 80, 443 } flags S/SA +.\"pass in quick on $internal_if proto tcp from $user_ip to any \e +.\" port { 21, 22, 80, 443 } +.\"pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp \e +.\" keep state +.\"pass in quick proto esp from $user_ip to $ipsec_gw +.\".Ed .Pp .Sy Dealing with NAT \- The following diff --git a/usr.sbin/inetd/Makefile b/usr.sbin/inetd/Makefile index 077425602b..779a30b769 100644 --- a/usr.sbin/inetd/Makefile +++ b/usr.sbin/inetd/Makefile @@ -1,18 +1,15 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD: src/usr.sbin/inetd/Makefile,v 1.18.2.4 2001/12/19 04:49:11 dd Exp $ -# $DragonFly: src/usr.sbin/inetd/Makefile,v 1.4 2008/05/23 23:40:59 swildner Exp $ PROG= inetd SRCS= inetd.c builtins.c MAN= inetd.8 MLINKS= inetd.8 inetd.conf.5 -CFLAGS+= -DLOGIN_CAP +CFLAGS+=-DINET6 -DLOGIN_CAP #CFLAGS+= -DSANITY_CHECK DPADD+= ${LIBUTIL} ${LIBWRAP} LDADD+= -lutil -lwrap -CFLAGS+=-DINET6 -DIPSEC -DPADD+= ${LIBIPSEC} -LDADD+= -lipsec + .include diff --git a/usr.sbin/inetd/inetd.8 b/usr.sbin/inetd/inetd.8 index 51723753ab..98bb626ae1 100644 --- a/usr.sbin/inetd/inetd.8 +++ b/usr.sbin/inetd/inetd.8 @@ -28,7 +28,7 @@ .\" from: @(#)inetd.8 8.3 (Berkeley) 4/13/94 .\" $FreeBSD: src/usr.sbin/inetd/inetd.8,v 1.46.2.13 2003/03/12 22:08:14 trhodes Exp $ .\" -.Dd December 31, 2017 +.Dd April 21, 2018 .Dt INETD 8 .Os .Sh NAME @@ -672,29 +672,6 @@ causes .Nm to list TCPMUX services in .Pa inetd.conf . -.Ss IPsec -The implementation includes a tiny hack -to support IPsec policy settings for each socket. -A special form of comment line, starting with -.Dq Li #@ , -is interpreted as a policy specifier. -Everything after the -.Dq Li #@ -will be used as an IPsec policy string, -as described in -.Xr ipsec_set_policy 3 . -Each -policy specifier is applied to all the following lines in -.Pa inetd.conf -until the next policy specifier. -An empty policy specifier resets the IPsec policy. -.Pp -If an invalid IPsec policy specifier appears in -.Pa inetd.conf , -.Nm -will provide an error message via the -.Xr syslog 3 -interface and abort execution. .Ss Ux Domain Sockets In addition to running services on IP sockets, .Nm @@ -785,9 +762,6 @@ tcpmux/+date stream tcp nowait guest /bin/date date tcpmux/phonebook stream tcp nowait guest /usr/local/bin/phonebook phonebook rstatd/1-3 dgram rpc/udp wait root /usr/libexec/rpc.rstatd rpc.rstatd /var/run/echo stream unix nowait root internal -#@ ipsec ah/require -chargen stream tcp nowait root internal -#@ .Ed .Sh ERROR MESSAGES The @@ -872,7 +846,6 @@ utility attempted to renounce the privileged state associated with a socket but was unable to. .El .Sh SEE ALSO -.Xr ipsec_set_policy 3 , .Xr hosts_access 5 , .Xr hosts_options 5 , .Xr login.conf 5 , @@ -904,7 +877,6 @@ based services is modeled after that provided by .Tn SunOS 4.1. -The IPsec hack was contributed by the KAME project in 1999. The .Fx TCP Wrappers support first appeared in diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c index 69f65d88a3..94de4d9365 100644 --- a/usr.sbin/inetd/inetd.c +++ b/usr.sbin/inetd/inetd.c @@ -89,13 +89,6 @@ * server program arguments maximum of MAXARGS * * Comment lines are indicated by a `#' in column 1. - * - * #ifdef IPSEC - * Comment lines that start with "#@" denote IPsec policy string, as described - * in ipsec_set_policy(3). This will affect all the following items in - * inetd.conf(8). To reset the policy, just use "#@" line. By default, - * there's no IPsec policy. - * #endif */ #include #include @@ -132,13 +125,6 @@ #include "inetd.h" #include "pathnames.h" -#ifdef IPSEC -#include -#ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */ -#undef IPSEC -#endif -#endif - /* wrapper for KAME-special getnameinfo() */ #ifndef NI_WITHSCOPEID #define NI_WITHSCOPEID 0 @@ -217,9 +203,6 @@ void flag_retry(int); void retry(void); int setconfig(void); void setup(struct servtab *); -#ifdef IPSEC -void ipsecsetup(struct servtab *); -#endif void unregisterrpc(struct servtab *sep); static struct conninfo *search_conn(struct servtab *sep, int ctrl); static int room_conn(struct servtab *sep, struct conninfo *conn); @@ -1026,10 +1009,6 @@ config(void) SWAP(sep->se_server_name, new->se_server_name); for (i = 0; i < MAXARGV; i++) SWAP(sep->se_argv[i], new->se_argv[i]); -#ifdef IPSEC - SWAP(sep->se_policy, new->se_policy); - ipsecsetup(sep); -#endif sigsetmask(omask); freeconfig(new); if (debug) @@ -1230,9 +1209,6 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof (on)) < 0) syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m"); -#ifdef IPSEC - ipsecsetup(sep); -#endif if (sep->se_family == AF_UNIX) { unlink(sep->se_ctrladdr_un.sun_path); umask(0777); /* Make socket with conservative permissions */ @@ -1301,78 +1277,6 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) } } -#ifdef IPSEC -void -ipsecsetup(struct servtab *sep) -{ - char *buf; - char *policy_in = NULL; - char *policy_out = NULL; - int level; - int opt; - - switch (sep->se_family) { - case AF_INET: - level = IPPROTO_IP; - opt = IP_IPSEC_POLICY; - break; -#ifdef INET6 - case AF_INET6: - level = IPPROTO_IPV6; - opt = IPV6_IPSEC_POLICY; - break; -#endif - default: - return; - } - - if (!sep->se_policy || sep->se_policy[0] == '\0') { - static char def_in[] = "in entrust", def_out[] = "out entrust"; - policy_in = def_in; - policy_out = def_out; - } else { - if (!strncmp("in", sep->se_policy, 2)) - policy_in = sep->se_policy; - else if (!strncmp("out", sep->se_policy, 3)) - policy_out = sep->se_policy; - else { - syslog(LOG_ERR, "invalid security policy \"%s\"", - sep->se_policy); - return; - } - } - - if (policy_in != NULL) { - buf = ipsec_set_policy(policy_in, strlen(policy_in)); - if (buf != NULL) { - if (setsockopt(sep->se_fd, level, opt, - buf, ipsec_get_policylen(buf)) < 0 && - debug != 0) - warnx("%s/%s: ipsec initialization failed; %s", - sep->se_service, sep->se_proto, - policy_in); - free(buf); - } else - syslog(LOG_ERR, "invalid security policy \"%s\"", - policy_in); - } - if (policy_out != NULL) { - buf = ipsec_set_policy(policy_out, strlen(policy_out)); - if (buf != NULL) { - if (setsockopt(sep->se_fd, level, opt, - buf, ipsec_get_policylen(buf)) < 0 && - debug != 0) - warnx("%s/%s: ipsec initialization failed; %s", - sep->se_service, sep->se_proto, - policy_out); - free(buf); - } else - syslog(LOG_ERR, "invalid security policy \"%s\"", - policy_out); - } -} -#endif - /* * Finish with a service and its socket. */ @@ -1529,9 +1433,6 @@ getconfigent(void) char *versp; static char TCPMUX_TOKEN[] = "tcpmux/"; #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) -#ifdef IPSEC - char *policy = NULL; -#endif int v4bind = 0; #ifdef INET6 int v6bind = 0; @@ -1540,28 +1441,6 @@ getconfigent(void) more: while ((cp = nextline(fconfig)) != NULL) { -#ifdef IPSEC - /* lines starting with #@ is not a comment, but the policy */ - if (cp[0] == '#' && cp[1] == '@') { - char *p; - for (p = cp + 2; p && *p && isspace(*p); p++) - ; - if (*p == '\0') { - if (policy) - free(policy); - policy = NULL; - } else if (ipsec_get_policylen(p) >= 0) { - if (policy) - free(policy); - policy = newstr(p); - } else { - syslog(LOG_ERR, - "%s: invalid ipsec policy \"%s\"", - CONFIG, p); - exit(EX_CONFIG); - } - } -#endif if (*cp == '#' || *cp == '\0') continue; break; @@ -1883,9 +1762,6 @@ more: sep->se_argv[argc++] = NULL; for (i = 0; i < PERIPSIZE; ++i) LIST_INIT(&sep->se_conn[i]); -#ifdef IPSEC - sep->se_policy = policy ? newstr(policy) : NULL; -#endif return (sep); } @@ -1914,10 +1790,6 @@ freeconfig(struct servtab *cp) if (cp->se_argv[i]) free(cp->se_argv[i]); free_connlist(cp); -#ifdef IPSEC - if (cp->se_policy) - free(cp->se_policy); -#endif } @@ -2066,9 +1938,6 @@ print_service(const char *action, const struct servtab *sep) "class=%s" #endif " builtin=%p server=%s" -#ifdef IPSEC - " policy=\"%s\"" -#endif "\n", action, sep->se_service, sep->se_proto, sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group, @@ -2076,9 +1945,6 @@ print_service(const char *action, const struct servtab *sep) sep->se_class, #endif (void *) sep->se_bi, sep->se_server -#ifdef IPSEC - , (sep->se_policy ? sep->se_policy : "") -#endif ); } diff --git a/usr.sbin/inetd/inetd.h b/usr.sbin/inetd/inetd.h index cb6138cae6..6f735b0956 100644 --- a/usr.sbin/inetd/inetd.h +++ b/usr.sbin/inetd/inetd.h @@ -84,9 +84,6 @@ struct servtab { char *se_server_name; /* server program without path */ #define MAXARGV 20 char *se_argv[MAXARGV+1]; /* program arguments */ -#ifdef IPSEC - char *se_policy; /* IPsec policy string */ -#endif int se_fd; /* open descriptor */ union { /* bound address */ struct sockaddr se_un_ctrladdr; diff --git a/usr.sbin/mld6query/Makefile b/usr.sbin/mld6query/Makefile index 2d541794dd..aebe4c18a4 100644 --- a/usr.sbin/mld6query/Makefile +++ b/usr.sbin/mld6query/Makefile @@ -17,6 +17,6 @@ PROG= mld6query MAN= mld6query.8 -CFLAGS+= -DINET6 -DIPSEC +CFLAGS+=-DINET6 .include diff --git a/usr.sbin/rrenumd/Makefile b/usr.sbin/rrenumd/Makefile index 1724e76a82..3bac475a9f 100644 --- a/usr.sbin/rrenumd/Makefile +++ b/usr.sbin/rrenumd/Makefile @@ -18,9 +18,9 @@ SRCS= rrenumd.c parser.y lexer.l YFLAGS+= -d WARNS?= 2 -CFLAGS+= -DINET6 -DIPSEC -I. -I${.CURDIR} -LDADD= -lipsec -ll -DPADD= ${LIBIPSEC} ${LIBL} +CFLAGS+=-DINET6 -I. -I${.CURDIR} +LDADD= -ll +DPADD= ${LIBL} MAN= rrenumd.conf.5 rrenumd.8 diff --git a/usr.sbin/rrenumd/rrenumd.c b/usr.sbin/rrenumd/rrenumd.c index 2fa1563670..e2f0d52bc0 100644 --- a/usr.sbin/rrenumd/rrenumd.c +++ b/usr.sbin/rrenumd/rrenumd.c @@ -48,10 +48,6 @@ #include -#ifdef IPSEC -#include -#endif - #include #include #include @@ -75,14 +71,6 @@ struct flags { u_long debug : 1; u_long fg : 1; -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - u_long policy : 1; -#else /* IPSEC_POLICY_IPSEC */ - u_long auth : 1; - u_long encrypt : 1; -#endif /* IPSEC_POLICY_IPSEC */ -#endif /*IPSEC*/ }; struct msghdr sndmhdr; @@ -104,13 +92,8 @@ static void join_multi(const char *); #endif static void init_globals(void); static void config(FILE **); -#ifdef IPSEC_POLICY_IPSEC -static void sock6_open(struct flags *, char *); -static void sock4_open(struct flags *, char *); -#else static void sock6_open(struct flags *); static void sock4_open(struct flags *); -#endif static void rrenum_output(struct payload_list *, struct dst_list *); static void rrenum_snd_eachdst(struct payload_list *); #if 0 @@ -123,15 +106,7 @@ static void rrenum_input(int); static void show_usage(void) { - fprintf(stderr, "usage: rrenumd [-c conf_file|-s] [-df" -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - "] [-P policy" -#else /* IPSEC_POLICY_IPSEC */ - "AE" -#endif /* IPSEC_POLICY_IPSEC */ -#endif /* IPSEC */ - "]\n"); + fprintf(stderr, "usage: rrenumd [-c conf_file|-s] [-df]\n"); exit(1); } @@ -261,19 +236,10 @@ config(FILE **fpp) } static void -sock6_open(struct flags *flags -#ifdef IPSEC_POLICY_IPSEC - , char *policy -#endif /* IPSEC_POLICY_IPSEC */ - ) +sock6_open(struct flags *flags) { struct icmp6_filter filt; int on; -#ifdef IPSEC -#ifndef IPSEC_POLICY_IPSEC - int optval; -#endif -#endif if (with_v6dest == 0) return; @@ -311,57 +277,12 @@ sock6_open(struct flags *flags exit(1); } -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - if (flags->policy) { - char *buf; - buf = ipsec_set_policy(policy, strlen(policy)); - if (buf == NULL) - errx(1, "%s", ipsec_strerror()); - /* XXX should handle in/out bound policy. */ - if (setsockopt(s6, IPPROTO_IPV6, IPV6_IPSEC_POLICY, - buf, ipsec_get_policylen(buf)) < 0) - err(1, "setsockopt(IPV6_IPSEC_POLICY)"); - free(buf); - } -#else /* IPSEC_POLICY_IPSEC */ - if (flags->auth) { - optval = IPSEC_LEVEL_REQUIRE; - if (setsockopt(s6, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, - &optval, sizeof(optval)) == -1) { - syslog(LOG_ERR, "<%s> IPV6_AUTH_TRANS_LEVEL: %s", - __func__, strerror(errno)); - exit(1); - } - } - if (flags->encrypt) { - optval = IPSEC_LEVEL_REQUIRE; - if (setsockopt(s6, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, - &optval, sizeof(optval)) == -1) { - syslog(LOG_ERR, "<%s> IPV6_ESP_TRANS_LEVEL: %s", - __func__, strerror(errno)); - exit(1); - } - } -#endif /* IPSEC_POLICY_IPSEC */ -#endif /* IPSEC */ - return; } static void -sock4_open(struct flags *flags -#ifdef IPSEC_POLICY_IPSEC - , char *policy -#endif /* IPSEC_POLICY_IPSEC */ - ) +sock4_open(struct flags *flags) { -#ifdef IPSEC -#ifndef IPSEC_POLICY_IPSEC - int optval; -#endif -#endif - if (with_v4dest == 0) return; if ((s4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { @@ -377,41 +298,6 @@ sock4_open(struct flags *flags some_join_function(); #endif -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - if (flags->policy) { - char *buf; - buf = ipsec_set_policy(policy, strlen(policy)); - if (buf == NULL) - errx(1, "%s", ipsec_strerror()); - /* XXX should handle in/out bound policy. */ - if (setsockopt(s4, IPPROTO_IP, IP_IPSEC_POLICY, - buf, ipsec_get_policylen(buf)) < 0) - err(1, "setsockopt(IP_IPSEC_POLICY)"); - free(buf); - } -#else /* IPSEC_POLICY_IPSEC */ - if (flags->auth) { - optval = IPSEC_LEVEL_REQUIRE; - if (setsockopt(s4, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, - &optval, sizeof(optval)) == -1) { - syslog(LOG_ERR, "<%s> IP_AUTH_TRANS_LEVEL: %s", - __func__, strerror(errno)); - exit(1); - } - } - if (flags->encrypt) { - optval = IPSEC_LEVEL_REQUIRE; - if (setsockopt(s4, IPPROTO_IP, IP_ESP_TRANS_LEVEL, - &optval, sizeof(optval)) == -1) { - syslog(LOG_ERR, "<%s> IP_ESP_TRANS_LEVEL: %s", - __func__, strerror(errno)); - exit(1); - } - } -#endif /* IPSEC_POLICY_IPSEC */ -#endif /* IPSEC */ - return; } @@ -533,23 +419,12 @@ main(int argc, char *argv[]) int ch, i, maxfd = 0, send_counter = 0; struct flags flags; struct payload_list *pl; -#ifdef IPSEC_POLICY_IPSEC - char *policy = NULL; -#endif memset(&flags, 0, sizeof(flags)); openlog("rrenumd", LOG_PID, LOG_DAEMON); /* get options */ - while ((ch = getopt(argc, argv, "c:sdf" -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - "P:" -#else /* IPSEC_POLICY_IPSEC */ - "AE" -#endif /* IPSEC_POLICY_IPSEC */ -#endif /* IPSEC */ - )) != -1){ + while ((ch = getopt(argc, argv, "c:sdf")) != -1) { switch (ch) { case 'c': if((fp = fopen(optarg, "r")) == NULL) { @@ -568,21 +443,6 @@ main(int argc, char *argv[]) case 'f': flags.fg = 1; break; -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - case 'P': - flags.policy = 1; - policy = strdup(optarg); - break; -#else /* IPSEC_POLICY_IPSEC */ - case 'A': - flags.auth = 1; - break; - case 'E': - flags.encrypt = 1; - break; -#endif /* IPSEC_POLICY_IPSEC */ -#endif /*IPSEC*/ default: show_usage(); } @@ -601,16 +461,8 @@ main(int argc, char *argv[]) config(&fp); - sock6_open(&flags -#ifdef IPSEC_POLICY_IPSEC - , policy -#endif /* IPSEC_POLICY_IPSEC */ - ); - sock4_open(&flags -#ifdef IPSEC_POLICY_IPSEC - , policy -#endif /* IPSEC_POLICY_IPSEC */ - ); + sock6_open(&flags); + sock4_open(&flags); if (!flags.fg) daemon(0, 0); diff --git a/usr.sbin/rtadvd/rtadvd.8 b/usr.sbin/rtadvd/rtadvd.8 index 6e36ad6b51..4d979aed08 100644 --- a/usr.sbin/rtadvd/rtadvd.8 +++ b/usr.sbin/rtadvd/rtadvd.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD: stable/10/usr.sbin/rtadvd/rtadvd.8 247270 2013-02-25 16:47:09Z des $ .\" -.Dd February 25, 2013 +.Dd April 21, 2018 .Dt RTADVD 8 .Os .Sh NAME @@ -154,7 +154,6 @@ The default is .Pa /var/run/rtadvd.pid . .It Fl R Accept router renumbering requests. -If you enable it, certain IPsec setup is suggested for security reasons. This option is currently disabled, and is ignored by .Nm with a warning message. diff --git a/usr.sbin/setkey/Makefile b/usr.sbin/setkey/Makefile deleted file mode 100644 index 97173c430e..0000000000 --- a/usr.sbin/setkey/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the project nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# $FreeBSD: src/usr.sbin/setkey/Makefile,v 1.1.2.5 2001/04/25 14:05:11 ru Exp $ - -PROG= setkey -SRCS= setkey.c parse.y token.l -CFLAGS+=-I${.CURDIR} -I${.CURDIR}/../../lib/libipsec -DPADD= ${LIBL} -LDADD= -ll -CLEANFILES+= y.tab.c y.tab.h key_test.o keytest -YFLAGS+=-d -WARNS?= 2 -NO_STRICT_ALIASING= - -# libpfkey. -# ipsec_strerror.c is for avoiding shlib reference to non-exported function. -.PATH: ${.CURDIR}/../../lib/libipsec ${.CURDIR}/../../sys/netproto/key -SRCS+= pfkey.c pfkey_dump.c key_debug.c ipsec_strerror.c - -SRCS+=y.tab.h -y.tab.h: parse.y -CFLAGS+=-DIPSEC_DEBUG -DINET6 -I. -DPADD+= ${LIBIPSEC} -LDADD+= -lipsec -CLEANFILES+= y.tab.h - -#SCRIPTS=scriptdump -MAN= setkey.8 - -.include diff --git a/usr.sbin/setkey/parse.y b/usr.sbin/setkey/parse.y deleted file mode 100644 index e48b2f9771..0000000000 --- a/usr.sbin/setkey/parse.y +++ /dev/null @@ -1,937 +0,0 @@ -/* $FreeBSD: src/usr.sbin/setkey/parse.y,v 1.1.2.2 2001/07/03 11:02:17 ume Exp $ */ -/* $DragonFly: src/usr.sbin/setkey/parse.y,v 1.4 2004/03/24 18:23:46 cpressey Exp $ */ -/* $KAME: kame/kame/kame/setkey/parse.y,v 1.36 2001/06/07 15:53:12 sakane Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -%{ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "libpfkey.h" -#include "vchar.h" - -#define ATOX(c) \ - (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) )) - -u_int p_type; -u_int32_t p_spi; -int p_no_spi; -struct sockaddr *p_src, *p_dst; -u_int p_prefs, p_prefd, p_upper; -u_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode; -u_int32_t p_reqid; -u_int p_key_enc_len, p_key_auth_len; -caddr_t p_key_enc, p_key_auth; -time_t p_lt_hard, p_lt_soft; - -u_int p_policy_len; -char *p_policy; - -/* temporary buffer */ -static struct sockaddr *pp_addr; -static u_int pp_prefix; -static u_int pp_port; -static caddr_t pp_key; - -extern u_char m_buf[BUFSIZ]; -extern u_int m_len; -extern char cmdarg[8192]; -extern int f_debug; - -static struct addrinfo *parse_addr(char *, char *, int); -static int setvarbuf(int *, struct sadb_ext *, int, caddr_t, int); -void parse_init(void); -void free_buffer(void); - -extern int setkeymsg(void); -extern int sendkeymsg(void); - -extern int yylex(void); -extern void yyfatal(const char *); -extern void yyerror(const char *); -%} - -%union { - unsigned long num; - vchar_t val; -} - -%token EOT -%token ADD GET DELETE DELETEALL FLUSH DUMP -%token ADDRESS PREFIX PORT PORTANY -%token UP_PROTO PR_ESP PR_AH PR_IPCOMP PR_TCP -%token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI -%token F_MODE MODE F_REQID -%token F_EXT EXTENSION NOCYCLICSEQ -%token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP -%token F_LIFETIME_HARD F_LIFETIME_SOFT -%token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY - /* SPD management */ -%token SPDADD SPDDELETE SPDDUMP SPDFLUSH -%token F_POLICY PL_REQUESTS - -%type PORT PREFIX EXTENSION MODE -%type UP_PROTO PR_ESP PR_AH PR_IPCOMP PR_TCP -%type ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP -%type DECSTRING -%type ADDRESS PL_REQUESTS -%type key_string policy_requests -%type QUOTEDSTRING HEXSTRING STRING - -%% -commands - : /*NOTHING*/ - | commands command - { - if (f_debug) { - printf("cmdarg:\n%s\n", cmdarg); - } else { - setkeymsg(); - sendkeymsg(); - } - free_buffer(); - parse_init(); - } - ; - -command - : add_command - | get_command - | delete_command - | deleteall_command - | flush_command - | dump_command - | spdadd_command - | spddelete_command - | spddump_command - | spdflush_command - ; - /* commands concerned with management, there is in tail of this file. */ - - /* add command */ -add_command - : ADD { p_type = SADB_ADD; } - sa_selector_spec extension_spec algorithm_spec EOT - ; - - /* delete */ -delete_command - : DELETE { p_type = SADB_DELETE; } - sa_selector_spec extension_spec - { - if (p_mode != IPSEC_MODE_ANY) - yyerror("WARNING: mode is obsoleted."); - } - EOT - ; - - /* deleteall command */ -deleteall_command - : DELETEALL { p_type = SADB_DELETE; } - ipaddress { p_src = pp_addr; } - ipaddress { p_dst = pp_addr; } - protocol_spec - { p_no_spi = 1; } - EOT - ; - - /* get command */ -get_command - : GET { p_type = SADB_GET; } - sa_selector_spec extension_spec - { - if (p_mode != IPSEC_MODE_ANY) - yyerror("WARNING: mode is obsoleted."); - } - EOT - ; - - /* flush */ -flush_command - : FLUSH { p_type = SADB_FLUSH; } - protocol_spec EOT - ; - - /* dump */ -dump_command - : DUMP { p_type = SADB_DUMP; } - protocol_spec EOT - ; - - /* sa_selector_spec */ -sa_selector_spec - : ipaddress { p_src = pp_addr; } - ipaddress { p_dst = pp_addr; } - protocol_spec spi - ; - -protocol_spec - : /*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; } - | PR_ESP - { - p_satype = SADB_SATYPE_ESP; - if ($1 == 1) - p_ext |= SADB_X_EXT_OLD; - else - p_ext &= ~SADB_X_EXT_OLD; - } - | PR_AH - { - p_satype = SADB_SATYPE_AH; - if ($1 == 1) - p_ext |= SADB_X_EXT_OLD; - else - p_ext &= ~SADB_X_EXT_OLD; - } - | PR_IPCOMP - { - p_satype = SADB_X_SATYPE_IPCOMP; - } - | PR_TCP - { - p_satype = SADB_X_SATYPE_TCPSIGNATURE; - } - ; - -spi - : DECSTRING { p_spi = $1; } - | HEXSTRING - { - caddr_t bp; - caddr_t yp = $1.buf; - char buf0[4], buf[4]; - int i, j; - - /* sanity check */ - if ($1.len > 4) { - yyerror("SPI too big."); - free($1.buf); - return -1; - } - - bp = buf0; - while (*yp) { - *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]); - yp += 2, bp++; - } - - /* initialize */ - for (i = 0; i < 4; i++) buf[i] = 0; - - for (j = $1.len - 1, i = 3; j >= 0; j--, i--) - buf[i] = buf0[j]; - - /* XXX: endian */ - p_spi = ntohl(*(u_int32_t *)buf); - - free($1.buf); - } - ; - -algorithm_spec - : esp_spec - | ah_spec - | ipcomp_spec - ; - -esp_spec - : F_ENC enc_alg enc_key F_AUTH auth_alg auth_key - | F_ENC enc_alg enc_key - ; - -ah_spec - : F_AUTH auth_alg auth_key - ; - -ipcomp_spec - : F_COMP ALG_COMP { p_alg_enc = $2; } - | F_COMP ALG_COMP { p_alg_enc = $2; } - F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; } - ; - -enc_alg - : ALG_ENC { p_alg_enc = $1; } - | ALG_ENC_DESDERIV - { - p_alg_enc = $1; - if (p_ext & SADB_X_EXT_OLD) { - yyerror("algorithm mismatched."); - return -1; - } - p_ext |= SADB_X_EXT_DERIV; - } - | ALG_ENC_DES32IV - { - p_alg_enc = $1; - if (!(p_ext & SADB_X_EXT_OLD)) { - yyerror("algorithm mismatched."); - return -1; - } - p_ext |= SADB_X_EXT_IV4B; - } - ; - -enc_key - : /*NOTHING*/ - { - if (p_alg_enc != SADB_EALG_NULL) { - yyerror("no key found."); - return -1; - } - } - | key_string - { - p_key_enc_len = $1.len; - p_key_enc = pp_key; - - if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT, - p_alg_enc, - PFKEY_UNUNIT64(p_key_enc_len)) < 0) { - yyerror(ipsec_strerror()); - return -1; - } - } - ; - -auth_alg - : ALG_AUTH { p_alg_auth = $1; } - ; - -auth_key - : /*NOTHING*/ - { - if (p_alg_auth != SADB_X_AALG_NULL) { - yyerror("no key found."); - return -1; - } - } - | key_string - { - p_key_auth_len = $1.len; - p_key_auth = pp_key; - - if (p_alg_auth == SADB_X_AALG_TCP_MD5) { - if ((p_key_auth_len < 1) || (p_key_auth_len > - 80)) - return -1; - } else if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH, - p_alg_auth, - PFKEY_UNUNIT64(p_key_auth_len)) < 0) { - yyerror(ipsec_strerror()); - return -1; - } - } - ; - -key_string - : QUOTEDSTRING - { - pp_key = $1.buf; - /* free pp_key later */ - } - | HEXSTRING - { - caddr_t bp; - caddr_t yp = $1.buf; - - if ((pp_key = malloc($1.len)) == 0) { - free($1.buf); - yyerror("not enough core"); - return -1; - } - memset(pp_key, 0, $1.len); - - bp = pp_key; - while (*yp) { - *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]); - yp += 2, bp++; - } - - free($1.buf); - } - ; - -extension_spec - : /*NOTHING*/ - | extension_spec extension - ; - -extension - : F_EXT EXTENSION { p_ext |= $2; } - | F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; } - | F_MODE MODE { p_mode = $2; } - | F_MODE ANY { p_mode = IPSEC_MODE_ANY; } - | F_REQID DECSTRING { p_reqid = $2; } - | F_REPLAY DECSTRING - { - if (p_ext & SADB_X_EXT_OLD) { - yyerror("replay prevention " - "only use on new spec."); - return -1; - } - p_replay = $2; - } - | F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; } - | F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; } - ; - - /* definition about command for SPD management */ - /* spdadd */ -spdadd_command - : SPDADD - { - p_type = SADB_X_SPDADD; - p_satype = SADB_SATYPE_UNSPEC; - } - sp_selector_spec policy_spec EOT - ; - -spddelete_command: - SPDDELETE - { - p_type = SADB_X_SPDDELETE; - p_satype = SADB_SATYPE_UNSPEC; - } - sp_selector_spec policy_spec EOT - ; - -spddump_command: - SPDDUMP - { - p_type = SADB_X_SPDDUMP; - p_satype = SADB_SATYPE_UNSPEC; - } - EOT - ; - -spdflush_command: - SPDFLUSH - { - p_type = SADB_X_SPDFLUSH; - p_satype = SADB_SATYPE_UNSPEC; - } - EOT - ; - - /* sp_selector_spec */ -sp_selector_spec - : ipaddress { p_src = pp_addr; } - prefix { p_prefs = pp_prefix; } - port - { - switch (p_src->sa_family) { - case AF_INET: - ((struct sockaddr_in *)p_src)->sin_port = - htons(pp_port); - break; -#ifdef INET6 - case AF_INET6: - ((struct sockaddr_in6 *)p_src)->sin6_port = - htons(pp_port); - break; -#endif - default: - exit(1); /*XXX*/ - } - } - ipaddress { p_dst = pp_addr; } - prefix { p_prefd = pp_prefix; } - port - { - switch (p_dst->sa_family) { - case AF_INET: - ((struct sockaddr_in *)p_dst)->sin_port = - htons(pp_port); - break; -#ifdef INET6 - case AF_INET6: - ((struct sockaddr_in6 *)p_dst)->sin6_port = - htons(pp_port); - break; -#endif - default: - exit(1); /*XXX*/ - } - } - upper_spec - { - /* XXX is it something userland should check? */ -#if 0 - switch (p_upper) { - case IPPROTO_ICMP: - case IPPROTO_ICMPV6: - if (_INPORTBYSA(p_src) != IPSEC_PORT_ANY - || _INPORTBYSA(p_dst) != IPSEC_PORT_ANY) { - yyerror("port number must be \"any\"."); - return -1; - } - if ((pp_addr->sa_family == AF_INET6 - && p_upper == IPPROTO_ICMP) - || (pp_addr->sa_family == AF_INET - && p_upper == IPPROTO_ICMPV6)) { - yyerror("upper layer protocol " - "mismatched.\n"); - return -1; - } - break; - default: - break; - } -#endif - } - ; - -ipaddress - : ADDRESS - { - struct addrinfo *res; - - res = parse_addr($1.buf, NULL, AI_NUMERICHOST); - if (res == NULL) { - free($1.buf); - return -1; - } - pp_addr = (struct sockaddr *)malloc(res->ai_addrlen); - if (!pp_addr) { - yyerror("not enough core"); - goto end; - } - - memcpy(pp_addr, res->ai_addr, res->ai_addrlen); - end: - freeaddrinfo(res); - free($1.buf); - } - ; - -prefix - : /*NOTHING*/ { pp_prefix = ~0; } - | PREFIX { pp_prefix = $1; } - ; - -port - : /*NOTHING*/ { pp_port = IPSEC_PORT_ANY; } - | PORT { pp_port = $1; } - | PORTANY { pp_port = IPSEC_PORT_ANY; } - ; - -upper_spec - : DECSTRING { p_upper = $1; } - | UP_PROTO { p_upper = $1; } - | ANY { p_upper = IPSEC_ULPROTO_ANY; } - | STRING - { - struct protoent *ent; - - ent = getprotobyname($1.buf); - if (ent) - p_upper = ent->p_proto; - else { - if (strcmp("icmp6", $1.buf) == 0) { - p_upper = IPPROTO_ICMPV6; - } else if(strcmp("ip4", $1.buf) == 0) { - p_upper = IPPROTO_IPV4; - } else { - yyerror("invalid upper layer protocol"); - free($1.buf); - return -1; - } - } - free($1.buf); - } - ; - -policy_spec - : F_POLICY policy_requests - { - p_policy = ipsec_set_policy($2.buf, $2.len); - if (p_policy == NULL) { - free($2.buf); - p_policy = NULL; - yyerror(ipsec_strerror()); - return -1; - } - - p_policy_len = ipsec_get_policylen(p_policy); - - free($2.buf); - } - ; - -policy_requests - : PL_REQUESTS { $$ = $1; } - ; - -%% - -int -setkeymsg(void) -{ - struct sadb_msg m_msg; - - m_msg.sadb_msg_version = PF_KEY_V2; - m_msg.sadb_msg_type = p_type; - m_msg.sadb_msg_errno = 0; - m_msg.sadb_msg_satype = p_satype; - m_msg.sadb_msg_reserved = 0; - m_msg.sadb_msg_seq = 0; - m_msg.sadb_msg_pid = getpid(); - - m_len = sizeof(struct sadb_msg); - memcpy(m_buf, &m_msg, m_len); - - switch (p_type) { - case SADB_FLUSH: - case SADB_DUMP: - break; - - case SADB_ADD: - /* set encryption algorithm, if present. */ - if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) { - struct sadb_key m_key; - - m_key.sadb_key_len = - PFKEY_UNIT64(sizeof(m_key) - + PFKEY_ALIGN8(p_key_enc_len)); - m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; - m_key.sadb_key_bits = p_key_enc_len * 8; - m_key.sadb_key_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_key, sizeof(m_key), - (caddr_t)p_key_enc, p_key_enc_len); - } - - /* set authentication algorithm, if present. */ - if (p_alg_auth != SADB_AALG_NONE) { - struct sadb_key m_key; - - m_key.sadb_key_len = - PFKEY_UNIT64(sizeof(m_key) - + PFKEY_ALIGN8(p_key_auth_len)); - m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH; - m_key.sadb_key_bits = p_key_auth_len * 8; - m_key.sadb_key_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_key, sizeof(m_key), - (caddr_t)p_key_auth, p_key_auth_len); - } - - /* set lifetime for HARD */ - if (p_lt_hard != 0) { - struct sadb_lifetime m_lt; - u_int len = sizeof(struct sadb_lifetime); - - m_lt.sadb_lifetime_len = PFKEY_UNIT64(len); - m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; - m_lt.sadb_lifetime_allocations = 0; - m_lt.sadb_lifetime_bytes = 0; - m_lt.sadb_lifetime_addtime = p_lt_hard; - m_lt.sadb_lifetime_usetime = 0; - - memcpy(m_buf + m_len, &m_lt, len); - m_len += len; - } - - /* set lifetime for SOFT */ - if (p_lt_soft != 0) { - struct sadb_lifetime m_lt; - u_int len = sizeof(struct sadb_lifetime); - - m_lt.sadb_lifetime_len = PFKEY_UNIT64(len); - m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; - m_lt.sadb_lifetime_allocations = 0; - m_lt.sadb_lifetime_bytes = 0; - m_lt.sadb_lifetime_addtime = p_lt_soft; - m_lt.sadb_lifetime_usetime = 0; - - memcpy(m_buf + m_len, &m_lt, len); - m_len += len; - } - /* FALLTHROUGH */ - - case SADB_DELETE: - case SADB_GET: - { - struct sadb_sa m_sa; - struct sadb_x_sa2 m_sa2; - struct sadb_address m_addr; - u_int len; - - if (p_no_spi == 0) { - len = sizeof(struct sadb_sa); - m_sa.sadb_sa_len = PFKEY_UNIT64(len); - m_sa.sadb_sa_exttype = SADB_EXT_SA; - m_sa.sadb_sa_spi = htonl(p_spi); - m_sa.sadb_sa_replay = p_replay; - m_sa.sadb_sa_state = 0; - m_sa.sadb_sa_auth = p_alg_auth; - m_sa.sadb_sa_encrypt = p_alg_enc; - m_sa.sadb_sa_flags = p_ext; - - memcpy(m_buf + m_len, &m_sa, len); - m_len += len; - - len = sizeof(struct sadb_x_sa2); - m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len); - m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; - m_sa2.sadb_x_sa2_mode = p_mode; - m_sa2.sadb_x_sa2_reqid = p_reqid; - - memcpy(m_buf + m_len, &m_sa2, len); - m_len += len; - } - - /* set src */ - m_addr.sadb_address_len = - PFKEY_UNIT64(sizeof(m_addr) - + PFKEY_ALIGN8(p_src->sa_len)); - m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; - m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; - switch (p_src->sa_family) { - case AF_INET: - m_addr.sadb_address_prefixlen = - sizeof(struct in_addr) << 3; - break; -#ifdef INET6 - case AF_INET6: - m_addr.sadb_address_prefixlen = - sizeof(struct in6_addr) << 3; - break; -#endif - default: - yyerror("unsupported address family"); - exit(1); /*XXX*/ - } - m_addr.sadb_address_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_addr, sizeof(m_addr), - (caddr_t)p_src, p_src->sa_len); - - /* set dst */ - m_addr.sadb_address_len = - PFKEY_UNIT64(sizeof(m_addr) - + PFKEY_ALIGN8(p_dst->sa_len)); - m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; - m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; - switch (p_dst->sa_family) { - case AF_INET: - m_addr.sadb_address_prefixlen = - sizeof(struct in_addr) << 3; - break; -#ifdef INET6 - case AF_INET6: - m_addr.sadb_address_prefixlen = - sizeof(struct in6_addr) << 3; - break; -#endif - default: - yyerror("unsupported address family"); - exit(1); /*XXX*/ - } - m_addr.sadb_address_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_addr, sizeof(m_addr), - (caddr_t)p_dst, p_dst->sa_len); - } - break; - - /* for SPD management */ - case SADB_X_SPDFLUSH: - case SADB_X_SPDDUMP: - break; - - case SADB_X_SPDADD: - case SADB_X_SPDDELETE: - { - struct sadb_address m_addr; - u_int8_t plen; - - memcpy(m_buf + m_len, p_policy, p_policy_len); - m_len += p_policy_len; - free(p_policy); - p_policy = NULL; - - /* set src */ - m_addr.sadb_address_len = - PFKEY_UNIT64(sizeof(m_addr) - + PFKEY_ALIGN8(p_src->sa_len)); - m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; - m_addr.sadb_address_proto = p_upper; - switch (p_src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; -#ifdef INET6 - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; -#endif - default: - yyerror("unsupported address family"); - exit(1); /*XXX*/ - } - m_addr.sadb_address_prefixlen = - (p_prefs != ~0 ? p_prefs : plen); - m_addr.sadb_address_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_addr, sizeof(m_addr), - (caddr_t)p_src, p_src->sa_len); - - /* set dst */ - m_addr.sadb_address_len = - PFKEY_UNIT64(sizeof(m_addr) - + PFKEY_ALIGN8(p_dst->sa_len)); - m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; - m_addr.sadb_address_proto = p_upper; - switch (p_dst->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; -#ifdef INET6 - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; -#endif - default: - yyerror("unsupported address family"); - exit(1); /*XXX*/ - } - m_addr.sadb_address_prefixlen = - (p_prefd != ~0 ? p_prefd : plen); - m_addr.sadb_address_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_addr, sizeof(m_addr), - (caddr_t)p_dst, p_dst->sa_len); - } - break; - } - - ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len); - - return 0; -} - -static struct addrinfo * -parse_addr(char *host, char *port, int flag) -{ - struct addrinfo hints, *res = NULL; - int error; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = flag; - error = getaddrinfo(host, port, &hints, &res); - if (error != 0) { - yyerror(gai_strerror(error)); - return NULL; - } - if (res->ai_next != NULL) { - yyerror(gai_strerror(error)); - } - return res; -} - -static int -setvarbuf(int *off, struct sadb_ext *ebuf, int elen, caddr_t vbuf, int vlen) -{ - memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len)); - memcpy(m_buf + *off, (caddr_t)ebuf, elen); - memcpy(m_buf + *off + elen, vbuf, vlen); - (*off) += PFKEY_ALIGN8(elen + vlen); - - return 0; -} - -void -parse_init(void) -{ - p_type = 0; - p_spi = 0; - p_no_spi = 0; - - p_src = 0, p_dst = 0; - pp_prefix = p_prefs = p_prefd = ~0; - pp_port = IPSEC_PORT_ANY; - p_upper = 0; - - p_satype = 0; - p_ext = SADB_X_EXT_CYCSEQ; - p_alg_enc = SADB_EALG_NONE; - p_alg_auth = SADB_AALG_NONE; - p_mode = IPSEC_MODE_ANY; - p_reqid = 0; - p_replay = 0; - p_key_enc_len = p_key_auth_len = 0; - p_key_enc = p_key_auth = 0; - p_lt_hard = p_lt_soft = 0; - - p_policy_len = 0; - p_policy = NULL; - - memset(cmdarg, 0, sizeof(cmdarg)); - - return; -} - -void -free_buffer(void) -{ - if (p_src) free(p_src); - if (p_dst) free(p_dst); - if (p_key_enc) free(p_key_enc); - if (p_key_auth) free(p_key_auth); - - return; -} - diff --git a/usr.sbin/setkey/sample.cf b/usr.sbin/setkey/sample.cf deleted file mode 100644 index 2ea439ed66..0000000000 --- a/usr.sbin/setkey/sample.cf +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the project nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# $FreeBSD: src/usr.sbin/setkey/sample.cf,v 1.1.2.1 2000/07/15 07:37:03 kris Exp $ -# $DragonFly: src/usr.sbin/setkey/sample.cf,v 1.2 2003/06/17 04:30:03 dillon Exp $ - -# There are sample scripts for IPsec configuration by manual keying. -# A security association is uniquely identified by a triple consisting -# of a Security Parameter Index (SPI), an IP Destination Address, and a -# security protocol (AH or ESP) identifier. You must take care of these -# parameters when you configure by manual keying. - -# ESP transport mode is recommended for TCP port number 110 between -# Host-A and Host-B. Encryption algorithm is blowfish-cbc whose key -# is "kamekame", and authentication algorithm is hmac-sha1 whose key -# is "this is the test key". -# -# ============ ESP ============ -# | | -# Host-A Host-B -# fec0::10 -------------------- fec0::11 -# -# At Host-A and Host-B, -spdadd fec0::10[any] fec0::11[110] tcp -P out ipsec - esp/transport/fec0::10-fec0::11/use ; -spdadd fec0::11[110] fec0::10[any] tcp -P in ipsec - esp/transport/fec0::11-fec0::10/use ; -add fec0::10 fec0::11 esp 0x10001 - -m transport - -E blowfish-cbc "kamekame" - -A hmac-sha1 "this is the test key" ; -add fec0::11 fec0::10 esp 0x10002 - -m transport - -E blowfish-cbc "kamekame" - -A hmac-sha1 "this is the test key" ; - -# "[any]" is wildcard of port number. Note that "[0]" is the number of -# zero in port number. - -# Security protocol is old AH tunnel mode, i.e. RFC1826, with keyed-md5 -# whose key is "this is the test" as authentication algorithm. -# That protocol takes place between Gateway-A and Gateway-B. -# -# ======= AH ======= -# | | -# Network-A Gateway-A Gateway-B Network-B -# 10.0.1.0/24 ---- 172.16.0.1 ----- 172.16.0.2 ---- 10.0.2.0/24 -# -# At Gateway-A: -spdadd 10.0.1.0/24 10.0.2.0/24 any -P out ipsec - ah/tunnel/172.16.0.1-172.16.0.2/require ; -spdadd 10.0.2.0/24 10.0.1.0/24 any -P in ipsec - ah/tunnel/172.16.0.2-172.16.0.1/require ; -add 172.16.0.1 172.16.0.2 ah-old 0x10003 - -m any - -A keyed-md5 "this is the test" ; -add 172.16.0.2 172.16.0.1 ah-old 0x10004 - -m any - -A keyed-md5 "this is the test" ; - -# If port number field is omitted such above then "[any]" is employed. -# -m specifies the mode of SA to be used. "-m any" means wildcard of -# mode of security protocol. You can use this SAs for both tunnel and -# transport mode. - -# At Gateway-B. Attention to the selector and peer's IP address for tunnel. -spdadd 10.0.2.0/24 10.0.1.0/24 any -P out ipsec - ah/tunnel/172.16.0.2-172.16.0.1/require ; -spdadd 10.0.1.0/24 10.0.2.0/24 any -P in ipsec - ah/tunnel/172.16.0.1-172.16.0.2/require ; -add 172.16.0.1 172.16.0.2 ah-old 0x10003 - -m tunnel - -A keyed-md5 "this is the test" ; -add 172.16.0.2 172.16.0.1 ah-old 0x10004 - -m tunnel - -A keyed-md5 "this is the test" ; - -# AH transport mode followed by ESP tunnel mode is required between -# Gateway-A and Gateway-B. -# Encryption algorithm is 3des-cbc, and authentication algorithm for ESP -# is hmac-sha1. Authentication algorithm for AH is hmac-md5. -# -# ========== AH ========= -# | ======= ESP ===== | -# | | | | -# Network-A Gateway-A Gateway-B Network-B -# fec0:0:0:1::/64 --- fec0:0:0:1::1 ---- fec0:0:0:2::1 --- fec0:0:0:2::/64 -# -# At Gateway-A: -spdadd fec0:0:0:1::/64 fec0:0:0:2::/64 any -P out ipsec - esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require - ah/transport/fec0:0:0:1::1-fec0:0:0:2::1/require ; -spdadd fec0:0:0:2::/64 fec0:0:0:1::/64 any -P in ipsec - esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require - ah/transport/fec0:0:0:2::1-fec0:0:0:1::1/require ; -add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10001 - -m tunnel - -E 3des-cbc "kamekame12341234kame1234" - -A hmac-sha1 "this is the test key" ; -add fec0:0:0:1::1 fec0:0:0:2::1 ah 0x10001 - -m transport - -A hmac-md5 "this is the test" ; -add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10001 - -m tunnel - -E 3des-cbc "kamekame12341234kame1234" - -A hmac-sha1 "this is the test key" ; -add fec0:0:0:2::1 fec0:0:0:1::1 ah 0x10001 - -m transport - -A hmac-md5 "this is the test" ; - -# ESP tunnel mode is required between Host-A and Gateway-A. -# Encryption algorithm is cast128-cbc, and authentication algorithm -# for ESP is hmac-sha1. -# ESP transport mode is recommended between Host-A and Host-B. -# Encryption algorithm is rc5-cbc, and authentication algorithm -# for ESP is hmac-md5. -# -# ================== ESP ================= -# | ======= ESP ======= | -# | | | | -# Host-A Gateway-A Host-B -# fec0:0:0:1::1 ---- fec0:0:0:2::1 ---- fec0:0:0:2::2 -# -# At Host-A: -spdadd fec0:0:0:1::1[any] fec0:0:0:2::2[80] tcp -P out ipsec - esp/transport/fec0:0:0:1::1-fec0:0:0:2::2/use - esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require ; -spdadd fec0:0:0:2::1[80] fec0:0:0:1::1[any] tcp -P in ipsec - esp/transport/fec0:0:0:2::2-fec0:0:0:1::1/use - esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require ; -add fec0:0:0:1::1 fec0:0:0:2::2 esp 0x10001 - -m transport - -E cast128-cbc "12341234" - -A hmac-sha1 "this is the test key" ; -add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10002 - -E rc5-cbc "kamekame" - -A hmac-md5 "this is the test" ; -add fec0:0:0:2::2 fec0:0:0:1::1 esp 0x10003 - -m transport - -E cast128-cbc "12341234" - -A hmac-sha1 "this is the test key" ; -add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10004 - -E rc5-cbc "kamekame" - -A hmac-md5 "this is the test" ; - -# By "get" command, you can get a entry of either SP or SA. -get fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ; - -# Also delete command, you can delete a entry of either SP or SA. -spddelete fec0:0:0:1::/64 fec0:0:0:2::/64 any -P out; -delete fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ; - -# By dump command, you can dump all entry of either SP or SA. -dump ; -spddump ; -dump esp ; -flush esp ; - -# By flush command, you can flush all entry of either SP or SA. -flush ; -spdflush ; - -# "flush" and "dump" commands can specify a security protocol. -dump esp ; -flush ah ; - -# XXX -add ::1 ::1 esp 10001 -m transport -E simple ; -add ::1 ::1 esp 10002 -m transport -E des-deriv "12341234" ; -add ::1 ::1 esp-old 10003 -m transport -E des-32iv "12341234" ; -add ::1 ::1 esp 10004 -m transport -E simple -A null ; -add ::1 ::1 esp 10005 -m transport -E simple -A hmac-md5 "1234123412341234" ; -add ::1 ::1 esp 10006 -m tunnel -E simple -A hmac-sha1 "12341234123412341234" ; -add ::1 ::1 esp 10007 -m transport -E simple -A keyed-md5 "1234123412341234" ; -add ::1 ::1 esp 10008 -m any -E simple -A keyed-sha1 "12341234123412341234" ; -add ::1 ::1 esp 10009 -m transport -E des-cbc "testtest" ; -add ::1 ::1 esp 10010 -m transport -E 3des-cbc "testtest12341234testtest" ; -add ::1 ::1 esp 10011 -m tunnel -E cast128-cbc "testtest1234" ; -add ::1 ::1 esp 10012 -m tunnel -E blowfish-cbc "testtest1234" ; -add ::1 ::1 esp 10013 -m tunnel -E rc5-cbc "testtest1234" ; -add ::1 ::1 esp 10014 -m any -E rc5-cbc "testtest1234" ; -add ::1 ::1 esp 10015 -m transport -f zero-pad -E simple ; -add ::1 ::1 esp 10016 -m tunnel -f random-pad -r 8 -lh 100 -ls 80 -E simple ; -add ::1 ::1 esp 10017 -m transport -f seq-pad -f nocyclic-seq -E simple ; -add ::1 ::1 esp 10018 -m transport -E simple ; -#add ::1 ::1 ah 20000 -m transport -A null ; -add ::1 ::1 ah 20001 -m any -A hmac-md5 "1234123412341234"; -add ::1 ::1 ah 20002 -m tunnel -A hmac-sha1 "12341234123412341234"; -add ::1 ::1 ah 20003 -m transport -A keyed-md5 "1234123412341234"; -add ::1 ::1 ah-old 20004 -m transport -A keyed-md5 "1234123412341234"; -add ::1 ::1 ah 20005 -m transport -A keyed-sha1 "12341234123412341234"; -#add ::1 ::1 ipcomp 30000 -C oui ; -add ::1 ::1 ipcomp 30001 -C deflate ; -#add ::1 ::1 ipcomp 30002 -C lzs ; - -# enjoy. diff --git a/usr.sbin/setkey/scriptdump b/usr.sbin/setkey/scriptdump deleted file mode 100644 index 87fb201a18..0000000000 --- a/usr.sbin/setkey/scriptdump +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env perl -# $FreeBSD: src/usr.sbin/setkey/scriptdump.pl,v 1.1.2.3 2001/10/24 19:49:16 ume Exp $ - -if ($< != 0) { - print STDERR "must be root to invoke this\n"; - exit 1; -} - -$mode = 'add'; -while ($i = shift @ARGV) { - if ($i eq '-d') { - $mode = 'delete'; - } else { - print STDERR "usage: scriptdump [-d]\n"; - exit 1; - } -} - -open(IN, "setkey -D |") || die; -foreach $_ () { - if (/^[^\t]/) { - ($src, $dst) = split(/\s+/, $_); - } elsif (/^\t(esp|ah) mode=(\S+) spi=(\d+).*reqid=(\d+)/) { - ($proto, $ipsecmode, $spi, $reqid) = ($1, $2, $3, $4); - } elsif (/^\tE: (\S+) (.*)/) { - $ealgo = $1; - $ekey = $2; - $ekey =~ s/\s//g; - $ekey =~ s/^/0x/g; - } elsif (/^\tA: (\S+) (.*)/) { - $aalgo = $1; - $akey = $2; - $akey =~ s/\s//g; - $akey =~ s/^/0x/g; - } elsif (/^\tseq=(0x\d+) replay=(\d+) flags=(0x\d+) state=/) { - print "$mode $src $dst $proto $spi"; - $replay = $2; - print " -u $reqid" if $reqid; - if ($mode eq 'add') { - print " -m $ipsecmode -r $replay" if $replay; - if ($proto eq 'esp') { - print " -E $ealgo $ekey" if $ealgo; - print " -A $aalgo $akey" if $aalgo; - } elsif ($proto eq 'ah') { - print " -A $aalgo $akey" if $aalgo; - } - } - print ";\n"; - - $src = $dst = $upper = $proxy = ''; - $ealgo = $ekey = $aalgo = $akey = ''; - } -} -close(IN); - -exit 0; diff --git a/usr.sbin/setkey/setkey.8 b/usr.sbin/setkey/setkey.8 deleted file mode 100644 index 119f54e2d0..0000000000 --- a/usr.sbin/setkey/setkey.8 +++ /dev/null @@ -1,627 +0,0 @@ -.\" $KAME: setkey.8,v 1.49 2001/05/18 05:49:51 sakane Exp $ -.\" $FreeBSD: src/usr.sbin/setkey/setkey.8,v 1.4.2.15 2003/03/12 22:08:15 trhodes Exp $ -.\" -.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. -.\" -.Dd November 20, 2000 -.Dt SETKEY 8 -.Os -.\" -.Sh NAME -.Nm setkey -.Nd "manually manipulate the IPsec SA/SP database" -.\" -.Sh SYNOPSIS -.Nm -.Op Fl dv -.Fl c -.Nm -.Op Fl dv -.Fl f Ar filename -.Nm -.Op Fl adPlv -.Fl D -.Nm -.Op Fl dPv -.Fl F -.Nm -.Op Fl h -.Fl x -.\" -.Sh DESCRIPTION -The -.Nm -utility adds, updates, dumps, or flushes -Security Association Database (SAD) entries -as well as Security Policy Database (SPD) entries in the kernel. -.Pp -The -.Nm -utility takes a series of operations from the standard input -(if invoked with -.Fl c ) -or the file named -.Ar filename -(if invoked with -.Fl f Ar filename ) . -.Bl -tag -width Ds -.It Fl D -Dump the SAD entries. -If with -.Fl P , -the SPD entries are dumped. -.It Fl F -Flush the SAD entries. -If with -.Fl P , -the SPD entries are flushed. -.It Fl a -Dead SAD entries are usually not displayed with -.Fl D . -If with -.Fl a , -the dead SAD entries will be displayed as well. -A dead SAD entry means that -it has been expired but remains -because it is referenced by SPD entries. -.It Fl d -Enable to print debugging messages for command parser, -without talking to kernel. -It is not used usually. -.It Fl x -Loop forever and dump all the messages transmitted to -.Dv PF_KEY -socket. -.Fl xx -makes each timestamp unformatted. -.It Fl h -Add hexadecimal dump on -.Fl x -mode. -.It Fl l -Loop forever with short output on -.Fl D . -.It Fl v -Be verbose. -The program will dump messages exchanged on -.Dv PF_KEY -socket, including messages sent from other processes to the kernel. -.El -.Pp -Operations have the following grammar. -Note that lines starting with -hashmarks ('#') are treated as comment lines. -.Bl -tag -width Ds -.It Xo -.Li add -.Ar src Ar dst Ar protocol Ar spi -.Op Ar extensions -.Ar algorithm... -.Li \&; -.Xc -Add an SAD entry. -.\" -.It Xo -.Li get -.Ar src Ar dst Ar protocol Ar spi -.Li \&; -.Xc -Show an SAD entry. -.\" -.It Xo -.Li delete -.Ar src Ar dst Ar protocol Ar spi -.Li \&; -.Xc -Remove an SAD entry. -.\" -.It Xo -.Li deleteall -.Ar src Ar dst Ar protocol -.Li \&; -.Xc -Remove all SAD entries that match the specification. -.\" -.It Xo -.Li flush -.Op Ar protocol -.Li \&; -.Xc -Clear all SAD entries matched by the options. -.\" -.It Xo -.Li dump -.Op Ar protocol -.Li \&; -.Xc -Dumps all SAD entries matched by the options. -.\" -.It Xo -.Li spdadd -.Ar src_range Ar dst_range Ar upperspec Ar policy -.Li \&; -.Xc -Add an SPD entry. -.\" -.It Xo -.Li spddelete -.Ar src_range Ar dst_range Ar upperspec Fl P Ar direction -.Li \&; -.Xc -Delete an SPD entry. -.\" -.It Xo -.Li spdflush -.Li \&; -.Xc -Clear all SPD entries. -.\" -.It Xo -.Li spddump -.Li \&; -.Xc -Dumps all SPD entries. -.El -.\" -.Pp -Meta-arguments are as follows: -.Pp -.Bl -tag -compact -width Ds -.It Ar src -.It Ar dst -Source/destination of the secure communication is specified as -IPv4/v6 address. -The -.Nm -utility does not consult hostname-to-address for arguments -.Ar src -and -.Ar dst . -They must be in numeric form. -.\" -.Pp -.It Ar protocol -.Ar protocol -is one of following: -.Bl -tag -width Fl -compact -.It Li esp -ESP based on rfc2405 -.It Li esp-old -ESP based on rfc1827 -.It Li ah -AH based on rfc2402 -.It Li ah-old -AH based on rfc1826 -.It Li ipcomp -IPCOMP -.It Li tcp -TCP-MD5 based on rfc2385 -.El -.\" -.Pp -.It Ar spi -Security Parameter Index (SPI) for the SAD and the SPD. -It must be decimal number or hexadecimal number -You cannot use the set of SPI values in the range 0 through 255. -(with -.Li 0x -attached). -TCP-MD5 associations must use 0x1000 and therefore only have per-host -granularity at this time. -.\" -.Pp -.It Ar extensions -takes some of the following: -.Bl -tag -width Fl -compact -.\" -.It Fl m Ar mode -Specify a security protocol mode for use. -.Ar mode -is one of following: -.Li transport , tunnel -or -.Li any . -The default value is -.Li any . -.\" -.It Fl r Ar size -Specify window size of bytes for replay prevention. -.Ar size -must be decimal number in 32-bit word. -If -.Ar size -is zero or not specified, replay check don't take place. -.\" -.It Fl u Ar id -Specify the identifier of the policy entry in SPD. -See -.Ar policy . -.\" -.It Fl f Ar pad_option -defines the content of the ESP padding. -.Ar pad_option -is one of following: -.Bl -tag -width random-pad -compact -.It Li zero-pad -All of the padding are zero. -.It Li random-pad -A series of randomized values are set. -.It Li seq-pad -A series of sequential increasing numbers started from 1 are set. -.El -.\" -.It Fl f Li nocyclic-seq -Don't allow cyclic sequence number. -.\" -.It Fl lh Ar time -.It Fl ls Ar time -Specify hard/soft life time duration of the SA. -.El -.\" -.Pp -.It Ar algorithm -.Bl -tag -width Fl -compact -.It Fl E Ar ealgo Ar key -Specify an encryption algorithm. -.It Fl A Ar aalgo Ar key -Specify an authentication algorithm. -If -.Fl A -is used with -.Ar protocol Li esp , -it will be treated as ESP payload authentication algorithm. -.It Fl C Ar calgo Op Fl R -Specify compression algorithm. -If -.Fl R -is not specified with -.Li ipcomp -line, the kernel will use well-known IPComp CPI -(compression parameter index) -on IPComp CPI field on packets, and -.Ar spi -field will be ignored. -.Ar spi -field is only for kernel internal use in this case. -.\"Therefore, compression protocol number will appear on IPComp CPI field. -If -.Fl R -is used, -the value on -.Ar spi -field will appear on IPComp CPI field on outgoing packets. -.Ar spi -field needs to be smaller than -.Li 0x10000 -in this case. -.El -.Pp -.Ar protocol Li esp -accepts -.Fl E -and -.Fl A . -.Ar protocol Li esp-old -accepts -.Fl E -only. -.Ar protocol Li ah -and -.Li ah-old -accept -.Fl A -only. -.Ar protocol Li ipcomp -accepts -.Fl C -only. -.Pp -.Ar key -must be double-quoted character string or series of hexadecimal digits. -.Pp -Possible values for -.Ar ealgo , -.Ar aalgo -and -.Ar calgo -are specified in separate section. -.\" -.Pp -.It Ar src_range -.It Ar dst_range -These are selections of the secure communication specified as -IPv4/v6 address or IPv4/v6 address range, and it may accompany -TCP/UDP port specification. -This takes the following form: -.Bd -literal -.Ar address -.Ar address/prefixlen -.Ar address[port] -.Ar address/prefixlen[port] -.Ed -.Pp -.Ar prefixlen -and -.Ar port -must be decimal number. -The square bracket around -.Ar port -is really necessary. -They are not manpage metacharacters. -.Pp -The -.Nm -utility does not consult hostname-to-address for arguments -.Ar src -and -.Ar dst . -They must be in numeric form. -.\" -.Pp -.It Ar upperspec -Upper-layer protocol to be used. -You can use one of words in -.Pa /etc/protocols -as -.Ar upperspec . -Or -.Li icmp6 , -.Li ip4 , -and -.Li any -can be specified. -.Li any -stands for -.Dq any protocol . -Also you can use the protocol number. -.Pp -NOTE: -.Ar upperspec -does not work against forwarding case at this moment, -as it requires extra reassembly at forwarding node -(not implemented at this moment). -We have many protocols in -.Pa /etc/protocols , -but protocols except of TCP, UDP and ICMP may not be suitable to use with IPsec. -You have to consider and be careful to use them. -.Li icmp -.Li tcp -.Li udp -all protocols -.\" -.Pp -.It Ar policy -.Ar policy -is the one of following: -.Bd -literal -.Xo -.Fl P Ar direction Li discard -.Xc -.Xo -.Fl P Ar direction Li none -.Xc -.Xo -.Fl P Ar direction Li ipsec Ar protocol/mode/src-dst/level -.Xc -.Ed -.Pp -You must specify the direction of its policy as -.Ar direction . -Either -.Li out -or -.Li in -are used. -.Li discard -means the packet matching indexes will be discarded. -.Li none -means that IPsec operation will not take place onto the packet. -.Li ipsec -means that IPsec operation will take place onto the packet. -Either -.Li ah , -.Li esp -or -.Li ipcomp -is to be set as -.Ar protocol . -.Ar mode -is either -.Li transport -or -.Li tunnel . -If -.Ar mode -is -.Li tunnel , -you must specify the end-points addresses of the SA as -.Ar src -and -.Ar dst -with -.Sq - -between these addresses which is used to specify the SA to use. -If -.Ar mode -is -.Li transport , -both -.Ar src -and -.Ar dst -can be omitted. -.Ar level -is to be one of the following: -.Li default , use , require -or -.Li unique . -If the SA is not available in every level, the kernel will request -getting SA to the key exchange daemon. -.Li default -means the kernel consults to the system wide default against protocol you -specified, e.g.\& -.Li esp_trans_deflev -sysctl variable, when the kernel processes the packet. -.Li use -means that the kernel use a SA if it's available, -otherwise the kernel keeps normal operation. -.Li require -means SA is required whenever the kernel sends a packet matched -with the policy. -.Li unique -is the same to require. -In addition, it allows the policy to bind with the unique out-bound SA. -If you use the SA by manual keying, -you can put the decimal number as the policy identifier after -.Li unique -separated by colon -.Sq \: -like the following; -.Li unique:number . -.Li number -must be between 1 and 32767. -It corresponds to -.Ar extensions Fl u . -.Pp -Note that -.Dq Li discard -and -.Dq Li none -are not in the syntax described in -.Xr ipsec_set_policy 3 . -There are little differences in the syntax. -See -.Xr ipsec_set_policy 3 -for detail. -.El -.\" -.Sh ALGORITHMS -The following list shows the supported algorithms. -.Sy protocol -and -.Sy algorithm -are almost orthogonal. -Followings are the list of authentication algorithms that can be used as -.Ar aalgo -in -.Fl A Ar aalgo -of -.Ar protocol -parameter: -.Bd -literal -offset indent -algorithm keylen (bits) comment -hmac-md5 128 ah: rfc2403 - 128 ah-old: rfc2085 -hmac-sha1 160 ah: rfc2404 - 160 ah-old: 128bit ICV (no document) -keyed-md5 128 ah: 96bit ICV (no document) - 128 ah-old: rfc1828 -keyed-sha1 160 ah: 96bit ICV (no document) - 160 ah-old: 128bit ICV (no document) -null 0 to 2048 for debugging -hmac-sha2-256 256 ah: 96bit ICV (no document) - 256 ah-old: 128bit ICV (no document) -hmac-sha2-384 384 ah: 96bit ICV (no document) - 384 ah-old: 128bit ICV (no document) -hmac-sha2-512 512 ah: 96bit ICV (no document) - 512 ah-old: 128bit ICV (no document) -tcp-md5 8 to 640 tcp: rfc2385 -.Ed -.Pp -Followings are the list of encryption algorithms that can be used as -.Ar ealgo -in -.Fl E Ar ealgo -of -.Ar protocol -parameter: -.Bd -literal -offset indent -algorithm keylen (bits) comment -des-cbc 64 esp-old: rfc1829, esp: rfc2405 -3des-cbc 192 rfc2451 -simple 0 to 2048 rfc2410 -blowfish-cbc 40 to 448 rfc2451 -cast128-cbc 40 to 128 rfc2451 -des-deriv 64 ipsec-ciph-des-derived-01 (expired) -3des-deriv 192 no document -rijndael-cbc 128/192/256 draft-ietf-ipsec-ciph-aes-cbc-00 -.Ed -.Pp -Followings are the list of compression algorithms that can be used as -.Ar calgo -in -.Fl C Ar calgo -of -.Ar protocol -parameter: -.Bd -literal -offset indent -algorithm comment -deflate rfc2394 -lzs rfc2395 -.Ed -.\" -.Sh EXIT STATUS -.Ex -std -.\" -.Sh EXAMPLES -.Bd -literal -add 2001:db8:4819::1 2001:db8:481d::1 esp 123457 - -E des-cbc "ESP SA!!" ; - -add 2001:db8:4819::1 2001:db8:481d::1 ah 123456 - -A hmac-sha1 "AH SA configuration!" ; - -add 10.0.11.41 10.0.11.33 esp 0x10001 - -E des-cbc "ESP with" - -A hmac-md5 "authentication!!" ; - -get 2001:db8:4819::1 2001:db8:481d::1 ah 123456 ; - -flush ; - -dump esp ; - -spdadd 10.0.11.41/32[21] 10.0.11.33/32[any] any - -P out ipsec esp/tunnel/192.168.0.1-192.168.1.2/require ; - -add 10.1.10.34 10.1.10.36 tcp 0x1000 -A tcp-md5 "TCP-MD5 BGP secret" ; - -.Ed -.\" -.Sh SEE ALSO -.Xr ipsec_set_policy 3 , -.Xr racoon 8 , -.Xr sysctl 8 -.\" -.Sh HISTORY -The -.Nm -utility first appeared in WIDE Hydrangea IPv6 protocol stack kit. -The command was completely re-designed in June 1998. -.\" -.\" .Sh BUGS diff --git a/usr.sbin/setkey/setkey.c b/usr.sbin/setkey/setkey.c deleted file mode 100644 index 55e3445cb3..0000000000 --- a/usr.sbin/setkey/setkey.c +++ /dev/null @@ -1,635 +0,0 @@ -/* $FreeBSD: src/usr.sbin/setkey/setkey.c,v 1.1.2.3 2003/04/26 23:53:54 sumikawa Exp $ */ -/* $KAME: setkey.c,v 1.18 2001/05/08 04:36:39 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libpfkey.h" - -void Usage(void) __dead2; -int get_supported(void); -void sendkeyshort(u_int); -void promisc(void) __dead2; -int sendkeymsg(void); -int postproc(struct sadb_msg *, int); -const char *numstr(int); -void shortdump_hdr(void); -void shortdump(struct sadb_msg *); -static void printdate(void); -static int32_t gmt2local(time_t); - -#define MODE_SCRIPT 1 -#define MODE_CMDDUMP 2 -#define MODE_CMDFLUSH 3 -#define MODE_PROMISC 4 - -int so; - -int f_forever = 0; -int f_all = 0; -int f_debug = 0; -int f_verbose = 0; -int f_mode = 0; -int f_cmddump = 0; -int f_policy = 0; -int f_hexdump = 0; -int f_tflag = 0; -char *pname; - -u_char m_buf[BUFSIZ]; -u_int m_len; - -static time_t thiszone; - -extern int lineno; - -extern int parse(FILE **); - -void -Usage(void) -{ - printf("Usage:\t%s [-dv] -c\n", pname); - printf("\t%s [-dv] -f (file)\n", pname); - printf("\t%s [-Padlv] -D\n", pname); - printf("\t%s [-Pdv] -F\n", pname); - printf("\t%s [-h] -x\n", pname); - pfkey_close(so); - exit(1); -} - -int -main(int argc, char **argv) -{ - FILE *fp = stdin; - int c; - - pname = *argv; - - if (argc == 1) Usage(); - - thiszone = gmt2local(0); - - while ((c = getopt(argc, argv, "acdf:hlvxDFP")) != -1) { - switch (c) { - case 'c': - f_mode = MODE_SCRIPT; - fp = stdin; - break; - case 'f': - f_mode = MODE_SCRIPT; - if ((fp = fopen(optarg, "r")) == NULL) { - err(-1, "fopen"); - /*NOTREACHED*/ - } - break; - case 'D': - f_mode = MODE_CMDDUMP; - break; - case 'F': - f_mode = MODE_CMDFLUSH; - break; - case 'a': - f_all = 1; - break; - case 'l': - f_forever = 1; - break; - case 'h': - f_hexdump = 1; - break; - case 'x': - f_mode = MODE_PROMISC; - f_tflag++; - break; - case 'P': - f_policy = 1; - break; - case 'd': - f_debug = 1; - break; - case 'v': - f_verbose = 1; - break; - default: - Usage(); - /*NOTREACHED*/ - } - } - - switch (f_mode) { - case MODE_CMDDUMP: - sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP); - break; - case MODE_CMDFLUSH: - sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH); - pfkey_close(so); - break; - case MODE_SCRIPT: - if (get_supported() < 0) { - errx(-1, "%s", ipsec_strerror()); - /*NOTREACHED*/ - } - if (parse(&fp)) - exit (1); - break; - case MODE_PROMISC: - promisc(); - /*NOTREACHED*/ - default: - Usage(); - /*NOTREACHED*/ - } - - exit(0); -} - -int -get_supported(void) -{ - int so; - - if ((so = pfkey_open()) < 0) { - perror("pfkey_open"); - return -1; - } - - /* debug mode ? */ - if (f_debug) - return 0; - - if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0) - return -1; - - if (pfkey_recv_register(so) < 0) - return -1; - - return 0; -} - -void -sendkeyshort(u_int type) -{ - struct sadb_msg *m_msg = (struct sadb_msg *)m_buf; - - m_len = sizeof(struct sadb_msg); - - m_msg->sadb_msg_version = PF_KEY_V2; - m_msg->sadb_msg_type = type; - m_msg->sadb_msg_errno = 0; - m_msg->sadb_msg_satype = SADB_SATYPE_UNSPEC; - m_msg->sadb_msg_len = PFKEY_UNIT64(m_len); - m_msg->sadb_msg_reserved = 0; - m_msg->sadb_msg_seq = 0; - m_msg->sadb_msg_pid = getpid(); - - sendkeymsg(); -} - -void -promisc(void) -{ - struct sadb_msg *m_msg = (struct sadb_msg *)m_buf; - u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ - int so, len; - - m_len = sizeof(struct sadb_msg); - - m_msg->sadb_msg_version = PF_KEY_V2; - m_msg->sadb_msg_type = SADB_X_PROMISC; - m_msg->sadb_msg_errno = 0; - m_msg->sadb_msg_satype = 1; - m_msg->sadb_msg_len = PFKEY_UNIT64(m_len); - m_msg->sadb_msg_reserved = 0; - m_msg->sadb_msg_seq = 0; - m_msg->sadb_msg_pid = getpid(); - - if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { - err(1, "socket(PF_KEY)"); - /*NOTREACHED*/ - } - - if ((len = send(so, m_buf, m_len, 0)) < 0) { - err(1, "send"); - /*NOTREACHED*/ - } - - while (1) { - struct sadb_msg *base; - - if ((len = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { - err(1, "recv"); - /*NOTREACHED*/ - } - - if (len != sizeof(*base)) - continue; - - base = (struct sadb_msg *)rbuf; - if ((len = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), - 0)) < 0) { - err(1, "recv"); - /*NOTREACHED*/ - } - printdate(); - if (f_hexdump) { - int i; - for (i = 0; i < len; i++) { - if (i % 16 == 0) - printf("%08x: ", i); - printf("%02x ", rbuf[i] & 0xff); - if (i % 16 == 15) - printf("\n"); - } - if (len % 16) - printf("\n"); - } - /* adjust base pointer for promisc mode */ - if (base->sadb_msg_type == SADB_X_PROMISC) { - if (sizeof(*base) < len) - base++; - else - base = NULL; - } - if (base) { - kdebug_sadb(base); - printf("\n"); - fflush(stdout); - } - } -} - -int -sendkeymsg(void) -{ - int so; - u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ - int len; - struct sadb_msg *msg; - struct timeval tv; - - if ((so = pfkey_open()) < 0) { - perror("pfkey_open"); - return -1; - } - - tv.tv_sec = 1; - tv.tv_usec = 0; - if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { - perror("setsockopt"); - goto end; - } - - if (f_forever) - shortdump_hdr(); -again: - if (f_verbose) { - kdebug_sadb((struct sadb_msg *)m_buf); - printf("\n"); - } - - if ((len = send(so, m_buf, m_len, 0)) < 0) { - perror("send"); - goto end; - } - - msg = (struct sadb_msg *)rbuf; - do { - if ((len = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { - perror("recv"); - goto end; - } - - if (PFKEY_UNUNIT64(msg->sadb_msg_len) != len) { - warnx("invalid keymsg length"); - break; - } - - if (f_verbose) { - kdebug_sadb((struct sadb_msg *)rbuf); - printf("\n"); - } - if (postproc(msg, len) < 0) - break; - } while (msg->sadb_msg_errno || msg->sadb_msg_seq); - - if (f_forever) { - fflush(stdout); - sleep(1); - goto again; - } - -end: - pfkey_close(so); - return(0); -} - -int -postproc(struct sadb_msg *msg, int len) -{ - if (msg->sadb_msg_errno != 0) { - char inf[80]; - char *errmsg = NULL; - - if (f_mode == MODE_SCRIPT) - snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); - else - inf[0] = '\0'; - - switch (msg->sadb_msg_errno) { - case ENOENT: - switch (msg->sadb_msg_type) { - case SADB_DELETE: - case SADB_GET: - case SADB_X_SPDDELETE: - errmsg = "No entry"; - break; - case SADB_DUMP: - errmsg = "No SAD entries"; - break; - case SADB_X_SPDDUMP: - errmsg = "No SPD entries"; - break; - } - break; - default: - errmsg = strerror(msg->sadb_msg_errno); - } - printf("%s%s.\n", inf, errmsg); - return(-1); - } - - switch (msg->sadb_msg_type) { - case SADB_GET: - pfkey_sadump(msg); - break; - - case SADB_DUMP: - /* filter out DEAD SAs */ - if (!f_all) { - caddr_t mhp[SADB_EXT_MAX + 1]; - struct sadb_sa *sa; - pfkey_align(msg, mhp); - pfkey_check(mhp); - if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { - if (sa->sadb_sa_state == SADB_SASTATE_DEAD) - break; - } - } - if (f_forever) - shortdump(msg); - else - pfkey_sadump(msg); - msg = (struct sadb_msg *)((caddr_t)msg + - PFKEY_UNUNIT64(msg->sadb_msg_len)); - if (f_verbose) { - kdebug_sadb((struct sadb_msg *)msg); - printf("\n"); - } - break; - - case SADB_X_SPDDUMP: - pfkey_spdump(msg); - if (msg->sadb_msg_seq == 0) break; - msg = (struct sadb_msg *)((caddr_t)msg + - PFKEY_UNUNIT64(msg->sadb_msg_len)); - if (f_verbose) { - kdebug_sadb((struct sadb_msg *)msg); - printf("\n"); - } - break; - } - - return(0); -} - -/*------------------------------------------------------------*/ -static char *satype[] = { - NULL, NULL, "ah", "esp" -}; -static char *sastate[] = { - "L", "M", "D", "d" -}; -static char *ipproto[] = { -/*0*/ "ip", "icmp", "igmp", "ggp", "ip4", - NULL, "tcp", NULL, "egp", NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, - NULL, NULL, "udp", NULL, NULL, -/*20*/ NULL, NULL, "idp", NULL, NULL, - NULL, NULL, NULL, NULL, "tp", -/*30*/ NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, -/*40*/ NULL, "ip6", NULL, "rt6", "frag6", - NULL, "rsvp", "gre", NULL, NULL, -/*50*/ "esp", "ah", NULL, NULL, NULL, - NULL, NULL, NULL, "icmp6", "none", -/*60*/ "dst6", -}; - -#define STR_OR_ID(x, tab) \ - (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) - -const char * -numstr(int x) -{ - static char buf[20]; - snprintf(buf, sizeof(buf), "#%d", x); - return buf; -} - -void -shortdump_hdr(void) -{ - printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", - "time", "p", "s", "spi", "ltime", "src", "dst"); -} - -void -shortdump(struct sadb_msg *msg) -{ - caddr_t mhp[SADB_EXT_MAX + 1]; - char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; - struct sadb_sa *sa; - struct sadb_address *saddr; - struct sadb_lifetime *lts, *lth, *ltc; - struct sockaddr *s; - u_int t; - time_t cur; - - cur = time(0); - - pfkey_align(msg, mhp); - pfkey_check(mhp); - - printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); - - printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); - - if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { - printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); - printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); - } else - printf("%-1s %-8s", "?", "?"); - - lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; - lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; - ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; - if (lts && lth && ltc) { - if (ltc->sadb_lifetime_addtime == 0) - t = (u_long)0; - else - t = (u_long)(cur - ltc->sadb_lifetime_addtime); - if (t >= 1000) - strcpy(buf, " big/"); - else - snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); - printf("%s", buf); - - t = (u_long)lth->sadb_lifetime_addtime; - if (t >= 1000) - strcpy(buf, "big"); - else - snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); - printf("%s", buf); - } else - printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ - - printf(" "); - - if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { - if (saddr->sadb_address_proto) - printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); - s = (struct sockaddr *)(saddr + 1); - getnameinfo(s, s->sa_len, buf, sizeof(buf), - pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); - if (strcmp(pbuf, "0") != 0) - printf("%s[%s]", buf, pbuf); - else - printf("%s", buf); - } else - printf("?"); - - printf(" -> "); - - if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { - if (saddr->sadb_address_proto) - printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); - - s = (struct sockaddr *)(saddr + 1); - getnameinfo(s, s->sa_len, buf, sizeof(buf), - pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); - if (strcmp(pbuf, "0") != 0) - printf("%s[%s]", buf, pbuf); - else - printf("%s", buf); - } else - printf("?"); - - printf("\n"); -} - -/* From: tcpdump(1):gmt2local.c and util.c */ -/* - * Print the timestamp - */ -static void -printdate(void) -{ - struct timeval tp; - int s; - - if (gettimeofday(&tp, NULL) == -1) { - perror("gettimeofday"); - return; - } - - if (f_tflag == 1) { - /* Default */ - s = (tp.tv_sec + thiszone ) % 86400; - printf("%02d:%02d:%02d.%06u ", - s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); - } else if (f_tflag > 1) { - /* Unix timeval style */ - printf("%u.%06u ", (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); - } - - printf("\n"); -} - -/* - * Returns the difference between gmt and local time in seconds. - * Use gmtime() and localtime() to keep things simple. - */ -int32_t -gmt2local(time_t t) -{ - int dt, dir; - struct tm *gmt, *loc; - struct tm sgmt; - - if (t == 0) - t = time(NULL); - gmt = &sgmt; - *gmt = *gmtime(&t); - loc = localtime(&t); - dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + - (loc->tm_min - gmt->tm_min) * 60; - - /* - * If the year or julian day is different, we span 00:00 GMT - * and must add or subtract a day. Check the year first to - * avoid problems when the julian day wraps. - */ - dir = loc->tm_year - gmt->tm_year; - if (dir == 0) - dir = loc->tm_yday - gmt->tm_yday; - dt += dir * 24 * 60 * 60; - - return (dt); -} diff --git a/usr.sbin/setkey/test-pfkey.c b/usr.sbin/setkey/test-pfkey.c deleted file mode 100644 index c868e30bc8..0000000000 --- a/usr.sbin/setkey/test-pfkey.c +++ /dev/null @@ -1,501 +0,0 @@ -/* $FreeBSD: src/usr.sbin/setkey/test-pfkey.c,v 1.1.2.1 2000/07/15 07:37:04 kris Exp $ */ -/* $DragonFly: src/usr.sbin/setkey/test-pfkey.c,v 1.5 2004/12/18 22:48:14 swildner Exp $ */ -/* $KAME: test-pfkey.c,v 1.4 2000/06/07 00:29:14 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -u_char m_buf[BUFSIZ]; -u_int m_len; -char *pname; - -void Usage(void); -int sendkeymsg(void); -void key_setsadbmsg(u_int); -void key_setsadbsens(void); -void key_setsadbprop(void); -void key_setsadbid(u_int, caddr_t); -void key_setsadblft(u_int, u_int); -void key_setspirange(void); -void key_setsadbkey(u_int, caddr_t); -void key_setsadbsa(void); -void key_setsadbaddr(u_int, u_int, caddr_t); -void key_setsadbextbuf(caddr_t, int, caddr_t, int, caddr_t, int); - -void -Usage(void) -{ - printf("Usage:\t%s number\n", pname); - exit(0); -} - -int -main(int argv, char **argv) -{ - pname = *argv; - - if (argc == 1) Usage(); - - key_setsadbmsg(atoi(*(argv+1))); - sendkeymsg(); - - exit(0); -} - -/* %%% */ -int -sendkeymsg(void) -{ - u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ - int so, len; - - if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { - perror("socket(PF_KEY)"); - goto end; - } -#if 0 - { -#include - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { - perror("setsockopt"); - goto end; - } - } -#endif - - pfkey_sadump((struct sadb_msg *)m_buf); - - if ((len = send(so, m_buf, m_len, 0)) < 0) { - perror("send"); - goto end; - } - - if ((len = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { - perror("recv"); - goto end; - } - - pfkey_sadump((struct sadb_msg *)rbuf); - -end: - close(so); - return(0); -} - -void -key_setsadbmsg(u_int type) -{ - struct sadb_msg m_msg; - - memset(&m_msg, 0, sizeof(m_msg)); - m_msg.sadb_msg_version = PF_KEY_V2; - m_msg.sadb_msg_type = type; - m_msg.sadb_msg_errno = 0; - m_msg.sadb_msg_satype = SADB_SATYPE_ESP; -#if 0 - m_msg.sadb_msg_reserved = 0; -#endif - m_msg.sadb_msg_seq = 0; - m_msg.sadb_msg_pid = getpid(); - - m_len = sizeof(struct sadb_msg); - memcpy(m_buf, &m_msg, m_len); - - switch (type) { - case SADB_GETSPI: - /**/ - key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "10.0.3.4"); - key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "127.0.0.1"); - key_setspirange(); - /**/ - break; - - case SADB_ADD: - /* */ - key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); - case SADB_UPDATE: - key_setsadbsa(); - key_setsadblft(SADB_EXT_LIFETIME_HARD, 10); - key_setsadblft(SADB_EXT_LIFETIME_SOFT, 5); - key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); - key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); - /* XXX key_setsadbkey(SADB_EXT_KEY_AUTH, "abcde"); */ - key_setsadbkey(SADB_EXT_KEY_AUTH, "1234567812345678"); - key_setsadbkey(SADB_EXT_KEY_ENCRYPT, "12345678"); - key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com"); - key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net"); - key_setsadbsens(); - /* */ - break; - - case SADB_DELETE: - /* */ - key_setsadbsa(); - key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); - key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); - key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); - /* */ - break; - - case SADB_GET: - /* */ - key_setsadbsa(); - key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); - key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); - key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); - /* */ - break; - - case SADB_ACQUIRE: - /* */ - key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); - key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); - key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); - key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com"); - key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net"); - key_setsadbsens(); - key_setsadbprop(); - /* */ - break; - - case SADB_REGISTER: - /* */ - /* */ - break; - - case SADB_EXPIRE: - case SADB_FLUSH: - break; - - case SADB_DUMP: - break; - - case SADB_X_PROMISC: - /* */ - /* */ - break; - - case SADB_X_PCHANGE: - break; - - /* for SPD management */ - case SADB_X_SPDFLUSH: - case SADB_X_SPDDUMP: - break; - - case SADB_X_SPDADD: -#if 0 - { - struct sadb_x_policy m_policy; - - m_policy.sadb_x_policy_len = PFKEY_UNIT64(sizeof(m_policy)); - m_policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY; - m_policy.sadb_x_policy_type = SADB_X_PL_IPSEC; - m_policy.sadb_x_policy_esp_trans = 1; - m_policy.sadb_x_policy_ah_trans = 2; - m_policy.sadb_x_policy_esp_network = 3; - m_policy.sadb_x_policy_ah_network = 4; - m_policy.sadb_x_policy_reserved = 0; - - memcpy(m_buf + m_len, &m_policy, sizeof(struct sadb_x_policy)); - m_len += sizeof(struct sadb_x_policy); - } -#endif - - case SADB_X_SPDDELETE: - key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); - key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); - break; - } - - ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len); -} - -void -key_setsadbsens(void) -{ - struct sadb_sens m_sens; - u_char buf[64]; - u_int s, i, slen, ilen, len; - - /* make sens & integ */ - s = htonl(0x01234567); - i = htonl(0x89abcdef); - slen = sizeof(s); - ilen = sizeof(i); - memcpy(buf, &s, slen); - memcpy(buf + slen, &i, ilen); - - len = sizeof(m_sens) + PFKEY_ALIGN8(slen) + PFKEY_ALIGN8(ilen); - m_sens.sadb_sens_len = PFKEY_UNIT64(len); - m_sens.sadb_sens_exttype = SADB_EXT_SENSITIVITY; - m_sens.sadb_sens_dpd = 1; - m_sens.sadb_sens_sens_level = 2; - m_sens.sadb_sens_sens_len = PFKEY_ALIGN8(slen); - m_sens.sadb_sens_integ_level = 3; - m_sens.sadb_sens_integ_len = PFKEY_ALIGN8(ilen); - m_sens.sadb_sens_reserved = 0; - - key_setsadbextbuf(m_buf, m_len, - (caddr_t)&m_sens, sizeof(struct sadb_sens), - buf, slen + ilen); - m_len += len; -} - -void -key_setsadbprop(void) -{ - struct sadb_prop m_prop; - struct sadb_comb *m_comb; - u_char buf[256]; - u_int len = sizeof(m_prop) + sizeof(m_comb) * 2; - - /* make prop & comb */ - m_prop.sadb_prop_len = PFKEY_UNIT64(len); - m_prop.sadb_prop_exttype = SADB_EXT_PROPOSAL; - m_prop.sadb_prop_replay = 0; - m_prop.sadb_prop_reserved[0] = 0; - m_prop.sadb_prop_reserved[1] = 0; - m_prop.sadb_prop_reserved[2] = 0; - - /* the 1st is ESP DES-CBC HMAC-MD5 */ - m_comb = (struct sadb_comb *)buf; - m_comb->sadb_comb_auth = SADB_AALG_MD5HMAC; - m_comb->sadb_comb_encrypt = SADB_EALG_DESCBC; - m_comb->sadb_comb_flags = 0; - m_comb->sadb_comb_auth_minbits = 8; - m_comb->sadb_comb_auth_maxbits = 96; - m_comb->sadb_comb_encrypt_minbits = 64; - m_comb->sadb_comb_encrypt_maxbits = 64; - m_comb->sadb_comb_reserved = 0; - m_comb->sadb_comb_soft_allocations = 0; - m_comb->sadb_comb_hard_allocations = 0; - m_comb->sadb_comb_soft_bytes = 0; - m_comb->sadb_comb_hard_bytes = 0; - m_comb->sadb_comb_soft_addtime = 0; - m_comb->sadb_comb_hard_addtime = 0; - m_comb->sadb_comb_soft_usetime = 0; - m_comb->sadb_comb_hard_usetime = 0; - - /* the 2st is ESP 3DES-CBC and AH HMAC-SHA1 */ - m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb)); - m_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC; - m_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC; - m_comb->sadb_comb_flags = 0; - m_comb->sadb_comb_auth_minbits = 8; - m_comb->sadb_comb_auth_maxbits = 96; - m_comb->sadb_comb_encrypt_minbits = 64; - m_comb->sadb_comb_encrypt_maxbits = 64; - m_comb->sadb_comb_reserved = 0; - m_comb->sadb_comb_soft_allocations = 0; - m_comb->sadb_comb_hard_allocations = 0; - m_comb->sadb_comb_soft_bytes = 0; - m_comb->sadb_comb_hard_bytes = 0; - m_comb->sadb_comb_soft_addtime = 0; - m_comb->sadb_comb_hard_addtime = 0; - m_comb->sadb_comb_soft_usetime = 0; - m_comb->sadb_comb_hard_usetime = 0; - - key_setsadbextbuf(m_buf, m_len, - (caddr_t)&m_prop, sizeof(struct sadb_prop), - buf, sizeof(*m_comb) * 2); - m_len += len; -} - -void -key_setsadbid(u_int ext, caddr_t str) -{ - struct sadb_ident m_id; - u_int idlen = strlen(str), len; - - len = sizeof(m_id) + PFKEY_ALIGN8(idlen); - m_id.sadb_ident_len = PFKEY_UNIT64(len); - m_id.sadb_ident_exttype = ext; - m_id.sadb_ident_type = SADB_IDENTTYPE_USERFQDN; - m_id.sadb_ident_reserved = 0; - m_id.sadb_ident_id = getpid(); - - key_setsadbextbuf(m_buf, m_len, - (caddr_t)&m_id, sizeof(struct sadb_ident), - str, idlen); - m_len += len; -} - -void -key_setsadblft(u_int ext, u_int time) -{ - struct sadb_lifetime m_lft; - - m_lft.sadb_lifetime_len = PFKEY_UNIT64(sizeof(m_lft)); - m_lft.sadb_lifetime_exttype = ext; - m_lft.sadb_lifetime_allocations = 0x2; - m_lft.sadb_lifetime_bytes = 0x1000; - m_lft.sadb_lifetime_addtime = time; - m_lft.sadb_lifetime_usetime = 0x0020; - - memcpy(m_buf + m_len, &m_lft, sizeof(struct sadb_lifetime)); - m_len += sizeof(struct sadb_lifetime); -} - -void -key_setspirange(void) -{ - struct sadb_spirange m_spi; - - m_spi.sadb_spirange_len = PFKEY_UNIT64(sizeof(m_spi)); - m_spi.sadb_spirange_exttype = SADB_EXT_SPIRANGE; - m_spi.sadb_spirange_min = 0x00001000; - m_spi.sadb_spirange_max = 0x00002000; - m_spi.sadb_spirange_reserved = 0; - - memcpy(m_buf + m_len, &m_spi, sizeof(struct sadb_spirange)); - m_len += sizeof(struct sadb_spirange); -} - -void -key_setsadbkey(u_int ext, caddr_t str) -{ - struct sadb_key m_key; - u_int keylen = strlen(str); - u_int len; - - len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen); - m_key.sadb_key_len = PFKEY_UNIT64(len); - m_key.sadb_key_exttype = ext; - m_key.sadb_key_bits = keylen * 8; - m_key.sadb_key_reserved = 0; - - key_setsadbextbuf(m_buf, m_len, - (caddr_t)&m_key, sizeof(struct sadb_key), - str, keylen); - m_len += len; -} - -void -key_setsadbsa(void) -{ - struct sadb_sa m_sa; - - m_sa.sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa)); - m_sa.sadb_sa_exttype = SADB_EXT_SA; - m_sa.sadb_sa_spi = htonl(0x12345678); - m_sa.sadb_sa_replay = 4; - m_sa.sadb_sa_state = 0; - m_sa.sadb_sa_auth = SADB_AALG_MD5HMAC; - m_sa.sadb_sa_encrypt = SADB_EALG_DESCBC; - m_sa.sadb_sa_flags = 0; - - memcpy(m_buf + m_len, &m_sa, sizeof(struct sadb_sa)); - m_len += sizeof(struct sadb_sa); -} - -void -key_setsadbaddr(u_int ext, u_int af, caddr_t str) -{ - struct sadb_address m_addr; - u_int len; - struct addrinfo hints, *res; - const char *serv; - int plen; - - switch (af) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - /* XXX bark */ - exit(1); - } - - /* make sockaddr buffer */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = af; - hints.ai_socktype = SOCK_DGRAM; /*dummy*/ - hints.ai_flags = AI_NUMERICHOST; - serv = (ext == SADB_EXT_ADDRESS_PROXY ? "0" : "4660"); /*0x1234*/ - if (getaddrinfo(str, serv, &hints, &res) != 0 || res->ai_next) { - /* XXX bark */ - exit(1); - } - - len = sizeof(struct sadb_address) + PFKEY_ALIGN8(res->ai_addrlen); - m_addr.sadb_address_len = PFKEY_UNIT64(len); - m_addr.sadb_address_exttype = ext; - m_addr.sadb_address_proto = - (ext == SADB_EXT_ADDRESS_PROXY ? 0 : IPPROTO_TCP); - m_addr.sadb_address_prefixlen = plen; - m_addr.sadb_address_reserved = 0; - - key_setsadbextbuf(m_buf, m_len, - (caddr_t)&m_addr, sizeof(struct sadb_address), - (caddr_t)res->ai_addr, res->ai_addrlen); - m_len += len; - - freeaddrinfo(res); -} - -void -key_setsadbextbuf(caddr_t dst, int off, caddr_t ebuf, int elen, - caddr_t vbuf, int vlen) -{ - memset(dst + off, 0, elen + vlen); - memcpy(dst + off, (caddr_t)ebuf, elen); - memcpy(dst + off + elen, vbuf, vlen); -} - diff --git a/usr.sbin/setkey/test-policy.c b/usr.sbin/setkey/test-policy.c deleted file mode 100644 index a58d671c8b..0000000000 --- a/usr.sbin/setkey/test-policy.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/usr.sbin/setkey/test-policy.c,v 1.1 2000/01/06 12:40:53 shin Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -char *requests[] = { -"must_error", /* must be error */ -"ipsec must_error", /* must be error */ -"ipsec esp/must_error", /* must be error */ -"discard", -"none", -"entrust", -"bypass", /* may be error */ -"ipsec esp", /* must be error */ -"ipsec ah/require", -"ipsec ah/use/", -"ipsec esp/require ah/default/203.178.141.194", -"ipsec ah/use/203.178.141.195 esp/use/203.178.141.194", -"ipsec esp/elf.wide.ydc.co.jp esp/www.wide.ydc.co.jp" -" -ipsec esp/require ah/use esp/require/10.0.0.1 -ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 -ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 -ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 -ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 -ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 -ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 -ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 -ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1ah/use/3ffe:501:481d::1 -", -}; - -u_char *p_secpolicy; - -int test(char *buf, int family); -char *setpolicy(char *req); - -int -main(int argc __unused, char **argv __unused) -{ - int i; - char *buf; - - for (i = 0; i < NELEM(requests); i++) { - printf("* requests:[%s]\n", requests[i]); - if ((buf = setpolicy(requests[i])) == NULL) - continue; - printf("\tsetlen:%d\n", PFKEY_EXTLEN(buf)); - - printf("\tPF_INET:\n"); - test(buf, PF_INET); - - printf("\tPF_INET6:\n"); - test(buf, PF_INET6); - free(buf); - } -} - -int -test(char *policy, int family) -{ - int so, proto, optname; - int len; - char getbuf[1024]; - char *buf = NULL; - - switch (family) { - case PF_INET: - proto = IPPROTO_IP; - optname = IP_IPSEC_POLICY; - break; - case PF_INET6: - proto = IPPROTO_IPV6; - optname = IPV6_IPSEC_POLICY; - break; - } - - if ((so = socket(family, SOCK_DGRAM, 0)) < 0) - perror("socket"); - - if (setsockopt(so, proto, optname, policy, PFKEY_EXTLEN(policy)) < 0) - perror("setsockopt"); - - len = sizeof(getbuf); - memset(getbuf, 0, sizeof(getbuf)); - if (getsockopt(so, proto, optname, getbuf, &len) < 0) - perror("getsockopt"); - - printf("\tgetlen:%d\n", len); - - if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL) - ipsec_strerror(); - else - printf("\t[%s]\n", buf); - - free(buf); - - close (so); -} - -char * -setpolicy(char *req) -{ - int len; - char *buf; - - if ((len = ipsec_get_policylen(req)) < 0) { - printf("ipsec_get_policylen: %s\n", ipsec_strerror()); - return NULL; - } - - if ((buf = malloc(len)) == NULL) { - perror("malloc"); - return NULL; - } - - if ((len = ipsec_set_policy(buf, len, req)) < 0) { - printf("ipsec_set_policy: %s\n", ipsec_strerror()); - free(buf); - return NULL; - } - - return buf; -} diff --git a/usr.sbin/setkey/token.l b/usr.sbin/setkey/token.l deleted file mode 100644 index 1b9ed72bda..0000000000 --- a/usr.sbin/setkey/token.l +++ /dev/null @@ -1,323 +0,0 @@ -/* $FreeBSD: src/usr.sbin/setkey/token.l,v 1.2.2.3 2001/07/03 11:02:17 ume Exp $ */ -/* $KAME: token.l,v 1.21 2001/05/18 05:35:01 sakane Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -%{ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "vchar.h" -#ifdef __NetBSD__ -#include "parse.h" -#else -#include "y.tab.h" -#endif - -#define DECHO \ - if (f_debug) {printf("<%d>", yy_start); ECHO ; printf("\n"); } - -#define CMDARG \ -{ \ - char *__buf__ = strdup(yytext), *__p__; \ - for (__p__ = __buf__; *__p__ != 0; __p__++) \ - if (*__p__ == '\n' || *__p__ == '\t') \ - *__p__ = ' '; \ - strcat(cmdarg, __buf__); \ - free(__buf__); \ -} - -#define PREPROC DECHO CMDARG - -int lineno = 1; -char cmdarg[8192]; /* XXX: BUFSIZ is the better ? */ - -extern u_char m_buf[BUFSIZ]; -extern u_int m_len; -extern int f_debug; - -void yyfatal(const char *s) __dead2; -void yyerror(const char *s); -extern void parse_init(void); -int parse(FILE **); -int yyparse(void); - -%} - -%option noinput -%option nounput - -/* common section */ -nl \n -ws [ \t]+ -digit [0-9] -letter [0-9A-Za-z] -hexdigit [0-9A-Fa-f] -/*octet (([01]?{digit}?{digit})|((2([0-4]{digit}))|(25[0-5])))*/ -special [()+\|\?\*,] -dot \. -comma \, -hyphen \- -colon \: -slash \/ -bcl \{ -ecl \} -blcl \[ -elcl \] -percent \% -semi \; -usec {dot}{digit}{1,6} -comment \#.* -ccomment "/*" -bracketstring \<[^>]*\> -quotedstring \"[^"]*\" -decstring {digit}+ -hexpair {hexdigit}{hexdigit} -hexstring 0[xX]{hexdigit}+ -octetstring {octet}({dot}{octet})+ -ipaddress [a-fA-F0-9:]([a-fA-F0-9:\.]*|[a-fA-F0-9:\.]*%[a-zA-Z0-9]*) -ipaddrmask {slash}{digit}{1,3} -ipaddrport {blcl}{decstring}{elcl} -keyword {letter}{letter}+ -name {letter}(({letter}|{digit}|{hyphen})*({letter}|{digit}))* -hostname {name}(({dot}{name})+{dot}?)? - -%s S_PL - -%% - -add { PREPROC; return(ADD); } -delete { PREPROC; return(DELETE); } -deleteall { PREPROC; return(DELETEALL); } -get { PREPROC; return(GET); } -flush { PREPROC; return(FLUSH); } -dump { PREPROC; return(DUMP); } - - /* for management SPD */ -spdadd { PREPROC; return(SPDADD); } -spddelete { PREPROC; return(SPDDELETE); } -spddump { PREPROC; return(SPDDUMP); } -spdflush { PREPROC; return(SPDFLUSH); } -{hyphen}P { BEGIN S_PL; PREPROC; return(F_POLICY); } -[a-zA-Z0-9:\.\-_/ \n\t][a-zA-Z0-9:\.\-_/ \n\t]* { - yymore(); - - /* count up for nl */ - { - char *p; - for (p = yytext; *p != 0; p++) - if (*p == '\n') - lineno++; - } - - yylval.val.len = strlen(yytext); - yylval.val.buf = strdup(yytext); - - return(PL_REQUESTS); -} -{semi} { PREPROC; BEGIN INITIAL; return(EOT); } - - /* security protocols */ -ah { PREPROC; yylval.num = 0; return(PR_AH); } -esp { PREPROC; yylval.num = 0; return(PR_ESP); } -ah-old { PREPROC; yylval.num = 1; return(PR_AH); } -esp-old { PREPROC; yylval.num = 1; return(PR_ESP); } -ipcomp { PREPROC; yylval.num = 0; return(PR_IPCOMP); } -tcp { PREPROC; yylval.num = 0; return(PR_TCP); } - - /* authentication alogorithm */ -{hyphen}A { PREPROC; return(F_AUTH); } -hmac-md5 { PREPROC; yylval.num = SADB_AALG_MD5HMAC; return(ALG_AUTH); } -hmac-sha1 { PREPROC; yylval.num = SADB_AALG_SHA1HMAC; return(ALG_AUTH); } -keyed-md5 { PREPROC; yylval.num = SADB_X_AALG_MD5; return(ALG_AUTH); } -keyed-sha1 { PREPROC; yylval.num = SADB_X_AALG_SHA; return(ALG_AUTH); } -hmac-sha2-256 { PREPROC; yylval.num = SADB_X_AALG_SHA2_256; return(ALG_AUTH); } -hmac-sha2-384 { PREPROC; yylval.num = SADB_X_AALG_SHA2_384; return(ALG_AUTH); } -hmac-sha2-512 { PREPROC; yylval.num = SADB_X_AALG_SHA2_512; return(ALG_AUTH); } -tcp-md5 { PREPROC; yylval.num = SADB_X_AALG_TCP_MD5; return(ALG_AUTH); } -null { PREPROC; yylval.num = SADB_X_AALG_NULL; return(ALG_AUTH); } - - /* encryption alogorithm */ -{hyphen}E { PREPROC; return(F_ENC); } -des-cbc { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC); } -3des-cbc { PREPROC; yylval.num = SADB_EALG_3DESCBC; return(ALG_ENC); } -simple { PREPROC; yylval.num = SADB_EALG_NULL; return(ALG_ENC); } -blowfish-cbc { PREPROC; yylval.num = SADB_X_EALG_BLOWFISHCBC; return(ALG_ENC); } -cast128-cbc { PREPROC; yylval.num = SADB_X_EALG_CAST128CBC; return(ALG_ENC); } -des-deriv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DESDERIV); } -des-32iv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DES32IV); } -rijndael-cbc { PREPROC; yylval.num = SADB_X_EALG_RIJNDAELCBC; return(ALG_ENC); } - - /* compression algorithms */ -{hyphen}C { PREPROC; return(F_COMP); } -oui { PREPROC; yylval.num = SADB_X_CALG_OUI; return(ALG_COMP); } -deflate { PREPROC; yylval.num = SADB_X_CALG_DEFLATE; return(ALG_COMP); } -lzs { PREPROC; yylval.num = SADB_X_CALG_LZS; return(ALG_COMP); } -{hyphen}R { PREPROC; return(F_RAWCPI); } - - /* extension */ -{hyphen}m { PREPROC; return(F_MODE); } -transport { PREPROC; yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); } -tunnel { PREPROC; yylval.num = IPSEC_MODE_TUNNEL; return(MODE); } -{hyphen}u { PREPROC; return(F_REQID); } -{hyphen}f { PREPROC; return(F_EXT); } -random-pad { PREPROC; yylval.num = SADB_X_EXT_PRAND; return(EXTENSION); } -seq-pad { PREPROC; yylval.num = SADB_X_EXT_PSEQ; return(EXTENSION); } -zero-pad { PREPROC; yylval.num = SADB_X_EXT_PZERO; return(EXTENSION); } -nocyclic-seq { PREPROC; return(NOCYCLICSEQ); } -{hyphen}r { PREPROC; return(F_REPLAY); } -{hyphen}lh { PREPROC; return(F_LIFETIME_HARD); } -{hyphen}ls { PREPROC; return(F_LIFETIME_SOFT); } - - /* ... */ -any { PREPROC; return(ANY); } -{ws} { PREPROC; } -{nl} { lineno++; } -{comment} -{semi} { PREPROC; return(EOT); } - - /* parameter */ -{decstring} { - char *bp; - - PREPROC; - yylval.num = strtoul(yytext, &bp, 10); - return(DECSTRING); - } - -{ipaddress} { - PREPROC; - - yylval.val.len = yyleng; - yylval.val.buf = strdup(yytext); - - return(ADDRESS); - } - -{ipaddrmask} { - PREPROC; - yytext++; - yylval.num = atoi(yytext); - return(PREFIX); - } - -{ipaddrport} { - char *p = yytext; - PREPROC; - while (*++p != ']') ; - *p = 0; - yytext++; - yylval.num = atoi(yytext); - return(PORT); - } - -{blcl}any{elcl} { - PREPROC; - return(PORTANY); - } - -{hexstring} { - int len = yyleng - 2; /* (str - "0x") */ - PREPROC; - yylval.val.len = (len & 1) + (len / 2); - /* fixed string if length is odd. */ - if (len & 1) { - yytext[1] = '0'; - yylval.val.buf = strdup(yytext + 1); - } else - yylval.val.buf = strdup(yytext + 2); - - return(HEXSTRING); - } - -{quotedstring} { - char *p = yytext; - PREPROC; - while (*++p != '"') ; - *p = 0; - yytext++; - yylval.val.len = yyleng - 2; - yylval.val.buf = strdup(yytext); - - return(QUOTEDSTRING); - } - -[a-z0-9.\-]* { - yylval.val.len = yyleng; - yylval.val.buf = strdup(yytext); - return(STRING); - } - -. { - yyfatal("Syntax error"); - /*NOTREACHED*/ - } - -%% - -void -yyfatal(const char *s) -{ - yyerror(s); - exit(1); -} - -void -yyerror(const char *s) -{ - printf("line %d: %s at [%s]\n", lineno, s, yytext); -} - -int -parse(FILE **fp) -{ - yyin = *fp; - - parse_init(); - - if (yyparse()) { - printf("parse failed, line %d.\n", lineno); - return(-1); - } - - return(0); -} diff --git a/usr.sbin/setkey/vchar.h b/usr.sbin/setkey/vchar.h deleted file mode 100644 index d13f546d37..0000000000 --- a/usr.sbin/setkey/vchar.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $FreeBSD: src/usr.sbin/setkey/vchar.h,v 1.1.2.1 2000/07/15 07:37:04 kris Exp $ */ -/* $DragonFly: src/usr.sbin/setkey/vchar.h,v 1.2 2003/06/17 04:30:03 dillon Exp $ */ -/* $KAME: vchar.h,v 1.2 2000/06/07 00:29:14 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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. - */ - -typedef struct { - u_int len; - caddr_t buf; -} vchar_t; diff --git a/usr.sbin/traceroute6/Makefile b/usr.sbin/traceroute6/Makefile index 0dda497ace..107ddc2da6 100644 --- a/usr.sbin/traceroute6/Makefile +++ b/usr.sbin/traceroute6/Makefile @@ -12,7 +12,6 @@ # LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE. # $FreeBSD: src/usr.sbin/traceroute6/Makefile,v 1.2.2.3 2002/07/23 07:48:27 ru Exp $ -# $DragonFly: src/usr.sbin/traceroute6/Makefile,v 1.3 2008/09/04 09:08:22 hasso Exp $ PROG= traceroute6 MAN= traceroute6.8 @@ -20,9 +19,6 @@ BINOWN= root BINMODE=4555 WARNS?= 2 -CFLAGS+=-DINET6 -DIPSEC -DHAVE_POLL -DUSE_RFC3542 - -DPADD= ${LIBIPSEC} -LDADD= -lipsec +CFLAGS+=-DINET6 -DHAVE_POLL -DUSE_RFC3542 .include diff --git a/usr.sbin/traceroute6/traceroute6.c b/usr.sbin/traceroute6/traceroute6.c index 18788ccec4..d42a7ec46a 100644 --- a/usr.sbin/traceroute6/traceroute6.c +++ b/usr.sbin/traceroute6/traceroute6.c @@ -264,11 +264,6 @@ #include #include -#ifdef IPSEC -#include -#include -#endif - #define DUMMY_PORT 10010 #define MAXPACKET 65535 /* max ip packet size */ @@ -297,11 +292,6 @@ static u_char packet[512]; /* last inbound (icmp) packet */ static struct opacket *outpacket; /* last output (udp) packet */ static int wait_for_reply(int, struct msghdr *); -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC -static int setpolicy(int so, char *policy); -#endif -#endif static void send_probe(int, u_long); static void *get_uphdr(struct ip6_hdr *, u_char *); static double deltaT(struct timeval *, struct timeval *); @@ -642,39 +632,6 @@ main(int argc, char **argv) if (options & SO_DONTROUTE) (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - /* - * do not raise error even if setsockopt fails, kernel may have ipsec - * turned off. - */ - if (setpolicy(rcvsock, "in bypass") < 0) - errx(1, "%s", ipsec_strerror()); - if (setpolicy(rcvsock, "out bypass") < 0) - errx(1, "%s", ipsec_strerror()); -#else - { - int level = IPSEC_LEVEL_NONE; - - (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, - sizeof(level)); - (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, - sizeof(level)); -#ifdef IP_AUTH_TRANS_LEVEL - (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, - sizeof(level)); -#else - (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, - sizeof(level)); -#endif -#ifdef IP_AUTH_NETWORK_LEVEL - (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, - sizeof(level)); -#endif - } -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ - #ifdef SO_SNDBUF i = datalen; if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i, @@ -689,39 +646,6 @@ main(int argc, char **argv) if (options & SO_DONTROUTE) (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - /* - * do not raise error even if setsockopt fails, kernel may have ipsec - * turned off. - */ - if (setpolicy(sndsock, "in bypass") < 0) - errx(1, "%s", ipsec_strerror()); - if (setpolicy(sndsock, "out bypass") < 0) - errx(1, "%s", ipsec_strerror()); -#else - { - int level = IPSEC_LEVEL_BYPASS; - - (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, - sizeof(level)); - (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, - sizeof(level)); -#ifdef IP_AUTH_TRANS_LEVEL - (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, - sizeof(level)); -#else - (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, - sizeof(level)); -#endif -#ifdef IP_AUTH_NETWORK_LEVEL - (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, - sizeof(level)); -#endif - } -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ - /* * Source selection */ @@ -913,28 +837,6 @@ wait_for_reply(int sock, struct msghdr *mhdr) #endif } -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC -static int -setpolicy(int so, char *policy) -{ - char *buf; - - buf = ipsec_set_policy(policy, strlen(policy)); - if (buf == NULL) { - warnx("%s", ipsec_strerror()); - return -1; - } - (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY, - buf, ipsec_get_policylen(buf)); - - free(buf); - - return 0; -} -#endif -#endif - static void send_probe(int seq, u_long hops) { -- 2.41.0