diff options
Diffstat (limited to 'recipes/linux/linux-mtx-2-2.4.27/13-openswan-2.2.0.patch')
-rw-r--r-- | recipes/linux/linux-mtx-2-2.4.27/13-openswan-2.2.0.patch | 61293 |
1 files changed, 61293 insertions, 0 deletions
diff --git a/recipes/linux/linux-mtx-2-2.4.27/13-openswan-2.2.0.patch b/recipes/linux/linux-mtx-2-2.4.27/13-openswan-2.2.0.patch new file mode 100644 index 0000000000..a6fba5d3f9 --- /dev/null +++ b/recipes/linux/linux-mtx-2-2.4.27/13-openswan-2.2.0.patch @@ -0,0 +1,61293 @@ +make[1]: Entering directory `/data/mtx/oe/tmp/work/openswan-2.2.0-r0/openswan-2.2.0' +packaging/utils/kernelpatch 2.4 +--- linux/Documentation/Configure.help.orig Fri Dec 21 12:41:53 2001 ++++ linux/Documentation/Configure.help Mon Jul 29 16:35:32 2002 +@@ -24237,5 +24237,65 @@ + +-# ++IP Security Protocol (IPSEC) (EXPERIMENTAL) ++CONFIG_IPSEC ++ This unit is experimental code. ++ Pick 'y' for static linking, 'm' for module support or 'n' for none. ++ This option adds support for network layer packet encryption and/or ++ authentication with participating hosts. The standards start with: ++ RFCs 2411, 2407 and 2401. Others are mentioned where they refer to ++ specific features below. There are more pending which can be found ++ at: ftp://ftp.ietf.org/internet-drafts/draft-ietf-ipsec-*. ++ A description of each document can also be found at: ++ http://ietf.org/ids.by.wg/ipsec.html. ++ Their charter can be found at: ++ http://www.ietf.org/html.charters/ipsec-charter.html ++ Snapshots and releases of the current work can be found at: ++ http://www.freeswan.org/ ++ ++IPSEC: IP-in-IP encapsulation ++CONFIG_IPSEC_IPIP ++ This option provides support for tunnel mode IPSEC. It is recommended ++ to enable this. ++ ++IPSEC: Authentication Header ++CONFIG_IPSEC_AH ++ This option provides support for the IPSEC Authentication Header ++ (IP protocol 51) which provides packet layer sender and content ++ authentication. It is recommended to enable this. RFC2402 ++ ++HMAC-MD5 algorithm ++CONFIG_IPSEC_AUTH_HMAC_MD5 ++ Provides support for authentication using the HMAC MD5 ++ algorithm with 96 bits of hash used as the authenticator. RFC2403 ++ ++HMAC-SHA1 algorithm ++CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ Provides support for Authentication Header using the HMAC SHA1 ++ algorithm with 96 bits of hash used as the authenticator. RFC2404 ++ ++IPSEC: Encapsulating Security Payload ++CONFIG_IPSEC_ESP ++ This option provides support for the IPSEC Encapsulation Security ++ Payload (IP protocol 50) which provides packet layer content ++ hiding. It is recommended to enable this. RFC2406 ++ ++3DES algorithm ++CONFIG_IPSEC_ENC_3DES ++ Provides support for Encapsulation Security Payload protocol, using ++ the triple DES encryption algorithm. RFC2451 ++ ++IPSEC Debugging Option ++CONFIG_IPSEC_DEBUG ++ Enables IPSEC kernel debugging. It is further controlled by the ++ user space utility 'klipsdebug'. ++ ++IPSEC Regression Testing option ++CONFIG_IPSEC_REGRESS ++ Enables IPSEC regression testing. Creates a number of switches in ++ /proc/sys/net/ipsec which cause various failure modes in KLIPS. ++ For more details see FreeSWAN source under ++ testing/doc/regression_options.txt. ++ ++# + # A couple of things I keep forgetting: + # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, + # Intel, IRQ, ISDN, Linux, MSDOS, NetWare, NetWinder, +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/README.openswan-2 Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,112 @@ ++* ++* RCSID $Id: README.openswan-2,v 1.1 2003/12/10 01:07:49 mcr Exp $ ++* ++ ++ **************************************** ++ * IPSEC for Linux, Release 2.xx series * ++ **************************************** ++ ++ ++ ++1. Files ++ ++The contents of linux/net/ipsec/ (see below) join the linux kernel source tree. ++as provided for higher up. ++ ++The programs/ directory contains the user-level utilities which you need ++to run IPSEC. See the top-level top/INSTALL to compile and install them. ++ ++The testing/ directory contains test scripts. ++ ++The doc/ directory contains -- what else -- documentation. ++ ++1.1. Kernel files ++ ++The following are found in net/ipsec/: ++ ++Makefile The Makefile ++Config.in The configuration script for make menuconfig ++defconfig Configuration defaults for first time. ++ ++radij.c General-purpose radix-tree operations ++ ++ipsec_ipcomp.c IPCOMP encapsulate/decapsulate code. ++ipsec_ah.c Authentication Header (AH) encapsulate/decapsulate code. ++ipsec_esp.c Encapsulated Security Payload (ESP) encap/decap code. ++ ++pfkey_v2.c PF_KEYv2 socket interface code. ++pfkey_v2_parser.c PF_KEYv2 message parsing and processing code. ++ ++ipsec_init.c Initialization code, /proc interface. ++ipsec_radij.c Interface with the radix tree code. ++ipsec_netlink.c Interface with the netlink code. ++ipsec_xform.c Routines and structures common to transforms. ++ipsec_tunnel.c The outgoing packet processing code. ++ipsec_rcv.c The incoming packet processing code. ++ipsec_md5c.c Somewhat modified RSADSI MD5 C code. ++ipsec_sha1.c Somewhat modified Steve Reid SHA-1 C code. ++ ++sysctl_net_ipsec.c /proc/sys/net/ipsec/* variable definitions. ++ ++version.c symbolic link to project version. ++ ++radij.h Headers for radij.c ++ ++ipcomp.h Headers used by IPCOMP code. ++ ++ipsec_radij.h Interface with the radix tree code. ++ipsec_netlink.h Headers used by the netlink interface. ++ipsec_encap.h Headers defining encapsulation structures. ++ipsec_xform.h Transform headers. ++ipsec_tunnel.h Headers used by tunneling code. ++ipsec_ipe4.h Headers for the IP-in-IP code. ++ipsec_ah.h Headers common to AH transforms. ++ipsec_md5h.h RSADSI MD5 headers. ++ipsec_sha1.h SHA-1 headers. ++ipsec_esp.h Headers common to ESP transfroms. ++ipsec_rcv.h Headers for incoming packet processing code. ++ ++1.2. User-level files. ++ ++The following are found in utils/: ++ ++eroute.c Create an "extended route" source code ++spi.c Set up Security Associations source code ++spigrp.c Link SPIs together source code. ++tncfg.c Configure the tunneling features of the virtual interface ++ source code ++klipsdebug.c Set/reset klips debugging features source code. ++version.c symbolic link to project version. ++ ++eroute.8 Create an "extended route" manual page ++spi.8 Set up Security Associations manual page ++spigrp.8 Link SPIs together manual page ++tncfg.8 Configure the tunneling features of the virtual interface ++ manual page ++klipsdebug.8 Set/reset klips debugging features manual page ++ ++eroute.5 /proc/net/ipsec_eroute format manual page ++spi.5 /proc/net/ipsec_spi format manual page ++spigrp.5 /proc/net/ipsec_spigrp format manual page ++tncfg.5 /proc/net/ipsec_tncfg format manual page ++klipsdebug.5 /proc/net/ipsec_klipsdebug format manual page ++version.5 /proc/net/ipsec_version format manual page ++pf_key.5 /proc/net/pf_key format manual page ++ ++Makefile Utilities makefile. ++ ++*.8 Manpages for the respective utils. ++ ++ ++1.3. Test files ++ ++The test scripts are locate in testing/ and and documentation is found ++at doc/src/umltesting.html. Automated testing via "make check" is available ++provided that the User-Mode-Linux patches are available. ++ ++* ++* $Log: README.openswan-2,v $ ++* Revision 1.1 2003/12/10 01:07:49 mcr ++* documentation for additions. ++* ++* +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/aes/Makefile.objs Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,13 @@ ++ ++ASM-$(ARCH_ASM):=1 ++ASM_X86:=$(ASM-i586)$(ASM-i686) ++ ++ifneq ($(strip $(ASM_X86)),) ++obj-$(CONFIG_IPSEC_ENC_AES) += aes-i586.o ++else ++obj-$(CONFIG_IPSEC_ENC_AES) += aes.o ++endif ++ ++obj-$(CONFIG_IPSEC_ENC_AES) += aes_cbc.o ++obj-$(CONFIG_IPSEC_ENC_AES) += aes_xcbc_mac.o ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/aes/aes-i586.S Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,892 @@ ++// ++// Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. ++// All rights reserved. ++// ++// TERMS ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted subject to the following conditions: ++// ++// 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 copyright holder's name must not be used to endorse or promote ++// any products derived from this software without his specific prior ++// written permission. ++// ++// This software is provided 'as is' with no express or implied warranties ++// of correctness or fitness for purpose. ++ ++// Modified by Jari Ruusu, December 24 2001 ++// - Converted syntax to GNU CPP/assembler syntax ++// - C programming interface converted back to "old" API ++// - Minor portability cleanups and speed optimizations ++ ++// An AES (Rijndael) implementation for the Pentium. This version only ++// implements the standard AES block length (128 bits, 16 bytes). This code ++// does not preserve the eax, ecx or edx registers or the artihmetic status ++// flags. However, the ebx, esi, edi, and ebp registers are preserved across ++// calls. ++ ++// void aes_set_key(aes_context *cx, const unsigned char key[], const int key_len, const int f) ++// void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) ++// void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) ++ ++#if defined(USE_UNDERLINE) ++# define aes_set_key _aes_set_key ++# define aes_encrypt _aes_encrypt ++# define aes_decrypt _aes_decrypt ++#endif ++#if !defined(ALIGN32BYTES) ++# define ALIGN32BYTES 32 ++#endif ++ ++ .file "aes-i586.S" ++ .globl aes_set_key ++ .globl aes_encrypt ++ .globl aes_decrypt ++ ++#define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words) ++ ++// offsets to parameters with one register pushed onto stack ++ ++#define ctx 8 // AES context structure ++#define in_blk 12 // input byte array address parameter ++#define out_blk 16 // output byte array address parameter ++ ++// offsets in context structure ++ ++#define nkey 0 // key length, size 4 ++#define nrnd 4 // number of rounds, size 4 ++#define ekey 8 // encryption key schedule base address, size 256 ++#define dkey 264 // decryption key schedule base address, size 256 ++ ++// This macro performs a forward encryption cycle. It is entered with ++// the first previous round column values in %eax, %ebx, %esi and %edi and ++// exits with the final values in the same registers. ++ ++#define fwd_rnd(p1,p2) \ ++ mov %ebx,(%esp) ;\ ++ movzbl %al,%edx ;\ ++ mov %eax,%ecx ;\ ++ mov p2(%ebp),%eax ;\ ++ mov %edi,4(%esp) ;\ ++ mov p2+12(%ebp),%edi ;\ ++ xor p1(,%edx,4),%eax ;\ ++ movzbl %ch,%edx ;\ ++ shr $16,%ecx ;\ ++ mov p2+4(%ebp),%ebx ;\ ++ xor p1+tlen(,%edx,4),%edi ;\ ++ movzbl %cl,%edx ;\ ++ movzbl %ch,%ecx ;\ ++ xor p1+3*tlen(,%ecx,4),%ebx ;\ ++ mov %esi,%ecx ;\ ++ mov p1+2*tlen(,%edx,4),%esi ;\ ++ movzbl %cl,%edx ;\ ++ xor p1(,%edx,4),%esi ;\ ++ movzbl %ch,%edx ;\ ++ shr $16,%ecx ;\ ++ xor p1+tlen(,%edx,4),%ebx ;\ ++ movzbl %cl,%edx ;\ ++ movzbl %ch,%ecx ;\ ++ xor p1+2*tlen(,%edx,4),%eax ;\ ++ mov (%esp),%edx ;\ ++ xor p1+3*tlen(,%ecx,4),%edi ;\ ++ movzbl %dl,%ecx ;\ ++ xor p2+8(%ebp),%esi ;\ ++ xor p1(,%ecx,4),%ebx ;\ ++ movzbl %dh,%ecx ;\ ++ shr $16,%edx ;\ ++ xor p1+tlen(,%ecx,4),%eax ;\ ++ movzbl %dl,%ecx ;\ ++ movzbl %dh,%edx ;\ ++ xor p1+2*tlen(,%ecx,4),%edi ;\ ++ mov 4(%esp),%ecx ;\ ++ xor p1+3*tlen(,%edx,4),%esi ;\ ++ movzbl %cl,%edx ;\ ++ xor p1(,%edx,4),%edi ;\ ++ movzbl %ch,%edx ;\ ++ shr $16,%ecx ;\ ++ xor p1+tlen(,%edx,4),%esi ;\ ++ movzbl %cl,%edx ;\ ++ movzbl %ch,%ecx ;\ ++ xor p1+2*tlen(,%edx,4),%ebx ;\ ++ xor p1+3*tlen(,%ecx,4),%eax ++ ++// This macro performs an inverse encryption cycle. It is entered with ++// the first previous round column values in %eax, %ebx, %esi and %edi and ++// exits with the final values in the same registers. ++ ++#define inv_rnd(p1,p2) \ ++ movzbl %al,%edx ;\ ++ mov %ebx,(%esp) ;\ ++ mov %eax,%ecx ;\ ++ mov p2(%ebp),%eax ;\ ++ mov %edi,4(%esp) ;\ ++ mov p2+4(%ebp),%ebx ;\ ++ xor p1(,%edx,4),%eax ;\ ++ movzbl %ch,%edx ;\ ++ shr $16,%ecx ;\ ++ mov p2+12(%ebp),%edi ;\ ++ xor p1+tlen(,%edx,4),%ebx ;\ ++ movzbl %cl,%edx ;\ ++ movzbl %ch,%ecx ;\ ++ xor p1+3*tlen(,%ecx,4),%edi ;\ ++ mov %esi,%ecx ;\ ++ mov p1+2*tlen(,%edx,4),%esi ;\ ++ movzbl %cl,%edx ;\ ++ xor p1(,%edx,4),%esi ;\ ++ movzbl %ch,%edx ;\ ++ shr $16,%ecx ;\ ++ xor p1+tlen(,%edx,4),%edi ;\ ++ movzbl %cl,%edx ;\ ++ movzbl %ch,%ecx ;\ ++ xor p1+2*tlen(,%edx,4),%eax ;\ ++ mov (%esp),%edx ;\ ++ xor p1+3*tlen(,%ecx,4),%ebx ;\ ++ movzbl %dl,%ecx ;\ ++ xor p2+8(%ebp),%esi ;\ ++ xor p1(,%ecx,4),%ebx ;\ ++ movzbl %dh,%ecx ;\ ++ shr $16,%edx ;\ ++ xor p1+tlen(,%ecx,4),%esi ;\ ++ movzbl %dl,%ecx ;\ ++ movzbl %dh,%edx ;\ ++ xor p1+2*tlen(,%ecx,4),%edi ;\ ++ mov 4(%esp),%ecx ;\ ++ xor p1+3*tlen(,%edx,4),%eax ;\ ++ movzbl %cl,%edx ;\ ++ xor p1(,%edx,4),%edi ;\ ++ movzbl %ch,%edx ;\ ++ shr $16,%ecx ;\ ++ xor p1+tlen(,%edx,4),%eax ;\ ++ movzbl %cl,%edx ;\ ++ movzbl %ch,%ecx ;\ ++ xor p1+2*tlen(,%edx,4),%ebx ;\ ++ xor p1+3*tlen(,%ecx,4),%esi ++ ++// AES (Rijndael) Encryption Subroutine ++ ++ .text ++ .align ALIGN32BYTES ++aes_encrypt: ++ push %ebp ++ mov ctx(%esp),%ebp // pointer to context ++ mov in_blk(%esp),%ecx ++ push %ebx ++ push %esi ++ push %edi ++ mov nrnd(%ebp),%edx // number of rounds ++ lea ekey+16(%ebp),%ebp // key pointer ++ ++// input four columns and xor in first round key ++ ++ mov (%ecx),%eax ++ mov 4(%ecx),%ebx ++ mov 8(%ecx),%esi ++ mov 12(%ecx),%edi ++ xor -16(%ebp),%eax ++ xor -12(%ebp),%ebx ++ xor -8(%ebp),%esi ++ xor -4(%ebp),%edi ++ ++ sub $8,%esp // space for register saves on stack ++ ++ sub $10,%edx ++ je aes_15 ++ add $32,%ebp ++ sub $2,%edx ++ je aes_13 ++ add $32,%ebp ++ ++ fwd_rnd(aes_ft_tab,-64) // 14 rounds for 256-bit key ++ fwd_rnd(aes_ft_tab,-48) ++aes_13: fwd_rnd(aes_ft_tab,-32) // 12 rounds for 192-bit key ++ fwd_rnd(aes_ft_tab,-16) ++aes_15: fwd_rnd(aes_ft_tab,0) // 10 rounds for 128-bit key ++ fwd_rnd(aes_ft_tab,16) ++ fwd_rnd(aes_ft_tab,32) ++ fwd_rnd(aes_ft_tab,48) ++ fwd_rnd(aes_ft_tab,64) ++ fwd_rnd(aes_ft_tab,80) ++ fwd_rnd(aes_ft_tab,96) ++ fwd_rnd(aes_ft_tab,112) ++ fwd_rnd(aes_ft_tab,128) ++ fwd_rnd(aes_fl_tab,144) // last round uses a different table ++ ++// move final values to the output array. ++ ++ mov out_blk+20(%esp),%ebp ++ add $8,%esp ++ mov %eax,(%ebp) ++ mov %ebx,4(%ebp) ++ mov %esi,8(%ebp) ++ mov %edi,12(%ebp) ++ pop %edi ++ pop %esi ++ pop %ebx ++ pop %ebp ++ ret ++ ++ ++// AES (Rijndael) Decryption Subroutine ++ ++ .align ALIGN32BYTES ++aes_decrypt: ++ push %ebp ++ mov ctx(%esp),%ebp // pointer to context ++ mov in_blk(%esp),%ecx ++ push %ebx ++ push %esi ++ push %edi ++ mov nrnd(%ebp),%edx // number of rounds ++ lea dkey+16(%ebp),%ebp // key pointer ++ ++// input four columns and xor in first round key ++ ++ mov (%ecx),%eax ++ mov 4(%ecx),%ebx ++ mov 8(%ecx),%esi ++ mov 12(%ecx),%edi ++ xor -16(%ebp),%eax ++ xor -12(%ebp),%ebx ++ xor -8(%ebp),%esi ++ xor -4(%ebp),%edi ++ ++ sub $8,%esp // space for register saves on stack ++ ++ sub $10,%edx ++ je aes_25 ++ add $32,%ebp ++ sub $2,%edx ++ je aes_23 ++ add $32,%ebp ++ ++ inv_rnd(aes_it_tab,-64) // 14 rounds for 256-bit key ++ inv_rnd(aes_it_tab,-48) ++aes_23: inv_rnd(aes_it_tab,-32) // 12 rounds for 192-bit key ++ inv_rnd(aes_it_tab,-16) ++aes_25: inv_rnd(aes_it_tab,0) // 10 rounds for 128-bit key ++ inv_rnd(aes_it_tab,16) ++ inv_rnd(aes_it_tab,32) ++ inv_rnd(aes_it_tab,48) ++ inv_rnd(aes_it_tab,64) ++ inv_rnd(aes_it_tab,80) ++ inv_rnd(aes_it_tab,96) ++ inv_rnd(aes_it_tab,112) ++ inv_rnd(aes_it_tab,128) ++ inv_rnd(aes_il_tab,144) // last round uses a different table ++ ++// move final values to the output array. ++ ++ mov out_blk+20(%esp),%ebp ++ add $8,%esp ++ mov %eax,(%ebp) ++ mov %ebx,4(%ebp) ++ mov %esi,8(%ebp) ++ mov %edi,12(%ebp) ++ pop %edi ++ pop %esi ++ pop %ebx ++ pop %ebp ++ ret ++ ++// AES (Rijndael) Key Schedule Subroutine ++ ++// input/output parameters ++ ++#define aes_cx 12 // AES context ++#define in_key 16 // key input array address ++#define key_ln 20 // key length, bytes (16,24,32) or bits (128,192,256) ++#define ed_flg 24 // 0=create both encr/decr keys, 1=create encr key only ++ ++// offsets for locals ++ ++#define cnt -4 ++#define kpf -8 ++#define slen 8 ++ ++// This macro performs a column mixing operation on an input 32-bit ++// word to give a 32-bit result. It uses each of the 4 bytes in the ++// the input column to index 4 different tables of 256 32-bit words ++// that are xored together to form the output value. ++ ++#define mix_col(p1) \ ++ movzbl %bl,%ecx ;\ ++ mov p1(,%ecx,4),%eax ;\ ++ movzbl %bh,%ecx ;\ ++ ror $16,%ebx ;\ ++ xor p1+tlen(,%ecx,4),%eax ;\ ++ movzbl %bl,%ecx ;\ ++ xor p1+2*tlen(,%ecx,4),%eax ;\ ++ movzbl %bh,%ecx ;\ ++ xor p1+3*tlen(,%ecx,4),%eax ++ ++// Key Schedule Macros ++ ++#define ksc4(p1) \ ++ rol $24,%ebx ;\ ++ mix_col(aes_fl_tab) ;\ ++ ror $8,%ebx ;\ ++ xor 4*p1+aes_rcon_tab,%eax ;\ ++ xor %eax,%esi ;\ ++ xor %esi,%ebp ;\ ++ mov %esi,16*p1(%edi) ;\ ++ mov %ebp,16*p1+4(%edi) ;\ ++ xor %ebp,%edx ;\ ++ xor %edx,%ebx ;\ ++ mov %edx,16*p1+8(%edi) ;\ ++ mov %ebx,16*p1+12(%edi) ++ ++#define ksc6(p1) \ ++ rol $24,%ebx ;\ ++ mix_col(aes_fl_tab) ;\ ++ ror $8,%ebx ;\ ++ xor 4*p1+aes_rcon_tab,%eax ;\ ++ xor 24*p1-24(%edi),%eax ;\ ++ mov %eax,24*p1(%edi) ;\ ++ xor 24*p1-20(%edi),%eax ;\ ++ mov %eax,24*p1+4(%edi) ;\ ++ xor %eax,%esi ;\ ++ xor %esi,%ebp ;\ ++ mov %esi,24*p1+8(%edi) ;\ ++ mov %ebp,24*p1+12(%edi) ;\ ++ xor %ebp,%edx ;\ ++ xor %edx,%ebx ;\ ++ mov %edx,24*p1+16(%edi) ;\ ++ mov %ebx,24*p1+20(%edi) ++ ++#define ksc8(p1) \ ++ rol $24,%ebx ;\ ++ mix_col(aes_fl_tab) ;\ ++ ror $8,%ebx ;\ ++ xor 4*p1+aes_rcon_tab,%eax ;\ ++ xor 32*p1-32(%edi),%eax ;\ ++ mov %eax,32*p1(%edi) ;\ ++ xor 32*p1-28(%edi),%eax ;\ ++ mov %eax,32*p1+4(%edi) ;\ ++ xor 32*p1-24(%edi),%eax ;\ ++ mov %eax,32*p1+8(%edi) ;\ ++ xor 32*p1-20(%edi),%eax ;\ ++ mov %eax,32*p1+12(%edi) ;\ ++ push %ebx ;\ ++ mov %eax,%ebx ;\ ++ mix_col(aes_fl_tab) ;\ ++ pop %ebx ;\ ++ xor %eax,%esi ;\ ++ xor %esi,%ebp ;\ ++ mov %esi,32*p1+16(%edi) ;\ ++ mov %ebp,32*p1+20(%edi) ;\ ++ xor %ebp,%edx ;\ ++ xor %edx,%ebx ;\ ++ mov %edx,32*p1+24(%edi) ;\ ++ mov %ebx,32*p1+28(%edi) ++ ++ .align ALIGN32BYTES ++aes_set_key: ++ pushfl ++ push %ebp ++ mov %esp,%ebp ++ sub $slen,%esp ++ push %ebx ++ push %esi ++ push %edi ++ ++ mov aes_cx(%ebp),%edx // edx -> AES context ++ ++ mov key_ln(%ebp),%ecx // key length ++ cmpl $128,%ecx ++ jb aes_30 ++ shr $3,%ecx ++aes_30: cmpl $32,%ecx ++ je aes_32 ++ cmpl $24,%ecx ++ je aes_32 ++ mov $16,%ecx ++aes_32: shr $2,%ecx ++ mov %ecx,nkey(%edx) ++ ++ lea 6(%ecx),%eax // 10/12/14 for 4/6/8 32-bit key length ++ mov %eax,nrnd(%edx) ++ ++ mov in_key(%ebp),%esi // key input array ++ lea ekey(%edx),%edi // key position in AES context ++ cld ++ push %ebp ++ mov %ecx,%eax // save key length in eax ++ rep ; movsl // words in the key schedule ++ mov -4(%esi),%ebx // put some values in registers ++ mov -8(%esi),%edx // to allow faster code ++ mov -12(%esi),%ebp ++ mov -16(%esi),%esi ++ ++ cmpl $4,%eax // jump on key size ++ je aes_36 ++ cmpl $6,%eax ++ je aes_35 ++ ++ ksc8(0) ++ ksc8(1) ++ ksc8(2) ++ ksc8(3) ++ ksc8(4) ++ ksc8(5) ++ ksc8(6) ++ jmp aes_37 ++aes_35: ksc6(0) ++ ksc6(1) ++ ksc6(2) ++ ksc6(3) ++ ksc6(4) ++ ksc6(5) ++ ksc6(6) ++ ksc6(7) ++ jmp aes_37 ++aes_36: ksc4(0) ++ ksc4(1) ++ ksc4(2) ++ ksc4(3) ++ ksc4(4) ++ ksc4(5) ++ ksc4(6) ++ ksc4(7) ++ ksc4(8) ++ ksc4(9) ++aes_37: pop %ebp ++ mov aes_cx(%ebp),%edx // edx -> AES context ++ cmpl $0,ed_flg(%ebp) ++ jne aes_39 ++ ++// compile decryption key schedule from encryption schedule - reverse ++// order and do mix_column operation on round keys except first and last ++ ++ mov nrnd(%edx),%eax // kt = cx->d_key + nc * cx->Nrnd ++ shl $2,%eax ++ lea dkey(%edx,%eax,4),%edi ++ lea ekey(%edx),%esi // kf = cx->e_key ++ ++ movsl // copy first round key (unmodified) ++ movsl ++ movsl ++ movsl ++ sub $32,%edi ++ movl $1,cnt(%ebp) ++aes_38: // do mix column on each column of ++ lodsl // each round key ++ mov %eax,%ebx ++ mix_col(aes_im_tab) ++ stosl ++ lodsl ++ mov %eax,%ebx ++ mix_col(aes_im_tab) ++ stosl ++ lodsl ++ mov %eax,%ebx ++ mix_col(aes_im_tab) ++ stosl ++ lodsl ++ mov %eax,%ebx ++ mix_col(aes_im_tab) ++ stosl ++ sub $32,%edi ++ ++ incl cnt(%ebp) ++ mov cnt(%ebp),%eax ++ cmp nrnd(%edx),%eax ++ jb aes_38 ++ ++ movsl // copy last round key (unmodified) ++ movsl ++ movsl ++ movsl ++aes_39: pop %edi ++ pop %esi ++ pop %ebx ++ mov %ebp,%esp ++ pop %ebp ++ popfl ++ ret ++ ++ ++// finite field multiplies by {02}, {04} and {08} ++ ++#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b)) ++#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b)) ++#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b)) ++ ++// finite field multiplies required in table generation ++ ++#define f3(x) (f2(x) ^ x) ++#define f9(x) (f8(x) ^ x) ++#define fb(x) (f8(x) ^ f2(x) ^ x) ++#define fd(x) (f8(x) ^ f4(x) ^ x) ++#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) ++ ++// These defines generate the forward table entries ++ ++#define u0(x) ((f3(x) << 24) | (x << 16) | (x << 8) | f2(x)) ++#define u1(x) ((x << 24) | (x << 16) | (f2(x) << 8) | f3(x)) ++#define u2(x) ((x << 24) | (f2(x) << 16) | (f3(x) << 8) | x) ++#define u3(x) ((f2(x) << 24) | (f3(x) << 16) | (x << 8) | x) ++ ++// These defines generate the inverse table entries ++ ++#define v0(x) ((fb(x) << 24) | (fd(x) << 16) | (f9(x) << 8) | fe(x)) ++#define v1(x) ((fd(x) << 24) | (f9(x) << 16) | (fe(x) << 8) | fb(x)) ++#define v2(x) ((f9(x) << 24) | (fe(x) << 16) | (fb(x) << 8) | fd(x)) ++#define v3(x) ((fe(x) << 24) | (fb(x) << 16) | (fd(x) << 8) | f9(x)) ++ ++// These defines generate entries for the last round tables ++ ++#define w0(x) (x) ++#define w1(x) (x << 8) ++#define w2(x) (x << 16) ++#define w3(x) (x << 24) ++ ++// macro to generate inverse mix column tables (needed for the key schedule) ++ ++#define im_data0(p1) \ ++ .long p1(0x00),p1(0x01),p1(0x02),p1(0x03),p1(0x04),p1(0x05),p1(0x06),p1(0x07) ;\ ++ .long p1(0x08),p1(0x09),p1(0x0a),p1(0x0b),p1(0x0c),p1(0x0d),p1(0x0e),p1(0x0f) ;\ ++ .long p1(0x10),p1(0x11),p1(0x12),p1(0x13),p1(0x14),p1(0x15),p1(0x16),p1(0x17) ;\ ++ .long p1(0x18),p1(0x19),p1(0x1a),p1(0x1b),p1(0x1c),p1(0x1d),p1(0x1e),p1(0x1f) ++#define im_data1(p1) \ ++ .long p1(0x20),p1(0x21),p1(0x22),p1(0x23),p1(0x24),p1(0x25),p1(0x26),p1(0x27) ;\ ++ .long p1(0x28),p1(0x29),p1(0x2a),p1(0x2b),p1(0x2c),p1(0x2d),p1(0x2e),p1(0x2f) ;\ ++ .long p1(0x30),p1(0x31),p1(0x32),p1(0x33),p1(0x34),p1(0x35),p1(0x36),p1(0x37) ;\ ++ .long p1(0x38),p1(0x39),p1(0x3a),p1(0x3b),p1(0x3c),p1(0x3d),p1(0x3e),p1(0x3f) ++#define im_data2(p1) \ ++ .long p1(0x40),p1(0x41),p1(0x42),p1(0x43),p1(0x44),p1(0x45),p1(0x46),p1(0x47) ;\ ++ .long p1(0x48),p1(0x49),p1(0x4a),p1(0x4b),p1(0x4c),p1(0x4d),p1(0x4e),p1(0x4f) ;\ ++ .long p1(0x50),p1(0x51),p1(0x52),p1(0x53),p1(0x54),p1(0x55),p1(0x56),p1(0x57) ;\ ++ .long p1(0x58),p1(0x59),p1(0x5a),p1(0x5b),p1(0x5c),p1(0x5d),p1(0x5e),p1(0x5f) ++#define im_data3(p1) \ ++ .long p1(0x60),p1(0x61),p1(0x62),p1(0x63),p1(0x64),p1(0x65),p1(0x66),p1(0x67) ;\ ++ .long p1(0x68),p1(0x69),p1(0x6a),p1(0x6b),p1(0x6c),p1(0x6d),p1(0x6e),p1(0x6f) ;\ ++ .long p1(0x70),p1(0x71),p1(0x72),p1(0x73),p1(0x74),p1(0x75),p1(0x76),p1(0x77) ;\ ++ .long p1(0x78),p1(0x79),p1(0x7a),p1(0x7b),p1(0x7c),p1(0x7d),p1(0x7e),p1(0x7f) ++#define im_data4(p1) \ ++ .long p1(0x80),p1(0x81),p1(0x82),p1(0x83),p1(0x84),p1(0x85),p1(0x86),p1(0x87) ;\ ++ .long p1(0x88),p1(0x89),p1(0x8a),p1(0x8b),p1(0x8c),p1(0x8d),p1(0x8e),p1(0x8f) ;\ ++ .long p1(0x90),p1(0x91),p1(0x92),p1(0x93),p1(0x94),p1(0x95),p1(0x96),p1(0x97) ;\ ++ .long p1(0x98),p1(0x99),p1(0x9a),p1(0x9b),p1(0x9c),p1(0x9d),p1(0x9e),p1(0x9f) ++#define im_data5(p1) \ ++ .long p1(0xa0),p1(0xa1),p1(0xa2),p1(0xa3),p1(0xa4),p1(0xa5),p1(0xa6),p1(0xa7) ;\ ++ .long p1(0xa8),p1(0xa9),p1(0xaa),p1(0xab),p1(0xac),p1(0xad),p1(0xae),p1(0xaf) ;\ ++ .long p1(0xb0),p1(0xb1),p1(0xb2),p1(0xb3),p1(0xb4),p1(0xb5),p1(0xb6),p1(0xb7) ;\ ++ .long p1(0xb8),p1(0xb9),p1(0xba),p1(0xbb),p1(0xbc),p1(0xbd),p1(0xbe),p1(0xbf) ++#define im_data6(p1) \ ++ .long p1(0xc0),p1(0xc1),p1(0xc2),p1(0xc3),p1(0xc4),p1(0xc5),p1(0xc6),p1(0xc7) ;\ ++ .long p1(0xc8),p1(0xc9),p1(0xca),p1(0xcb),p1(0xcc),p1(0xcd),p1(0xce),p1(0xcf) ;\ ++ .long p1(0xd0),p1(0xd1),p1(0xd2),p1(0xd3),p1(0xd4),p1(0xd5),p1(0xd6),p1(0xd7) ;\ ++ .long p1(0xd8),p1(0xd9),p1(0xda),p1(0xdb),p1(0xdc),p1(0xdd),p1(0xde),p1(0xdf) ++#define im_data7(p1) \ ++ .long p1(0xe0),p1(0xe1),p1(0xe2),p1(0xe3),p1(0xe4),p1(0xe5),p1(0xe6),p1(0xe7) ;\ ++ .long p1(0xe8),p1(0xe9),p1(0xea),p1(0xeb),p1(0xec),p1(0xed),p1(0xee),p1(0xef) ;\ ++ .long p1(0xf0),p1(0xf1),p1(0xf2),p1(0xf3),p1(0xf4),p1(0xf5),p1(0xf6),p1(0xf7) ;\ ++ .long p1(0xf8),p1(0xf9),p1(0xfa),p1(0xfb),p1(0xfc),p1(0xfd),p1(0xfe),p1(0xff) ++ ++// S-box data - 256 entries ++ ++#define sb_data0(p1) \ ++ .long p1(0x63),p1(0x7c),p1(0x77),p1(0x7b),p1(0xf2),p1(0x6b),p1(0x6f),p1(0xc5) ;\ ++ .long p1(0x30),p1(0x01),p1(0x67),p1(0x2b),p1(0xfe),p1(0xd7),p1(0xab),p1(0x76) ;\ ++ .long p1(0xca),p1(0x82),p1(0xc9),p1(0x7d),p1(0xfa),p1(0x59),p1(0x47),p1(0xf0) ;\ ++ .long p1(0xad),p1(0xd4),p1(0xa2),p1(0xaf),p1(0x9c),p1(0xa4),p1(0x72),p1(0xc0) ++#define sb_data1(p1) \ ++ .long p1(0xb7),p1(0xfd),p1(0x93),p1(0x26),p1(0x36),p1(0x3f),p1(0xf7),p1(0xcc) ;\ ++ .long p1(0x34),p1(0xa5),p1(0xe5),p1(0xf1),p1(0x71),p1(0xd8),p1(0x31),p1(0x15) ;\ ++ .long p1(0x04),p1(0xc7),p1(0x23),p1(0xc3),p1(0x18),p1(0x96),p1(0x05),p1(0x9a) ;\ ++ .long p1(0x07),p1(0x12),p1(0x80),p1(0xe2),p1(0xeb),p1(0x27),p1(0xb2),p1(0x75) ++#define sb_data2(p1) \ ++ .long p1(0x09),p1(0x83),p1(0x2c),p1(0x1a),p1(0x1b),p1(0x6e),p1(0x5a),p1(0xa0) ;\ ++ .long p1(0x52),p1(0x3b),p1(0xd6),p1(0xb3),p1(0x29),p1(0xe3),p1(0x2f),p1(0x84) ;\ ++ .long p1(0x53),p1(0xd1),p1(0x00),p1(0xed),p1(0x20),p1(0xfc),p1(0xb1),p1(0x5b) ;\ ++ .long p1(0x6a),p1(0xcb),p1(0xbe),p1(0x39),p1(0x4a),p1(0x4c),p1(0x58),p1(0xcf) ++#define sb_data3(p1) \ ++ .long p1(0xd0),p1(0xef),p1(0xaa),p1(0xfb),p1(0x43),p1(0x4d),p1(0x33),p1(0x85) ;\ ++ .long p1(0x45),p1(0xf9),p1(0x02),p1(0x7f),p1(0x50),p1(0x3c),p1(0x9f),p1(0xa8) ;\ ++ .long p1(0x51),p1(0xa3),p1(0x40),p1(0x8f),p1(0x92),p1(0x9d),p1(0x38),p1(0xf5) ;\ ++ .long p1(0xbc),p1(0xb6),p1(0xda),p1(0x21),p1(0x10),p1(0xff),p1(0xf3),p1(0xd2) ++#define sb_data4(p1) \ ++ .long p1(0xcd),p1(0x0c),p1(0x13),p1(0xec),p1(0x5f),p1(0x97),p1(0x44),p1(0x17) ;\ ++ .long p1(0xc4),p1(0xa7),p1(0x7e),p1(0x3d),p1(0x64),p1(0x5d),p1(0x19),p1(0x73) ;\ ++ .long p1(0x60),p1(0x81),p1(0x4f),p1(0xdc),p1(0x22),p1(0x2a),p1(0x90),p1(0x88) ;\ ++ .long p1(0x46),p1(0xee),p1(0xb8),p1(0x14),p1(0xde),p1(0x5e),p1(0x0b),p1(0xdb) ++#define sb_data5(p1) \ ++ .long p1(0xe0),p1(0x32),p1(0x3a),p1(0x0a),p1(0x49),p1(0x06),p1(0x24),p1(0x5c) ;\ ++ .long p1(0xc2),p1(0xd3),p1(0xac),p1(0x62),p1(0x91),p1(0x95),p1(0xe4),p1(0x79) ;\ ++ .long p1(0xe7),p1(0xc8),p1(0x37),p1(0x6d),p1(0x8d),p1(0xd5),p1(0x4e),p1(0xa9) ;\ ++ .long p1(0x6c),p1(0x56),p1(0xf4),p1(0xea),p1(0x65),p1(0x7a),p1(0xae),p1(0x08) ++#define sb_data6(p1) \ ++ .long p1(0xba),p1(0x78),p1(0x25),p1(0x2e),p1(0x1c),p1(0xa6),p1(0xb4),p1(0xc6) ;\ ++ .long p1(0xe8),p1(0xdd),p1(0x74),p1(0x1f),p1(0x4b),p1(0xbd),p1(0x8b),p1(0x8a) ;\ ++ .long p1(0x70),p1(0x3e),p1(0xb5),p1(0x66),p1(0x48),p1(0x03),p1(0xf6),p1(0x0e) ;\ ++ .long p1(0x61),p1(0x35),p1(0x57),p1(0xb9),p1(0x86),p1(0xc1),p1(0x1d),p1(0x9e) ++#define sb_data7(p1) \ ++ .long p1(0xe1),p1(0xf8),p1(0x98),p1(0x11),p1(0x69),p1(0xd9),p1(0x8e),p1(0x94) ;\ ++ .long p1(0x9b),p1(0x1e),p1(0x87),p1(0xe9),p1(0xce),p1(0x55),p1(0x28),p1(0xdf) ;\ ++ .long p1(0x8c),p1(0xa1),p1(0x89),p1(0x0d),p1(0xbf),p1(0xe6),p1(0x42),p1(0x68) ;\ ++ .long p1(0x41),p1(0x99),p1(0x2d),p1(0x0f),p1(0xb0),p1(0x54),p1(0xbb),p1(0x16) ++ ++// Inverse S-box data - 256 entries ++ ++#define ib_data0(p1) \ ++ .long p1(0x52),p1(0x09),p1(0x6a),p1(0xd5),p1(0x30),p1(0x36),p1(0xa5),p1(0x38) ;\ ++ .long p1(0xbf),p1(0x40),p1(0xa3),p1(0x9e),p1(0x81),p1(0xf3),p1(0xd7),p1(0xfb) ;\ ++ .long p1(0x7c),p1(0xe3),p1(0x39),p1(0x82),p1(0x9b),p1(0x2f),p1(0xff),p1(0x87) ;\ ++ .long p1(0x34),p1(0x8e),p1(0x43),p1(0x44),p1(0xc4),p1(0xde),p1(0xe9),p1(0xcb) ++#define ib_data1(p1) \ ++ .long p1(0x54),p1(0x7b),p1(0x94),p1(0x32),p1(0xa6),p1(0xc2),p1(0x23),p1(0x3d) ;\ ++ .long p1(0xee),p1(0x4c),p1(0x95),p1(0x0b),p1(0x42),p1(0xfa),p1(0xc3),p1(0x4e) ;\ ++ .long p1(0x08),p1(0x2e),p1(0xa1),p1(0x66),p1(0x28),p1(0xd9),p1(0x24),p1(0xb2) ;\ ++ .long p1(0x76),p1(0x5b),p1(0xa2),p1(0x49),p1(0x6d),p1(0x8b),p1(0xd1),p1(0x25) ++#define ib_data2(p1) \ ++ .long p1(0x72),p1(0xf8),p1(0xf6),p1(0x64),p1(0x86),p1(0x68),p1(0x98),p1(0x16) ;\ ++ .long p1(0xd4),p1(0xa4),p1(0x5c),p1(0xcc),p1(0x5d),p1(0x65),p1(0xb6),p1(0x92) ;\ ++ .long p1(0x6c),p1(0x70),p1(0x48),p1(0x50),p1(0xfd),p1(0xed),p1(0xb9),p1(0xda) ;\ ++ .long p1(0x5e),p1(0x15),p1(0x46),p1(0x57),p1(0xa7),p1(0x8d),p1(0x9d),p1(0x84) ++#define ib_data3(p1) \ ++ .long p1(0x90),p1(0xd8),p1(0xab),p1(0x00),p1(0x8c),p1(0xbc),p1(0xd3),p1(0x0a) ;\ ++ .long p1(0xf7),p1(0xe4),p1(0x58),p1(0x05),p1(0xb8),p1(0xb3),p1(0x45),p1(0x06) ;\ ++ .long p1(0xd0),p1(0x2c),p1(0x1e),p1(0x8f),p1(0xca),p1(0x3f),p1(0x0f),p1(0x02) ;\ ++ .long p1(0xc1),p1(0xaf),p1(0xbd),p1(0x03),p1(0x01),p1(0x13),p1(0x8a),p1(0x6b) ++#define ib_data4(p1) \ ++ .long p1(0x3a),p1(0x91),p1(0x11),p1(0x41),p1(0x4f),p1(0x67),p1(0xdc),p1(0xea) ;\ ++ .long p1(0x97),p1(0xf2),p1(0xcf),p1(0xce),p1(0xf0),p1(0xb4),p1(0xe6),p1(0x73) ;\ ++ .long p1(0x96),p1(0xac),p1(0x74),p1(0x22),p1(0xe7),p1(0xad),p1(0x35),p1(0x85) ;\ ++ .long p1(0xe2),p1(0xf9),p1(0x37),p1(0xe8),p1(0x1c),p1(0x75),p1(0xdf),p1(0x6e) ++#define ib_data5(p1) \ ++ .long p1(0x47),p1(0xf1),p1(0x1a),p1(0x71),p1(0x1d),p1(0x29),p1(0xc5),p1(0x89) ;\ ++ .long p1(0x6f),p1(0xb7),p1(0x62),p1(0x0e),p1(0xaa),p1(0x18),p1(0xbe),p1(0x1b) ;\ ++ .long p1(0xfc),p1(0x56),p1(0x3e),p1(0x4b),p1(0xc6),p1(0xd2),p1(0x79),p1(0x20) ;\ ++ .long p1(0x9a),p1(0xdb),p1(0xc0),p1(0xfe),p1(0x78),p1(0xcd),p1(0x5a),p1(0xf4) ++#define ib_data6(p1) \ ++ .long p1(0x1f),p1(0xdd),p1(0xa8),p1(0x33),p1(0x88),p1(0x07),p1(0xc7),p1(0x31) ;\ ++ .long p1(0xb1),p1(0x12),p1(0x10),p1(0x59),p1(0x27),p1(0x80),p1(0xec),p1(0x5f) ;\ ++ .long p1(0x60),p1(0x51),p1(0x7f),p1(0xa9),p1(0x19),p1(0xb5),p1(0x4a),p1(0x0d) ;\ ++ .long p1(0x2d),p1(0xe5),p1(0x7a),p1(0x9f),p1(0x93),p1(0xc9),p1(0x9c),p1(0xef) ++#define ib_data7(p1) \ ++ .long p1(0xa0),p1(0xe0),p1(0x3b),p1(0x4d),p1(0xae),p1(0x2a),p1(0xf5),p1(0xb0) ;\ ++ .long p1(0xc8),p1(0xeb),p1(0xbb),p1(0x3c),p1(0x83),p1(0x53),p1(0x99),p1(0x61) ;\ ++ .long p1(0x17),p1(0x2b),p1(0x04),p1(0x7e),p1(0xba),p1(0x77),p1(0xd6),p1(0x26) ;\ ++ .long p1(0xe1),p1(0x69),p1(0x14),p1(0x63),p1(0x55),p1(0x21),p1(0x0c),p1(0x7d) ++ ++// The rcon_table (needed for the key schedule) ++// ++// Here is original Dr Brian Gladman's source code: ++// _rcon_tab: ++// %assign x 1 ++// %rep 29 ++// dd x ++// %assign x f2(x) ++// %endrep ++// ++// Here is precomputed output (it's more portable this way): ++ ++ .align ALIGN32BYTES ++aes_rcon_tab: ++ .long 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 ++ .long 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f ++ .long 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4 ++ .long 0xb3,0x7d,0xfa,0xef,0xc5 ++ ++// The forward xor tables ++ ++ .align ALIGN32BYTES ++aes_ft_tab: ++ sb_data0(u0) ++ sb_data1(u0) ++ sb_data2(u0) ++ sb_data3(u0) ++ sb_data4(u0) ++ sb_data5(u0) ++ sb_data6(u0) ++ sb_data7(u0) ++ ++ sb_data0(u1) ++ sb_data1(u1) ++ sb_data2(u1) ++ sb_data3(u1) ++ sb_data4(u1) ++ sb_data5(u1) ++ sb_data6(u1) ++ sb_data7(u1) ++ ++ sb_data0(u2) ++ sb_data1(u2) ++ sb_data2(u2) ++ sb_data3(u2) ++ sb_data4(u2) ++ sb_data5(u2) ++ sb_data6(u2) ++ sb_data7(u2) ++ ++ sb_data0(u3) ++ sb_data1(u3) ++ sb_data2(u3) ++ sb_data3(u3) ++ sb_data4(u3) ++ sb_data5(u3) ++ sb_data6(u3) ++ sb_data7(u3) ++ ++ .align ALIGN32BYTES ++aes_fl_tab: ++ sb_data0(w0) ++ sb_data1(w0) ++ sb_data2(w0) ++ sb_data3(w0) ++ sb_data4(w0) ++ sb_data5(w0) ++ sb_data6(w0) ++ sb_data7(w0) ++ ++ sb_data0(w1) ++ sb_data1(w1) ++ sb_data2(w1) ++ sb_data3(w1) ++ sb_data4(w1) ++ sb_data5(w1) ++ sb_data6(w1) ++ sb_data7(w1) ++ ++ sb_data0(w2) ++ sb_data1(w2) ++ sb_data2(w2) ++ sb_data3(w2) ++ sb_data4(w2) ++ sb_data5(w2) ++ sb_data6(w2) ++ sb_data7(w2) ++ ++ sb_data0(w3) ++ sb_data1(w3) ++ sb_data2(w3) ++ sb_data3(w3) ++ sb_data4(w3) ++ sb_data5(w3) ++ sb_data6(w3) ++ sb_data7(w3) ++ ++// The inverse xor tables ++ ++ .align ALIGN32BYTES ++aes_it_tab: ++ ib_data0(v0) ++ ib_data1(v0) ++ ib_data2(v0) ++ ib_data3(v0) ++ ib_data4(v0) ++ ib_data5(v0) ++ ib_data6(v0) ++ ib_data7(v0) ++ ++ ib_data0(v1) ++ ib_data1(v1) ++ ib_data2(v1) ++ ib_data3(v1) ++ ib_data4(v1) ++ ib_data5(v1) ++ ib_data6(v1) ++ ib_data7(v1) ++ ++ ib_data0(v2) ++ ib_data1(v2) ++ ib_data2(v2) ++ ib_data3(v2) ++ ib_data4(v2) ++ ib_data5(v2) ++ ib_data6(v2) ++ ib_data7(v2) ++ ++ ib_data0(v3) ++ ib_data1(v3) ++ ib_data2(v3) ++ ib_data3(v3) ++ ib_data4(v3) ++ ib_data5(v3) ++ ib_data6(v3) ++ ib_data7(v3) ++ ++ .align ALIGN32BYTES ++aes_il_tab: ++ ib_data0(w0) ++ ib_data1(w0) ++ ib_data2(w0) ++ ib_data3(w0) ++ ib_data4(w0) ++ ib_data5(w0) ++ ib_data6(w0) ++ ib_data7(w0) ++ ++ ib_data0(w1) ++ ib_data1(w1) ++ ib_data2(w1) ++ ib_data3(w1) ++ ib_data4(w1) ++ ib_data5(w1) ++ ib_data6(w1) ++ ib_data7(w1) ++ ++ ib_data0(w2) ++ ib_data1(w2) ++ ib_data2(w2) ++ ib_data3(w2) ++ ib_data4(w2) ++ ib_data5(w2) ++ ib_data6(w2) ++ ib_data7(w2) ++ ++ ib_data0(w3) ++ ib_data1(w3) ++ ib_data2(w3) ++ ib_data3(w3) ++ ib_data4(w3) ++ ib_data5(w3) ++ ib_data6(w3) ++ ib_data7(w3) ++ ++// The inverse mix column tables ++ ++ .align ALIGN32BYTES ++aes_im_tab: ++ im_data0(v0) ++ im_data1(v0) ++ im_data2(v0) ++ im_data3(v0) ++ im_data4(v0) ++ im_data5(v0) ++ im_data6(v0) ++ im_data7(v0) ++ ++ im_data0(v1) ++ im_data1(v1) ++ im_data2(v1) ++ im_data3(v1) ++ im_data4(v1) ++ im_data5(v1) ++ im_data6(v1) ++ im_data7(v1) ++ ++ im_data0(v2) ++ im_data1(v2) ++ im_data2(v2) ++ im_data3(v2) ++ im_data4(v2) ++ im_data5(v2) ++ im_data6(v2) ++ im_data7(v2) ++ ++ im_data0(v3) ++ im_data1(v3) ++ im_data2(v3) ++ im_data3(v3) ++ im_data4(v3) ++ im_data5(v3) ++ im_data6(v3) ++ im_data7(v3) +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/aes/aes.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1415 @@ ++// I retain copyright in this code but I encourage its free use provided ++// that I don't carry any responsibility for the results. I am especially ++// happy to see it used in free and open source software. If you do use ++// it I would appreciate an acknowledgement of its origin in the code or ++// the product that results and I would also appreciate knowing a little ++// about the use to which it is being put. I am grateful to Frank Yellin ++// for some ideas that are used in this implementation. ++// ++// Dr B. R. Gladman <brg@gladman.uk.net> 6th April 2001. ++// ++// This is an implementation of the AES encryption algorithm (Rijndael) ++// designed by Joan Daemen and Vincent Rijmen. This version is designed ++// to provide both fixed and dynamic block and key lengths and can also ++// run with either big or little endian internal byte order (see aes.h). ++// It inputs block and key lengths in bytes with the legal values being ++// 16, 24 and 32. ++ ++/* ++ * Modified by Jari Ruusu, May 1 2001 ++ * - Fixed some compile warnings, code was ok but gcc warned anyway. ++ * - Changed basic types: byte -> unsigned char, word -> u_int32_t ++ * - Major name space cleanup: Names visible to outside now begin ++ * with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c ++ * - Removed C++ and DLL support as part of name space cleanup. ++ * - Eliminated unnecessary recomputation of tables. (actual bug fix) ++ * - Merged precomputed constant tables to aes.c file. ++ * - Removed data alignment restrictions for portability reasons. ++ * - Made block and key lengths accept bit count (128/192/256) ++ * as well byte count (16/24/32). ++ * - Removed all error checks. This change also eliminated the need ++ * to preinitialize the context struct to zero. ++ * - Removed some totally unused constants. ++ */ ++ ++#include "crypto/aes.h" ++ ++// CONFIGURATION OPTIONS (see also aes.h) ++// ++// 1. Define UNROLL for full loop unrolling in encryption and decryption. ++// 2. Define PARTIAL_UNROLL to unroll two loops in encryption and decryption. ++// 3. Define FIXED_TABLES for compiled rather than dynamic tables. ++// 4. Define FF_TABLES to use tables for field multiplies and inverses. ++// Do not enable this without understanding stack space requirements. ++// 5. Define ARRAYS to use arrays to hold the local state block. If this ++// is not defined, individually declared 32-bit words are used. ++// 6. Define FAST_VARIABLE if a high speed variable block implementation ++// is needed (essentially three separate fixed block size code sequences) ++// 7. Define either ONE_TABLE or FOUR_TABLES for a fast table driven ++// version using 1 table (2 kbytes of table space) or 4 tables (8 ++// kbytes of table space) for higher speed. ++// 8. Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed ++// increase by using tables for the last rounds but with more table ++// space (2 or 8 kbytes extra). ++// 9. If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but ++// slower version is provided. ++// 10. If fast decryption key scheduling is needed define ONE_IM_TABLE ++// or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra). ++ ++#define UNROLL ++//#define PARTIAL_UNROLL ++ ++#define FIXED_TABLES ++//#define FF_TABLES ++//#define ARRAYS ++#define FAST_VARIABLE ++ ++//#define ONE_TABLE ++#define FOUR_TABLES ++ ++//#define ONE_LR_TABLE ++#define FOUR_LR_TABLES ++ ++//#define ONE_IM_TABLE ++#define FOUR_IM_TABLES ++ ++#if defined(UNROLL) && defined (PARTIAL_UNROLL) ++#error both UNROLL and PARTIAL_UNROLL are defined ++#endif ++ ++#if defined(ONE_TABLE) && defined (FOUR_TABLES) ++#error both ONE_TABLE and FOUR_TABLES are defined ++#endif ++ ++#if defined(ONE_LR_TABLE) && defined (FOUR_LR_TABLES) ++#error both ONE_LR_TABLE and FOUR_LR_TABLES are defined ++#endif ++ ++#if defined(ONE_IM_TABLE) && defined (FOUR_IM_TABLES) ++#error both ONE_IM_TABLE and FOUR_IM_TABLES are defined ++#endif ++ ++#if defined(AES_BLOCK_SIZE) && AES_BLOCK_SIZE != 16 && AES_BLOCK_SIZE != 24 && AES_BLOCK_SIZE != 32 ++#error an illegal block size has been specified ++#endif ++ ++// upr(x,n): rotates bytes within words by n positions, moving bytes ++// to higher index positions with wrap around into low positions ++// ups(x,n): moves bytes by n positions to higher index positions in ++// words but without wrap around ++// bval(x,n): extracts a byte from a word ++ ++#define upr(x,n) (((x) << 8 * (n)) | ((x) >> (32 - 8 * (n)))) ++#define ups(x,n) ((x) << 8 * (n)) ++#define bval(x,n) ((unsigned char)((x) >> 8 * (n))) ++#define bytes2word(b0, b1, b2, b3) \ ++ ((u_int32_t)(b3) << 24 | (u_int32_t)(b2) << 16 | (u_int32_t)(b1) << 8 | (b0)) ++ ++ ++/* little endian processor without data alignment restrictions: AES_LE_OK */ ++/* original code: i386 */ ++#if defined(i386) || defined(_I386) || defined(__i386__) || defined(__i386) ++#define AES_LE_OK 1 ++/* added (tested): alpha --jjo */ ++#elif defined(__alpha__)|| defined (__alpha) ++#define AES_LE_OK 1 ++/* added (tested): ia64 --jjo */ ++#elif defined(__ia64__)|| defined (__ia64) ++#define AES_LE_OK 1 ++#endif ++ ++#ifdef AES_LE_OK ++/* little endian processor without data alignment restrictions */ ++#define word_in(x) *(u_int32_t*)(x) ++#define const_word_in(x) *(const u_int32_t*)(x) ++#define word_out(x,v) *(u_int32_t*)(x) = (v) ++#define const_word_out(x,v) *(const u_int32_t*)(x) = (v) ++#else ++/* slower but generic big endian or with data alignment restrictions */ ++/* some additional "const" touches to stop "gcc -Wcast-qual" complains --jjo */ ++#define word_in(x) ((u_int32_t)(((unsigned char *)(x))[0])|((u_int32_t)(((unsigned char *)(x))[1])<<8)|((u_int32_t)(((unsigned char *)(x))[2])<<16)|((u_int32_t)(((unsigned char *)(x))[3])<<24)) ++#define const_word_in(x) ((const u_int32_t)(((const unsigned char *)(x))[0])|((const u_int32_t)(((const unsigned char *)(x))[1])<<8)|((const u_int32_t)(((const unsigned char *)(x))[2])<<16)|((const u_int32_t)(((const unsigned char *)(x))[3])<<24)) ++#define word_out(x,v) ((unsigned char *)(x))[0]=(v),((unsigned char *)(x))[1]=((v)>>8),((unsigned char *)(x))[2]=((v)>>16),((unsigned char *)(x))[3]=((v)>>24) ++#define const_word_out(x,v) ((const unsigned char *)(x))[0]=(v),((const unsigned char *)(x))[1]=((v)>>8),((const unsigned char *)(x))[2]=((v)>>16),((const unsigned char *)(x))[3]=((v)>>24) ++#endif ++ ++// Disable at least some poor combinations of options ++ ++#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) ++#define FIXED_TABLES ++#undef UNROLL ++#undef ONE_LR_TABLE ++#undef FOUR_LR_TABLES ++#undef ONE_IM_TABLE ++#undef FOUR_IM_TABLES ++#elif !defined(FOUR_TABLES) ++#ifdef FOUR_LR_TABLES ++#undef FOUR_LR_TABLES ++#define ONE_LR_TABLE ++#endif ++#ifdef FOUR_IM_TABLES ++#undef FOUR_IM_TABLES ++#define ONE_IM_TABLE ++#endif ++#elif !defined(AES_BLOCK_SIZE) ++#if defined(UNROLL) ++#define PARTIAL_UNROLL ++#undef UNROLL ++#endif ++#endif ++ ++// the finite field modular polynomial and elements ++ ++#define ff_poly 0x011b ++#define ff_hi 0x80 ++ ++// multiply four bytes in GF(2^8) by 'x' {02} in parallel ++ ++#define m1 0x80808080 ++#define m2 0x7f7f7f7f ++#define m3 0x0000001b ++#define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * m3)) ++ ++// The following defines provide alternative definitions of FFmulX that might ++// give improved performance if a fast 32-bit multiply is not available. Note ++// that a temporary variable u needs to be defined where FFmulX is used. ++ ++// #define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) ++// #define m4 0x1b1b1b1b ++// #define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) ++ ++// perform column mix operation on four bytes in parallel ++ ++#define fwd_mcol(x) (f2 = FFmulX(x), f2 ^ upr(x ^ f2,3) ^ upr(x,2) ^ upr(x,1)) ++ ++#if defined(FIXED_TABLES) ++ ++// the S-Box table ++ ++static const unsigned char s_box[256] = ++{ ++ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, ++ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, ++ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, ++ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, ++ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, ++ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, ++ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, ++ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, ++ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, ++ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, ++ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, ++ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, ++ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, ++ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, ++ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, ++ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, ++ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, ++ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, ++ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, ++ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, ++ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, ++ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, ++ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, ++ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, ++ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, ++ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, ++ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, ++ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, ++ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, ++ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, ++ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, ++ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ++}; ++ ++// the inverse S-Box table ++ ++static const unsigned char inv_s_box[256] = ++{ ++ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, ++ 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, ++ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, ++ 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, ++ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, ++ 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, ++ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, ++ 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, ++ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, ++ 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, ++ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, ++ 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, ++ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, ++ 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, ++ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, ++ 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, ++ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, ++ 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, ++ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, ++ 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, ++ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, ++ 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, ++ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, ++ 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, ++ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, ++ 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, ++ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, ++ 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, ++ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, ++ 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, ++ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, ++ 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d ++}; ++ ++#define w0(p) 0x000000##p ++ ++// Number of elements required in this table for different ++// block and key lengths is: ++// ++// Nk = 4 6 8 ++// ---------- ++// Nb = 4 | 10 8 7 ++// 6 | 19 12 11 ++// 8 | 29 19 14 ++// ++// this table can be a table of bytes if the key schedule ++// code is adjusted accordingly ++ ++static const u_int32_t rcon_tab[29] = ++{ ++ w0(01), w0(02), w0(04), w0(08), ++ w0(10), w0(20), w0(40), w0(80), ++ w0(1b), w0(36), w0(6c), w0(d8), ++ w0(ab), w0(4d), w0(9a), w0(2f), ++ w0(5e), w0(bc), w0(63), w0(c6), ++ w0(97), w0(35), w0(6a), w0(d4), ++ w0(b3), w0(7d), w0(fa), w0(ef), ++ w0(c5) ++}; ++ ++#undef w0 ++ ++#define r0(p,q,r,s) 0x##p##q##r##s ++#define r1(p,q,r,s) 0x##q##r##s##p ++#define r2(p,q,r,s) 0x##r##s##p##q ++#define r3(p,q,r,s) 0x##s##p##q##r ++#define w0(p) 0x000000##p ++#define w1(p) 0x0000##p##00 ++#define w2(p) 0x00##p##0000 ++#define w3(p) 0x##p##000000 ++ ++#if defined(FIXED_TABLES) && (defined(ONE_TABLE) || defined(FOUR_TABLES)) ++ ++// data for forward tables (other than last round) ++ ++#define f_table \ ++ r(a5,63,63,c6), r(84,7c,7c,f8), r(99,77,77,ee), r(8d,7b,7b,f6),\ ++ r(0d,f2,f2,ff), r(bd,6b,6b,d6), r(b1,6f,6f,de), r(54,c5,c5,91),\ ++ r(50,30,30,60), r(03,01,01,02), r(a9,67,67,ce), r(7d,2b,2b,56),\ ++ r(19,fe,fe,e7), r(62,d7,d7,b5), r(e6,ab,ab,4d), r(9a,76,76,ec),\ ++ r(45,ca,ca,8f), r(9d,82,82,1f), r(40,c9,c9,89), r(87,7d,7d,fa),\ ++ r(15,fa,fa,ef), r(eb,59,59,b2), r(c9,47,47,8e), r(0b,f0,f0,fb),\ ++ r(ec,ad,ad,41), r(67,d4,d4,b3), r(fd,a2,a2,5f), r(ea,af,af,45),\ ++ r(bf,9c,9c,23), r(f7,a4,a4,53), r(96,72,72,e4), r(5b,c0,c0,9b),\ ++ r(c2,b7,b7,75), r(1c,fd,fd,e1), r(ae,93,93,3d), r(6a,26,26,4c),\ ++ r(5a,36,36,6c), r(41,3f,3f,7e), r(02,f7,f7,f5), r(4f,cc,cc,83),\ ++ r(5c,34,34,68), r(f4,a5,a5,51), r(34,e5,e5,d1), r(08,f1,f1,f9),\ ++ r(93,71,71,e2), r(73,d8,d8,ab), r(53,31,31,62), r(3f,15,15,2a),\ ++ r(0c,04,04,08), r(52,c7,c7,95), r(65,23,23,46), r(5e,c3,c3,9d),\ ++ r(28,18,18,30), r(a1,96,96,37), r(0f,05,05,0a), r(b5,9a,9a,2f),\ ++ r(09,07,07,0e), r(36,12,12,24), r(9b,80,80,1b), r(3d,e2,e2,df),\ ++ r(26,eb,eb,cd), r(69,27,27,4e), r(cd,b2,b2,7f), r(9f,75,75,ea),\ ++ r(1b,09,09,12), r(9e,83,83,1d), r(74,2c,2c,58), r(2e,1a,1a,34),\ ++ r(2d,1b,1b,36), r(b2,6e,6e,dc), r(ee,5a,5a,b4), r(fb,a0,a0,5b),\ ++ r(f6,52,52,a4), r(4d,3b,3b,76), r(61,d6,d6,b7), r(ce,b3,b3,7d),\ ++ r(7b,29,29,52), r(3e,e3,e3,dd), r(71,2f,2f,5e), r(97,84,84,13),\ ++ r(f5,53,53,a6), r(68,d1,d1,b9), r(00,00,00,00), r(2c,ed,ed,c1),\ ++ r(60,20,20,40), r(1f,fc,fc,e3), r(c8,b1,b1,79), r(ed,5b,5b,b6),\ ++ r(be,6a,6a,d4), r(46,cb,cb,8d), r(d9,be,be,67), r(4b,39,39,72),\ ++ r(de,4a,4a,94), r(d4,4c,4c,98), r(e8,58,58,b0), r(4a,cf,cf,85),\ ++ r(6b,d0,d0,bb), r(2a,ef,ef,c5), r(e5,aa,aa,4f), r(16,fb,fb,ed),\ ++ r(c5,43,43,86), r(d7,4d,4d,9a), r(55,33,33,66), r(94,85,85,11),\ ++ r(cf,45,45,8a), r(10,f9,f9,e9), r(06,02,02,04), r(81,7f,7f,fe),\ ++ r(f0,50,50,a0), r(44,3c,3c,78), r(ba,9f,9f,25), r(e3,a8,a8,4b),\ ++ r(f3,51,51,a2), r(fe,a3,a3,5d), r(c0,40,40,80), r(8a,8f,8f,05),\ ++ r(ad,92,92,3f), r(bc,9d,9d,21), r(48,38,38,70), r(04,f5,f5,f1),\ ++ r(df,bc,bc,63), r(c1,b6,b6,77), r(75,da,da,af), r(63,21,21,42),\ ++ r(30,10,10,20), r(1a,ff,ff,e5), r(0e,f3,f3,fd), r(6d,d2,d2,bf),\ ++ r(4c,cd,cd,81), r(14,0c,0c,18), r(35,13,13,26), r(2f,ec,ec,c3),\ ++ r(e1,5f,5f,be), r(a2,97,97,35), r(cc,44,44,88), r(39,17,17,2e),\ ++ r(57,c4,c4,93), r(f2,a7,a7,55), r(82,7e,7e,fc), r(47,3d,3d,7a),\ ++ r(ac,64,64,c8), r(e7,5d,5d,ba), r(2b,19,19,32), r(95,73,73,e6),\ ++ r(a0,60,60,c0), r(98,81,81,19), r(d1,4f,4f,9e), r(7f,dc,dc,a3),\ ++ r(66,22,22,44), r(7e,2a,2a,54), r(ab,90,90,3b), r(83,88,88,0b),\ ++ r(ca,46,46,8c), r(29,ee,ee,c7), r(d3,b8,b8,6b), r(3c,14,14,28),\ ++ r(79,de,de,a7), r(e2,5e,5e,bc), r(1d,0b,0b,16), r(76,db,db,ad),\ ++ r(3b,e0,e0,db), r(56,32,32,64), r(4e,3a,3a,74), r(1e,0a,0a,14),\ ++ r(db,49,49,92), r(0a,06,06,0c), r(6c,24,24,48), r(e4,5c,5c,b8),\ ++ r(5d,c2,c2,9f), r(6e,d3,d3,bd), r(ef,ac,ac,43), r(a6,62,62,c4),\ ++ r(a8,91,91,39), r(a4,95,95,31), r(37,e4,e4,d3), r(8b,79,79,f2),\ ++ r(32,e7,e7,d5), r(43,c8,c8,8b), r(59,37,37,6e), r(b7,6d,6d,da),\ ++ r(8c,8d,8d,01), r(64,d5,d5,b1), r(d2,4e,4e,9c), r(e0,a9,a9,49),\ ++ r(b4,6c,6c,d8), r(fa,56,56,ac), r(07,f4,f4,f3), r(25,ea,ea,cf),\ ++ r(af,65,65,ca), r(8e,7a,7a,f4), r(e9,ae,ae,47), r(18,08,08,10),\ ++ r(d5,ba,ba,6f), r(88,78,78,f0), r(6f,25,25,4a), r(72,2e,2e,5c),\ ++ r(24,1c,1c,38), r(f1,a6,a6,57), r(c7,b4,b4,73), r(51,c6,c6,97),\ ++ r(23,e8,e8,cb), r(7c,dd,dd,a1), r(9c,74,74,e8), r(21,1f,1f,3e),\ ++ r(dd,4b,4b,96), r(dc,bd,bd,61), r(86,8b,8b,0d), r(85,8a,8a,0f),\ ++ r(90,70,70,e0), r(42,3e,3e,7c), r(c4,b5,b5,71), r(aa,66,66,cc),\ ++ r(d8,48,48,90), r(05,03,03,06), r(01,f6,f6,f7), r(12,0e,0e,1c),\ ++ r(a3,61,61,c2), r(5f,35,35,6a), r(f9,57,57,ae), r(d0,b9,b9,69),\ ++ r(91,86,86,17), r(58,c1,c1,99), r(27,1d,1d,3a), r(b9,9e,9e,27),\ ++ r(38,e1,e1,d9), r(13,f8,f8,eb), r(b3,98,98,2b), r(33,11,11,22),\ ++ r(bb,69,69,d2), r(70,d9,d9,a9), r(89,8e,8e,07), r(a7,94,94,33),\ ++ r(b6,9b,9b,2d), r(22,1e,1e,3c), r(92,87,87,15), r(20,e9,e9,c9),\ ++ r(49,ce,ce,87), r(ff,55,55,aa), r(78,28,28,50), r(7a,df,df,a5),\ ++ r(8f,8c,8c,03), r(f8,a1,a1,59), r(80,89,89,09), r(17,0d,0d,1a),\ ++ r(da,bf,bf,65), r(31,e6,e6,d7), r(c6,42,42,84), r(b8,68,68,d0),\ ++ r(c3,41,41,82), r(b0,99,99,29), r(77,2d,2d,5a), r(11,0f,0f,1e),\ ++ r(cb,b0,b0,7b), r(fc,54,54,a8), r(d6,bb,bb,6d), r(3a,16,16,2c) ++ ++// data for inverse tables (other than last round) ++ ++#define i_table \ ++ r(50,a7,f4,51), r(53,65,41,7e), r(c3,a4,17,1a), r(96,5e,27,3a),\ ++ r(cb,6b,ab,3b), r(f1,45,9d,1f), r(ab,58,fa,ac), r(93,03,e3,4b),\ ++ r(55,fa,30,20), r(f6,6d,76,ad), r(91,76,cc,88), r(25,4c,02,f5),\ ++ r(fc,d7,e5,4f), r(d7,cb,2a,c5), r(80,44,35,26), r(8f,a3,62,b5),\ ++ r(49,5a,b1,de), r(67,1b,ba,25), r(98,0e,ea,45), r(e1,c0,fe,5d),\ ++ r(02,75,2f,c3), r(12,f0,4c,81), r(a3,97,46,8d), r(c6,f9,d3,6b),\ ++ r(e7,5f,8f,03), r(95,9c,92,15), r(eb,7a,6d,bf), r(da,59,52,95),\ ++ r(2d,83,be,d4), r(d3,21,74,58), r(29,69,e0,49), r(44,c8,c9,8e),\ ++ r(6a,89,c2,75), r(78,79,8e,f4), r(6b,3e,58,99), r(dd,71,b9,27),\ ++ r(b6,4f,e1,be), r(17,ad,88,f0), r(66,ac,20,c9), r(b4,3a,ce,7d),\ ++ r(18,4a,df,63), r(82,31,1a,e5), r(60,33,51,97), r(45,7f,53,62),\ ++ r(e0,77,64,b1), r(84,ae,6b,bb), r(1c,a0,81,fe), r(94,2b,08,f9),\ ++ r(58,68,48,70), r(19,fd,45,8f), r(87,6c,de,94), r(b7,f8,7b,52),\ ++ r(23,d3,73,ab), r(e2,02,4b,72), r(57,8f,1f,e3), r(2a,ab,55,66),\ ++ r(07,28,eb,b2), r(03,c2,b5,2f), r(9a,7b,c5,86), r(a5,08,37,d3),\ ++ r(f2,87,28,30), r(b2,a5,bf,23), r(ba,6a,03,02), r(5c,82,16,ed),\ ++ r(2b,1c,cf,8a), r(92,b4,79,a7), r(f0,f2,07,f3), r(a1,e2,69,4e),\ ++ r(cd,f4,da,65), r(d5,be,05,06), r(1f,62,34,d1), r(8a,fe,a6,c4),\ ++ r(9d,53,2e,34), r(a0,55,f3,a2), r(32,e1,8a,05), r(75,eb,f6,a4),\ ++ r(39,ec,83,0b), r(aa,ef,60,40), r(06,9f,71,5e), r(51,10,6e,bd),\ ++ r(f9,8a,21,3e), r(3d,06,dd,96), r(ae,05,3e,dd), r(46,bd,e6,4d),\ ++ r(b5,8d,54,91), r(05,5d,c4,71), r(6f,d4,06,04), r(ff,15,50,60),\ ++ r(24,fb,98,19), r(97,e9,bd,d6), r(cc,43,40,89), r(77,9e,d9,67),\ ++ r(bd,42,e8,b0), r(88,8b,89,07), r(38,5b,19,e7), r(db,ee,c8,79),\ ++ r(47,0a,7c,a1), r(e9,0f,42,7c), r(c9,1e,84,f8), r(00,00,00,00),\ ++ r(83,86,80,09), r(48,ed,2b,32), r(ac,70,11,1e), r(4e,72,5a,6c),\ ++ r(fb,ff,0e,fd), r(56,38,85,0f), r(1e,d5,ae,3d), r(27,39,2d,36),\ ++ r(64,d9,0f,0a), r(21,a6,5c,68), r(d1,54,5b,9b), r(3a,2e,36,24),\ ++ r(b1,67,0a,0c), r(0f,e7,57,93), r(d2,96,ee,b4), r(9e,91,9b,1b),\ ++ r(4f,c5,c0,80), r(a2,20,dc,61), r(69,4b,77,5a), r(16,1a,12,1c),\ ++ r(0a,ba,93,e2), r(e5,2a,a0,c0), r(43,e0,22,3c), r(1d,17,1b,12),\ ++ r(0b,0d,09,0e), r(ad,c7,8b,f2), r(b9,a8,b6,2d), r(c8,a9,1e,14),\ ++ r(85,19,f1,57), r(4c,07,75,af), r(bb,dd,99,ee), r(fd,60,7f,a3),\ ++ r(9f,26,01,f7), r(bc,f5,72,5c), r(c5,3b,66,44), r(34,7e,fb,5b),\ ++ r(76,29,43,8b), r(dc,c6,23,cb), r(68,fc,ed,b6), r(63,f1,e4,b8),\ ++ r(ca,dc,31,d7), r(10,85,63,42), r(40,22,97,13), r(20,11,c6,84),\ ++ r(7d,24,4a,85), r(f8,3d,bb,d2), r(11,32,f9,ae), r(6d,a1,29,c7),\ ++ r(4b,2f,9e,1d), r(f3,30,b2,dc), r(ec,52,86,0d), r(d0,e3,c1,77),\ ++ r(6c,16,b3,2b), r(99,b9,70,a9), r(fa,48,94,11), r(22,64,e9,47),\ ++ r(c4,8c,fc,a8), r(1a,3f,f0,a0), r(d8,2c,7d,56), r(ef,90,33,22),\ ++ r(c7,4e,49,87), r(c1,d1,38,d9), r(fe,a2,ca,8c), r(36,0b,d4,98),\ ++ r(cf,81,f5,a6), r(28,de,7a,a5), r(26,8e,b7,da), r(a4,bf,ad,3f),\ ++ r(e4,9d,3a,2c), r(0d,92,78,50), r(9b,cc,5f,6a), r(62,46,7e,54),\ ++ r(c2,13,8d,f6), r(e8,b8,d8,90), r(5e,f7,39,2e), r(f5,af,c3,82),\ ++ r(be,80,5d,9f), r(7c,93,d0,69), r(a9,2d,d5,6f), r(b3,12,25,cf),\ ++ r(3b,99,ac,c8), r(a7,7d,18,10), r(6e,63,9c,e8), r(7b,bb,3b,db),\ ++ r(09,78,26,cd), r(f4,18,59,6e), r(01,b7,9a,ec), r(a8,9a,4f,83),\ ++ r(65,6e,95,e6), r(7e,e6,ff,aa), r(08,cf,bc,21), r(e6,e8,15,ef),\ ++ r(d9,9b,e7,ba), r(ce,36,6f,4a), r(d4,09,9f,ea), r(d6,7c,b0,29),\ ++ r(af,b2,a4,31), r(31,23,3f,2a), r(30,94,a5,c6), r(c0,66,a2,35),\ ++ r(37,bc,4e,74), r(a6,ca,82,fc), r(b0,d0,90,e0), r(15,d8,a7,33),\ ++ r(4a,98,04,f1), r(f7,da,ec,41), r(0e,50,cd,7f), r(2f,f6,91,17),\ ++ r(8d,d6,4d,76), r(4d,b0,ef,43), r(54,4d,aa,cc), r(df,04,96,e4),\ ++ r(e3,b5,d1,9e), r(1b,88,6a,4c), r(b8,1f,2c,c1), r(7f,51,65,46),\ ++ r(04,ea,5e,9d), r(5d,35,8c,01), r(73,74,87,fa), r(2e,41,0b,fb),\ ++ r(5a,1d,67,b3), r(52,d2,db,92), r(33,56,10,e9), r(13,47,d6,6d),\ ++ r(8c,61,d7,9a), r(7a,0c,a1,37), r(8e,14,f8,59), r(89,3c,13,eb),\ ++ r(ee,27,a9,ce), r(35,c9,61,b7), r(ed,e5,1c,e1), r(3c,b1,47,7a),\ ++ r(59,df,d2,9c), r(3f,73,f2,55), r(79,ce,14,18), r(bf,37,c7,73),\ ++ r(ea,cd,f7,53), r(5b,aa,fd,5f), r(14,6f,3d,df), r(86,db,44,78),\ ++ r(81,f3,af,ca), r(3e,c4,68,b9), r(2c,34,24,38), r(5f,40,a3,c2),\ ++ r(72,c3,1d,16), r(0c,25,e2,bc), r(8b,49,3c,28), r(41,95,0d,ff),\ ++ r(71,01,a8,39), r(de,b3,0c,08), r(9c,e4,b4,d8), r(90,c1,56,64),\ ++ r(61,84,cb,7b), r(70,b6,32,d5), r(74,5c,6c,48), r(42,57,b8,d0) ++ ++// generate the required tables in the desired endian format ++ ++#undef r ++#define r r0 ++ ++#if defined(ONE_TABLE) ++static const u_int32_t ft_tab[256] = ++ { f_table }; ++#elif defined(FOUR_TABLES) ++static const u_int32_t ft_tab[4][256] = ++{ { f_table }, ++#undef r ++#define r r1 ++ { f_table }, ++#undef r ++#define r r2 ++ { f_table }, ++#undef r ++#define r r3 ++ { f_table } ++}; ++#endif ++ ++#undef r ++#define r r0 ++#if defined(ONE_TABLE) ++static const u_int32_t it_tab[256] = ++ { i_table }; ++#elif defined(FOUR_TABLES) ++static const u_int32_t it_tab[4][256] = ++{ { i_table }, ++#undef r ++#define r r1 ++ { i_table }, ++#undef r ++#define r r2 ++ { i_table }, ++#undef r ++#define r r3 ++ { i_table } ++}; ++#endif ++ ++#endif ++ ++#if defined(FIXED_TABLES) && (defined(ONE_LR_TABLE) || defined(FOUR_LR_TABLES)) ++ ++// data for inverse tables (last round) ++ ++#define li_table \ ++ w(52), w(09), w(6a), w(d5), w(30), w(36), w(a5), w(38),\ ++ w(bf), w(40), w(a3), w(9e), w(81), w(f3), w(d7), w(fb),\ ++ w(7c), w(e3), w(39), w(82), w(9b), w(2f), w(ff), w(87),\ ++ w(34), w(8e), w(43), w(44), w(c4), w(de), w(e9), w(cb),\ ++ w(54), w(7b), w(94), w(32), w(a6), w(c2), w(23), w(3d),\ ++ w(ee), w(4c), w(95), w(0b), w(42), w(fa), w(c3), w(4e),\ ++ w(08), w(2e), w(a1), w(66), w(28), w(d9), w(24), w(b2),\ ++ w(76), w(5b), w(a2), w(49), w(6d), w(8b), w(d1), w(25),\ ++ w(72), w(f8), w(f6), w(64), w(86), w(68), w(98), w(16),\ ++ w(d4), w(a4), w(5c), w(cc), w(5d), w(65), w(b6), w(92),\ ++ w(6c), w(70), w(48), w(50), w(fd), w(ed), w(b9), w(da),\ ++ w(5e), w(15), w(46), w(57), w(a7), w(8d), w(9d), w(84),\ ++ w(90), w(d8), w(ab), w(00), w(8c), w(bc), w(d3), w(0a),\ ++ w(f7), w(e4), w(58), w(05), w(b8), w(b3), w(45), w(06),\ ++ w(d0), w(2c), w(1e), w(8f), w(ca), w(3f), w(0f), w(02),\ ++ w(c1), w(af), w(bd), w(03), w(01), w(13), w(8a), w(6b),\ ++ w(3a), w(91), w(11), w(41), w(4f), w(67), w(dc), w(ea),\ ++ w(97), w(f2), w(cf), w(ce), w(f0), w(b4), w(e6), w(73),\ ++ w(96), w(ac), w(74), w(22), w(e7), w(ad), w(35), w(85),\ ++ w(e2), w(f9), w(37), w(e8), w(1c), w(75), w(df), w(6e),\ ++ w(47), w(f1), w(1a), w(71), w(1d), w(29), w(c5), w(89),\ ++ w(6f), w(b7), w(62), w(0e), w(aa), w(18), w(be), w(1b),\ ++ w(fc), w(56), w(3e), w(4b), w(c6), w(d2), w(79), w(20),\ ++ w(9a), w(db), w(c0), w(fe), w(78), w(cd), w(5a), w(f4),\ ++ w(1f), w(dd), w(a8), w(33), w(88), w(07), w(c7), w(31),\ ++ w(b1), w(12), w(10), w(59), w(27), w(80), w(ec), w(5f),\ ++ w(60), w(51), w(7f), w(a9), w(19), w(b5), w(4a), w(0d),\ ++ w(2d), w(e5), w(7a), w(9f), w(93), w(c9), w(9c), w(ef),\ ++ w(a0), w(e0), w(3b), w(4d), w(ae), w(2a), w(f5), w(b0),\ ++ w(c8), w(eb), w(bb), w(3c), w(83), w(53), w(99), w(61),\ ++ w(17), w(2b), w(04), w(7e), w(ba), w(77), w(d6), w(26),\ ++ w(e1), w(69), w(14), w(63), w(55), w(21), w(0c), w(7d), ++ ++// generate the required tables in the desired endian format ++ ++#undef r ++#define r(p,q,r,s) w0(q) ++#if defined(ONE_LR_TABLE) ++static const u_int32_t fl_tab[256] = ++ { f_table }; ++#elif defined(FOUR_LR_TABLES) ++static const u_int32_t fl_tab[4][256] = ++{ { f_table }, ++#undef r ++#define r(p,q,r,s) w1(q) ++ { f_table }, ++#undef r ++#define r(p,q,r,s) w2(q) ++ { f_table }, ++#undef r ++#define r(p,q,r,s) w3(q) ++ { f_table } ++}; ++#endif ++ ++#undef w ++#define w w0 ++#if defined(ONE_LR_TABLE) ++static const u_int32_t il_tab[256] = ++ { li_table }; ++#elif defined(FOUR_LR_TABLES) ++static const u_int32_t il_tab[4][256] = ++{ { li_table }, ++#undef w ++#define w w1 ++ { li_table }, ++#undef w ++#define w w2 ++ { li_table }, ++#undef w ++#define w w3 ++ { li_table } ++}; ++#endif ++ ++#endif ++ ++#if defined(FIXED_TABLES) && (defined(ONE_IM_TABLE) || defined(FOUR_IM_TABLES)) ++ ++#define m_table \ ++ r(00,00,00,00), r(0b,0d,09,0e), r(16,1a,12,1c), r(1d,17,1b,12),\ ++ r(2c,34,24,38), r(27,39,2d,36), r(3a,2e,36,24), r(31,23,3f,2a),\ ++ r(58,68,48,70), r(53,65,41,7e), r(4e,72,5a,6c), r(45,7f,53,62),\ ++ r(74,5c,6c,48), r(7f,51,65,46), r(62,46,7e,54), r(69,4b,77,5a),\ ++ r(b0,d0,90,e0), r(bb,dd,99,ee), r(a6,ca,82,fc), r(ad,c7,8b,f2),\ ++ r(9c,e4,b4,d8), r(97,e9,bd,d6), r(8a,fe,a6,c4), r(81,f3,af,ca),\ ++ r(e8,b8,d8,90), r(e3,b5,d1,9e), r(fe,a2,ca,8c), r(f5,af,c3,82),\ ++ r(c4,8c,fc,a8), r(cf,81,f5,a6), r(d2,96,ee,b4), r(d9,9b,e7,ba),\ ++ r(7b,bb,3b,db), r(70,b6,32,d5), r(6d,a1,29,c7), r(66,ac,20,c9),\ ++ r(57,8f,1f,e3), r(5c,82,16,ed), r(41,95,0d,ff), r(4a,98,04,f1),\ ++ r(23,d3,73,ab), r(28,de,7a,a5), r(35,c9,61,b7), r(3e,c4,68,b9),\ ++ r(0f,e7,57,93), r(04,ea,5e,9d), r(19,fd,45,8f), r(12,f0,4c,81),\ ++ r(cb,6b,ab,3b), r(c0,66,a2,35), r(dd,71,b9,27), r(d6,7c,b0,29),\ ++ r(e7,5f,8f,03), r(ec,52,86,0d), r(f1,45,9d,1f), r(fa,48,94,11),\ ++ r(93,03,e3,4b), r(98,0e,ea,45), r(85,19,f1,57), r(8e,14,f8,59),\ ++ r(bf,37,c7,73), r(b4,3a,ce,7d), r(a9,2d,d5,6f), r(a2,20,dc,61),\ ++ r(f6,6d,76,ad), r(fd,60,7f,a3), r(e0,77,64,b1), r(eb,7a,6d,bf),\ ++ r(da,59,52,95), r(d1,54,5b,9b), r(cc,43,40,89), r(c7,4e,49,87),\ ++ r(ae,05,3e,dd), r(a5,08,37,d3), r(b8,1f,2c,c1), r(b3,12,25,cf),\ ++ r(82,31,1a,e5), r(89,3c,13,eb), r(94,2b,08,f9), r(9f,26,01,f7),\ ++ r(46,bd,e6,4d), r(4d,b0,ef,43), r(50,a7,f4,51), r(5b,aa,fd,5f),\ ++ r(6a,89,c2,75), r(61,84,cb,7b), r(7c,93,d0,69), r(77,9e,d9,67),\ ++ r(1e,d5,ae,3d), r(15,d8,a7,33), r(08,cf,bc,21), r(03,c2,b5,2f),\ ++ r(32,e1,8a,05), r(39,ec,83,0b), r(24,fb,98,19), r(2f,f6,91,17),\ ++ r(8d,d6,4d,76), r(86,db,44,78), r(9b,cc,5f,6a), r(90,c1,56,64),\ ++ r(a1,e2,69,4e), r(aa,ef,60,40), r(b7,f8,7b,52), r(bc,f5,72,5c),\ ++ r(d5,be,05,06), r(de,b3,0c,08), r(c3,a4,17,1a), r(c8,a9,1e,14),\ ++ r(f9,8a,21,3e), r(f2,87,28,30), r(ef,90,33,22), r(e4,9d,3a,2c),\ ++ r(3d,06,dd,96), r(36,0b,d4,98), r(2b,1c,cf,8a), r(20,11,c6,84),\ ++ r(11,32,f9,ae), r(1a,3f,f0,a0), r(07,28,eb,b2), r(0c,25,e2,bc),\ ++ r(65,6e,95,e6), r(6e,63,9c,e8), r(73,74,87,fa), r(78,79,8e,f4),\ ++ r(49,5a,b1,de), r(42,57,b8,d0), r(5f,40,a3,c2), r(54,4d,aa,cc),\ ++ r(f7,da,ec,41), r(fc,d7,e5,4f), r(e1,c0,fe,5d), r(ea,cd,f7,53),\ ++ r(db,ee,c8,79), r(d0,e3,c1,77), r(cd,f4,da,65), r(c6,f9,d3,6b),\ ++ r(af,b2,a4,31), r(a4,bf,ad,3f), r(b9,a8,b6,2d), r(b2,a5,bf,23),\ ++ r(83,86,80,09), r(88,8b,89,07), r(95,9c,92,15), r(9e,91,9b,1b),\ ++ r(47,0a,7c,a1), r(4c,07,75,af), r(51,10,6e,bd), r(5a,1d,67,b3),\ ++ r(6b,3e,58,99), r(60,33,51,97), r(7d,24,4a,85), r(76,29,43,8b),\ ++ r(1f,62,34,d1), r(14,6f,3d,df), r(09,78,26,cd), r(02,75,2f,c3),\ ++ r(33,56,10,e9), r(38,5b,19,e7), r(25,4c,02,f5), r(2e,41,0b,fb),\ ++ r(8c,61,d7,9a), r(87,6c,de,94), r(9a,7b,c5,86), r(91,76,cc,88),\ ++ r(a0,55,f3,a2), r(ab,58,fa,ac), r(b6,4f,e1,be), r(bd,42,e8,b0),\ ++ r(d4,09,9f,ea), r(df,04,96,e4), r(c2,13,8d,f6), r(c9,1e,84,f8),\ ++ r(f8,3d,bb,d2), r(f3,30,b2,dc), r(ee,27,a9,ce), r(e5,2a,a0,c0),\ ++ r(3c,b1,47,7a), r(37,bc,4e,74), r(2a,ab,55,66), r(21,a6,5c,68),\ ++ r(10,85,63,42), r(1b,88,6a,4c), r(06,9f,71,5e), r(0d,92,78,50),\ ++ r(64,d9,0f,0a), r(6f,d4,06,04), r(72,c3,1d,16), r(79,ce,14,18),\ ++ r(48,ed,2b,32), r(43,e0,22,3c), r(5e,f7,39,2e), r(55,fa,30,20),\ ++ r(01,b7,9a,ec), r(0a,ba,93,e2), r(17,ad,88,f0), r(1c,a0,81,fe),\ ++ r(2d,83,be,d4), r(26,8e,b7,da), r(3b,99,ac,c8), r(30,94,a5,c6),\ ++ r(59,df,d2,9c), r(52,d2,db,92), r(4f,c5,c0,80), r(44,c8,c9,8e),\ ++ r(75,eb,f6,a4), r(7e,e6,ff,aa), r(63,f1,e4,b8), r(68,fc,ed,b6),\ ++ r(b1,67,0a,0c), r(ba,6a,03,02), r(a7,7d,18,10), r(ac,70,11,1e),\ ++ r(9d,53,2e,34), r(96,5e,27,3a), r(8b,49,3c,28), r(80,44,35,26),\ ++ r(e9,0f,42,7c), r(e2,02,4b,72), r(ff,15,50,60), r(f4,18,59,6e),\ ++ r(c5,3b,66,44), r(ce,36,6f,4a), r(d3,21,74,58), r(d8,2c,7d,56),\ ++ r(7a,0c,a1,37), r(71,01,a8,39), r(6c,16,b3,2b), r(67,1b,ba,25),\ ++ r(56,38,85,0f), r(5d,35,8c,01), r(40,22,97,13), r(4b,2f,9e,1d),\ ++ r(22,64,e9,47), r(29,69,e0,49), r(34,7e,fb,5b), r(3f,73,f2,55),\ ++ r(0e,50,cd,7f), r(05,5d,c4,71), r(18,4a,df,63), r(13,47,d6,6d),\ ++ r(ca,dc,31,d7), r(c1,d1,38,d9), r(dc,c6,23,cb), r(d7,cb,2a,c5),\ ++ r(e6,e8,15,ef), r(ed,e5,1c,e1), r(f0,f2,07,f3), r(fb,ff,0e,fd),\ ++ r(92,b4,79,a7), r(99,b9,70,a9), r(84,ae,6b,bb), r(8f,a3,62,b5),\ ++ r(be,80,5d,9f), r(b5,8d,54,91), r(a8,9a,4f,83), r(a3,97,46,8d) ++ ++#undef r ++#define r r0 ++ ++#if defined(ONE_IM_TABLE) ++static const u_int32_t im_tab[256] = ++ { m_table }; ++#elif defined(FOUR_IM_TABLES) ++static const u_int32_t im_tab[4][256] = ++{ { m_table }, ++#undef r ++#define r r1 ++ { m_table }, ++#undef r ++#define r r2 ++ { m_table }, ++#undef r ++#define r r3 ++ { m_table } ++}; ++#endif ++ ++#endif ++ ++#else ++ ++static int tab_gen = 0; ++ ++static unsigned char s_box[256]; // the S box ++static unsigned char inv_s_box[256]; // the inverse S box ++static u_int32_t rcon_tab[AES_RC_LENGTH]; // table of round constants ++ ++#if defined(ONE_TABLE) ++static u_int32_t ft_tab[256]; ++static u_int32_t it_tab[256]; ++#elif defined(FOUR_TABLES) ++static u_int32_t ft_tab[4][256]; ++static u_int32_t it_tab[4][256]; ++#endif ++ ++#if defined(ONE_LR_TABLE) ++static u_int32_t fl_tab[256]; ++static u_int32_t il_tab[256]; ++#elif defined(FOUR_LR_TABLES) ++static u_int32_t fl_tab[4][256]; ++static u_int32_t il_tab[4][256]; ++#endif ++ ++#if defined(ONE_IM_TABLE) ++static u_int32_t im_tab[256]; ++#elif defined(FOUR_IM_TABLES) ++static u_int32_t im_tab[4][256]; ++#endif ++ ++// Generate the tables for the dynamic table option ++ ++#if !defined(FF_TABLES) ++ ++// It will generally be sensible to use tables to compute finite ++// field multiplies and inverses but where memory is scarse this ++// code might sometimes be better. ++ ++// return 2 ^ (n - 1) where n is the bit number of the highest bit ++// set in x with x in the range 1 < x < 0x00000200. This form is ++// used so that locals within FFinv can be bytes rather than words ++ ++static unsigned char hibit(const u_int32_t x) ++{ unsigned char r = (unsigned char)((x >> 1) | (x >> 2)); ++ ++ r |= (r >> 2); ++ r |= (r >> 4); ++ return (r + 1) >> 1; ++} ++ ++// return the inverse of the finite field element x ++ ++static unsigned char FFinv(const unsigned char x) ++{ unsigned char p1 = x, p2 = 0x1b, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; ++ ++ if(x < 2) return x; ++ ++ for(;;) ++ { ++ if(!n1) return v1; ++ ++ while(n2 >= n1) ++ { ++ n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); ++ } ++ ++ if(!n2) return v2; ++ ++ while(n1 >= n2) ++ { ++ n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); ++ } ++ } ++} ++ ++// define the finite field multiplies required for Rijndael ++ ++#define FFmul02(x) ((((x) & 0x7f) << 1) ^ ((x) & 0x80 ? 0x1b : 0)) ++#define FFmul03(x) ((x) ^ FFmul02(x)) ++#define FFmul09(x) ((x) ^ FFmul02(FFmul02(FFmul02(x)))) ++#define FFmul0b(x) ((x) ^ FFmul02((x) ^ FFmul02(FFmul02(x)))) ++#define FFmul0d(x) ((x) ^ FFmul02(FFmul02((x) ^ FFmul02(x)))) ++#define FFmul0e(x) FFmul02((x) ^ FFmul02((x) ^ FFmul02(x))) ++ ++#else ++ ++#define FFinv(x) ((x) ? pow[255 - log[x]]: 0) ++ ++#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0) ++#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0) ++#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0) ++#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0) ++#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0) ++#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0) ++ ++#endif ++ ++// The forward and inverse affine transformations used in the S-box ++ ++#define fwd_affine(x) \ ++ (w = (u_int32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(unsigned char)(w^(w>>8))) ++ ++#define inv_affine(x) \ ++ (w = (u_int32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(unsigned char)(w^(w>>8))) ++ ++static void gen_tabs(void) ++{ u_int32_t i, w; ++ ++#if defined(FF_TABLES) ++ ++ unsigned char pow[512], log[256]; ++ ++ // log and power tables for GF(2^8) finite field with ++ // 0x011b as modular polynomial - the simplest primitive ++ // root is 0x03, used here to generate the tables ++ ++ i = 0; w = 1; ++ do ++ { ++ pow[i] = (unsigned char)w; ++ pow[i + 255] = (unsigned char)w; ++ log[w] = (unsigned char)i++; ++ w ^= (w << 1) ^ (w & ff_hi ? ff_poly : 0); ++ } ++ while (w != 1); ++ ++#endif ++ ++ for(i = 0, w = 1; i < AES_RC_LENGTH; ++i) ++ { ++ rcon_tab[i] = bytes2word(w, 0, 0, 0); ++ w = (w << 1) ^ (w & ff_hi ? ff_poly : 0); ++ } ++ ++ for(i = 0; i < 256; ++i) ++ { unsigned char b; ++ ++ s_box[i] = b = fwd_affine(FFinv((unsigned char)i)); ++ ++ w = bytes2word(b, 0, 0, 0); ++#if defined(ONE_LR_TABLE) ++ fl_tab[i] = w; ++#elif defined(FOUR_LR_TABLES) ++ fl_tab[0][i] = w; ++ fl_tab[1][i] = upr(w,1); ++ fl_tab[2][i] = upr(w,2); ++ fl_tab[3][i] = upr(w,3); ++#endif ++ w = bytes2word(FFmul02(b), b, b, FFmul03(b)); ++#if defined(ONE_TABLE) ++ ft_tab[i] = w; ++#elif defined(FOUR_TABLES) ++ ft_tab[0][i] = w; ++ ft_tab[1][i] = upr(w,1); ++ ft_tab[2][i] = upr(w,2); ++ ft_tab[3][i] = upr(w,3); ++#endif ++ inv_s_box[i] = b = FFinv(inv_affine((unsigned char)i)); ++ ++ w = bytes2word(b, 0, 0, 0); ++#if defined(ONE_LR_TABLE) ++ il_tab[i] = w; ++#elif defined(FOUR_LR_TABLES) ++ il_tab[0][i] = w; ++ il_tab[1][i] = upr(w,1); ++ il_tab[2][i] = upr(w,2); ++ il_tab[3][i] = upr(w,3); ++#endif ++ w = bytes2word(FFmul0e(b), FFmul09(b), FFmul0d(b), FFmul0b(b)); ++#if defined(ONE_TABLE) ++ it_tab[i] = w; ++#elif defined(FOUR_TABLES) ++ it_tab[0][i] = w; ++ it_tab[1][i] = upr(w,1); ++ it_tab[2][i] = upr(w,2); ++ it_tab[3][i] = upr(w,3); ++#endif ++#if defined(ONE_IM_TABLE) ++ im_tab[b] = w; ++#elif defined(FOUR_IM_TABLES) ++ im_tab[0][b] = w; ++ im_tab[1][b] = upr(w,1); ++ im_tab[2][b] = upr(w,2); ++ im_tab[3][b] = upr(w,3); ++#endif ++ ++ } ++} ++ ++#endif ++ ++#define no_table(x,box,vf,rf,c) bytes2word( \ ++ box[bval(vf(x,0,c),rf(0,c))], \ ++ box[bval(vf(x,1,c),rf(1,c))], \ ++ box[bval(vf(x,2,c),rf(2,c))], \ ++ box[bval(vf(x,3,c),rf(3,c))]) ++ ++#define one_table(x,op,tab,vf,rf,c) \ ++ ( tab[bval(vf(x,0,c),rf(0,c))] \ ++ ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ ++ ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ ++ ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) ++ ++#define four_tables(x,tab,vf,rf,c) \ ++ ( tab[0][bval(vf(x,0,c),rf(0,c))] \ ++ ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ ++ ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ ++ ^ tab[3][bval(vf(x,3,c),rf(3,c))]) ++ ++#define vf1(x,r,c) (x) ++#define rf1(r,c) (r) ++#define rf2(r,c) ((r-c)&3) ++ ++#if defined(FOUR_LR_TABLES) ++#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c) ++#elif defined(ONE_LR_TABLE) ++#define ls_box(x,c) one_table(x,upr,fl_tab,vf1,rf2,c) ++#else ++#define ls_box(x,c) no_table(x,s_box,vf1,rf2,c) ++#endif ++ ++#if defined(FOUR_IM_TABLES) ++#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0) ++#elif defined(ONE_IM_TABLE) ++#define inv_mcol(x) one_table(x,upr,im_tab,vf1,rf1,0) ++#else ++#define inv_mcol(x) \ ++ (f9 = (x),f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \ ++ f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1)) ++#endif ++ ++// Subroutine to set the block size (if variable) in bytes, legal ++// values being 16, 24 and 32. ++ ++#if defined(AES_BLOCK_SIZE) ++#define nc (AES_BLOCK_SIZE / 4) ++#else ++#define nc (cx->aes_Ncol) ++ ++void aes_set_blk(aes_context *cx, int n_bytes) ++{ ++#if !defined(FIXED_TABLES) ++ if(!tab_gen) { gen_tabs(); tab_gen = 1; } ++#endif ++ ++ switch(n_bytes) { ++ case 32: /* bytes */ ++ case 256: /* bits */ ++ nc = 8; ++ break; ++ case 24: /* bytes */ ++ case 192: /* bits */ ++ nc = 6; ++ break; ++ case 16: /* bytes */ ++ case 128: /* bits */ ++ default: ++ nc = 4; ++ break; ++ } ++} ++ ++#endif ++ ++// Initialise the key schedule from the user supplied key. The key ++// length is now specified in bytes - 16, 24 or 32 as appropriate. ++// This corresponds to bit lengths of 128, 192 and 256 bits, and ++// to Nk values of 4, 6 and 8 respectively. ++ ++#define mx(t,f) (*t++ = inv_mcol(*f),f++) ++#define cp(t,f) *t++ = *f++ ++ ++#if AES_BLOCK_SIZE == 16 ++#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s) ++#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s) ++#elif AES_BLOCK_SIZE == 24 ++#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ ++ cp(d,s); cp(d,s) ++#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ ++ mx(d,s); mx(d,s) ++#elif AES_BLOCK_SIZE == 32 ++#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ ++ cp(d,s); cp(d,s); cp(d,s); cp(d,s) ++#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ ++ mx(d,s); mx(d,s); mx(d,s); mx(d,s) ++#else ++ ++#define cpy(d,s) \ ++switch(nc) \ ++{ case 8: cp(d,s); cp(d,s); \ ++ case 6: cp(d,s); cp(d,s); \ ++ case 4: cp(d,s); cp(d,s); \ ++ cp(d,s); cp(d,s); \ ++} ++ ++#define mix(d,s) \ ++switch(nc) \ ++{ case 8: mx(d,s); mx(d,s); \ ++ case 6: mx(d,s); mx(d,s); \ ++ case 4: mx(d,s); mx(d,s); \ ++ mx(d,s); mx(d,s); \ ++} ++ ++#endif ++ ++void aes_set_key(aes_context *cx, const unsigned char in_key[], int n_bytes, const int f) ++{ u_int32_t *kf, *kt, rci; ++ ++#if !defined(FIXED_TABLES) ++ if(!tab_gen) { gen_tabs(); tab_gen = 1; } ++#endif ++ ++ switch(n_bytes) { ++ case 32: /* bytes */ ++ case 256: /* bits */ ++ cx->aes_Nkey = 8; ++ break; ++ case 24: /* bytes */ ++ case 192: /* bits */ ++ cx->aes_Nkey = 6; ++ break; ++ case 16: /* bytes */ ++ case 128: /* bits */ ++ default: ++ cx->aes_Nkey = 4; ++ break; ++ } ++ ++ cx->aes_Nrnd = (cx->aes_Nkey > nc ? cx->aes_Nkey : nc) + 6; ++ ++ cx->aes_e_key[0] = const_word_in(in_key ); ++ cx->aes_e_key[1] = const_word_in(in_key + 4); ++ cx->aes_e_key[2] = const_word_in(in_key + 8); ++ cx->aes_e_key[3] = const_word_in(in_key + 12); ++ ++ kf = cx->aes_e_key; ++ kt = kf + nc * (cx->aes_Nrnd + 1) - cx->aes_Nkey; ++ rci = 0; ++ ++ switch(cx->aes_Nkey) ++ { ++ case 4: do ++ { kf[4] = kf[0] ^ ls_box(kf[3],3) ^ rcon_tab[rci++]; ++ kf[5] = kf[1] ^ kf[4]; ++ kf[6] = kf[2] ^ kf[5]; ++ kf[7] = kf[3] ^ kf[6]; ++ kf += 4; ++ } ++ while(kf < kt); ++ break; ++ ++ case 6: cx->aes_e_key[4] = const_word_in(in_key + 16); ++ cx->aes_e_key[5] = const_word_in(in_key + 20); ++ do ++ { kf[ 6] = kf[0] ^ ls_box(kf[5],3) ^ rcon_tab[rci++]; ++ kf[ 7] = kf[1] ^ kf[ 6]; ++ kf[ 8] = kf[2] ^ kf[ 7]; ++ kf[ 9] = kf[3] ^ kf[ 8]; ++ kf[10] = kf[4] ^ kf[ 9]; ++ kf[11] = kf[5] ^ kf[10]; ++ kf += 6; ++ } ++ while(kf < kt); ++ break; ++ ++ case 8: cx->aes_e_key[4] = const_word_in(in_key + 16); ++ cx->aes_e_key[5] = const_word_in(in_key + 20); ++ cx->aes_e_key[6] = const_word_in(in_key + 24); ++ cx->aes_e_key[7] = const_word_in(in_key + 28); ++ do ++ { kf[ 8] = kf[0] ^ ls_box(kf[7],3) ^ rcon_tab[rci++]; ++ kf[ 9] = kf[1] ^ kf[ 8]; ++ kf[10] = kf[2] ^ kf[ 9]; ++ kf[11] = kf[3] ^ kf[10]; ++ kf[12] = kf[4] ^ ls_box(kf[11],0); ++ kf[13] = kf[5] ^ kf[12]; ++ kf[14] = kf[6] ^ kf[13]; ++ kf[15] = kf[7] ^ kf[14]; ++ kf += 8; ++ } ++ while (kf < kt); ++ break; ++ } ++ ++ if(!f) ++ { u_int32_t i; ++ ++ kt = cx->aes_d_key + nc * cx->aes_Nrnd; ++ kf = cx->aes_e_key; ++ ++ cpy(kt, kf); kt -= 2 * nc; ++ ++ for(i = 1; i < cx->aes_Nrnd; ++i) ++ { ++#if defined(ONE_TABLE) || defined(FOUR_TABLES) ++#if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES) ++ u_int32_t f2, f4, f8, f9; ++#endif ++ mix(kt, kf); ++#else ++ cpy(kt, kf); ++#endif ++ kt -= 2 * nc; ++ } ++ ++ cpy(kt, kf); ++ } ++} ++ ++// y = output word, x = input word, r = row, c = column ++// for r = 0, 1, 2 and 3 = column accessed for row r ++ ++#if defined(ARRAYS) ++#define s(x,c) x[c] ++#else ++#define s(x,c) x##c ++#endif ++ ++// I am grateful to Frank Yellin for the following constructions ++// which, given the column (c) of the output state variable that ++// is being computed, return the input state variables which are ++// needed for each row (r) of the state ++ ++// For the fixed block size options, compilers reduce these two ++// expressions to fixed variable references. For variable block ++// size code conditional clauses will sometimes be returned ++ ++#define unused 77 // Sunset Strip ++ ++#define fwd_var(x,r,c) \ ++ ( r==0 ? \ ++ ( c==0 ? s(x,0) \ ++ : c==1 ? s(x,1) \ ++ : c==2 ? s(x,2) \ ++ : c==3 ? s(x,3) \ ++ : c==4 ? s(x,4) \ ++ : c==5 ? s(x,5) \ ++ : c==6 ? s(x,6) \ ++ : s(x,7)) \ ++ : r==1 ? \ ++ ( c==0 ? s(x,1) \ ++ : c==1 ? s(x,2) \ ++ : c==2 ? s(x,3) \ ++ : c==3 ? nc==4 ? s(x,0) : s(x,4) \ ++ : c==4 ? s(x,5) \ ++ : c==5 ? nc==8 ? s(x,6) : s(x,0) \ ++ : c==6 ? s(x,7) \ ++ : s(x,0)) \ ++ : r==2 ? \ ++ ( c==0 ? nc==8 ? s(x,3) : s(x,2) \ ++ : c==1 ? nc==8 ? s(x,4) : s(x,3) \ ++ : c==2 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ ++ : c==3 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ ++ : c==4 ? nc==8 ? s(x,7) : s(x,0) \ ++ : c==5 ? nc==8 ? s(x,0) : s(x,1) \ ++ : c==6 ? s(x,1) \ ++ : s(x,2)) \ ++ : \ ++ ( c==0 ? nc==8 ? s(x,4) : s(x,3) \ ++ : c==1 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ ++ : c==2 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ ++ : c==3 ? nc==4 ? s(x,2) : nc==8 ? s(x,7) : s(x,0) \ ++ : c==4 ? nc==8 ? s(x,0) : s(x,1) \ ++ : c==5 ? nc==8 ? s(x,1) : s(x,2) \ ++ : c==6 ? s(x,2) \ ++ : s(x,3))) ++ ++#define inv_var(x,r,c) \ ++ ( r==0 ? \ ++ ( c==0 ? s(x,0) \ ++ : c==1 ? s(x,1) \ ++ : c==2 ? s(x,2) \ ++ : c==3 ? s(x,3) \ ++ : c==4 ? s(x,4) \ ++ : c==5 ? s(x,5) \ ++ : c==6 ? s(x,6) \ ++ : s(x,7)) \ ++ : r==1 ? \ ++ ( c==0 ? nc==4 ? s(x,3) : nc==8 ? s(x,7) : s(x,5) \ ++ : c==1 ? s(x,0) \ ++ : c==2 ? s(x,1) \ ++ : c==3 ? s(x,2) \ ++ : c==4 ? s(x,3) \ ++ : c==5 ? s(x,4) \ ++ : c==6 ? s(x,5) \ ++ : s(x,6)) \ ++ : r==2 ? \ ++ ( c==0 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ ++ : c==1 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ ++ : c==2 ? nc==8 ? s(x,7) : s(x,0) \ ++ : c==3 ? nc==8 ? s(x,0) : s(x,1) \ ++ : c==4 ? nc==8 ? s(x,1) : s(x,2) \ ++ : c==5 ? nc==8 ? s(x,2) : s(x,3) \ ++ : c==6 ? s(x,3) \ ++ : s(x,4)) \ ++ : \ ++ ( c==0 ? nc==4 ? s(x,1) : nc==8 ? s(x,4) : s(x,3) \ ++ : c==1 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ ++ : c==2 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ ++ : c==3 ? nc==8 ? s(x,7) : s(x,0) \ ++ : c==4 ? nc==8 ? s(x,0) : s(x,1) \ ++ : c==5 ? nc==8 ? s(x,1) : s(x,2) \ ++ : c==6 ? s(x,2) \ ++ : s(x,3))) ++ ++#define si(y,x,k,c) s(y,c) = const_word_in(x + 4 * c) ^ k[c] ++#define so(y,x,c) word_out(y + 4 * c, s(x,c)) ++ ++#if defined(FOUR_TABLES) ++#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c) ++#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c) ++#elif defined(ONE_TABLE) ++#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c) ++#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c) ++#else ++#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c] ++#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]) ++#endif ++ ++#if defined(FOUR_LR_TABLES) ++#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c) ++#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c) ++#elif defined(ONE_LR_TABLE) ++#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c) ++#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c) ++#else ++#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c] ++#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c] ++#endif ++ ++#if AES_BLOCK_SIZE == 16 ++ ++#if defined(ARRAYS) ++#define locals(y,x) x[4],y[4] ++#else ++#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 ++// the following defines prevent the compiler requiring the declaration ++// of generated but unused variables in the fwd_var and inv_var macros ++#define b04 unused ++#define b05 unused ++#define b06 unused ++#define b07 unused ++#define b14 unused ++#define b15 unused ++#define b16 unused ++#define b17 unused ++#endif ++#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ ++ s(y,2) = s(x,2); s(y,3) = s(x,3); ++#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) ++#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) ++#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) ++ ++#elif AES_BLOCK_SIZE == 24 ++ ++#if defined(ARRAYS) ++#define locals(y,x) x[6],y[6] ++#else ++#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \ ++ y##0,y##1,y##2,y##3,y##4,y##5 ++#define b06 unused ++#define b07 unused ++#define b16 unused ++#define b17 unused ++#endif ++#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ ++ s(y,2) = s(x,2); s(y,3) = s(x,3); \ ++ s(y,4) = s(x,4); s(y,5) = s(x,5); ++#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ ++ si(y,x,k,3); si(y,x,k,4); si(y,x,k,5) ++#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ ++ so(y,x,3); so(y,x,4); so(y,x,5) ++#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ ++ rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5) ++#else ++ ++#if defined(ARRAYS) ++#define locals(y,x) x[8],y[8] ++#else ++#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \ ++ y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7 ++#endif ++#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ ++ s(y,2) = s(x,2); s(y,3) = s(x,3); \ ++ s(y,4) = s(x,4); s(y,5) = s(x,5); \ ++ s(y,6) = s(x,6); s(y,7) = s(x,7); ++ ++#if AES_BLOCK_SIZE == 32 ++ ++#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \ ++ si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7) ++#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \ ++ so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7) ++#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \ ++ rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7) ++#else ++ ++#define state_in(y,x,k) \ ++switch(nc) \ ++{ case 8: si(y,x,k,7); si(y,x,k,6); \ ++ case 6: si(y,x,k,5); si(y,x,k,4); \ ++ case 4: si(y,x,k,3); si(y,x,k,2); \ ++ si(y,x,k,1); si(y,x,k,0); \ ++} ++ ++#define state_out(y,x) \ ++switch(nc) \ ++{ case 8: so(y,x,7); so(y,x,6); \ ++ case 6: so(y,x,5); so(y,x,4); \ ++ case 4: so(y,x,3); so(y,x,2); \ ++ so(y,x,1); so(y,x,0); \ ++} ++ ++#if defined(FAST_VARIABLE) ++ ++#define round(rm,y,x,k) \ ++switch(nc) \ ++{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ ++ rm(y,x,k,5); rm(y,x,k,4); \ ++ rm(y,x,k,3); rm(y,x,k,2); \ ++ rm(y,x,k,1); rm(y,x,k,0); \ ++ break; \ ++ case 6: rm(y,x,k,5); rm(y,x,k,4); \ ++ rm(y,x,k,3); rm(y,x,k,2); \ ++ rm(y,x,k,1); rm(y,x,k,0); \ ++ break; \ ++ case 4: rm(y,x,k,3); rm(y,x,k,2); \ ++ rm(y,x,k,1); rm(y,x,k,0); \ ++ break; \ ++} ++#else ++ ++#define round(rm,y,x,k) \ ++switch(nc) \ ++{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ ++ case 6: rm(y,x,k,5); rm(y,x,k,4); \ ++ case 4: rm(y,x,k,3); rm(y,x,k,2); \ ++ rm(y,x,k,1); rm(y,x,k,0); \ ++} ++ ++#endif ++ ++#endif ++#endif ++ ++void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) ++{ u_int32_t locals(b0, b1); ++ const u_int32_t *kp = cx->aes_e_key; ++ ++#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) ++ u_int32_t f2; ++#endif ++ ++ state_in(b0, in_blk, kp); kp += nc; ++ ++#if defined(UNROLL) ++ ++ switch(cx->aes_Nrnd) ++ { ++ case 14: round(fwd_rnd, b1, b0, kp ); ++ round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; ++ case 12: round(fwd_rnd, b1, b0, kp ); ++ round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; ++ case 10: round(fwd_rnd, b1, b0, kp ); ++ round(fwd_rnd, b0, b1, kp + nc); ++ round(fwd_rnd, b1, b0, kp + 2 * nc); ++ round(fwd_rnd, b0, b1, kp + 3 * nc); ++ round(fwd_rnd, b1, b0, kp + 4 * nc); ++ round(fwd_rnd, b0, b1, kp + 5 * nc); ++ round(fwd_rnd, b1, b0, kp + 6 * nc); ++ round(fwd_rnd, b0, b1, kp + 7 * nc); ++ round(fwd_rnd, b1, b0, kp + 8 * nc); ++ round(fwd_lrnd, b0, b1, kp + 9 * nc); ++ } ++ ++#elif defined(PARTIAL_UNROLL) ++ { u_int32_t rnd; ++ ++ for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd) ++ { ++ round(fwd_rnd, b1, b0, kp); ++ round(fwd_rnd, b0, b1, kp + nc); kp += 2 * nc; ++ } ++ ++ round(fwd_rnd, b1, b0, kp); ++ round(fwd_lrnd, b0, b1, kp + nc); ++ } ++#else ++ { u_int32_t rnd; ++ ++ for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd) ++ { ++ round(fwd_rnd, b1, b0, kp); ++ l_copy(b0, b1); kp += nc; ++ } ++ ++ round(fwd_lrnd, b0, b1, kp); ++ } ++#endif ++ ++ state_out(out_blk, b0); ++} ++ ++void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) ++{ u_int32_t locals(b0, b1); ++ const u_int32_t *kp = cx->aes_d_key; ++ ++#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) ++ u_int32_t f2, f4, f8, f9; ++#endif ++ ++ state_in(b0, in_blk, kp); kp += nc; ++ ++#if defined(UNROLL) ++ ++ switch(cx->aes_Nrnd) ++ { ++ case 14: round(inv_rnd, b1, b0, kp ); ++ round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; ++ case 12: round(inv_rnd, b1, b0, kp ); ++ round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; ++ case 10: round(inv_rnd, b1, b0, kp ); ++ round(inv_rnd, b0, b1, kp + nc); ++ round(inv_rnd, b1, b0, kp + 2 * nc); ++ round(inv_rnd, b0, b1, kp + 3 * nc); ++ round(inv_rnd, b1, b0, kp + 4 * nc); ++ round(inv_rnd, b0, b1, kp + 5 * nc); ++ round(inv_rnd, b1, b0, kp + 6 * nc); ++ round(inv_rnd, b0, b1, kp + 7 * nc); ++ round(inv_rnd, b1, b0, kp + 8 * nc); ++ round(inv_lrnd, b0, b1, kp + 9 * nc); ++ } ++ ++#elif defined(PARTIAL_UNROLL) ++ { u_int32_t rnd; ++ ++ for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd) ++ { ++ round(inv_rnd, b1, b0, kp); ++ round(inv_rnd, b0, b1, kp + nc); kp += 2 * nc; ++ } ++ ++ round(inv_rnd, b1, b0, kp); ++ round(inv_lrnd, b0, b1, kp + nc); ++ } ++#else ++ { u_int32_t rnd; ++ ++ for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd) ++ { ++ round(inv_rnd, b1, b0, kp); ++ l_copy(b0, b1); kp += nc; ++ } ++ ++ round(inv_lrnd, b0, b1, kp); ++ } ++#endif ++ ++ state_out(out_blk, b0); ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/aes/aes_cbc.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,43 @@ ++/* ++// I retain copyright in this code but I encourage its free use provided ++// that I don't carry any responsibility for the results. I am especially ++// happy to see it used in free and open source software. If you do use ++// it I would appreciate an acknowledgement of its origin in the code or ++// the product that results and I would also appreciate knowing a little ++// about the use to which it is being put. I am grateful to Frank Yellin ++// for some ideas that are used in this implementation. ++// ++// Dr B. R. Gladman <brg@gladman.uk.net> 6th April 2001. ++// ++// This is an implementation of the AES encryption algorithm (Rijndael) ++// designed by Joan Daemen and Vincent Rijmen. This version is designed ++// to provide both fixed and dynamic block and key lengths and can also ++// run with either big or little endian internal byte order (see aes.h). ++// It inputs block and key lengths in bytes with the legal values being ++// 16, 24 and 32. ++* ++*/ ++ ++#ifdef __KERNEL__ ++#include <linux/types.h> ++#else ++#include <sys/types.h> ++#endif ++#include "crypto/aes_cbc.h" ++#include "crypto/cbc_generic.h" ++ ++/* returns bool success */ ++int AES_set_key(aes_context *aes_ctx, const u_int8_t *key, int keysize) { ++ aes_set_key(aes_ctx, key, keysize, 0); ++ return 1; ++} ++CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); ++ ++ ++/* ++ * $Log: aes_cbc.c,v $ ++ * Revision 1.1 2004/04/06 02:48:12 mcr ++ * pullup of AES cipher from alg-branch. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/aes/aes_xcbc_mac.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,67 @@ ++#ifdef __KERNEL__ ++#include <linux/types.h> ++#include <linux/kernel.h> ++#define DEBUG(x) ++#else ++#include <stdio.h> ++#include <sys/types.h> ++#define DEBUG(x) x ++#endif ++ ++#include "crypto/aes.h" ++#include "crypto/aes_xcbc_mac.h" ++ ++int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen) ++{ ++ int ret=1; ++ aes_block kn[3] = { ++ { 0x01010101, 0x01010101, 0x01010101, 0x01010101 }, ++ { 0x02020202, 0x02020202, 0x02020202, 0x02020202 }, ++ { 0x03030303, 0x03030303, 0x03030303, 0x03030303 }, ++ }; ++ aes_set_key(&ctxm->ctx_k1, key, keylen, 0); ++ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[0], (u_int8_t *) kn[0]); ++ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[1], (u_int8_t *) ctxm->k2); ++ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[2], (u_int8_t *) ctxm->k3); ++ aes_set_key(&ctxm->ctx_k1, (u_int8_t *) kn[0], 16, 0); ++ return ret; ++} ++static void do_pad_xor(u_int8_t *out, const u_int8_t *in, int len) { ++ int pos=0; ++ for (pos=1; pos <= 16; pos++, in++, out++) { ++ if (pos <= len) ++ *out ^= *in; ++ if (pos > len) { ++ DEBUG(printf("put 0x80 at pos=%d\n", pos)); ++ *out ^= 0x80; ++ break; ++ } ++ } ++} ++static void xor_block(aes_block res, const aes_block op) { ++ res[0] ^= op[0]; ++ res[1] ^= op[1]; ++ res[2] ^= op[2]; ++ res[3] ^= op[3]; ++} ++int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]) { ++ int ret=ilen; ++ u_int32_t out[4] = { 0, 0, 0, 0 }; ++ for (; ilen > 16 ; ilen-=16) { ++ xor_block(out, (const u_int32_t*) &in[0]); ++ aes_encrypt(&ctxm->ctx_k1, in, (u_int8_t *)&out[0]); ++ in+=16; ++ } ++ do_pad_xor((u_int8_t *)&out, in, ilen); ++ if (ilen==16) { ++ DEBUG(printf("using k3\n")); ++ xor_block(out, ctxm->k3); ++ } ++ else ++ { ++ DEBUG(printf("using k2\n")); ++ xor_block(out, ctxm->k2); ++ } ++ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *)out, hash); ++ return ret; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/aes/test_main.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,41 @@ ++#include <stdio.h> ++#include <string.h> ++#include <sys/types.h> ++#include "aes_cbc.h" ++#define AES_BLOCK_SIZE 16 ++#define KEY_SIZE 128 /* bits */ ++#define KEY "1234567890123456" ++#define STR "hola guaso como estaisss ... 012" ++#define STRSZ (sizeof(STR)-1) ++ ++#define EMT_AESCBC_BLKLEN AES_BLOCK_SIZE ++#define AES_CONTEXT_T aes_context ++#define EMT_ESPAES_KEY_SZ 16 ++int pretty_print(const unsigned char *buf, int count) { ++ int i=0; ++ for (;i<count;i++) { ++ if (i%8==0) putchar(' '); ++ if (i%16==0) putchar('\n'); ++ printf ("%02hhx ", buf[i]); ++ } ++ putchar('\n'); ++ return i; ++} ++//#define SIZE STRSZ/2 ++#define SIZE STRSZ ++int main() { ++ int ret; ++ char buf0[SIZE+1], buf1[SIZE+1]; ++ char IV[AES_BLOCK_SIZE]="\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0"; ++ aes_context ac; ++ AES_set_key(&ac, KEY, KEY_SIZE); ++ //pretty_print((char *)&ac.aes_e_key, sizeof(ac.aes_e_key)); ++ memset(buf0, 0, sizeof (buf0)); ++ memset(buf1, 0, sizeof (buf1)); ++ ret=AES_cbc_encrypt(&ac, STR, buf0, SIZE, IV, 1); ++ pretty_print(buf0, SIZE); ++ printf("size=%d ret=%d\n%s\n", SIZE, ret, buf0); ++ ret=AES_cbc_encrypt(&ac, buf0, buf1, SIZE, IV, 0); ++ printf("size=%d ret=%d\n%s\n", SIZE, ret, buf1); ++ return 0; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/aes/test_main_mac.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,30 @@ ++#include <stdio.h> ++#include <sys/types.h> ++#include <string.h> ++#include "aes.h" ++#include "aes_xcbc_mac.h" ++#define STR "Hola guasssso c|mo estais ...012" ++void print_hash(const __u8 *hash) { ++ printf("%08x %08x %08x %08x\n", ++ *(__u32*)(&hash[0]), ++ *(__u32*)(&hash[4]), ++ *(__u32*)(&hash[8]), ++ *(__u32*)(&hash[12])); ++} ++int main(int argc, char *argv[]) { ++ aes_block key= { 0xdeadbeef, 0xceedcaca, 0xcafebabe, 0xff010204 }; ++ __u8 hash[16]; ++ char *str = argv[1]; ++ aes_context_mac ctx; ++ if (str==NULL) { ++ fprintf(stderr, "pasame el str\n"); ++ return 255; ++ } ++ AES_xcbc_mac_set_key(&ctx, (__u8 *)&key, sizeof(key)); ++ AES_xcbc_mac_hash(&ctx, str, strlen(str), hash); ++ print_hash(hash); ++ str[2]='x'; ++ AES_xcbc_mac_hash(&ctx, str, strlen(str), hash); ++ print_hash(hash); ++ return 0; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/COPYRIGHT Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,50 @@ ++Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) ++All rights reserved. ++ ++This package is an DES implementation written by Eric Young (eay@cryptsoft.com). ++The implementation was written so as to conform with MIT's libdes. ++ ++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. ++ ++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 that the SSL library. 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 software developed by Eric Young (eay@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 license 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 distrubution license ++[including the GNU Public License.] ++ ++The reason behind this being stated in this direct manner is past ++experience in code simply being copied and the attribution removed ++from it and then being distributed as part of other packages. This ++implementation was a non-trivial and unpaid effort. +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/INSTALL Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,69 @@ ++Check the CC and CFLAGS lines in the makefile ++ ++If your C library does not support the times(3) function, change the ++#define TIMES to ++#undef TIMES in speed.c ++If it does, check the HZ value for the times(3) function. ++If your system does not define CLK_TCK it will be assumed to ++be 100.0. ++ ++If possible use gcc v 2.7.? ++Turn on the maximum optimising (normally '-O3 -fomit-frame-pointer' for gcc) ++In recent times, some system compilers give better performace. ++ ++type 'make' ++ ++run './destest' to check things are ok. ++run './rpw' to check the tty code for reading passwords works. ++run './speed' to see how fast those optimisations make the library run :-) ++run './des_opts' to determin the best compile time options. ++ ++The output from des_opts should be put in the makefile options and des_enc.c ++should be rebuilt. For 64 bit computers, do not use the DES_PTR option. ++For the DEC Alpha, edit des.h and change DES_LONG to 'unsigned int' ++and then you can use the 'DES_PTR' option. ++ ++The file options.txt has the options listed for best speed on quite a ++few systems. Look and the options (UNROLL, PTR, RISC2 etc) and then ++turn on the relevent option in the Makefile ++ ++There are some special Makefile targets that make life easier. ++make cc - standard cc build ++make gcc - standard gcc build ++make x86-elf - x86 assembler (elf), linux-elf. ++make x86-out - x86 assembler (a.out), FreeBSD ++make x86-solaris- x86 assembler ++make x86-bsdi - x86 assembler (a.out with primative assembler). ++ ++If at all possible use the assembler (for Windows NT/95, use ++asm/win32.obj to link with). The x86 assembler is very very fast. ++ ++A make install will by default install ++libdes.a in /usr/local/lib/libdes.a ++des in /usr/local/bin/des ++des_crypt.man in /usr/local/man/man3/des_crypt.3 ++des.man in /usr/local/man/man1/des.1 ++des.h in /usr/include/des.h ++ ++des(1) should be compatible with sunOS's but I have been unable to ++test it. ++ ++These routines should compile on MSDOS, most 32bit and 64bit version ++of Unix (BSD and SYSV) and VMS, without modification. ++The only problems should be #include files that are in the wrong places. ++ ++These routines can be compiled under MSDOS. ++I have successfully encrypted files using des(1) under MSDOS and then ++decrypted the files on a SparcStation. ++I have been able to compile and test the routines with ++Microsoft C v 5.1 and Turbo C v 2.0. ++The code in this library is in no way optimised for the 16bit ++operation of MSDOS. ++ ++When building for glibc, ignore all of the above and just unpack into ++glibc-1.??/des and then gmake as per normal. ++ ++As a final note on performace. Certain CPUs like sparcs and Alpha often give ++a %10 speed difference depending on the link order. It is rather anoying ++when one program reports 'x' DES encrypts a second and another reports ++'x*0.9' the speed. +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/Makefile.objs Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,20 @@ ++obj-$(CONFIG_IPSEC_ENC_3DES) += cbc_enc.o ++#obj-$(CONFIG_IPSEC_ENC_3DES) += des_opts.o ++obj-$(CONFIG_IPSEC_ENC_3DES) += ecb_enc.o ++#obj-$(CONFIG_IPSEC_ENC_3DES) += fcrypt.o ++obj-$(CONFIG_IPSEC_ENC_3DES) += set_key.o ++ ++ifeq ($(strip ${SUBARCH}),) ++SUBARCH:=${ARCH} ++endif ++ ++ifeq (${SUBARCH},i386) ++obj-$(CONFIG_IPSEC_ENC_3DES) += dx86unix.o ++else ++obj-$(CONFIG_IPSEC_ENC_3DES) += des_enc.o ++endif ++ ++ ++ ++ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/README Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,54 @@ ++ ++ libdes, Version 4.01 10-Jan-97 ++ ++ Copyright (c) 1997, Eric Young ++ All rights reserved. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms specified in COPYRIGHT. ++ ++-- ++The primary ftp site for this library is ++ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/libdes-x.xx.tar.gz ++libdes is now also shipped with SSLeay. Primary ftp site of ++ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/SSLeay-x.x.x.tar.gz ++ ++The best way to build this library is to build it as part of SSLeay. ++ ++This kit builds a DES encryption library and a DES encryption program. ++It supports ecb, cbc, ofb, cfb, triple ecb, triple cbc, triple ofb, ++triple cfb, desx, and MIT's pcbc encryption modes and also has a fast ++implementation of crypt(3). ++It contains support routines to read keys from a terminal, ++generate a random key, generate a key from an arbitrary length string, ++read/write encrypted data from/to a file descriptor. ++ ++The implementation was written so as to conform with the manual entry ++for the des_crypt(3) library routines from MIT's project Athena. ++ ++destest should be run after compilation to test the des routines. ++rpw should be run after compilation to test the read password routines. ++The des program is a replacement for the sun des command. I believe it ++conforms to the sun version. ++ ++The Imakefile is setup for use in the kerberos distribution. ++ ++These routines are best compiled with gcc or any other good ++optimising compiler. ++Just turn you optimiser up to the highest settings and run destest ++after the build to make sure everything works. ++ ++I believe these routines are close to the fastest and most portable DES ++routines that use small lookup tables (4.5k) that are publicly available. ++The fcrypt routine is faster than ufc's fcrypt (when compiling with ++gcc2 -O2) on the sparc 2 (1410 vs 1270) but is not so good on other machines ++(on a sun3/260 168 vs 336). It is a function of CPU on chip cache size. ++[ 10-Jan-97 and a function of an incorrect speed testing program in ++ ufc which gave much better test figures that reality ]. ++ ++It is worth noting that on sparc and Alpha CPUs, performance of the DES ++library can vary by upto %10 due to the positioning of files after application ++linkage. ++ ++Eric Young (eay@cryptsoft.com) ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/README.freeswan Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,33 @@ ++The only changes the FreeS/WAN project has made to libdes-lite 4.04b are: ++ ++We #ifdef-ed the declaration of DES_LONG in des.h, so it's more efficient ++on the Alpha, instead of just noting the issue in a comment. ++ ++We #ifdef-ed out the des_options() function in ecb_enc.c, because we don't ++use it, and its call to sprintf() can cause subtle difficulties when KLIPS ++is built as a module (depending on details of Linux configuration options). ++ ++We changed some instances of CC=$(CC) in the Makefile to CC='$(CC)' to make ++it cope better with Linux kernel Makefile stupidities, and took out an ++explicit CC=gcc (unwise on systems with strange compilers). ++ ++We deleted some references to <stdio.h> and <stdlib.h>, and a declaration ++of one function found only in the full libdes (not in libdes-lite), to ++avoid dragging in bits of stdio/stdlib unnecessarily. (Our thanks to Hans ++Schultz for spotting this and pointing out the fixes.) ++ ++We deleted a couple of .obj files in the asm subdirectory, which appear to ++have been included in the original library by accident. ++ ++We have added an include of our Makefile.inc file, to permit overriding ++things like choice of compiler (although the libdes Makefile would ++probably need some work to make this effective). ++ ++ ++ ++Note that Eric Young is no longer at the email address listed in these ++files, and is (alas) no longer working on free crypto software. ++ ++ ++ ++This file is RCSID $Id: README.freeswan,v 1.11 2002/04/24 07:36:37 mcr Exp $ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/VERSION Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,406 @@ ++Version 4.04 ++ Fixed a few tests in destest. Also added x86 assember for ++ des_ncbc_encrypt() which is the standard cbc mode function. ++ This makes a very very large performace difference. ++ Ariel Glenn ariel@columbia.edu reports that the terminal ++ 'turn echo off' can return (errno == EINVAL) under solaris ++ when redirection is used. So I now catch that as well as ENOTTY. ++ ++ ++Version 4.03 ++ Left a static out of enc_write.c, which caused to buffer to be ++ continiously malloc()ed. Does anyone use these functions? I keep ++ on feeling like removing them since I only had these in there ++ for a version of kerberised login. Anyway, this was pointed out ++ by Theo de Raadt <deraadt@cvs.openbsd.org> ++ The 'n' bit ofb code was wrong, it was not shifting the shift ++ register. It worked correctly for n == 64. Thanks to ++ Gigi Ankeny <Gigi.Ankeny@Eng.Sun.COM> for pointing this one out. ++ ++Version 4.02 ++ I was doing 'if (memcmp(weak_keys[i],key,sizeof(key)) == 0)' ++ when checking for weak keys which is wrong :-(, pointed out by ++ Markus F.X.J. Oberhumer <markus.oberhumer@jk.uni-linz.ac.at>. ++ ++Version 4.01 ++ Even faster inner loop in the DES assembler for x86 and a modification ++ for IP/FP which is faster on x86. Both of these changes are ++ from Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk>. His ++ changes make the assembler run %40 faster on a pentium. This is just ++ a case of getting the instruction sequence 'just right'. ++ All credit to 'Svend' :-) ++ Quite a few special x86 'make' targets. ++ A libdes-l (lite) distribution. ++ ++Version 4.00 ++ After a bit of a pause, I'll up the major version number since this ++ is mostly a performace release. I've added x86 assembler and ++ added more options for performance. A %28 speedup for gcc ++ on a pentium and the assembler is a %50 speedup. ++ MIPS CPU's, sparc and Alpha are the main CPU's with speedups. ++ Run des_opts to work out which options should be used. ++ DES_RISC1/DES_RISC2 use alternative inner loops which use ++ more registers but should give speedups on any CPU that does ++ dual issue (pentium). DES_UNROLL unrolls the inner loop, ++ which costs in code size. ++ ++Version 3.26 ++ I've finally removed one of the shifts in D_ENCRYPT. This ++ meant I've changed the des_SPtrans table (spr.h), the set_key() ++ function and some things in des_enc.c. This has definitly ++ made things faster :-). I've known about this one for some ++ time but I've been too lazy to follow it up :-). ++ Noticed that in the D_ENCRYPT() macro, we can just do L^=(..)^(..)^.. ++ instead of L^=((..)|(..)|(..).. This should save a register at ++ least. ++ Assember for x86. The file to replace is des_enc.c, which is replaced ++ by one of the assembler files found in asm. Look at des/asm/readme ++ for more info. ++ ++ /* Modification to fcrypt so it can be compiled to support ++ HPUX 10.x's long password format, define -DLONGCRYPT to use this. ++ Thanks to Jens Kupferschmidt <bt1cu@hpboot.rz.uni-leipzig.de>. */ ++ ++ SIGWINCH case put in des_read_passwd() so the function does not ++ 'exit' if this function is recieved. ++ ++Version 3.25 17/07/96 ++ Modified read_pwd.c so that stdin can be read if not a tty. ++ Thanks to Jeff Barber <jeffb@issl.atl.hp.com> for the patches. ++ des_init_random_number_generator() shortened due to VMS linker ++ limits. ++ Added RSA's DESX cbc mode. It is a form of cbc encryption, with 2 ++ 8 byte quantites xored before and after encryption. ++ des_xcbc_encryption() - the name is funny to preserve the des_ ++ prefix on all functions. ++ ++Version 3.24 20/04/96 ++ The DES_PTR macro option checked and used by SSLeay configuration ++ ++Version 3.23 11/04/96 ++ Added DES_LONG. If defined to 'unsigned int' on the DEC Alpha, ++ it gives a %20 speedup :-) ++ Fixed the problem with des.pl under perl5. The patches were ++ sent by Ed Kubaitis (ejk@uiuc.edu). ++ if fcrypt.c, changed values to handle illegal salt values the way ++ normal crypt() implementations do. Some programs apparently use ++ them :-(. The patch was sent by Bjorn Gronvall <bg@sics.se> ++ ++Version 3.22 29/11/95 ++ Bug in des(1), an error with the uuencoding stuff when the ++ 'data' is small, thanks to Geoff Keating <keagchon@mehta.anu.edu.au> ++ for the patch. ++ ++Version 3.21 22/11/95 ++ After some emailing back and forth with ++ Colin Plumb <colin@nyx10.cs.du.edu>, I've tweaked a few things ++ and in a future version I will probably put in some of the ++ optimisation he suggested for use with the DES_USE_PTR option. ++ Extra routines from Mark Murray <mark@grondar.za> for use in ++ freeBSD. They mostly involve random number generation for use ++ with kerberos. They involve evil machine specific system calls ++ etc so I would normally suggest pushing this stuff into the ++ application and/or using RAND_seed()/RAND_bytes() if you are ++ using this DES library as part of SSLeay. ++ Redone the read_pw() function so that it is cleaner and ++ supports termios, thanks to Sameer Parekh <sameer@c2.org> ++ for the initial patches for this. ++ Renamed 3ecb_encrypt() to ecb3_encrypt(). This has been ++ done just to make things more consistent. ++ I have also now added triple DES versions of cfb and ofb. ++ ++Version 3.20 ++ Damn, Damn, Damn, as pointed out by Mike_Spreitzer.PARC@xerox.com, ++ my des_random_seed() function was only copying 4 bytes of the ++ passed seed into the init structure. It is now fixed to copy 8. ++ My own suggestion is to used something like MD5 :-) ++ ++Version 3.19 ++ While looking at my code one day, I though, why do I keep on ++ calling des_encrypt(in,out,ks,enc) when every function that ++ calls it has in and out the same. So I dropped the 'out' ++ parameter, people should not be using this function. ++ ++Version 3.18 30/08/95 ++ Fixed a few bit with the distribution and the filenames. ++ 3.17 had been munged via a move to DOS and back again. ++ NO CODE CHANGES ++ ++Version 3.17 14/07/95 ++ Fixed ede3 cbc which I had broken in 3.16. I have also ++ removed some unneeded variables in 7-8 of the routines. ++ ++Version 3.16 26/06/95 ++ Added des_encrypt2() which does not use IP/FP, used by triple ++ des routines. Tweaked things a bit elsewhere. %13 speedup on ++ sparc and %6 on a R4400 for ede3 cbc mode. ++ ++Version 3.15 06/06/95 ++ Added des_ncbc_encrypt(), it is des_cbc mode except that it is ++ 'normal' and copies the new iv value back over the top of the ++ passed parameter. ++ CHANGED des_ede3_cbc_encrypt() so that it too now overwrites ++ the iv. THIS WILL BREAK EXISTING CODE, but since this function ++ only new, I feel I can change it, not so with des_cbc_encrypt :-(. ++ I need to update the documentation. ++ ++Version 3.14 31/05/95 ++ New release upon the world, as part of my SSL implementation. ++ New copyright and usage stuff. Basically free for all to use ++ as long as you say it came from me :-) ++ ++Version 3.13 31/05/95 ++ A fix in speed.c, if HZ is not defined, I set it to 100.0 ++ which is reasonable for most unixes except SunOS 4.x. ++ I now have a #ifdef sun but timing for SunOS 4.x looked very ++ good :-(. At my last job where I used SunOS 4.x, it was ++ defined to be 60.0 (look at the old INSTALL documentation), at ++ the last release had it changed to 100.0 since I now work with ++ Solaris2 and SVR4 boxes. ++ Thanks to Rory Chisholm <rchishol@math.ethz.ch> for pointing this ++ one out. ++ ++Version 3.12 08/05/95 ++ As pointed out by The Crypt Keeper <tck@bend.UCSD.EDU>, ++ my D_ENCRYPT macro in crypt() had an un-necessary variable. ++ It has been removed. ++ ++Version 3.11 03/05/95 ++ Added des_ede3_cbc_encrypt() which is cbc mode des with 3 keys ++ and one iv. It is a standard and I needed it for my SSL code. ++ It makes more sense to use this for triple DES than ++ 3cbc_encrypt(). I have also added (or should I say tested :-) ++ cfb64_encrypt() which is cfb64 but it will encrypt a partial ++ number of bytes - 3 bytes in 3 bytes out. Again this is for ++ my SSL library, as a form of encryption to use with SSL ++ telnet. ++ ++Version 3.10 22/03/95 ++ Fixed a bug in 3cbc_encrypt() :-(. When making repeated calls ++ to cbc3_encrypt, the 2 iv values that were being returned to ++ be used in the next call were reversed :-(. ++ Many thanks to Bill Wade <wade@Stoner.COM> for pointing out ++ this error. ++ ++Version 3.09 01/02/95 ++ Fixed des_random_key to far more random, it was rather feeble ++ with regards to picking the initial seed. The problem was ++ pointed out by Olaf Kirch <okir@monad.swb.de>. ++ ++Version 3.08 14/12/94 ++ Added Makefile.PL so libdes can be built into perl5. ++ Changed des_locl.h so RAND is always defined. ++ ++Version 3.07 05/12/94 ++ Added GNUmake and stuff so the library can be build with ++ glibc. ++ ++Version 3.06 30/08/94 ++ Added rpc_enc.c which contains _des_crypt. This is for use in ++ secure_rpc v 4.0 ++ Finally fixed the cfb_enc problems. ++ Fixed a few parameter parsing bugs in des (-3 and -b), thanks ++ to Rob McMillan <R.McMillan@its.gu.edu.au> ++ ++Version 3.05 21/04/94 ++ for unsigned long l; gcc does not produce ((l>>34) == 0) ++ This causes bugs in cfb_enc. ++ Thanks to Hadmut Danisch <danisch@ira.uka.de> ++ ++Version 3.04 20/04/94 ++ Added a version number to des.c and libdes.a ++ ++Version 3.03 12/01/94 ++ Fixed a bug in non zero iv in 3cbc_enc. ++ ++Version 3.02 29/10/93 ++ I now work in a place where there are 6+ architectures and 14+ ++ OS versions :-). ++ Fixed TERMIO definition so the most sys V boxes will work :-) ++ ++Release upon comp.sources.misc ++Version 3.01 08/10/93 ++ Added des_3cbc_encrypt() ++ ++Version 3.00 07/10/93 ++ Fixed up documentation. ++ quad_cksum definitely compatible with MIT's now. ++ ++Version 2.30 24/08/93 ++ Triple DES now defaults to triple cbc but can do triple ecb ++ with the -b flag. ++ Fixed some MSDOS uuen/uudecoding problems, thanks to ++ Added prototypes. ++ ++Version 2.22 29/06/93 ++ Fixed a bug in des_is_weak_key() which stopped it working :-( ++ thanks to engineering@MorningStar.Com. ++ ++Version 2.21 03/06/93 ++ des(1) with no arguments gives quite a bit of help. ++ Added -c (generate ckecksum) flag to des(1). ++ Added -3 (triple DES) flag to des(1). ++ Added cfb and ofb routines to the library. ++ ++Version 2.20 11/03/93 ++ Added -u (uuencode) flag to des(1). ++ I have been playing with byte order in quad_cksum to make it ++ compatible with MIT's version. All I can say is avid this ++ function if possible since MIT's output is endian dependent. ++ ++Version 2.12 14/10/92 ++ Added MSDOS specific macro in ecb_encrypt which gives a %70 ++ speed up when the code is compiled with turbo C. ++ ++Version 2.11 12/10/92 ++ Speedup in set_key (recoding of PC-1) ++ I now do it in 47 simple operations, down from 60. ++ Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) ++ for motivating me to look for a faster system :-) ++ The speedup is probably less that 1% but it is still 13 ++ instructions less :-). ++ ++Version 2.10 06/10/92 ++ The code now works on the 64bit ETA10 and CRAY without modifications or ++ #defines. I believe the code should work on any machine that ++ defines long, int or short to be 8 bytes long. ++ Thanks to Shabbir J. Safdar (shabby@mentor.cc.purdue.edu) ++ for helping me fix the code to run on 64bit machines (he had ++ access to an ETA10). ++ Thanks also to John Fletcher <john_fletcher@lccmail.ocf.llnl.gov> ++ for testing the routines on a CRAY. ++ read_password.c has been renamed to read_passwd.c ++ string_to_key.c has been renamed to string2key.c ++ ++Version 2.00 14/09/92 ++ Made mods so that the library should work on 64bit CPU's. ++ Removed all my uchar and ulong defs. To many different ++ versions of unix define them in their header files in too many ++ different combinations :-) ++ IRIX - Sillicon Graphics mods (mostly in read_password.c). ++ Thanks to Andrew Daviel (advax@erich.triumf.ca) ++ ++Version 1.99 26/08/92 ++ Fixed a bug or 2 in enc_read.c ++ Fixed a bug in enc_write.c ++ Fixed a pseudo bug in fcrypt.c (very obscure). ++ ++Version 1.98 31/07/92 ++ Support for the ETA10. This is a strange machine that defines ++ longs and ints as 8 bytes and shorts as 4 bytes. ++ Since I do evil things with long * that assume that they are 4 ++ bytes. Look in the Makefile for the option to compile for ++ this machine. quad_cksum appears to have problems but I ++ will don't have the time to fix it right now, and this is not ++ a function that uses DES and so will not effect the main uses ++ of the library. ++ ++Version 1.97 20/05/92 eay ++ Fixed the Imakefile and made some changes to des.h to fix some ++ problems when building this package with Kerberos v 4. ++ ++Version 1.96 18/05/92 eay ++ Fixed a small bug in string_to_key() where problems could ++ occur if des_check_key was set to true and the string ++ generated a weak key. ++ ++Patch2 posted to comp.sources.misc ++Version 1.95 13/05/92 eay ++ Added an alternative version of the D_ENCRYPT macro in ++ ecb_encrypt and fcrypt. Depending on the compiler, one version or the ++ other will be faster. This was inspired by ++ Dana How <how@isl.stanford.edu>, and her pointers about doing the ++ *(ulong *)((uchar *)ptr+(value&0xfc)) ++ vs ++ ptr[value&0x3f] ++ to stop the C compiler doing a <<2 to convert the long array index. ++ ++Version 1.94 05/05/92 eay ++ Fixed an incompatibility between my string_to_key and the MIT ++ version. When the key is longer than 8 chars, I was wrapping ++ with a different method. To use the old version, define ++ OLD_STR_TO_KEY in the makefile. Thanks to ++ viktor@newsu.shearson.com (Viktor Dukhovni). ++ ++Version 1.93 28/04/92 eay ++ Fixed the VMS mods so that echo is now turned off in ++ read_password. Thanks again to brennan@coco.cchs.su.oz.AU. ++ MSDOS support added. The routines can be compiled with ++ Turbo C (v2.0) and MSC (v5.1). Make sure MSDOS is defined. ++ ++Patch1 posted to comp.sources.misc ++Version 1.92 13/04/92 eay ++ Changed D_ENCRYPT so that the rotation of R occurs outside of ++ the loop. This required rotating all the longs in sp.h (now ++ called spr.h). Thanks to Richard Outerbridge <71755.204@CompuServe.COM> ++ speed.c has been changed so it will work without SIGALRM. If ++ times(3) is not present it will try to use ftime() instead. ++ ++Version 1.91 08/04/92 eay ++ Added -E/-D options to des(1) so it can use string_to_key. ++ Added SVR4 mods suggested by witr@rwwa.COM ++ Added VMS mods suggested by brennan@coco.cchs.su.oz.AU. If ++ anyone knows how to turn of tty echo in VMS please tell me or ++ implement it yourself :-). ++ Changed FILE *IN/*OUT to *DES_IN/*DES_OUT since it appears VMS ++ does not like IN/OUT being used. ++ ++Libdes posted to comp.sources.misc ++Version 1.9 24/03/92 eay ++ Now contains a fast small crypt replacement. ++ Added des(1) command. ++ Added des_rw_mode so people can use cbc encryption with ++ enc_read and enc_write. ++ ++Version 1.8 15/10/91 eay ++ Bug in cbc_cksum. ++ Many thanks to Keith Reynolds (keithr@sco.COM) for pointing this ++ one out. ++ ++Version 1.7 24/09/91 eay ++ Fixed set_key :-) ++ set_key is 4 times faster and takes less space. ++ There are a few minor changes that could be made. ++ ++Version 1.6 19/09/1991 eay ++ Finally go IP and FP finished. ++ Now I need to fix set_key. ++ This version is quite a bit faster that 1.51 ++ ++Version 1.52 15/06/1991 eay ++ 20% speedup in ecb_encrypt by changing the E bit selection ++ to use 2 32bit words. This also required modification of the ++ sp table. There is still a way to speedup the IP and IP-1 ++ (hints from outer@sq.com) still working on this one :-(. ++ ++Version 1.51 07/06/1991 eay ++ Faster des_encrypt by loop unrolling ++ Fixed bug in quad_cksum.c (thanks to hughes@logos.ucs.indiana.edu) ++ ++Version 1.50 28/05/1991 eay ++ Optimised the code a bit more for the sparc. I have improved the ++ speed of the inner des_encrypt by speeding up the initial and ++ final permutations. ++ ++Version 1.40 23/10/1990 eay ++ Fixed des_random_key, it did not produce a random key :-( ++ ++Version 1.30 2/10/1990 eay ++ Have made des_quad_cksum the same as MIT's, the full package ++ should be compatible with MIT's ++ Have tested on a DECstation 3100 ++ Still need to fix des_set_key (make it faster). ++ Does des_cbc_encrypts at 70.5k/sec on a 3100. ++ ++Version 1.20 18/09/1990 eay ++ Fixed byte order dependencies. ++ Fixed (I hope) all the word alignment problems. ++ Speedup in des_ecb_encrypt. ++ ++Version 1.10 11/09/1990 eay ++ Added des_enc_read and des_enc_write. ++ Still need to fix des_quad_cksum. ++ Still need to document des_enc_read and des_enc_write. ++ ++Version 1.00 27/08/1990 eay ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/crypt586.pl Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,204 @@ ++#!/usr/bin/perl ++# ++# The inner loop instruction sequence and the IP/FP modifications are from ++# Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk> ++# I've added the stuff needed for crypt() but I've not worried about making ++# things perfect. ++# ++ ++push(@INC,"perlasm","../../perlasm"); ++require "x86asm.pl"; ++ ++&asm_init($ARGV[0],"crypt586.pl"); ++ ++$L="edi"; ++$R="esi"; ++ ++&external_label("des_SPtrans"); ++&fcrypt_body("fcrypt_body"); ++&asm_finish(); ++ ++sub fcrypt_body ++ { ++ local($name,$do_ip)=@_; ++ ++ &function_begin($name,"EXTRN _des_SPtrans:DWORD"); ++ ++ &comment(""); ++ &comment("Load the 2 words"); ++ $ks="ebp"; ++ ++ &xor( $L, $L); ++ &xor( $R, $R); ++ &mov($ks,&wparam(1)); ++ ++ &push(25); # add a variable ++ ++ &set_label("start"); ++ for ($i=0; $i<16; $i+=2) ++ { ++ &comment(""); ++ &comment("Round $i"); ++ &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); ++ ++ &comment(""); ++ &comment("Round ".sprintf("%d",$i+1)); ++ &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); ++ } ++ &mov("ebx", &swtmp(0)); ++ &mov("eax", $L); ++ &dec("ebx"); ++ &mov($L, $R); ++ &mov($R, "eax"); ++ &mov(&swtmp(0), "ebx"); ++ &jnz(&label("start")); ++ ++ &comment(""); ++ &comment("FP"); ++ &mov("edx",&wparam(0)); ++ ++ &FP_new($R,$L,"eax",3); ++ &mov(&DWP(0,"edx","",0),"eax"); ++ &mov(&DWP(4,"edx","",0),$L); ++ ++ &pop("ecx"); # remove variable ++ ++ &function_end($name); ++ } ++ ++sub D_ENCRYPT ++ { ++ local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_; ++ ++ &mov( $u, &wparam(2)); # 2 ++ &mov( $t, $R); ++ &shr( $t, 16); # 1 ++ &mov( $tmp2, &wparam(3)); # 2 ++ &xor( $t, $R); # 1 ++ ++ &and( $u, $t); # 2 ++ &and( $t, $tmp2); # 2 ++ ++ &mov( $tmp1, $u); ++ &shl( $tmp1, 16); # 1 ++ &mov( $tmp2, $t); ++ &shl( $tmp2, 16); # 1 ++ &xor( $u, $tmp1); # 2 ++ &xor( $t, $tmp2); # 2 ++ &mov( $tmp1, &DWP(&n2a($S*4),$ks,"",0)); # 2 ++ &xor( $u, $tmp1); ++ &mov( $tmp2, &DWP(&n2a(($S+1)*4),$ks,"",0)); # 2 ++ &xor( $u, $R); ++ &xor( $t, $R); ++ &xor( $t, $tmp2); ++ ++ &and( $u, "0xfcfcfcfc" ); # 2 ++ &xor( $tmp1, $tmp1); # 1 ++ &and( $t, "0xcfcfcfcf" ); # 2 ++ &xor( $tmp2, $tmp2); ++ &movb( &LB($tmp1), &LB($u) ); ++ &movb( &LB($tmp2), &HB($u) ); ++ &rotr( $t, 4 ); ++ &mov( $ks, &DWP(" $desSP",$tmp1,"",0)); ++ &movb( &LB($tmp1), &LB($t) ); ++ &xor( $L, $ks); ++ &mov( $ks, &DWP("0x200+$desSP",$tmp2,"",0)); ++ &xor( $L, $ks); ++ &movb( &LB($tmp2), &HB($t) ); ++ &shr( $u, 16); ++ &mov( $ks, &DWP("0x100+$desSP",$tmp1,"",0)); ++ &xor( $L, $ks); ++ &movb( &LB($tmp1), &HB($u) ); ++ &shr( $t, 16); ++ &mov( $ks, &DWP("0x300+$desSP",$tmp2,"",0)); ++ &xor( $L, $ks); ++ &mov( $ks, &wparam(1)); ++ &movb( &LB($tmp2), &HB($t) ); ++ &and( $u, "0xff" ); ++ &and( $t, "0xff" ); ++ &mov( $tmp1, &DWP("0x600+$desSP",$tmp1,"",0)); ++ &xor( $L, $tmp1); ++ &mov( $tmp1, &DWP("0x700+$desSP",$tmp2,"",0)); ++ &xor( $L, $tmp1); ++ &mov( $tmp1, &DWP("0x400+$desSP",$u,"",0)); ++ &xor( $L, $tmp1); ++ &mov( $tmp1, &DWP("0x500+$desSP",$t,"",0)); ++ &xor( $L, $tmp1); ++ } ++ ++sub n2a ++ { ++ sprintf("%d",$_[0]); ++ } ++ ++# now has a side affect of rotating $a by $shift ++sub R_PERM_OP ++ { ++ local($a,$b,$tt,$shift,$mask,$last)=@_; ++ ++ &rotl( $a, $shift ) if ($shift != 0); ++ &mov( $tt, $a ); ++ &xor( $a, $b ); ++ &and( $a, $mask ); ++ if ($notlast eq $b) ++ { ++ &xor( $b, $a ); ++ &xor( $tt, $a ); ++ } ++ else ++ { ++ &xor( $tt, $a ); ++ &xor( $b, $a ); ++ } ++ &comment(""); ++ } ++ ++sub IP_new ++ { ++ local($l,$r,$tt,$lr)=@_; ++ ++ &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l); ++ &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l); ++ &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r); ++ &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r); ++ &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r); ++ ++ if ($lr != 3) ++ { ++ if (($lr-3) < 0) ++ { &rotr($tt, 3-$lr); } ++ else { &rotl($tt, $lr-3); } ++ } ++ if ($lr != 2) ++ { ++ if (($lr-2) < 0) ++ { &rotr($r, 2-$lr); } ++ else { &rotl($r, $lr-2); } ++ } ++ } ++ ++sub FP_new ++ { ++ local($l,$r,$tt,$lr)=@_; ++ ++ if ($lr != 2) ++ { ++ if (($lr-2) < 0) ++ { &rotl($r, 2-$lr); } ++ else { &rotr($r, $lr-2); } ++ } ++ if ($lr != 3) ++ { ++ if (($lr-3) < 0) ++ { &rotl($l, 3-$lr); } ++ else { &rotr($l, $lr-3); } ++ } ++ ++ &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r); ++ &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r); ++ &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l); ++ &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l); ++ &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r); ++ &rotr($tt , 4); ++ } ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/des-586.pl Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,251 @@ ++#!/usr/bin/perl ++# ++# The inner loop instruction sequence and the IP/FP modifications are from ++# Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk> ++# ++ ++push(@INC,"perlasm","../../perlasm"); ++require "x86asm.pl"; ++require "cbc.pl"; ++require "desboth.pl"; ++ ++# base code is in microsft ++# op dest, source ++# format. ++# ++ ++&asm_init($ARGV[0],"des-586.pl"); ++ ++$L="edi"; ++$R="esi"; ++ ++&external_label("des_SPtrans"); ++&des_encrypt("des_encrypt",1); ++&des_encrypt("des_encrypt2",0); ++&des_encrypt3("des_encrypt3",1); ++&des_encrypt3("des_decrypt3",0); ++&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1); ++&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5); ++ ++&asm_finish(); ++ ++sub des_encrypt ++ { ++ local($name,$do_ip)=@_; ++ ++ &function_begin_B($name,"EXTRN _des_SPtrans:DWORD"); ++ ++ &push("esi"); ++ &push("edi"); ++ ++ &comment(""); ++ &comment("Load the 2 words"); ++ $ks="ebp"; ++ ++ if ($do_ip) ++ { ++ &mov($R,&wparam(0)); ++ &xor( "ecx", "ecx" ); ++ ++ &push("ebx"); ++ &push("ebp"); ++ ++ &mov("eax",&DWP(0,$R,"",0)); ++ &mov("ebx",&wparam(2)); # get encrypt flag ++ &mov($L,&DWP(4,$R,"",0)); ++ &comment(""); ++ &comment("IP"); ++ &IP_new("eax",$L,$R,3); ++ } ++ else ++ { ++ &mov("eax",&wparam(0)); ++ &xor( "ecx", "ecx" ); ++ ++ &push("ebx"); ++ &push("ebp"); ++ ++ &mov($R,&DWP(0,"eax","",0)); ++ &mov("ebx",&wparam(2)); # get encrypt flag ++ &rotl($R,3); ++ &mov($L,&DWP(4,"eax","",0)); ++ &rotl($L,3); ++ } ++ ++ &mov( $ks, &wparam(1) ); ++ &cmp("ebx","0"); ++ &je(&label("start_decrypt")); ++ ++ for ($i=0; $i<16; $i+=2) ++ { ++ &comment(""); ++ &comment("Round $i"); ++ &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); ++ ++ &comment(""); ++ &comment("Round ".sprintf("%d",$i+1)); ++ &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); ++ } ++ &jmp(&label("end")); ++ ++ &set_label("start_decrypt"); ++ ++ for ($i=15; $i>0; $i-=2) ++ { ++ &comment(""); ++ &comment("Round $i"); ++ &D_ENCRYPT(15-$i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); ++ &comment(""); ++ &comment("Round ".sprintf("%d",$i-1)); ++ &D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); ++ } ++ ++ &set_label("end"); ++ ++ if ($do_ip) ++ { ++ &comment(""); ++ &comment("FP"); ++ &mov("edx",&wparam(0)); ++ &FP_new($L,$R,"eax",3); ++ ++ &mov(&DWP(0,"edx","",0),"eax"); ++ &mov(&DWP(4,"edx","",0),$R); ++ } ++ else ++ { ++ &comment(""); ++ &comment("Fixup"); ++ &rotr($L,3); # r ++ &mov("eax",&wparam(0)); ++ &rotr($R,3); # l ++ &mov(&DWP(0,"eax","",0),$L); ++ &mov(&DWP(4,"eax","",0),$R); ++ } ++ ++ &pop("ebp"); ++ &pop("ebx"); ++ &pop("edi"); ++ &pop("esi"); ++ &ret(); ++ ++ &function_end_B($name); ++ } ++ ++sub D_ENCRYPT ++ { ++ local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_; ++ ++ &mov( $u, &DWP(&n2a($S*4),$ks,"",0)); ++ &xor( $tmp1, $tmp1); ++ &mov( $t, &DWP(&n2a(($S+1)*4),$ks,"",0)); ++ &xor( $u, $R); ++ &xor( $t, $R); ++ &and( $u, "0xfcfcfcfc" ); ++ &and( $t, "0xcfcfcfcf" ); ++ &movb( &LB($tmp1), &LB($u) ); ++ &movb( &LB($tmp2), &HB($u) ); ++ &rotr( $t, 4 ); ++ &mov( $ks, &DWP(" $desSP",$tmp1,"",0)); ++ &movb( &LB($tmp1), &LB($t) ); ++ &xor( $L, $ks); ++ &mov( $ks, &DWP("0x200+$desSP",$tmp2,"",0)); ++ &xor( $L, $ks); ###### ++ &movb( &LB($tmp2), &HB($t) ); ++ &shr( $u, 16); ++ &mov( $ks, &DWP("0x100+$desSP",$tmp1,"",0)); ++ &xor( $L, $ks); ###### ++ &movb( &LB($tmp1), &HB($u) ); ++ &shr( $t, 16); ++ &mov( $ks, &DWP("0x300+$desSP",$tmp2,"",0)); ++ &xor( $L, $ks); ++ &mov( $ks, &wparam(1) ); ++ &movb( &LB($tmp2), &HB($t) ); ++ &and( $u, "0xff" ); ++ &and( $t, "0xff" ); ++ &mov( $tmp1, &DWP("0x600+$desSP",$tmp1,"",0)); ++ &xor( $L, $tmp1); ++ &mov( $tmp1, &DWP("0x700+$desSP",$tmp2,"",0)); ++ &xor( $L, $tmp1); ++ &mov( $tmp1, &DWP("0x400+$desSP",$u,"",0)); ++ &xor( $L, $tmp1); ++ &mov( $tmp1, &DWP("0x500+$desSP",$t,"",0)); ++ &xor( $L, $tmp1); ++ } ++ ++sub n2a ++ { ++ sprintf("%d",$_[0]); ++ } ++ ++# now has a side affect of rotating $a by $shift ++sub R_PERM_OP ++ { ++ local($a,$b,$tt,$shift,$mask,$last)=@_; ++ ++ &rotl( $a, $shift ) if ($shift != 0); ++ &mov( $tt, $a ); ++ &xor( $a, $b ); ++ &and( $a, $mask ); ++ if (!$last eq $b) ++ { ++ &xor( $b, $a ); ++ &xor( $tt, $a ); ++ } ++ else ++ { ++ &xor( $tt, $a ); ++ &xor( $b, $a ); ++ } ++ &comment(""); ++ } ++ ++sub IP_new ++ { ++ local($l,$r,$tt,$lr)=@_; ++ ++ &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l); ++ &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l); ++ &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r); ++ &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r); ++ &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r); ++ ++ if ($lr != 3) ++ { ++ if (($lr-3) < 0) ++ { &rotr($tt, 3-$lr); } ++ else { &rotl($tt, $lr-3); } ++ } ++ if ($lr != 2) ++ { ++ if (($lr-2) < 0) ++ { &rotr($r, 2-$lr); } ++ else { &rotl($r, $lr-2); } ++ } ++ } ++ ++sub FP_new ++ { ++ local($l,$r,$tt,$lr)=@_; ++ ++ if ($lr != 2) ++ { ++ if (($lr-2) < 0) ++ { &rotl($r, 2-$lr); } ++ else { &rotr($r, $lr-2); } ++ } ++ if ($lr != 3) ++ { ++ if (($lr-3) < 0) ++ { &rotl($l, 3-$lr); } ++ else { &rotr($l, $lr-3); } ++ } ++ ++ &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r); ++ &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r); ++ &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l); ++ &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l); ++ &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r); ++ &rotr($tt , 4); ++ } ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/des686.pl Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,230 @@ ++#!/usr/bin/perl ++ ++$prog="des686.pl"; ++ ++# base code is in microsft ++# op dest, source ++# format. ++# ++ ++# WILL NOT WORK ANYMORE WITH desboth.pl ++require "desboth.pl"; ++ ++if ( ($ARGV[0] eq "elf")) ++ { require "x86unix.pl"; } ++elsif ( ($ARGV[0] eq "a.out")) ++ { $aout=1; require "x86unix.pl"; } ++elsif ( ($ARGV[0] eq "sol")) ++ { $sol=1; require "x86unix.pl"; } ++elsif ( ($ARGV[0] eq "cpp")) ++ { $cpp=1; require "x86unix.pl"; } ++elsif ( ($ARGV[0] eq "win32")) ++ { require "x86ms.pl"; } ++else ++ { ++ print STDERR <<"EOF"; ++Pick one target type from ++ elf - linux, FreeBSD etc ++ a.out - old linux ++ sol - x86 solaris ++ cpp - format so x86unix.cpp can be used ++ win32 - Windows 95/Windows NT ++EOF ++ exit(1); ++ } ++ ++&comment("Don't even think of reading this code"); ++&comment("It was automatically generated by $prog"); ++&comment("Which is a perl program used to generate the x86 assember for"); ++&comment("any of elf, a.out, Win32, or Solaris"); ++&comment("It can be found in SSLeay 0.6.5+ or in libdes 3.26+"); ++&comment("eric <eay\@cryptsoft.com>"); ++&comment(""); ++ ++&file("dx86xxxx"); ++ ++$L="edi"; ++$R="esi"; ++ ++&des_encrypt("des_encrypt",1); ++&des_encrypt("des_encrypt2",0); ++ ++&des_encrypt3("des_encrypt3",1); ++&des_encrypt3("des_decrypt3",0); ++ ++&file_end(); ++ ++sub des_encrypt ++ { ++ local($name,$do_ip)=@_; ++ ++ &function_begin($name,"EXTRN _des_SPtrans:DWORD"); ++ ++ &comment(""); ++ &comment("Load the 2 words"); ++ &mov("eax",&wparam(0)); ++ &mov($L,&DWP(0,"eax","",0)); ++ &mov($R,&DWP(4,"eax","",0)); ++ ++ $ksp=&wparam(1); ++ ++ if ($do_ip) ++ { ++ &comment(""); ++ &comment("IP"); ++ &IP_new($L,$R,"eax"); ++ } ++ ++ &comment(""); ++ &comment("fixup rotate"); ++ &rotl($R,3); ++ &rotl($L,3); ++ &exch($L,$R); ++ ++ &comment(""); ++ &comment("load counter, key_schedule and enc flag"); ++ &mov("eax",&wparam(2)); # get encrypt flag ++ &mov("ebp",&wparam(1)); # get ks ++ &cmp("eax","0"); ++ &je(&label("start_decrypt")); ++ ++ # encrypting part ++ ++ for ($i=0; $i<16; $i+=2) ++ { ++ &comment(""); ++ &comment("Round $i"); ++ &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); ++ ++ &comment(""); ++ &comment("Round ".sprintf("%d",$i+1)); ++ &D_ENCRYPT($R,$L,($i+1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); ++ } ++ &jmp(&label("end")); ++ ++ &set_label("start_decrypt"); ++ ++ for ($i=15; $i>0; $i-=2) ++ { ++ &comment(""); ++ &comment("Round $i"); ++ &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); ++ &comment(""); ++ &comment("Round ".sprintf("%d",$i-1)); ++ &D_ENCRYPT($R,$L,($i-1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); ++ } ++ ++ &set_label("end"); ++ ++ &comment(""); ++ &comment("Fixup"); ++ &rotr($L,3); # r ++ &rotr($R,3); # l ++ ++ if ($do_ip) ++ { ++ &comment(""); ++ &comment("FP"); ++ &FP_new($R,$L,"eax"); ++ } ++ ++ &mov("eax",&wparam(0)); ++ &mov(&DWP(0,"eax","",0),$L); ++ &mov(&DWP(4,"eax","",0),$R); ++ ++ &function_end($name); ++ } ++ ++ ++# The logic is to load R into 2 registers and operate on both at the same time. ++# We also load the 2 R's into 2 more registers so we can do the 'move word down a byte' ++# while also masking the other copy and doing a lookup. We then also accumulate the ++# L value in 2 registers then combine them at the end. ++sub D_ENCRYPT ++ { ++ local($L,$R,$S,$ks,$desSP,$u,$t,$tmp1,$tmp2,$tmp3)=@_; ++ ++ &mov( $u, &DWP(&n2a($S*4),$ks,"",0)); ++ &mov( $t, &DWP(&n2a(($S+1)*4),$ks,"",0)); ++ &xor( $u, $R ); ++ &xor( $t, $R ); ++ &rotr( $t, 4 ); ++ ++ # the numbers at the end of the line are origional instruction order ++ &mov( $tmp2, $u ); # 1 2 ++ &mov( $tmp1, $t ); # 1 1 ++ &and( $tmp2, "0xfc" ); # 1 4 ++ &and( $tmp1, "0xfc" ); # 1 3 ++ &shr( $t, 8 ); # 1 5 ++ &xor( $L, &DWP("0x100+$desSP",$tmp1,"",0)); # 1 7 ++ &shr( $u, 8 ); # 1 6 ++ &mov( $tmp1, &DWP(" $desSP",$tmp2,"",0)); # 1 8 ++ ++ &mov( $tmp2, $u ); # 2 2 ++ &xor( $L, $tmp1 ); # 1 9 ++ &and( $tmp2, "0xfc" ); # 2 4 ++ &mov( $tmp1, $t ); # 2 1 ++ &and( $tmp1, "0xfc" ); # 2 3 ++ &shr( $t, 8 ); # 2 5 ++ &xor( $L, &DWP("0x300+$desSP",$tmp1,"",0)); # 2 7 ++ &shr( $u, 8 ); # 2 6 ++ &mov( $tmp1, &DWP("0x200+$desSP",$tmp2,"",0)); # 2 8 ++ &mov( $tmp2, $u ); # 3 2 ++ ++ &xor( $L, $tmp1 ); # 2 9 ++ &and( $tmp2, "0xfc" ); # 3 4 ++ ++ &mov( $tmp1, $t ); # 3 1 ++ &shr( $u, 8 ); # 3 6 ++ &and( $tmp1, "0xfc" ); # 3 3 ++ &shr( $t, 8 ); # 3 5 ++ &xor( $L, &DWP("0x500+$desSP",$tmp1,"",0)); # 3 7 ++ &mov( $tmp1, &DWP("0x400+$desSP",$tmp2,"",0)); # 3 8 ++ ++ &and( $t, "0xfc" ); # 4 1 ++ &xor( $L, $tmp1 ); # 3 9 ++ ++ &and( $u, "0xfc" ); # 4 2 ++ &xor( $L, &DWP("0x700+$desSP",$t,"",0)); # 4 3 ++ &xor( $L, &DWP("0x600+$desSP",$u,"",0)); # 4 4 ++ } ++ ++sub PERM_OP ++ { ++ local($a,$b,$tt,$shift,$mask)=@_; ++ ++ &mov( $tt, $a ); ++ &shr( $tt, $shift ); ++ &xor( $tt, $b ); ++ &and( $tt, $mask ); ++ &xor( $b, $tt ); ++ &shl( $tt, $shift ); ++ &xor( $a, $tt ); ++ } ++ ++sub IP_new ++ { ++ local($l,$r,$tt)=@_; ++ ++ &PERM_OP($r,$l,$tt, 4,"0x0f0f0f0f"); ++ &PERM_OP($l,$r,$tt,16,"0x0000ffff"); ++ &PERM_OP($r,$l,$tt, 2,"0x33333333"); ++ &PERM_OP($l,$r,$tt, 8,"0x00ff00ff"); ++ &PERM_OP($r,$l,$tt, 1,"0x55555555"); ++ } ++ ++sub FP_new ++ { ++ local($l,$r,$tt)=@_; ++ ++ &PERM_OP($l,$r,$tt, 1,"0x55555555"); ++ &PERM_OP($r,$l,$tt, 8,"0x00ff00ff"); ++ &PERM_OP($l,$r,$tt, 2,"0x33333333"); ++ &PERM_OP($r,$l,$tt,16,"0x0000ffff"); ++ &PERM_OP($l,$r,$tt, 4,"0x0f0f0f0f"); ++ } ++ ++sub n2a ++ { ++ sprintf("%d",$_[0]); ++ } +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/desboth.pl Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,79 @@ ++#!/usr/bin/perl ++ ++$L="edi"; ++$R="esi"; ++ ++sub des_encrypt3 ++ { ++ local($name,$enc)=@_; ++ ++ &function_begin_B($name,""); ++ &push("ebx"); ++ &mov("ebx",&wparam(0)); ++ ++ &push("ebp"); ++ &push("esi"); ++ ++ &push("edi"); ++ ++ &comment(""); ++ &comment("Load the data words"); ++ &mov($L,&DWP(0,"ebx","",0)); ++ &mov($R,&DWP(4,"ebx","",0)); ++ &stack_push(3); ++ ++ &comment(""); ++ &comment("IP"); ++ &IP_new($L,$R,"edx",0); ++ ++ # put them back ++ ++ if ($enc) ++ { ++ &mov(&DWP(4,"ebx","",0),$R); ++ &mov("eax",&wparam(1)); ++ &mov(&DWP(0,"ebx","",0),"edx"); ++ &mov("edi",&wparam(2)); ++ &mov("esi",&wparam(3)); ++ } ++ else ++ { ++ &mov(&DWP(4,"ebx","",0),$R); ++ &mov("esi",&wparam(1)); ++ &mov(&DWP(0,"ebx","",0),"edx"); ++ &mov("edi",&wparam(2)); ++ &mov("eax",&wparam(3)); ++ } ++ &mov(&swtmp(2), (($enc)?"1":"0")); ++ &mov(&swtmp(1), "eax"); ++ &mov(&swtmp(0), "ebx"); ++ &call("des_encrypt2"); ++ &mov(&swtmp(2), (($enc)?"0":"1")); ++ &mov(&swtmp(1), "edi"); ++ &mov(&swtmp(0), "ebx"); ++ &call("des_encrypt2"); ++ &mov(&swtmp(2), (($enc)?"1":"0")); ++ &mov(&swtmp(1), "esi"); ++ &mov(&swtmp(0), "ebx"); ++ &call("des_encrypt2"); ++ ++ &stack_pop(3); ++ &mov($L,&DWP(0,"ebx","",0)); ++ &mov($R,&DWP(4,"ebx","",0)); ++ ++ &comment(""); ++ &comment("FP"); ++ &FP_new($L,$R,"eax",0); ++ ++ &mov(&DWP(0,"ebx","",0),"eax"); ++ &mov(&DWP(4,"ebx","",0),$R); ++ ++ &pop("edi"); ++ &pop("esi"); ++ &pop("ebp"); ++ &pop("ebx"); ++ &ret(); ++ &function_end_B($name); ++ } ++ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/perlasm/cbc.pl Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,342 @@ ++#!/usr/bin/perl ++ ++# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) ++# des_cblock (*input); ++# des_cblock (*output); ++# long length; ++# des_key_schedule schedule; ++# des_cblock (*ivec); ++# int enc; ++# ++# calls ++# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); ++# ++ ++#&cbc("des_ncbc_encrypt","des_encrypt",0); ++#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt", ++# 1,4,5,3,5,-1); ++#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt", ++# 0,4,5,3,5,-1); ++#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3", ++# 0,6,7,3,4,5); ++# ++# When doing a cipher that needs bigendian order, ++# for encrypt, the iv is kept in bigendian form, ++# while for decrypt, it is kept in little endian. ++sub cbc ++ { ++ local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_; ++ # name is the function name ++ # enc_func and dec_func and the functions to call for encrypt/decrypt ++ # swap is true if byte order needs to be reversed ++ # iv_off is parameter number for the iv ++ # enc_off is parameter number for the encrypt/decrypt flag ++ # p1,p2,p3 are the offsets for parameters to be passed to the ++ # underlying calls. ++ ++ &function_begin_B($name,""); ++ &comment(""); ++ ++ $in="esi"; ++ $out="edi"; ++ $count="ebp"; ++ ++ &push("ebp"); ++ &push("ebx"); ++ &push("esi"); ++ &push("edi"); ++ ++ $data_off=4; ++ $data_off+=4 if ($p1 > 0); ++ $data_off+=4 if ($p2 > 0); ++ $data_off+=4 if ($p3 > 0); ++ ++ &mov($count, &wparam(2)); # length ++ ++ &comment("getting iv ptr from parameter $iv_off"); ++ &mov("ebx", &wparam($iv_off)); # Get iv ptr ++ ++ &mov($in, &DWP(0,"ebx","",0));# iv[0] ++ &mov($out, &DWP(4,"ebx","",0));# iv[1] ++ ++ &push($out); ++ &push($in); ++ &push($out); # used in decrypt for iv[1] ++ &push($in); # used in decrypt for iv[0] ++ ++ &mov("ebx", "esp"); # This is the address of tin[2] ++ ++ &mov($in, &wparam(0)); # in ++ &mov($out, &wparam(1)); # out ++ ++ # We have loaded them all, how lets push things ++ &comment("getting encrypt flag from parameter $enc_off"); ++ &mov("ecx", &wparam($enc_off)); # Get enc flag ++ if ($p3 > 0) ++ { ++ &comment("get and push parameter $p3"); ++ if ($enc_off != $p3) ++ { &mov("eax", &wparam($p3)); &push("eax"); } ++ else { &push("ecx"); } ++ } ++ if ($p2 > 0) ++ { ++ &comment("get and push parameter $p2"); ++ if ($enc_off != $p2) ++ { &mov("eax", &wparam($p2)); &push("eax"); } ++ else { &push("ecx"); } ++ } ++ if ($p1 > 0) ++ { ++ &comment("get and push parameter $p1"); ++ if ($enc_off != $p1) ++ { &mov("eax", &wparam($p1)); &push("eax"); } ++ else { &push("ecx"); } ++ } ++ &push("ebx"); # push data/iv ++ ++ &cmp("ecx",0); ++ &jz(&label("decrypt")); ++ ++ &and($count,0xfffffff8); ++ &mov("eax", &DWP($data_off,"esp","",0)); # load iv[0] ++ &mov("ebx", &DWP($data_off+4,"esp","",0)); # load iv[1] ++ ++ &jz(&label("encrypt_finish")); ++ ++ ############################################################# ++ ++ &set_label("encrypt_loop"); ++ # encrypt start ++ # "eax" and "ebx" hold iv (or the last cipher text) ++ ++ &mov("ecx", &DWP(0,$in,"",0)); # load first 4 bytes ++ &mov("edx", &DWP(4,$in,"",0)); # second 4 bytes ++ ++ &xor("eax", "ecx"); ++ &xor("ebx", "edx"); ++ ++ &bswap("eax") if $swap; ++ &bswap("ebx") if $swap; ++ ++ &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call ++ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # ++ ++ &call($enc_func); ++ ++ &mov("eax", &DWP($data_off,"esp","",0)); ++ &mov("ebx", &DWP($data_off+4,"esp","",0)); ++ ++ &bswap("eax") if $swap; ++ &bswap("ebx") if $swap; ++ ++ &mov(&DWP(0,$out,"",0),"eax"); ++ &mov(&DWP(4,$out,"",0),"ebx"); ++ ++ # eax and ebx are the next iv. ++ ++ &add($in, 8); ++ &add($out, 8); ++ ++ &sub($count, 8); ++ &jnz(&label("encrypt_loop")); ++ ++###################################################################3 ++ &set_label("encrypt_finish"); ++ &mov($count, &wparam(2)); # length ++ &and($count, 7); ++ &jz(&label("finish")); ++ &xor("ecx","ecx"); ++ &xor("edx","edx"); ++ &mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4)); ++ &jmp_ptr($count); ++ ++&set_label("ej7"); ++ &xor("edx", "edx") if $ppro; # ppro friendly ++ &movb(&HB("edx"), &BP(6,$in,"",0)); ++ &shl("edx",8); ++&set_label("ej6"); ++ &movb(&HB("edx"), &BP(5,$in,"",0)); ++&set_label("ej5"); ++ &movb(&LB("edx"), &BP(4,$in,"",0)); ++&set_label("ej4"); ++ &mov("ecx", &DWP(0,$in,"",0)); ++ &jmp(&label("ejend")); ++&set_label("ej3"); ++ &movb(&HB("ecx"), &BP(2,$in,"",0)); ++ &xor("ecx", "ecx") if $ppro; # ppro friendly ++ &shl("ecx",8); ++&set_label("ej2"); ++ &movb(&HB("ecx"), &BP(1,$in,"",0)); ++&set_label("ej1"); ++ &movb(&LB("ecx"), &BP(0,$in,"",0)); ++&set_label("ejend"); ++ ++ &xor("eax", "ecx"); ++ &xor("ebx", "edx"); ++ ++ &bswap("eax") if $swap; ++ &bswap("ebx") if $swap; ++ ++ &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call ++ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # ++ ++ &call($enc_func); ++ ++ &mov("eax", &DWP($data_off,"esp","",0)); ++ &mov("ebx", &DWP($data_off+4,"esp","",0)); ++ ++ &bswap("eax") if $swap; ++ &bswap("ebx") if $swap; ++ ++ &mov(&DWP(0,$out,"",0),"eax"); ++ &mov(&DWP(4,$out,"",0),"ebx"); ++ ++ &jmp(&label("finish")); ++ ++ ############################################################# ++ ############################################################# ++ &set_label("decrypt",1); ++ # decrypt start ++ &and($count,0xfffffff8); ++ # The next 2 instructions are only for if the jz is taken ++ &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0] ++ &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1] ++ &jz(&label("decrypt_finish")); ++ ++ &set_label("decrypt_loop"); ++ &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes ++ &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes ++ ++ &bswap("eax") if $swap; ++ &bswap("ebx") if $swap; ++ ++ &mov(&DWP($data_off,"esp","",0), "eax"); # put back ++ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # ++ ++ &call($dec_func); ++ ++ &mov("eax", &DWP($data_off,"esp","",0)); # get return ++ &mov("ebx", &DWP($data_off+4,"esp","",0)); # ++ ++ &bswap("eax") if $swap; ++ &bswap("ebx") if $swap; ++ ++ &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] ++ &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] ++ ++ &xor("ecx", "eax"); ++ &xor("edx", "ebx"); ++ ++ &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, ++ &mov("ebx", &DWP(4,$in,"",0)); # next iv actually ++ ++ &mov(&DWP(0,$out,"",0),"ecx"); ++ &mov(&DWP(4,$out,"",0),"edx"); ++ ++ &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv ++ &mov(&DWP($data_off+12,"esp","",0), "ebx"); # ++ ++ &add($in, 8); ++ &add($out, 8); ++ ++ &sub($count, 8); ++ &jnz(&label("decrypt_loop")); ++############################ ENDIT #######################3 ++ &set_label("decrypt_finish"); ++ &mov($count, &wparam(2)); # length ++ &and($count, 7); ++ &jz(&label("finish")); ++ ++ &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes ++ &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes ++ ++ &bswap("eax") if $swap; ++ &bswap("ebx") if $swap; ++ ++ &mov(&DWP($data_off,"esp","",0), "eax"); # put back ++ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # ++ ++ &call($dec_func); ++ ++ &mov("eax", &DWP($data_off,"esp","",0)); # get return ++ &mov("ebx", &DWP($data_off+4,"esp","",0)); # ++ ++ &bswap("eax") if $swap; ++ &bswap("ebx") if $swap; ++ ++ &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] ++ &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] ++ ++ &xor("ecx", "eax"); ++ &xor("edx", "ebx"); ++ ++ # this is for when we exit ++ &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, ++ &mov("ebx", &DWP(4,$in,"",0)); # next iv actually ++ ++&set_label("dj7"); ++ &rotr("edx", 16); ++ &movb(&BP(6,$out,"",0), &LB("edx")); ++ &shr("edx",16); ++&set_label("dj6"); ++ &movb(&BP(5,$out,"",0), &HB("edx")); ++&set_label("dj5"); ++ &movb(&BP(4,$out,"",0), &LB("edx")); ++&set_label("dj4"); ++ &mov(&DWP(0,$out,"",0), "ecx"); ++ &jmp(&label("djend")); ++&set_label("dj3"); ++ &rotr("ecx", 16); ++ &movb(&BP(2,$out,"",0), &LB("ecx")); ++ &shl("ecx",16); ++&set_label("dj2"); ++ &movb(&BP(1,$in,"",0), &HB("ecx")); ++&set_label("dj1"); ++ &movb(&BP(0,$in,"",0), &LB("ecx")); ++&set_label("djend"); ++ ++ # final iv is still in eax:ebx ++ &jmp(&label("finish")); ++ ++ ++############################ FINISH #######################3 ++ &set_label("finish",1); ++ &mov("ecx", &wparam($iv_off)); # Get iv ptr ++ ++ ################################################# ++ $total=16+4; ++ $total+=4 if ($p1 > 0); ++ $total+=4 if ($p2 > 0); ++ $total+=4 if ($p3 > 0); ++ &add("esp",$total); ++ ++ &mov(&DWP(0,"ecx","",0), "eax"); # save iv ++ &mov(&DWP(4,"ecx","",0), "ebx"); # save iv ++ ++ &function_end_A($name); ++ ++ &set_label("cbc_enc_jmp_table",1); ++ &data_word("0"); ++ &data_word(&label("ej1")); ++ &data_word(&label("ej2")); ++ &data_word(&label("ej3")); ++ &data_word(&label("ej4")); ++ &data_word(&label("ej5")); ++ &data_word(&label("ej6")); ++ &data_word(&label("ej7")); ++ &set_label("cbc_dec_jmp_table",1); ++ &data_word("0"); ++ &data_word(&label("dj1")); ++ &data_word(&label("dj2")); ++ &data_word(&label("dj3")); ++ &data_word(&label("dj4")); ++ &data_word(&label("dj5")); ++ &data_word(&label("dj6")); ++ &data_word(&label("dj7")); ++ ++ &function_end_B($name); ++ ++ } ++ ++1; +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/perlasm/readme Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,124 @@ ++The perl scripts in this directory are my 'hack' to generate ++multiple different assembler formats via the one origional script. ++ ++The way to use this library is to start with adding the path to this directory ++and then include it. ++ ++push(@INC,"perlasm","../../perlasm"); ++require "x86asm.pl"; ++ ++The first thing we do is setup the file and type of assember ++ ++&asm_init($ARGV[0],$0); ++ ++The first argument is the 'type'. Currently ++'cpp', 'sol', 'a.out', 'elf' or 'win32'. ++Argument 2 is the file name. ++ ++The reciprocal function is ++&asm_finish() which should be called at the end. ++ ++There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler, ++and x86unix.pl which is the unix (gas) version. ++ ++Functions of interest are: ++&external_label("des_SPtrans"); declare and external variable ++&LB(reg); Low byte for a register ++&HB(reg); High byte for a register ++&BP(off,base,index,scale) Byte pointer addressing ++&DWP(off,base,index,scale) Word pointer addressing ++&stack_push(num) Basically a 'sub esp, num*4' with extra ++&stack_pop(num) inverse of stack_push ++&function_begin(name,extra) Start a function with pushing of ++ edi, esi, ebx and ebp. extra is extra win32 ++ external info that may be required. ++&function_begin_B(name,extra) Same as norma function_begin but no pushing. ++&function_end(name) Call at end of function. ++&function_end_A(name) Standard pop and ret, for use inside functions ++&function_end_B(name) Call at end but with poping or 'ret'. ++&swtmp(num) Address on stack temp word. ++&wparam(num) Parameter number num, that was push ++ in C convention. This all works over pushes ++ and pops. ++&comment("hello there") Put in a comment. ++&label("loop") Refer to a label, normally a jmp target. ++&set_label("loop") Set a label at this point. ++&data_word(word) Put in a word of data. ++ ++So how does this all hold together? Given ++ ++int calc(int len, int *data) ++ { ++ int i,j=0; ++ ++ for (i=0; i<len; i++) ++ { ++ j+=other(data[i]); ++ } ++ } ++ ++So a very simple version of this function could be coded as ++ ++ push(@INC,"perlasm","../../perlasm"); ++ require "x86asm.pl"; ++ ++ &asm_init($ARGV[0],"cacl.pl"); ++ ++ &external_label("other"); ++ ++ $tmp1= "eax"; ++ $j= "edi"; ++ $data= "esi"; ++ $i= "ebp"; ++ ++ &comment("a simple function"); ++ &function_begin("calc"); ++ &mov( $data, &wparam(1)); # data ++ &xor( $j, $j); ++ &xor( $i, $i); ++ ++ &set_label("loop"); ++ &cmp( $i, &wparam(0)); ++ &jge( &label("end")); ++ ++ &mov( $tmp1, &DWP(0,$data,$i,4)); ++ &push( $tmp1); ++ &call( "other"); ++ &add( $j, "eax"); ++ &pop( $tmp1); ++ &inc( $i); ++ &jmp( &label("loop")); ++ ++ &set_label("end"); ++ &mov( "eax", $j); ++ ++ &function_end("calc"); ++ ++ &asm_finish(); ++ ++The above example is very very unoptimised but gives an idea of how ++things work. ++ ++There is also a cbc mode function generator in cbc.pl ++ ++&cbc( $name, ++ $encrypt_function_name, ++ $decrypt_function_name, ++ $true_if_byte_swap_needed, ++ $parameter_number_for_iv, ++ $parameter_number_for_encrypt_flag, ++ $first_parameter_to_pass, ++ $second_parameter_to_pass, ++ $third_parameter_to_pass); ++ ++So for example, given ++void BF_encrypt(BF_LONG *data,BF_KEY *key); ++void BF_decrypt(BF_LONG *data,BF_KEY *key); ++void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length, ++ BF_KEY *ks, unsigned char *iv, int enc); ++ ++&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1); ++ ++&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1); ++&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5); ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/perlasm/x86asm.pl Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,111 @@ ++#!/usr/bin/perl ++ ++# require 'x86asm.pl'; ++# &asm_init("cpp","des-586.pl"); ++# XXX ++# XXX ++# main'asm_finish ++ ++sub main'asm_finish ++ { ++ &file_end(); ++ &asm_finish_cpp() if $cpp; ++ print &asm_get_output(); ++ } ++ ++sub main'asm_init ++ { ++ ($type,$fn)=@_; ++ $filename=$fn; ++ ++ $cpp=$sol=$aout=$win32=0; ++ if ( ($type eq "elf")) ++ { require "x86unix.pl"; } ++ elsif ( ($type eq "a.out")) ++ { $aout=1; require "x86unix.pl"; } ++ elsif ( ($type eq "sol")) ++ { $sol=1; require "x86unix.pl"; } ++ elsif ( ($type eq "cpp")) ++ { $cpp=1; require "x86unix.pl"; } ++ elsif ( ($type eq "win32")) ++ { $win32=1; require "x86ms.pl"; } ++ else ++ { ++ print STDERR <<"EOF"; ++Pick one target type from ++ elf - linux, FreeBSD etc ++ a.out - old linux ++ sol - x86 solaris ++ cpp - format so x86unix.cpp can be used ++ win32 - Windows 95/Windows NT ++EOF ++ exit(1); ++ } ++ ++ &asm_init_output(); ++ ++&comment("Don't even think of reading this code"); ++&comment("It was automatically generated by $filename"); ++&comment("Which is a perl program used to generate the x86 assember for"); ++&comment("any of elf, a.out, BSDI,Win32, or Solaris"); ++&comment("eric <eay\@cryptsoft.com>"); ++&comment(""); ++ ++ $filename =~ s/\.pl$//; ++ &file($filename); ++ } ++ ++sub asm_finish_cpp ++ { ++ return unless $cpp; ++ ++ local($tmp,$i); ++ foreach $i (&get_labels()) ++ { ++ $tmp.="#define $i _$i\n"; ++ } ++ print <<"EOF"; ++/* Run the C pre-processor over this file with one of the following defined ++ * ELF - elf object files, ++ * OUT - a.out object files, ++ * BSDI - BSDI style a.out object files ++ * SOL - Solaris style elf ++ */ ++ ++#define TYPE(a,b) .type a,b ++#define SIZE(a,b) .size a,b ++ ++#if defined(OUT) || defined(BSDI) ++$tmp ++#endif ++ ++#ifdef OUT ++#define OK 1 ++#define ALIGN 4 ++#endif ++ ++#ifdef BSDI ++#define OK 1 ++#define ALIGN 4 ++#undef SIZE ++#undef TYPE ++#endif ++ ++#if defined(ELF) || defined(SOL) ++#define OK 1 ++#define ALIGN 16 ++#endif ++ ++#ifndef OK ++You need to define one of ++ELF - elf systems - linux-elf, NetBSD and DG-UX ++OUT - a.out systems - linux-a.out and FreeBSD ++SOL - solaris systems, which are elf with strange comment lines ++BSDI - a.out with a very primative version of as. ++#endif ++ ++/* Let the Assembler begin :-) */ ++EOF ++ } ++ ++1; +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/perlasm/x86ms.pl Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,345 @@ ++#!/usr/bin/perl ++ ++package x86ms; ++ ++$label="L000"; ++ ++%lb=( 'eax', 'al', ++ 'ebx', 'bl', ++ 'ecx', 'cl', ++ 'edx', 'dl', ++ 'ax', 'al', ++ 'bx', 'bl', ++ 'cx', 'cl', ++ 'dx', 'dl', ++ ); ++ ++%hb=( 'eax', 'ah', ++ 'ebx', 'bh', ++ 'ecx', 'ch', ++ 'edx', 'dh', ++ 'ax', 'ah', ++ 'bx', 'bh', ++ 'cx', 'ch', ++ 'dx', 'dh', ++ ); ++ ++sub main'asm_init_output { @out=(); } ++sub main'asm_get_output { return(@out); } ++sub main'get_labels { return(@labels); } ++sub main'external_label { push(@labels,@_); } ++ ++sub main'LB ++ { ++ (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; ++ return($lb{$_[0]}); ++ } ++ ++sub main'HB ++ { ++ (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; ++ return($hb{$_[0]}); ++ } ++ ++sub main'BP ++ { ++ &get_mem("BYTE",@_); ++ } ++ ++sub main'DWP ++ { ++ &get_mem("DWORD",@_); ++ } ++ ++sub main'stack_push ++ { ++ local($num)=@_; ++ $stack+=$num*4; ++ &main'sub("esp",$num*4); ++ } ++ ++sub main'stack_pop ++ { ++ local($num)=@_; ++ $stack-=$num*4; ++ &main'add("esp",$num*4); ++ } ++ ++sub get_mem ++ { ++ local($size,$addr,$reg1,$reg2,$idx)=@_; ++ local($t,$post); ++ local($ret)="$size PTR "; ++ ++ $addr =~ s/^\s+//; ++ if ($addr =~ /^(.+)\+(.+)$/) ++ { ++ $reg2=&conv($1); ++ $addr="_$2"; ++ } ++ elsif ($addr =~ /^[_a-zA-Z]/) ++ { ++ $addr="_$addr"; ++ } ++ ++ $reg1="$regs{$reg1}" if defined($regs{$reg1}); ++ $reg2="$regs{$reg2}" if defined($regs{$reg2}); ++ if (($addr ne "") && ($addr ne 0)) ++ { ++ if ($addr !~ /^-/) ++ { $ret.=$addr; } ++ else { $post=$addr; } ++ } ++ if ($reg2 ne "") ++ { ++ $t=""; ++ $t="*$idx" if ($idx != 0); ++ $reg1="+".$reg1 if ("$reg1$post" ne ""); ++ $ret.="[$reg2$t$reg1$post]"; ++ } ++ else ++ { ++ $ret.="[$reg1$post]" ++ } ++ return($ret); ++ } ++ ++sub main'mov { &out2("mov",@_); } ++sub main'movb { &out2("mov",@_); } ++sub main'and { &out2("and",@_); } ++sub main'or { &out2("or",@_); } ++sub main'shl { &out2("shl",@_); } ++sub main'shr { &out2("shr",@_); } ++sub main'xor { &out2("xor",@_); } ++sub main'xorb { &out2("xor",@_); } ++sub main'add { &out2("add",@_); } ++sub main'adc { &out2("adc",@_); } ++sub main'sub { &out2("sub",@_); } ++sub main'rotl { &out2("rol",@_); } ++sub main'rotr { &out2("ror",@_); } ++sub main'exch { &out2("xchg",@_); } ++sub main'cmp { &out2("cmp",@_); } ++sub main'lea { &out2("lea",@_); } ++sub main'mul { &out1("mul",@_); } ++sub main'div { &out1("div",@_); } ++sub main'dec { &out1("dec",@_); } ++sub main'inc { &out1("inc",@_); } ++sub main'jmp { &out1("jmp",@_); } ++sub main'jmp_ptr { &out1p("jmp",@_); } ++sub main'je { &out1("je",@_); } ++sub main'jle { &out1("jle",@_); } ++sub main'jz { &out1("jz",@_); } ++sub main'jge { &out1("jge",@_); } ++sub main'jl { &out1("jl",@_); } ++sub main'jb { &out1("jb",@_); } ++sub main'jnz { &out1("jnz",@_); } ++sub main'jne { &out1("jne",@_); } ++sub main'push { &out1("push",@_); $stack+=4; } ++sub main'pop { &out1("pop",@_); $stack-=4; } ++sub main'bswap { &out1("bswap",@_); &using486(); } ++sub main'not { &out1("not",@_); } ++sub main'call { &out1("call",'_'.$_[0]); } ++sub main'ret { &out0("ret"); } ++sub main'nop { &out0("nop"); } ++ ++sub out2 ++ { ++ local($name,$p1,$p2)=@_; ++ local($l,$t); ++ ++ push(@out,"\t$name\t"); ++ $t=&conv($p1).","; ++ $l=length($t); ++ push(@out,$t); ++ $l=4-($l+9)/8; ++ push(@out,"\t" x $l); ++ push(@out,&conv($p2)); ++ push(@out,"\n"); ++ } ++ ++sub out0 ++ { ++ local($name)=@_; ++ ++ push(@out,"\t$name\n"); ++ } ++ ++sub out1 ++ { ++ local($name,$p1)=@_; ++ local($l,$t); ++ ++ push(@out,"\t$name\t".&conv($p1)."\n"); ++ } ++ ++sub conv ++ { ++ local($p)=@_; ++ ++ $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; ++ return $p; ++ } ++ ++sub using486 ++ { ++ return if $using486; ++ $using486++; ++ grep(s/\.386/\.486/,@out); ++ } ++ ++sub main'file ++ { ++ local($file)=@_; ++ ++ local($tmp)=<<"EOF"; ++ TITLE $file.asm ++ .386 ++.model FLAT ++EOF ++ push(@out,$tmp); ++ } ++ ++sub main'function_begin ++ { ++ local($func,$extra)=@_; ++ ++ push(@labels,$func); ++ ++ local($tmp)=<<"EOF"; ++_TEXT SEGMENT ++PUBLIC _$func ++$extra ++_$func PROC NEAR ++ push ebp ++ push ebx ++ push esi ++ push edi ++EOF ++ push(@out,$tmp); ++ $stack=20; ++ } ++ ++sub main'function_begin_B ++ { ++ local($func,$extra)=@_; ++ ++ local($tmp)=<<"EOF"; ++_TEXT SEGMENT ++PUBLIC _$func ++$extra ++_$func PROC NEAR ++EOF ++ push(@out,$tmp); ++ $stack=4; ++ } ++ ++sub main'function_end ++ { ++ local($func)=@_; ++ ++ local($tmp)=<<"EOF"; ++ pop edi ++ pop esi ++ pop ebx ++ pop ebp ++ ret ++_$func ENDP ++_TEXT ENDS ++EOF ++ push(@out,$tmp); ++ $stack=0; ++ %label=(); ++ } ++ ++sub main'function_end_B ++ { ++ local($func)=@_; ++ ++ local($tmp)=<<"EOF"; ++_$func ENDP ++_TEXT ENDS ++EOF ++ push(@out,$tmp); ++ $stack=0; ++ %label=(); ++ } ++ ++sub main'function_end_A ++ { ++ local($func)=@_; ++ ++ local($tmp)=<<"EOF"; ++ pop edi ++ pop esi ++ pop ebx ++ pop ebp ++ ret ++EOF ++ push(@out,$tmp); ++ } ++ ++sub main'file_end ++ { ++ push(@out,"END\n"); ++ } ++ ++sub main'wparam ++ { ++ local($num)=@_; ++ ++ return(&main'DWP($stack+$num*4,"esp","",0)); ++ } ++ ++sub main'swtmp ++ { ++ return(&main'DWP($_[0]*4,"esp","",0)); ++ } ++ ++# Should use swtmp, which is above esp. Linix can trash the stack above esp ++#sub main'wtmp ++# { ++# local($num)=@_; ++# ++# return(&main'DWP(-(($num+1)*4),"esp","",0)); ++# } ++ ++sub main'comment ++ { ++ foreach (@_) ++ { ++ push(@out,"\t; $_\n"); ++ } ++ } ++ ++sub main'label ++ { ++ if (!defined($label{$_[0]})) ++ { ++ $label{$_[0]}="\$${label}${_[0]}"; ++ $label++; ++ } ++ return($label{$_[0]}); ++ } ++ ++sub main'set_label ++ { ++ if (!defined($label{$_[0]})) ++ { ++ $label{$_[0]}="${label}${_[0]}"; ++ $label++; ++ } ++ push(@out,"$label{$_[0]}:\n"); ++ } ++ ++sub main'data_word ++ { ++ push(@out,"\tDD\t$_[0]\n"); ++ } ++ ++sub out1p ++ { ++ local($name,$p1)=@_; ++ local($l,$t); ++ ++ push(@out,"\t$name\t ".&conv($p1)."\n"); ++ } +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/perlasm/x86unix.pl Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,403 @@ ++#!/usr/bin/perl ++ ++package x86unix; ++ ++$label="L000"; ++ ++$align=($main'aout)?"4":"16"; ++$under=($main'aout)?"_":""; ++$com_start=($main'sol)?"/":"#"; ++ ++sub main'asm_init_output { @out=(); } ++sub main'asm_get_output { return(@out); } ++sub main'get_labels { return(@labels); } ++sub main'external_label { push(@labels,@_); } ++ ++if ($main'cpp) ++ { ++ $align="ALIGN"; ++ $under=""; ++ $com_start='/*'; ++ $com_end='*/'; ++ } ++ ++%lb=( 'eax', '%al', ++ 'ebx', '%bl', ++ 'ecx', '%cl', ++ 'edx', '%dl', ++ 'ax', '%al', ++ 'bx', '%bl', ++ 'cx', '%cl', ++ 'dx', '%dl', ++ ); ++ ++%hb=( 'eax', '%ah', ++ 'ebx', '%bh', ++ 'ecx', '%ch', ++ 'edx', '%dh', ++ 'ax', '%ah', ++ 'bx', '%bh', ++ 'cx', '%ch', ++ 'dx', '%dh', ++ ); ++ ++%regs=( 'eax', '%eax', ++ 'ebx', '%ebx', ++ 'ecx', '%ecx', ++ 'edx', '%edx', ++ 'esi', '%esi', ++ 'edi', '%edi', ++ 'ebp', '%ebp', ++ 'esp', '%esp', ++ ); ++ ++%reg_val=( ++ 'eax', 0x00, ++ 'ebx', 0x03, ++ 'ecx', 0x01, ++ 'edx', 0x02, ++ 'esi', 0x06, ++ 'edi', 0x07, ++ 'ebp', 0x05, ++ 'esp', 0x04, ++ ); ++ ++sub main'LB ++ { ++ (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; ++ return($lb{$_[0]}); ++ } ++ ++sub main'HB ++ { ++ (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; ++ return($hb{$_[0]}); ++ } ++ ++sub main'DWP ++ { ++ local($addr,$reg1,$reg2,$idx)=@_; ++ ++ $ret=""; ++ $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/; ++ $reg1="$regs{$reg1}" if defined($regs{$reg1}); ++ $reg2="$regs{$reg2}" if defined($regs{$reg2}); ++ $ret.=$addr if ($addr ne "") && ($addr ne 0); ++ if ($reg2 ne "") ++ { $ret.="($reg1,$reg2,$idx)"; } ++ else ++ { $ret.="($reg1)" } ++ return($ret); ++ } ++ ++sub main'BP ++ { ++ return(&main'DWP(@_)); ++ } ++ ++#sub main'BP ++# { ++# local($addr,$reg1,$reg2,$idx)=@_; ++# ++# $ret=""; ++# ++# $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/; ++# $reg1="$regs{$reg1}" if defined($regs{$reg1}); ++# $reg2="$regs{$reg2}" if defined($regs{$reg2}); ++# $ret.=$addr if ($addr ne "") && ($addr ne 0); ++# if ($reg2 ne "") ++# { $ret.="($reg1,$reg2,$idx)"; } ++# else ++# { $ret.="($reg1)" } ++# return($ret); ++# } ++ ++sub main'mov { &out2("movl",@_); } ++sub main'movb { &out2("movb",@_); } ++sub main'and { &out2("andl",@_); } ++sub main'or { &out2("orl",@_); } ++sub main'shl { &out2("sall",@_); } ++sub main'shr { &out2("shrl",@_); } ++sub main'xor { &out2("xorl",@_); } ++sub main'xorb { &out2("xorb",@_); } ++sub main'add { &out2("addl",@_); } ++sub main'adc { &out2("adcl",@_); } ++sub main'sub { &out2("subl",@_); } ++sub main'rotl { &out2("roll",@_); } ++sub main'rotr { &out2("rorl",@_); } ++sub main'exch { &out2("xchg",@_); } ++sub main'cmp { &out2("cmpl",@_); } ++sub main'lea { &out2("leal",@_); } ++sub main'mul { &out1("mull",@_); } ++sub main'div { &out1("divl",@_); } ++sub main'jmp { &out1("jmp",@_); } ++sub main'jmp_ptr { &out1p("jmp",@_); } ++sub main'je { &out1("je",@_); } ++sub main'jle { &out1("jle",@_); } ++sub main'jne { &out1("jne",@_); } ++sub main'jnz { &out1("jnz",@_); } ++sub main'jz { &out1("jz",@_); } ++sub main'jge { &out1("jge",@_); } ++sub main'jl { &out1("jl",@_); } ++sub main'jb { &out1("jb",@_); } ++sub main'dec { &out1("decl",@_); } ++sub main'inc { &out1("incl",@_); } ++sub main'push { &out1("pushl",@_); $stack+=4; } ++sub main'pop { &out1("popl",@_); $stack-=4; } ++sub main'bswap { &out1("bswapl",@_); } ++sub main'not { &out1("notl",@_); } ++sub main'call { &out1("call",$under.$_[0]); } ++sub main'ret { &out0("ret"); } ++sub main'nop { &out0("nop"); } ++ ++sub out2 ++ { ++ local($name,$p1,$p2)=@_; ++ local($l,$ll,$t); ++ local(%special)=( "roll",0xD1C0,"rorl",0xD1C8, ++ "rcll",0xD1D0,"rcrl",0xD1D8, ++ "shll",0xD1E0,"shrl",0xD1E8, ++ "sarl",0xD1F8); ++ ++ if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1)) ++ { ++ $op=$special{$name}|$reg_val{$p1}; ++ $tmp1=sprintf ".byte %d\n",($op>>8)&0xff; ++ $tmp2=sprintf ".byte %d\t",$op &0xff; ++ push(@out,$tmp1); ++ push(@out,$tmp2); ++ ++ $p2=&conv($p2); ++ $p1=&conv($p1); ++ &main'comment("$name $p2 $p1"); ++ return; ++ } ++ ++ push(@out,"\t$name\t"); ++ $t=&conv($p2).","; ++ $l=length($t); ++ push(@out,$t); ++ $ll=4-($l+9)/8; ++ $tmp1=sprintf "\t" x $ll; ++ push(@out,$tmp1); ++ push(@out,&conv($p1)."\n"); ++ } ++ ++sub out1 ++ { ++ local($name,$p1)=@_; ++ local($l,$t); ++ ++ push(@out,"\t$name\t".&conv($p1)."\n"); ++ } ++ ++sub out1p ++ { ++ local($name,$p1)=@_; ++ local($l,$t); ++ ++ push(@out,"\t$name\t*".&conv($p1)."\n"); ++ } ++ ++sub out0 ++ { ++ push(@out,"\t$_[0]\n"); ++ } ++ ++sub conv ++ { ++ local($p)=@_; ++ ++# $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; ++ ++ $p=$regs{$p} if (defined($regs{$p})); ++ ++ $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/; ++ $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/; ++ return $p; ++ } ++ ++sub main'file ++ { ++ local($file)=@_; ++ ++ local($tmp)=<<"EOF"; ++ .file "$file.s" ++ .version "01.01" ++gcc2_compiled.: ++EOF ++ push(@out,$tmp); ++ } ++ ++sub main'function_begin ++ { ++ local($func)=@_; ++ ++ $func=$under.$func; ++ ++ local($tmp)=<<"EOF"; ++.text ++ .align $align ++.globl $func ++EOF ++ push(@out,$tmp); ++ if ($main'cpp) ++ { $tmp=push(@out,"\tTYPE($func,\@function)\n"); } ++ else { $tmp=push(@out,"\t.type\t$func,\@function\n"); } ++ push(@out,"$func:\n"); ++ $tmp=<<"EOF"; ++ pushl %ebp ++ pushl %ebx ++ pushl %esi ++ pushl %edi ++ ++EOF ++ push(@out,$tmp); ++ $stack=20; ++ } ++ ++sub main'function_begin_B ++ { ++ local($func,$extra)=@_; ++ ++ $func=$under.$func; ++ ++ local($tmp)=<<"EOF"; ++.text ++ .align $align ++.globl $func ++EOF ++ push(@out,$tmp); ++ if ($main'cpp) ++ { push(@out,"\tTYPE($func,\@function)\n"); } ++ else { push(@out,"\t.type $func,\@function\n"); } ++ push(@out,"$func:\n"); ++ $stack=4; ++ } ++ ++sub main'function_end ++ { ++ local($func)=@_; ++ ++ $func=$under.$func; ++ ++ local($tmp)=<<"EOF"; ++ popl %edi ++ popl %esi ++ popl %ebx ++ popl %ebp ++ ret ++.${func}_end: ++EOF ++ push(@out,$tmp); ++ if ($main'cpp) ++ { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); } ++ else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); } ++ push(@out,".ident \"$func\"\n"); ++ $stack=0; ++ %label=(); ++ } ++ ++sub main'function_end_A ++ { ++ local($func)=@_; ++ ++ local($tmp)=<<"EOF"; ++ popl %edi ++ popl %esi ++ popl %ebx ++ popl %ebp ++ ret ++EOF ++ push(@out,$tmp); ++ } ++ ++sub main'function_end_B ++ { ++ local($func)=@_; ++ ++ $func=$under.$func; ++ ++ push(@out,".${func}_end:\n"); ++ if ($main'cpp) ++ { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); } ++ else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); } ++ push(@out,".ident \"desasm.pl\"\n"); ++ $stack=0; ++ %label=(); ++ } ++ ++sub main'wparam ++ { ++ local($num)=@_; ++ ++ return(&main'DWP($stack+$num*4,"esp","",0)); ++ } ++ ++sub main'stack_push ++ { ++ local($num)=@_; ++ $stack+=$num*4; ++ &main'sub("esp",$num*4); ++ } ++ ++sub main'stack_pop ++ { ++ local($num)=@_; ++ $stack-=$num*4; ++ &main'add("esp",$num*4); ++ } ++ ++sub main'swtmp ++ { ++ return(&main'DWP($_[0]*4,"esp","",0)); ++ } ++ ++# Should use swtmp, which is above esp. Linix can trash the stack above esp ++#sub main'wtmp ++# { ++# local($num)=@_; ++# ++# return(&main'DWP(-($num+1)*4,"esp","",0)); ++# } ++ ++sub main'comment ++ { ++ foreach (@_) ++ { ++ if (/^\s*$/) ++ { push(@out,"\n"); } ++ else ++ { push(@out,"\t$com_start $_ $com_end\n"); } ++ } ++ } ++ ++sub main'label ++ { ++ if (!defined($label{$_[0]})) ++ { ++ $label{$_[0]}=".${label}${_[0]}"; ++ $label++; ++ } ++ return($label{$_[0]}); ++ } ++ ++sub main'set_label ++ { ++ if (!defined($label{$_[0]})) ++ { ++ $label{$_[0]}=".${label}${_[0]}"; ++ $label++; ++ } ++ push(@out,".align $align\n") if ($_[1] != 0); ++ push(@out,"$label{$_[0]}:\n"); ++ } ++ ++sub main'file_end ++ { ++ } ++ ++sub main'data_word ++ { ++ push(@out,"\t.long $_[0]\n"); ++ } +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/asm/readme Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,131 @@ ++First up, let me say I don't like writing in assembler. It is not portable, ++dependant on the particular CPU architecture release and is generally a pig ++to debug and get right. Having said that, the x86 architecture is probably ++the most important for speed due to number of boxes and since ++it appears to be the worst architecture to to get ++good C compilers for. So due to this, I have lowered myself to do ++assembler for the inner DES routines in libdes :-). ++ ++The file to implement in assembler is des_enc.c. Replace the following ++4 functions ++des_encrypt(DES_LONG data[2],des_key_schedule ks, int encrypt); ++des_encrypt2(DES_LONG data[2],des_key_schedule ks, int encrypt); ++des_encrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3); ++des_decrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3); ++ ++They encrypt/decrypt the 64 bits held in 'data' using ++the 'ks' key schedules. The only difference between the 4 functions is that ++des_encrypt2() does not perform IP() or FP() on the data (this is an ++optimization for when doing triple DES and des_encrypt3() and des_decrypt3() ++perform triple des. The triple DES routines are in here because it does ++make a big difference to have them located near the des_encrypt2 function ++at link time.. ++ ++Now as we all know, there are lots of different operating systems running on ++x86 boxes, and unfortunately they normally try to make sure their assembler ++formating is not the same as the other peoples. ++The 4 main formats I know of are ++Microsoft Windows 95/Windows NT ++Elf Includes Linux and FreeBSD(?). ++a.out The older Linux. ++Solaris Same as Elf but different comments :-(. ++ ++Now I was not overly keen to write 4 different copies of the same code, ++so I wrote a few perl routines to output the correct assembler, given ++a target assembler type. This code is ugly and is just a hack. ++The libraries are x86unix.pl and x86ms.pl. ++des586.pl, des686.pl and des-som[23].pl are the programs to actually ++generate the assembler. ++ ++So to generate elf assembler ++perl des-som3.pl elf >dx86-elf.s ++For Windows 95/NT ++perl des-som2.pl win32 >win32.asm ++ ++[ update 4 Jan 1996 ] ++I have added another way to do things. ++perl des-som3.pl cpp >dx86-cpp.s ++generates a file that will be included by dx86unix.cpp when it is compiled. ++To build for elf, a.out, solaris, bsdi etc, ++cc -E -DELF asm/dx86unix.cpp | as -o asm/dx86-elf.o ++cc -E -DSOL asm/dx86unix.cpp | as -o asm/dx86-sol.o ++cc -E -DOUT asm/dx86unix.cpp | as -o asm/dx86-out.o ++cc -E -DBSDI asm/dx86unix.cpp | as -o asm/dx86bsdi.o ++This was done to cut down the number of files in the distribution. ++ ++Now the ugly part. I acquired my copy of Intels ++"Optimization's For Intel's 32-Bit Processors" and found a few interesting ++things. First, the aim of the exersize is to 'extract' one byte at a time ++from a word and do an array lookup. This involves getting the byte from ++the 4 locations in the word and moving it to a new word and doing the lookup. ++The most obvious way to do this is ++xor eax, eax # clear word ++movb al, cl # get low byte ++xor edi DWORD PTR 0x100+des_SP[eax] # xor in word ++movb al, ch # get next byte ++xor edi DWORD PTR 0x300+des_SP[eax] # xor in word ++shr ecx 16 ++which seems ok. For the pentium, this system appears to be the best. ++One has to do instruction interleaving to keep both functional units ++operating, but it is basically very efficient. ++ ++Now the crunch. When a full register is used after a partial write, eg. ++mov al, cl ++xor edi, DWORD PTR 0x100+des_SP[eax] ++386 - 1 cycle stall ++486 - 1 cycle stall ++586 - 0 cycle stall ++686 - at least 7 cycle stall (page 22 of the above mentioned document). ++ ++So the technique that produces the best results on a pentium, according to ++the documentation, will produce hideous results on a pentium pro. ++ ++To get around this, des686.pl will generate code that is not as fast on ++a pentium, should be very good on a pentium pro. ++mov eax, ecx # copy word ++shr ecx, 8 # line up next byte ++and eax, 0fch # mask byte ++xor edi DWORD PTR 0x100+des_SP[eax] # xor in array lookup ++mov eax, ecx # get word ++shr ecx 8 # line up next byte ++and eax, 0fch # mask byte ++xor edi DWORD PTR 0x300+des_SP[eax] # xor in array lookup ++ ++Due to the execution units in the pentium, this actually works quite well. ++For a pentium pro it should be very good. This is the type of output ++Visual C++ generates. ++ ++There is a third option. instead of using ++mov al, ch ++which is bad on the pentium pro, one may be able to use ++movzx eax, ch ++which may not incur the partial write penalty. On the pentium, ++this instruction takes 4 cycles so is not worth using but on the ++pentium pro it appears it may be worth while. I need access to one to ++experiment :-). ++ ++eric (20 Oct 1996) ++ ++22 Nov 1996 - I have asked people to run the 2 different version on pentium ++pros and it appears that the intel documentation is wrong. The ++mov al,bh is still faster on a pentium pro, so just use the des586.pl ++install des686.pl ++ ++3 Dec 1996 - I added des_encrypt3/des_decrypt3 because I have moved these ++functions into des_enc.c because it does make a massive performance ++difference on some boxes to have the functions code located close to ++the des_encrypt2() function. ++ ++9 Jan 1997 - des-som2.pl is now the correct perl script to use for ++pentiums. It contains an inner loop from ++Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk> which does raw ecb DES calls at ++273,000 per second. He had a previous version at 250,000 and the best ++I was able to get was 203,000. The content has not changed, this is all ++due to instruction sequencing (and actual instructions choice) which is able ++to keep both functional units of the pentium going. ++We may have lost the ugly register usage restrictions when x86 went 32 bit ++but for the pentium it has been replaced by evil instruction ordering tricks. ++ ++13 Jan 1997 - des-som3.pl, more optimizations from Svend Olaf. ++raw DES at 281,000 per second on a pentium 100. ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/cbc_enc.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,135 @@ ++/* crypto/des/cbc_enc.c */ ++/* Copyright (C) 1995-1997 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 "des_locl.h" ++ ++void des_cbc_encrypt(input, output, length, schedule, ivec, enc) ++des_cblock (*input); ++des_cblock (*output); ++long length; ++des_key_schedule schedule; ++des_cblock (*ivec); ++int enc; ++ { ++ register DES_LONG tin0,tin1; ++ register DES_LONG tout0,tout1,xor0,xor1; ++ register unsigned char *in,*out; ++ register long l=length; ++ DES_LONG tin[2]; ++ unsigned char *iv; ++ ++ in=(unsigned char *)input; ++ out=(unsigned char *)output; ++ iv=(unsigned char *)ivec; ++ ++ if (enc) ++ { ++ c2l(iv,tout0); ++ c2l(iv,tout1); ++ for (l-=8; l>=0; l-=8) ++ { ++ c2l(in,tin0); ++ c2l(in,tin1); ++ tin0^=tout0; tin[0]=tin0; ++ tin1^=tout1; tin[1]=tin1; ++ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); ++ tout0=tin[0]; l2c(tout0,out); ++ tout1=tin[1]; l2c(tout1,out); ++ } ++ if (l != -8) ++ { ++ c2ln(in,tin0,tin1,l+8); ++ tin0^=tout0; tin[0]=tin0; ++ tin1^=tout1; tin[1]=tin1; ++ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); ++ tout0=tin[0]; l2c(tout0,out); ++ tout1=tin[1]; l2c(tout1,out); ++ } ++ } ++ else ++ { ++ c2l(iv,xor0); ++ c2l(iv,xor1); ++ for (l-=8; l>=0; l-=8) ++ { ++ c2l(in,tin0); tin[0]=tin0; ++ c2l(in,tin1); tin[1]=tin1; ++ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); ++ tout0=tin[0]^xor0; ++ tout1=tin[1]^xor1; ++ l2c(tout0,out); ++ l2c(tout1,out); ++ xor0=tin0; ++ xor1=tin1; ++ } ++ if (l != -8) ++ { ++ c2l(in,tin0); tin[0]=tin0; ++ c2l(in,tin1); tin[1]=tin1; ++ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); ++ tout0=tin[0]^xor0; ++ tout1=tin[1]^xor1; ++ l2cn(tout0,tout1,out,l+8); ++ /* xor0=tin0; ++ xor1=tin1; */ ++ } ++ } ++ tin0=tin1=tout0=tout1=xor0=xor1=0; ++ tin[0]=tin[1]=0; ++ } ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/des.doc Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,505 @@ ++The DES library. ++ ++Please note that this library was originally written to operate with ++eBones, a version of Kerberos that had had encryption removed when it left ++the USA and then put back in. As such there are some routines that I will ++advise not using but they are still in the library for historical reasons. ++For all calls that have an 'input' and 'output' variables, they can be the ++same. ++ ++This library requires the inclusion of 'des.h'. ++ ++All of the encryption functions take what is called a des_key_schedule as an ++argument. A des_key_schedule is an expanded form of the des key. ++A des_key is 8 bytes of odd parity, the type used to hold the key is a ++des_cblock. A des_cblock is an array of 8 bytes, often in this library ++description I will refer to input bytes when the function specifies ++des_cblock's as input or output, this just means that the variable should ++be a multiple of 8 bytes. ++ ++The define DES_ENCRYPT is passed to specify encryption, DES_DECRYPT to ++specify decryption. The functions and global variable are as follows: ++ ++int des_check_key; ++ DES keys are supposed to be odd parity. If this variable is set to ++ a non-zero value, des_set_key() will check that the key has odd ++ parity and is not one of the known weak DES keys. By default this ++ variable is turned off; ++ ++void des_set_odd_parity( ++des_cblock *key ); ++ This function takes a DES key (8 bytes) and sets the parity to odd. ++ ++int des_is_weak_key( ++des_cblock *key ); ++ This function returns a non-zero value if the DES key passed is a ++ weak, DES key. If it is a weak key, don't use it, try a different ++ one. If you are using 'random' keys, the chances of hitting a weak ++ key are 1/2^52 so it is probably not worth checking for them. ++ ++int des_set_key( ++des_cblock *key, ++des_key_schedule schedule); ++ Des_set_key converts an 8 byte DES key into a des_key_schedule. ++ A des_key_schedule is an expanded form of the key which is used to ++ perform actual encryption. It can be regenerated from the DES key ++ so it only needs to be kept when encryption or decryption is about ++ to occur. Don't save or pass around des_key_schedule's since they ++ are CPU architecture dependent, DES keys are not. If des_check_key ++ is non zero, zero is returned if the key has the wrong parity or ++ the key is a weak key, else 1 is returned. ++ ++int des_key_sched( ++des_cblock *key, ++des_key_schedule schedule); ++ An alternative name for des_set_key(). ++ ++int des_rw_mode; /* defaults to DES_PCBC_MODE */ ++ This flag holds either DES_CBC_MODE or DES_PCBC_MODE (default). ++ This specifies the function to use in the enc_read() and enc_write() ++ functions. ++ ++void des_encrypt( ++unsigned long *data, ++des_key_schedule ks, ++int enc); ++ This is the DES encryption function that gets called by just about ++ every other DES routine in the library. You should not use this ++ function except to implement 'modes' of DES. I say this because the ++ functions that call this routine do the conversion from 'char *' to ++ long, and this needs to be done to make sure 'non-aligned' memory ++ access do not occur. The characters are loaded 'little endian', ++ have a look at my source code for more details on how I use this ++ function. ++ Data is a pointer to 2 unsigned long's and ks is the ++ des_key_schedule to use. enc, is non zero specifies encryption, ++ zero if decryption. ++ ++void des_encrypt2( ++unsigned long *data, ++des_key_schedule ks, ++int enc); ++ This functions is the same as des_encrypt() except that the DES ++ initial permutation (IP) and final permutation (FP) have been left ++ out. As for des_encrypt(), you should not use this function. ++ It is used by the routines in my library that implement triple DES. ++ IP() des_encrypt2() des_encrypt2() des_encrypt2() FP() is the same ++ as des_encrypt() des_encrypt() des_encrypt() except faster :-). ++ ++void des_ecb_encrypt( ++des_cblock *input, ++des_cblock *output, ++des_key_schedule ks, ++int enc); ++ This is the basic Electronic Code Book form of DES, the most basic ++ form. Input is encrypted into output using the key represented by ++ ks. If enc is non zero (DES_ENCRYPT), encryption occurs, otherwise ++ decryption occurs. Input is 8 bytes long and output is 8 bytes. ++ (the des_cblock structure is 8 chars). ++ ++void des_ecb3_encrypt( ++des_cblock *input, ++des_cblock *output, ++des_key_schedule ks1, ++des_key_schedule ks2, ++des_key_schedule ks3, ++int enc); ++ This is the 3 key EDE mode of ECB DES. What this means is that ++ the 8 bytes of input is encrypted with ks1, decrypted with ks2 and ++ then encrypted again with ks3, before being put into output; ++ C=E(ks3,D(ks2,E(ks1,M))). There is a macro, des_ecb2_encrypt() ++ that only takes 2 des_key_schedules that implements, ++ C=E(ks1,D(ks2,E(ks1,M))) in that the final encrypt is done with ks1. ++ ++void des_cbc_encrypt( ++des_cblock *input, ++des_cblock *output, ++long length, ++des_key_schedule ks, ++des_cblock *ivec, ++int enc); ++ This routine implements DES in Cipher Block Chaining mode. ++ Input, which should be a multiple of 8 bytes is encrypted ++ (or decrypted) to output which will also be a multiple of 8 bytes. ++ The number of bytes is in length (and from what I've said above, ++ should be a multiple of 8). If length is not a multiple of 8, I'm ++ not being held responsible :-). ivec is the initialisation vector. ++ This function does not modify this variable. To correctly implement ++ cbc mode, you need to do one of 2 things; copy the last 8 bytes of ++ cipher text for use as the next ivec in your application, ++ or use des_ncbc_encrypt(). ++ Only this routine has this problem with updating the ivec, all ++ other routines that are implementing cbc mode update ivec. ++ ++void des_ncbc_encrypt( ++des_cblock *input, ++des_cblock *output, ++long length, ++des_key_schedule sk, ++des_cblock *ivec, ++int enc); ++ For historical reasons, des_cbc_encrypt() did not update the ++ ivec with the value requires so that subsequent calls to ++ des_cbc_encrypt() would 'chain'. This was needed so that the same ++ 'length' values would not need to be used when decrypting. ++ des_ncbc_encrypt() does the right thing. It is the same as ++ des_cbc_encrypt accept that ivec is updates with the correct value ++ to pass in subsequent calls to des_ncbc_encrypt(). I advise using ++ des_ncbc_encrypt() instead of des_cbc_encrypt(); ++ ++void des_xcbc_encrypt( ++des_cblock *input, ++des_cblock *output, ++long length, ++des_key_schedule sk, ++des_cblock *ivec, ++des_cblock *inw, ++des_cblock *outw, ++int enc); ++ This is RSA's DESX mode of DES. It uses inw and outw to ++ 'whiten' the encryption. inw and outw are secret (unlike the iv) ++ and are as such, part of the key. So the key is sort of 24 bytes. ++ This is much better than cbc des. ++ ++void des_3cbc_encrypt( ++des_cblock *input, ++des_cblock *output, ++long length, ++des_key_schedule sk1, ++des_key_schedule sk2, ++des_cblock *ivec1, ++des_cblock *ivec2, ++int enc); ++ This function is flawed, do not use it. I have left it in the ++ library because it is used in my des(1) program and will function ++ correctly when used by des(1). If I removed the function, people ++ could end up unable to decrypt files. ++ This routine implements outer triple cbc encryption using 2 ks and ++ 2 ivec's. Use des_ede2_cbc_encrypt() instead. ++ ++void des_ede3_cbc_encrypt( ++des_cblock *input, ++des_cblock *output, ++long length, ++des_key_schedule ks1, ++des_key_schedule ks2, ++des_key_schedule ks3, ++des_cblock *ivec, ++int enc); ++ This function implements inner triple CBC DES encryption with 3 ++ keys. What this means is that each 'DES' operation ++ inside the cbc mode is really an C=E(ks3,D(ks2,E(ks1,M))). ++ Again, this is cbc mode so an ivec is requires. ++ This mode is used by SSL. ++ There is also a des_ede2_cbc_encrypt() that only uses 2 ++ des_key_schedule's, the first being reused for the final ++ encryption. C=E(ks1,D(ks2,E(ks1,M))). This form of triple DES ++ is used by the RSAref library. ++ ++void des_pcbc_encrypt( ++des_cblock *input, ++des_cblock *output, ++long length, ++des_key_schedule ks, ++des_cblock *ivec, ++int enc); ++ This is Propagating Cipher Block Chaining mode of DES. It is used ++ by Kerberos v4. It's parameters are the same as des_ncbc_encrypt(). ++ ++void des_cfb_encrypt( ++unsigned char *in, ++unsigned char *out, ++int numbits, ++long length, ++des_key_schedule ks, ++des_cblock *ivec, ++int enc); ++ Cipher Feedback Back mode of DES. This implementation 'feeds back' ++ in numbit blocks. The input (and output) is in multiples of numbits ++ bits. numbits should to be a multiple of 8 bits. Length is the ++ number of bytes input. If numbits is not a multiple of 8 bits, ++ the extra bits in the bytes will be considered padding. So if ++ numbits is 12, for each 2 input bytes, the 4 high bits of the ++ second byte will be ignored. So to encode 72 bits when using ++ a numbits of 12 take 12 bytes. To encode 72 bits when using ++ numbits of 9 will take 16 bytes. To encode 80 bits when using ++ numbits of 16 will take 10 bytes. etc, etc. This padding will ++ apply to both input and output. ++ ++ ++void des_cfb64_encrypt( ++unsigned char *in, ++unsigned char *out, ++long length, ++des_key_schedule ks, ++des_cblock *ivec, ++int *num, ++int enc); ++ This is one of the more useful functions in this DES library, it ++ implements CFB mode of DES with 64bit feedback. Why is this ++ useful you ask? Because this routine will allow you to encrypt an ++ arbitrary number of bytes, no 8 byte padding. Each call to this ++ routine will encrypt the input bytes to output and then update ivec ++ and num. num contains 'how far' we are though ivec. If this does ++ not make much sense, read more about cfb mode of DES :-). ++ ++void des_ede3_cfb64_encrypt( ++unsigned char *in, ++unsigned char *out, ++long length, ++des_key_schedule ks1, ++des_key_schedule ks2, ++des_key_schedule ks3, ++des_cblock *ivec, ++int *num, ++int enc); ++ Same as des_cfb64_encrypt() accept that the DES operation is ++ triple DES. As usual, there is a macro for ++ des_ede2_cfb64_encrypt() which reuses ks1. ++ ++void des_ofb_encrypt( ++unsigned char *in, ++unsigned char *out, ++int numbits, ++long length, ++des_key_schedule ks, ++des_cblock *ivec); ++ This is a implementation of Output Feed Back mode of DES. It is ++ the same as des_cfb_encrypt() in that numbits is the size of the ++ units dealt with during input and output (in bits). ++ ++void des_ofb64_encrypt( ++unsigned char *in, ++unsigned char *out, ++long length, ++des_key_schedule ks, ++des_cblock *ivec, ++int *num); ++ The same as des_cfb64_encrypt() except that it is Output Feed Back ++ mode. ++ ++void des_ede3_ofb64_encrypt( ++unsigned char *in, ++unsigned char *out, ++long length, ++des_key_schedule ks1, ++des_key_schedule ks2, ++des_key_schedule ks3, ++des_cblock *ivec, ++int *num); ++ Same as des_ofb64_encrypt() accept that the DES operation is ++ triple DES. As usual, there is a macro for ++ des_ede2_ofb64_encrypt() which reuses ks1. ++ ++int des_read_pw_string( ++char *buf, ++int length, ++char *prompt, ++int verify); ++ This routine is used to get a password from the terminal with echo ++ turned off. Buf is where the string will end up and length is the ++ size of buf. Prompt is a string presented to the 'user' and if ++ verify is set, the key is asked for twice and unless the 2 copies ++ match, an error is returned. A return code of -1 indicates a ++ system error, 1 failure due to use interaction, and 0 is success. ++ ++unsigned long des_cbc_cksum( ++des_cblock *input, ++des_cblock *output, ++long length, ++des_key_schedule ks, ++des_cblock *ivec); ++ This function produces an 8 byte checksum from input that it puts in ++ output and returns the last 4 bytes as a long. The checksum is ++ generated via cbc mode of DES in which only the last 8 byes are ++ kept. I would recommend not using this function but instead using ++ the EVP_Digest routines, or at least using MD5 or SHA. This ++ function is used by Kerberos v4 so that is why it stays in the ++ library. ++ ++char *des_fcrypt( ++const char *buf, ++const char *salt ++char *ret); ++ This is my fast version of the unix crypt(3) function. This version ++ takes only a small amount of space relative to other fast ++ crypt() implementations. This is different to the normal crypt ++ in that the third parameter is the buffer that the return value ++ is written into. It needs to be at least 14 bytes long. This ++ function is thread safe, unlike the normal crypt. ++ ++char *crypt( ++const char *buf, ++const char *salt); ++ This function calls des_fcrypt() with a static array passed as the ++ third parameter. This emulates the normal non-thread safe semantics ++ of crypt(3). ++ ++void des_string_to_key( ++char *str, ++des_cblock *key); ++ This function takes str and converts it into a DES key. I would ++ recommend using MD5 instead and use the first 8 bytes of output. ++ When I wrote the first version of these routines back in 1990, MD5 ++ did not exist but I feel these routines are still sound. This ++ routines is compatible with the one in MIT's libdes. ++ ++void des_string_to_2keys( ++char *str, ++des_cblock *key1, ++des_cblock *key2); ++ This function takes str and converts it into 2 DES keys. ++ I would recommend using MD5 and using the 16 bytes as the 2 keys. ++ I have nothing against these 2 'string_to_key' routines, it's just ++ that if you say that your encryption key is generated by using the ++ 16 bytes of an MD5 hash, every-one knows how you generated your ++ keys. ++ ++int des_read_password( ++des_cblock *key, ++char *prompt, ++int verify); ++ This routine combines des_read_pw_string() with des_string_to_key(). ++ ++int des_read_2passwords( ++des_cblock *key1, ++des_cblock *key2, ++char *prompt, ++int verify); ++ This routine combines des_read_pw_string() with des_string_to_2key(). ++ ++void des_random_seed( ++des_cblock key); ++ This routine sets a starting point for des_random_key(). ++ ++void des_random_key( ++des_cblock ret); ++ This function return a random key. Make sure to 'seed' the random ++ number generator (with des_random_seed()) before using this function. ++ I personally now use a MD5 based random number system. ++ ++int des_enc_read( ++int fd, ++char *buf, ++int len, ++des_key_schedule ks, ++des_cblock *iv); ++ This function will write to a file descriptor the encrypted data ++ from buf. This data will be preceded by a 4 byte 'byte count' and ++ will be padded out to 8 bytes. The encryption is either CBC of ++ PCBC depending on the value of des_rw_mode. If it is DES_PCBC_MODE, ++ pcbc is used, if DES_CBC_MODE, cbc is used. The default is to use ++ DES_PCBC_MODE. ++ ++int des_enc_write( ++int fd, ++char *buf, ++int len, ++des_key_schedule ks, ++des_cblock *iv); ++ This routines read stuff written by des_enc_read() and decrypts it. ++ I have used these routines quite a lot but I don't believe they are ++ suitable for non-blocking io. If you are after a full ++ authentication/encryption over networks, have a look at SSL instead. ++ ++unsigned long des_quad_cksum( ++des_cblock *input, ++des_cblock *output, ++long length, ++int out_count, ++des_cblock *seed); ++ This is a function from Kerberos v4 that is not anything to do with ++ DES but was needed. It is a cksum that is quicker to generate than ++ des_cbc_cksum(); I personally would use MD5 routines now. ++===== ++Modes of DES ++Quite a bit of the following information has been taken from ++ AS 2805.5.2 ++ Australian Standard ++ Electronic funds transfer - Requirements for interfaces, ++ Part 5.2: Modes of operation for an n-bit block cipher algorithm ++ Appendix A ++ ++There are several different modes in which DES can be used, they are ++as follows. ++ ++Electronic Codebook Mode (ECB) (des_ecb_encrypt()) ++- 64 bits are enciphered at a time. ++- The order of the blocks can be rearranged without detection. ++- The same plaintext block always produces the same ciphertext block ++ (for the same key) making it vulnerable to a 'dictionary attack'. ++- An error will only affect one ciphertext block. ++ ++Cipher Block Chaining Mode (CBC) (des_cbc_encrypt()) ++- a multiple of 64 bits are enciphered at a time. ++- The CBC mode produces the same ciphertext whenever the same ++ plaintext is encrypted using the same key and starting variable. ++- The chaining operation makes the ciphertext blocks dependent on the ++ current and all preceding plaintext blocks and therefore blocks can not ++ be rearranged. ++- The use of different starting variables prevents the same plaintext ++ enciphering to the same ciphertext. ++- An error will affect the current and the following ciphertext blocks. ++ ++Cipher Feedback Mode (CFB) (des_cfb_encrypt()) ++- a number of bits (j) <= 64 are enciphered at a time. ++- The CFB mode produces the same ciphertext whenever the same ++ plaintext is encrypted using the same key and starting variable. ++- The chaining operation makes the ciphertext variables dependent on the ++ current and all preceding variables and therefore j-bit variables are ++ chained together and can not be rearranged. ++- The use of different starting variables prevents the same plaintext ++ enciphering to the same ciphertext. ++- The strength of the CFB mode depends on the size of k (maximal if ++ j == k). In my implementation this is always the case. ++- Selection of a small value for j will require more cycles through ++ the encipherment algorithm per unit of plaintext and thus cause ++ greater processing overheads. ++- Only multiples of j bits can be enciphered. ++- An error will affect the current and the following ciphertext variables. ++ ++Output Feedback Mode (OFB) (des_ofb_encrypt()) ++- a number of bits (j) <= 64 are enciphered at a time. ++- The OFB mode produces the same ciphertext whenever the same ++ plaintext enciphered using the same key and starting variable. More ++ over, in the OFB mode the same key stream is produced when the same ++ key and start variable are used. Consequently, for security reasons ++ a specific start variable should be used only once for a given key. ++- The absence of chaining makes the OFB more vulnerable to specific attacks. ++- The use of different start variables values prevents the same ++ plaintext enciphering to the same ciphertext, by producing different ++ key streams. ++- Selection of a small value for j will require more cycles through ++ the encipherment algorithm per unit of plaintext and thus cause ++ greater processing overheads. ++- Only multiples of j bits can be enciphered. ++- OFB mode of operation does not extend ciphertext errors in the ++ resultant plaintext output. Every bit error in the ciphertext causes ++ only one bit to be in error in the deciphered plaintext. ++- OFB mode is not self-synchronising. If the two operation of ++ encipherment and decipherment get out of synchronism, the system needs ++ to be re-initialised. ++- Each re-initialisation should use a value of the start variable ++ different from the start variable values used before with the same ++ key. The reason for this is that an identical bit stream would be ++ produced each time from the same parameters. This would be ++ susceptible to a ' known plaintext' attack. ++ ++Triple ECB Mode (des_ecb3_encrypt()) ++- Encrypt with key1, decrypt with key2 and encrypt with key3 again. ++- As for ECB encryption but increases the key length to 168 bits. ++ There are theoretic attacks that can be used that make the effective ++ key length 112 bits, but this attack also requires 2^56 blocks of ++ memory, not very likely, even for the NSA. ++- If both keys are the same it is equivalent to encrypting once with ++ just one key. ++- If the first and last key are the same, the key length is 112 bits. ++ There are attacks that could reduce the key space to 55 bit's but it ++ requires 2^56 blocks of memory. ++- If all 3 keys are the same, this is effectively the same as normal ++ ecb mode. ++ ++Triple CBC Mode (des_ede3_cbc_encrypt()) ++- Encrypt with key1, decrypt with key2 and then encrypt with key3. ++- As for CBC encryption but increases the key length to 168 bits with ++ the same restrictions as for triple ecb mode. +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/des_crypt.man Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,508 @@ ++.TH DES_CRYPT 3 ++.SH NAME ++des_read_password, des_read_2password, ++des_string_to_key, des_string_to_2key, des_read_pw_string, ++des_random_key, des_set_key, ++des_key_sched, des_ecb_encrypt, des_ecb3_encrypt, des_cbc_encrypt, ++des_3cbc_encrypt, ++des_pcbc_encrypt, des_cfb_encrypt, des_ofb_encrypt, ++des_cbc_cksum, des_quad_cksum, ++des_enc_read, des_enc_write, des_set_odd_parity, ++des_is_weak_key, crypt \- (non USA) DES encryption ++.SH SYNOPSIS ++.nf ++.nj ++.ft B ++#include <des.h> ++.PP ++.B int des_read_password(key,prompt,verify) ++des_cblock *key; ++char *prompt; ++int verify; ++.PP ++.B int des_read_2password(key1,key2,prompt,verify) ++des_cblock *key1,*key2; ++char *prompt; ++int verify; ++.PP ++.B int des_string_to_key(str,key) ++char *str; ++des_cblock *key; ++.PP ++.B int des_string_to_2keys(str,key1,key2) ++char *str; ++des_cblock *key1,*key2; ++.PP ++.B int des_read_pw_string(buf,length,prompt,verify) ++char *buf; ++int length; ++char *prompt; ++int verify; ++.PP ++.B int des_random_key(key) ++des_cblock *key; ++.PP ++.B int des_set_key(key,schedule) ++des_cblock *key; ++des_key_schedule schedule; ++.PP ++.B int des_key_sched(key,schedule) ++des_cblock *key; ++des_key_schedule schedule; ++.PP ++.B int des_ecb_encrypt(input,output,schedule,encrypt) ++des_cblock *input; ++des_cblock *output; ++des_key_schedule schedule; ++int encrypt; ++.PP ++.B int des_ecb3_encrypt(input,output,ks1,ks2,encrypt) ++des_cblock *input; ++des_cblock *output; ++des_key_schedule ks1,ks2; ++int encrypt; ++.PP ++.B int des_cbc_encrypt(input,output,length,schedule,ivec,encrypt) ++des_cblock *input; ++des_cblock *output; ++long length; ++des_key_schedule schedule; ++des_cblock *ivec; ++int encrypt; ++.PP ++.B int des_3cbc_encrypt(input,output,length,sk1,sk2,ivec1,ivec2,encrypt) ++des_cblock *input; ++des_cblock *output; ++long length; ++des_key_schedule sk1; ++des_key_schedule sk2; ++des_cblock *ivec1; ++des_cblock *ivec2; ++int encrypt; ++.PP ++.B int des_pcbc_encrypt(input,output,length,schedule,ivec,encrypt) ++des_cblock *input; ++des_cblock *output; ++long length; ++des_key_schedule schedule; ++des_cblock *ivec; ++int encrypt; ++.PP ++.B int des_cfb_encrypt(input,output,numbits,length,schedule,ivec,encrypt) ++unsigned char *input; ++unsigned char *output; ++int numbits; ++long length; ++des_key_schedule schedule; ++des_cblock *ivec; ++int encrypt; ++.PP ++.B int des_ofb_encrypt(input,output,numbits,length,schedule,ivec) ++unsigned char *input,*output; ++int numbits; ++long length; ++des_key_schedule schedule; ++des_cblock *ivec; ++.PP ++.B unsigned long des_cbc_cksum(input,output,length,schedule,ivec) ++des_cblock *input; ++des_cblock *output; ++long length; ++des_key_schedule schedule; ++des_cblock *ivec; ++.PP ++.B unsigned long des_quad_cksum(input,output,length,out_count,seed) ++des_cblock *input; ++des_cblock *output; ++long length; ++int out_count; ++des_cblock *seed; ++.PP ++.B int des_check_key; ++.PP ++.B int des_enc_read(fd,buf,len,sched,iv) ++int fd; ++char *buf; ++int len; ++des_key_schedule sched; ++des_cblock *iv; ++.PP ++.B int des_enc_write(fd,buf,len,sched,iv) ++int fd; ++char *buf; ++int len; ++des_key_schedule sched; ++des_cblock *iv; ++.PP ++.B extern int des_rw_mode; ++.PP ++.B void des_set_odd_parity(key) ++des_cblock *key; ++.PP ++.B int des_is_weak_key(key) ++des_cblock *key; ++.PP ++.B char *crypt(passwd,salt) ++char *passwd; ++char *salt; ++.PP ++.fi ++.SH DESCRIPTION ++This library contains a fast implementation of the DES encryption ++algorithm. ++.PP ++There are two phases to the use of DES encryption. ++The first is the generation of a ++.I des_key_schedule ++from a key, ++the second is the actual encryption. ++A des key is of type ++.I des_cblock. ++This type is made from 8 characters with odd parity. ++The least significant bit in the character is the parity bit. ++The key schedule is an expanded form of the key; it is used to speed the ++encryption process. ++.PP ++.I des_read_password ++writes the string specified by prompt to the standard output, ++turns off echo and reads an input string from standard input ++until terminated with a newline. ++If verify is non-zero, it prompts and reads the input again and verifies ++that both entered passwords are the same. ++The entered string is converted into a des key by using the ++.I des_string_to_key ++routine. ++The new key is placed in the ++.I des_cblock ++that was passed (by reference) to the routine. ++If there were no errors, ++.I des_read_password ++returns 0, ++-1 is returned if there was a terminal error and 1 is returned for ++any other error. ++.PP ++.I des_read_2password ++operates in the same way as ++.I des_read_password ++except that it generates 2 keys by using the ++.I des_string_to_2key ++function. ++.PP ++.I des_read_pw_string ++is called by ++.I des_read_password ++to read and verify a string from a terminal device. ++The string is returned in ++.I buf. ++The size of ++.I buf ++is passed to the routine via the ++.I length ++parameter. ++.PP ++.I des_string_to_key ++converts a string into a valid des key. ++.PP ++.I des_string_to_2key ++converts a string into 2 valid des keys. ++This routine is best suited for used to generate keys for use with ++.I des_ecb3_encrypt. ++.PP ++.I des_random_key ++returns a random key that is made of a combination of process id, ++time and an increasing counter. ++.PP ++Before a des key can be used it is converted into a ++.I des_key_schedule ++via the ++.I des_set_key ++routine. ++If the ++.I des_check_key ++flag is non-zero, ++.I des_set_key ++will check that the key passed is of odd parity and is not a week or ++semi-weak key. ++If the parity is wrong, ++then -1 is returned. ++If the key is a weak key, ++then -2 is returned. ++If an error is returned, ++the key schedule is not generated. ++.PP ++.I des_key_sched ++is another name for the ++.I des_set_key ++function. ++.PP ++The following routines mostly operate on an input and output stream of ++.I des_cblock's. ++.PP ++.I des_ecb_encrypt ++is the basic DES encryption routine that encrypts or decrypts a single 8-byte ++.I des_cblock ++in ++.I electronic code book ++mode. ++It always transforms the input data, pointed to by ++.I input, ++into the output data, ++pointed to by the ++.I output ++argument. ++If the ++.I encrypt ++argument is non-zero (DES_ENCRYPT), ++the ++.I input ++(cleartext) is encrypted in to the ++.I output ++(ciphertext) using the key_schedule specified by the ++.I schedule ++argument, ++previously set via ++.I des_set_key. ++If ++.I encrypt ++is zero (DES_DECRYPT), ++the ++.I input ++(now ciphertext) ++is decrypted into the ++.I output ++(now cleartext). ++Input and output may overlap. ++No meaningful value is returned. ++.PP ++.I des_ecb3_encrypt ++encrypts/decrypts the ++.I input ++block by using triple ecb DES encryption. ++This involves encrypting the input with ++.I ks1, ++decryption with the key schedule ++.I ks2, ++and then encryption with the first again. ++This routine greatly reduces the chances of brute force breaking of ++DES and has the advantage of if ++.I ks1 ++and ++.I ks2 ++are the same, it is equivalent to just encryption using ecb mode and ++.I ks1 ++as the key. ++.PP ++.I des_cbc_encrypt ++encrypts/decrypts using the ++.I cipher-block-chaining ++mode of DES. ++If the ++.I encrypt ++argument is non-zero, ++the routine cipher-block-chain encrypts the cleartext data pointed to by the ++.I input ++argument into the ciphertext pointed to by the ++.I output ++argument, ++using the key schedule provided by the ++.I schedule ++argument, ++and initialisation vector provided by the ++.I ivec ++argument. ++If the ++.I length ++argument is not an integral multiple of eight bytes, ++the last block is copied to a temporary area and zero filled. ++The output is always ++an integral multiple of eight bytes. ++To make multiple cbc encrypt calls on a large amount of data appear to ++be one ++.I des_cbc_encrypt ++call, the ++.I ivec ++of subsequent calls should be the last 8 bytes of the output. ++.PP ++.I des_3cbc_encrypt ++encrypts/decrypts the ++.I input ++block by using triple cbc DES encryption. ++This involves encrypting the input with key schedule ++.I ks1, ++decryption with the key schedule ++.I ks2, ++and then encryption with the first again. ++2 initialisation vectors are required, ++.I ivec1 ++and ++.I ivec2. ++Unlike ++.I des_cbc_encrypt, ++these initialisation vectors are modified by the subroutine. ++This routine greatly reduces the chances of brute force breaking of ++DES and has the advantage of if ++.I ks1 ++and ++.I ks2 ++are the same, it is equivalent to just encryption using cbc mode and ++.I ks1 ++as the key. ++.PP ++.I des_pcbc_encrypt ++encrypt/decrypts using a modified block chaining mode. ++It provides better error propagation characteristics than cbc ++encryption. ++.PP ++.I des_cfb_encrypt ++encrypt/decrypts using cipher feedback mode. This method takes an ++array of characters as input and outputs and array of characters. It ++does not require any padding to 8 character groups. Note: the ivec ++variable is changed and the new changed value needs to be passed to ++the next call to this function. Since this function runs a complete ++DES ecb encryption per numbits, this function is only suggested for ++use when sending small numbers of characters. ++.PP ++.I des_ofb_encrypt ++encrypt using output feedback mode. This method takes an ++array of characters as input and outputs and array of characters. It ++does not require any padding to 8 character groups. Note: the ivec ++variable is changed and the new changed value needs to be passed to ++the next call to this function. Since this function runs a complete ++DES ecb encryption per numbits, this function is only suggested for ++use when sending small numbers of characters. ++.PP ++.I des_cbc_cksum ++produces an 8 byte checksum based on the input stream (via cbc encryption). ++The last 4 bytes of the checksum is returned and the complete 8 bytes is ++placed in ++.I output. ++.PP ++.I des_quad_cksum ++returns a 4 byte checksum from the input bytes. ++The algorithm can be iterated over the input, ++depending on ++.I out_count, ++1, 2, 3 or 4 times. ++If ++.I output ++is non-NULL, ++the 8 bytes generated by each pass are written into ++.I output. ++.PP ++.I des_enc_write ++is used to write ++.I len ++bytes ++to file descriptor ++.I fd ++from buffer ++.I buf. ++The data is encrypted via ++.I pcbc_encrypt ++(default) using ++.I sched ++for the key and ++.I iv ++as a starting vector. ++The actual data send down ++.I fd ++consists of 4 bytes (in network byte order) containing the length of the ++following encrypted data. The encrypted data then follows, padded with random ++data out to a multiple of 8 bytes. ++.PP ++.I des_enc_read ++is used to read ++.I len ++bytes ++from file descriptor ++.I fd ++into buffer ++.I buf. ++The data being read from ++.I fd ++is assumed to have come from ++.I des_enc_write ++and is decrypted using ++.I sched ++for the key schedule and ++.I iv ++for the initial vector. ++The ++.I des_enc_read/des_enc_write ++pair can be used to read/write to files, pipes and sockets. ++I have used them in implementing a version of rlogin in which all ++data is encrypted. ++.PP ++.I des_rw_mode ++is used to specify the encryption mode to use with ++.I des_enc_read ++and ++.I des_end_write. ++If set to ++.I DES_PCBC_MODE ++(the default), des_pcbc_encrypt is used. ++If set to ++.I DES_CBC_MODE ++des_cbc_encrypt is used. ++These two routines and the variable are not part of the normal MIT library. ++.PP ++.I des_set_odd_parity ++sets the parity of the passed ++.I key ++to odd. This routine is not part of the standard MIT library. ++.PP ++.I des_is_weak_key ++returns 1 is the passed key is a weak key (pick again :-), ++0 if it is ok. ++This routine is not part of the standard MIT library. ++.PP ++.I crypt ++is a replacement for the normal system crypt. ++It is much faster than the system crypt. ++.PP ++.SH FILES ++/usr/include/des.h ++.br ++/usr/lib/libdes.a ++.PP ++The encryption routines have been tested on 16bit, 32bit and 64bit ++machines of various endian and even works under VMS. ++.PP ++.SH BUGS ++.PP ++If you think this manual is sparse, ++read the des_crypt(3) manual from the MIT kerberos (or bones outside ++of the USA) distribution. ++.PP ++.I des_cfb_encrypt ++and ++.I des_ofb_encrypt ++operates on input of 8 bits. What this means is that if you set ++numbits to 12, and length to 2, the first 12 bits will come from the 1st ++input byte and the low half of the second input byte. The second 12 ++bits will have the low 8 bits taken from the 3rd input byte and the ++top 4 bits taken from the 4th input byte. The same holds for output. ++This function has been implemented this way because most people will ++be using a multiple of 8 and because once you get into pulling bytes input ++bytes apart things get ugly! ++.PP ++.I des_read_pw_string ++is the most machine/OS dependent function and normally generates the ++most problems when porting this code. ++.PP ++.I des_string_to_key ++is probably different from the MIT version since there are lots ++of fun ways to implement one-way encryption of a text string. ++.PP ++The routines are optimised for 32 bit machines and so are not efficient ++on IBM PCs. ++.PP ++NOTE: extensive work has been done on this library since this document ++was origionally written. Please try to read des.doc from the libdes ++distribution since it is far more upto date and documents more of the ++functions. Libdes is now also being shipped as part of SSLeay, a ++general cryptographic library that amonst other things implements ++netscapes SSL protocoll. The most recent version can be found in ++SSLeay distributions. ++.SH AUTHOR ++Eric Young (eay@cryptsoft.com) +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/des_enc.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,502 @@ ++/* crypto/des/des_enc.c */ ++/* Copyright (C) 1995-1997 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 "des_locl.h" ++ ++void des_encrypt(data, ks, enc) ++DES_LONG *data; ++des_key_schedule ks; ++int enc; ++ { ++ register DES_LONG l,r,t,u; ++#ifdef DES_PTR ++ register unsigned char *des_SP=(unsigned char *)des_SPtrans; ++#endif ++#ifndef DES_UNROLL ++ register int i; ++#endif ++ register DES_LONG *s; ++ ++ r=data[0]; ++ l=data[1]; ++ ++ IP(r,l); ++ /* Things have been modified so that the initial rotate is ++ * done outside the loop. This required the ++ * des_SPtrans values in sp.h to be rotated 1 bit to the right. ++ * One perl script later and things have a 5% speed up on a sparc2. ++ * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> ++ * for pointing this out. */ ++ /* clear the top bits on machines with 8byte longs */ ++ /* shift left by 2 */ ++ r=ROTATE(r,29)&0xffffffffL; ++ l=ROTATE(l,29)&0xffffffffL; ++ ++ s=(DES_LONG *)ks; ++ /* I don't know if it is worth the effort of loop unrolling the ++ * inner loop */ ++ if (enc) ++ { ++#ifdef DES_UNROLL ++ D_ENCRYPT(l,r, 0); /* 1 */ ++ D_ENCRYPT(r,l, 2); /* 2 */ ++ D_ENCRYPT(l,r, 4); /* 3 */ ++ D_ENCRYPT(r,l, 6); /* 4 */ ++ D_ENCRYPT(l,r, 8); /* 5 */ ++ D_ENCRYPT(r,l,10); /* 6 */ ++ D_ENCRYPT(l,r,12); /* 7 */ ++ D_ENCRYPT(r,l,14); /* 8 */ ++ D_ENCRYPT(l,r,16); /* 9 */ ++ D_ENCRYPT(r,l,18); /* 10 */ ++ D_ENCRYPT(l,r,20); /* 11 */ ++ D_ENCRYPT(r,l,22); /* 12 */ ++ D_ENCRYPT(l,r,24); /* 13 */ ++ D_ENCRYPT(r,l,26); /* 14 */ ++ D_ENCRYPT(l,r,28); /* 15 */ ++ D_ENCRYPT(r,l,30); /* 16 */ ++#else ++ for (i=0; i<32; i+=8) ++ { ++ D_ENCRYPT(l,r,i+0); /* 1 */ ++ D_ENCRYPT(r,l,i+2); /* 2 */ ++ D_ENCRYPT(l,r,i+4); /* 3 */ ++ D_ENCRYPT(r,l,i+6); /* 4 */ ++ } ++#endif ++ } ++ else ++ { ++#ifdef DES_UNROLL ++ D_ENCRYPT(l,r,30); /* 16 */ ++ D_ENCRYPT(r,l,28); /* 15 */ ++ D_ENCRYPT(l,r,26); /* 14 */ ++ D_ENCRYPT(r,l,24); /* 13 */ ++ D_ENCRYPT(l,r,22); /* 12 */ ++ D_ENCRYPT(r,l,20); /* 11 */ ++ D_ENCRYPT(l,r,18); /* 10 */ ++ D_ENCRYPT(r,l,16); /* 9 */ ++ D_ENCRYPT(l,r,14); /* 8 */ ++ D_ENCRYPT(r,l,12); /* 7 */ ++ D_ENCRYPT(l,r,10); /* 6 */ ++ D_ENCRYPT(r,l, 8); /* 5 */ ++ D_ENCRYPT(l,r, 6); /* 4 */ ++ D_ENCRYPT(r,l, 4); /* 3 */ ++ D_ENCRYPT(l,r, 2); /* 2 */ ++ D_ENCRYPT(r,l, 0); /* 1 */ ++#else ++ for (i=30; i>0; i-=8) ++ { ++ D_ENCRYPT(l,r,i-0); /* 16 */ ++ D_ENCRYPT(r,l,i-2); /* 15 */ ++ D_ENCRYPT(l,r,i-4); /* 14 */ ++ D_ENCRYPT(r,l,i-6); /* 13 */ ++ } ++#endif ++ } ++ ++ /* rotate and clear the top bits on machines with 8byte longs */ ++ l=ROTATE(l,3)&0xffffffffL; ++ r=ROTATE(r,3)&0xffffffffL; ++ ++ FP(r,l); ++ data[0]=l; ++ data[1]=r; ++ l=r=t=u=0; ++ } ++ ++void des_encrypt2(data, ks, enc) ++DES_LONG *data; ++des_key_schedule ks; ++int enc; ++ { ++ register DES_LONG l,r,t,u; ++#ifdef DES_PTR ++ register unsigned char *des_SP=(unsigned char *)des_SPtrans; ++#endif ++#ifndef DES_UNROLL ++ register int i; ++#endif ++ register DES_LONG *s; ++ ++ r=data[0]; ++ l=data[1]; ++ ++ /* Things have been modified so that the initial rotate is ++ * done outside the loop. This required the ++ * des_SPtrans values in sp.h to be rotated 1 bit to the right. ++ * One perl script later and things have a 5% speed up on a sparc2. ++ * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> ++ * for pointing this out. */ ++ /* clear the top bits on machines with 8byte longs */ ++ r=ROTATE(r,29)&0xffffffffL; ++ l=ROTATE(l,29)&0xffffffffL; ++ ++ s=(DES_LONG *)ks; ++ /* I don't know if it is worth the effort of loop unrolling the ++ * inner loop */ ++ if (enc) ++ { ++#ifdef DES_UNROLL ++ D_ENCRYPT(l,r, 0); /* 1 */ ++ D_ENCRYPT(r,l, 2); /* 2 */ ++ D_ENCRYPT(l,r, 4); /* 3 */ ++ D_ENCRYPT(r,l, 6); /* 4 */ ++ D_ENCRYPT(l,r, 8); /* 5 */ ++ D_ENCRYPT(r,l,10); /* 6 */ ++ D_ENCRYPT(l,r,12); /* 7 */ ++ D_ENCRYPT(r,l,14); /* 8 */ ++ D_ENCRYPT(l,r,16); /* 9 */ ++ D_ENCRYPT(r,l,18); /* 10 */ ++ D_ENCRYPT(l,r,20); /* 11 */ ++ D_ENCRYPT(r,l,22); /* 12 */ ++ D_ENCRYPT(l,r,24); /* 13 */ ++ D_ENCRYPT(r,l,26); /* 14 */ ++ D_ENCRYPT(l,r,28); /* 15 */ ++ D_ENCRYPT(r,l,30); /* 16 */ ++#else ++ for (i=0; i<32; i+=8) ++ { ++ D_ENCRYPT(l,r,i+0); /* 1 */ ++ D_ENCRYPT(r,l,i+2); /* 2 */ ++ D_ENCRYPT(l,r,i+4); /* 3 */ ++ D_ENCRYPT(r,l,i+6); /* 4 */ ++ } ++#endif ++ } ++ else ++ { ++#ifdef DES_UNROLL ++ D_ENCRYPT(l,r,30); /* 16 */ ++ D_ENCRYPT(r,l,28); /* 15 */ ++ D_ENCRYPT(l,r,26); /* 14 */ ++ D_ENCRYPT(r,l,24); /* 13 */ ++ D_ENCRYPT(l,r,22); /* 12 */ ++ D_ENCRYPT(r,l,20); /* 11 */ ++ D_ENCRYPT(l,r,18); /* 10 */ ++ D_ENCRYPT(r,l,16); /* 9 */ ++ D_ENCRYPT(l,r,14); /* 8 */ ++ D_ENCRYPT(r,l,12); /* 7 */ ++ D_ENCRYPT(l,r,10); /* 6 */ ++ D_ENCRYPT(r,l, 8); /* 5 */ ++ D_ENCRYPT(l,r, 6); /* 4 */ ++ D_ENCRYPT(r,l, 4); /* 3 */ ++ D_ENCRYPT(l,r, 2); /* 2 */ ++ D_ENCRYPT(r,l, 0); /* 1 */ ++#else ++ for (i=30; i>0; i-=8) ++ { ++ D_ENCRYPT(l,r,i-0); /* 16 */ ++ D_ENCRYPT(r,l,i-2); /* 15 */ ++ D_ENCRYPT(l,r,i-4); /* 14 */ ++ D_ENCRYPT(r,l,i-6); /* 13 */ ++ } ++#endif ++ } ++ /* rotate and clear the top bits on machines with 8byte longs */ ++ data[0]=ROTATE(l,3)&0xffffffffL; ++ data[1]=ROTATE(r,3)&0xffffffffL; ++ l=r=t=u=0; ++ } ++ ++void des_encrypt3(data,ks1,ks2,ks3) ++DES_LONG *data; ++des_key_schedule ks1; ++des_key_schedule ks2; ++des_key_schedule ks3; ++ { ++ register DES_LONG l,r; ++ ++ l=data[0]; ++ r=data[1]; ++ IP(l,r); ++ data[0]=l; ++ data[1]=r; ++ des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT); ++ des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT); ++ des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT); ++ l=data[0]; ++ r=data[1]; ++ FP(r,l); ++ data[0]=l; ++ data[1]=r; ++ } ++ ++void des_decrypt3(data,ks1,ks2,ks3) ++DES_LONG *data; ++des_key_schedule ks1; ++des_key_schedule ks2; ++des_key_schedule ks3; ++ { ++ register DES_LONG l,r; ++ ++ l=data[0]; ++ r=data[1]; ++ IP(l,r); ++ data[0]=l; ++ data[1]=r; ++ des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT); ++ des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT); ++ des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT); ++ l=data[0]; ++ r=data[1]; ++ FP(r,l); ++ data[0]=l; ++ data[1]=r; ++ } ++ ++#ifndef DES_DEFAULT_OPTIONS ++ ++void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) ++des_cblock (*input); ++des_cblock (*output); ++long length; ++des_key_schedule schedule; ++des_cblock (*ivec); ++int enc; ++ { ++ register DES_LONG tin0,tin1; ++ register DES_LONG tout0,tout1,xor0,xor1; ++ register unsigned char *in,*out; ++ register long l=length; ++ DES_LONG tin[2]; ++ unsigned char *iv; ++ ++ in=(unsigned char *)input; ++ out=(unsigned char *)output; ++ iv=(unsigned char *)ivec; ++ ++ if (enc) ++ { ++ c2l(iv,tout0); ++ c2l(iv,tout1); ++ for (l-=8; l>=0; l-=8) ++ { ++ c2l(in,tin0); ++ c2l(in,tin1); ++ tin0^=tout0; tin[0]=tin0; ++ tin1^=tout1; tin[1]=tin1; ++ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); ++ tout0=tin[0]; l2c(tout0,out); ++ tout1=tin[1]; l2c(tout1,out); ++ } ++ if (l != -8) ++ { ++ c2ln(in,tin0,tin1,l+8); ++ tin0^=tout0; tin[0]=tin0; ++ tin1^=tout1; tin[1]=tin1; ++ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); ++ tout0=tin[0]; l2c(tout0,out); ++ tout1=tin[1]; l2c(tout1,out); ++ } ++ iv=(unsigned char *)ivec; ++ l2c(tout0,iv); ++ l2c(tout1,iv); ++ } ++ else ++ { ++ c2l(iv,xor0); ++ c2l(iv,xor1); ++ for (l-=8; l>=0; l-=8) ++ { ++ c2l(in,tin0); tin[0]=tin0; ++ c2l(in,tin1); tin[1]=tin1; ++ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); ++ tout0=tin[0]^xor0; ++ tout1=tin[1]^xor1; ++ l2c(tout0,out); ++ l2c(tout1,out); ++ xor0=tin0; ++ xor1=tin1; ++ } ++ if (l != -8) ++ { ++ c2l(in,tin0); tin[0]=tin0; ++ c2l(in,tin1); tin[1]=tin1; ++ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); ++ tout0=tin[0]^xor0; ++ tout1=tin[1]^xor1; ++ l2cn(tout0,tout1,out,l+8); ++ xor0=tin0; ++ xor1=tin1; ++ } ++ ++ iv=(unsigned char *)ivec; ++ l2c(xor0,iv); ++ l2c(xor1,iv); ++ } ++ tin0=tin1=tout0=tout1=xor0=xor1=0; ++ tin[0]=tin[1]=0; ++ } ++ ++void des_ede3_cbc_encrypt(input, output, length, ks1, ks2, ks3, ivec, enc) ++des_cblock (*input); ++des_cblock (*output); ++long length; ++des_key_schedule ks1; ++des_key_schedule ks2; ++des_key_schedule ks3; ++des_cblock (*ivec); ++int enc; ++ { ++ register DES_LONG tin0,tin1; ++ register DES_LONG tout0,tout1,xor0,xor1; ++ register unsigned char *in,*out; ++ register long l=length; ++ DES_LONG tin[2]; ++ unsigned char *iv; ++ ++ in=(unsigned char *)input; ++ out=(unsigned char *)output; ++ iv=(unsigned char *)ivec; ++ ++ if (enc) ++ { ++ c2l(iv,tout0); ++ c2l(iv,tout1); ++ for (l-=8; l>=0; l-=8) ++ { ++ c2l(in,tin0); ++ c2l(in,tin1); ++ tin0^=tout0; ++ tin1^=tout1; ++ ++ tin[0]=tin0; ++ tin[1]=tin1; ++ des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); ++ tout0=tin[0]; ++ tout1=tin[1]; ++ ++ l2c(tout0,out); ++ l2c(tout1,out); ++ } ++ if (l != -8) ++ { ++ c2ln(in,tin0,tin1,l+8); ++ tin0^=tout0; ++ tin1^=tout1; ++ ++ tin[0]=tin0; ++ tin[1]=tin1; ++ des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); ++ tout0=tin[0]; ++ tout1=tin[1]; ++ ++ l2c(tout0,out); ++ l2c(tout1,out); ++ } ++ iv=(unsigned char *)ivec; ++ l2c(tout0,iv); ++ l2c(tout1,iv); ++ } ++ else ++ { ++ register DES_LONG t0,t1; ++ ++ c2l(iv,xor0); ++ c2l(iv,xor1); ++ for (l-=8; l>=0; l-=8) ++ { ++ c2l(in,tin0); ++ c2l(in,tin1); ++ ++ t0=tin0; ++ t1=tin1; ++ ++ tin[0]=tin0; ++ tin[1]=tin1; ++ des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); ++ tout0=tin[0]; ++ tout1=tin[1]; ++ ++ tout0^=xor0; ++ tout1^=xor1; ++ l2c(tout0,out); ++ l2c(tout1,out); ++ xor0=t0; ++ xor1=t1; ++ } ++ if (l != -8) ++ { ++ c2l(in,tin0); ++ c2l(in,tin1); ++ ++ t0=tin0; ++ t1=tin1; ++ ++ tin[0]=tin0; ++ tin[1]=tin1; ++ des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); ++ tout0=tin[0]; ++ tout1=tin[1]; ++ ++ tout0^=xor0; ++ tout1^=xor1; ++ l2cn(tout0,tout1,out,l+8); ++ xor0=t0; ++ xor1=t1; ++ } ++ ++ iv=(unsigned char *)ivec; ++ l2c(xor0,iv); ++ l2c(xor1,iv); ++ } ++ tin0=tin1=tout0=tout1=xor0=xor1=0; ++ tin[0]=tin[1]=0; ++ } ++ ++#endif /* DES_DEFAULT_OPTIONS */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/des_locl.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,515 @@ ++/* crypto/des/des_locl.org */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ++ * ++ * Always modify des_locl.org since des_locl.h is automatically generated from ++ * it during SSLeay configuration. ++ * ++ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ++ */ ++ ++#ifndef HEADER_DES_LOCL_H ++#define HEADER_DES_LOCL_H ++ ++#if defined(WIN32) || defined(WIN16) ++#ifndef MSDOS ++#define MSDOS ++#endif ++#endif ++ ++#include "crypto/des.h" ++ ++#ifndef DES_DEFAULT_OPTIONS ++/* the following is tweaked from a config script, that is why it is a ++ * protected undef/define */ ++#ifndef DES_PTR ++#define DES_PTR ++#endif ++ ++/* This helps C compiler generate the correct code for multiple functional ++ * units. It reduces register dependancies at the expense of 2 more ++ * registers */ ++#ifndef DES_RISC1 ++#define DES_RISC1 ++#endif ++ ++#ifndef DES_RISC2 ++#undef DES_RISC2 ++#endif ++ ++#if defined(DES_RISC1) && defined(DES_RISC2) ++YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! ++#endif ++ ++/* Unroll the inner loop, this sometimes helps, sometimes hinders. ++ * Very mucy CPU dependant */ ++#ifndef DES_UNROLL ++#define DES_UNROLL ++#endif ++ ++/* These default values were supplied by ++ * Peter Gutman <pgut001@cs.auckland.ac.nz> ++ * They are only used if nothing else has been defined */ ++#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) ++/* Special defines which change the way the code is built depending on the ++ CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find ++ even newer MIPS CPU's, but at the moment one size fits all for ++ optimization options. Older Sparc's work better with only UNROLL, but ++ there's no way to tell at compile time what it is you're running on */ ++ ++#if defined( sun ) /* Newer Sparc's */ ++ #define DES_PTR ++ #define DES_RISC1 ++ #define DES_UNROLL ++#elif defined( __ultrix ) /* Older MIPS */ ++ #define DES_PTR ++ #define DES_RISC2 ++ #define DES_UNROLL ++#elif defined( __osf1__ ) /* Alpha */ ++ #define DES_PTR ++ #define DES_RISC2 ++#elif defined ( _AIX ) /* RS6000 */ ++ /* Unknown */ ++#elif defined( __hpux ) /* HP-PA */ ++ /* Unknown */ ++#elif defined( __aux ) /* 68K */ ++ /* Unknown */ ++#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ ++ #define DES_UNROLL ++#elif defined( __sgi ) /* Newer MIPS */ ++ #define DES_PTR ++ #define DES_RISC2 ++ #define DES_UNROLL ++#elif defined( i386 ) /* x86 boxes, should be gcc */ ++ #define DES_PTR ++ #define DES_RISC1 ++ #define DES_UNROLL ++#endif /* Systems-specific speed defines */ ++#endif ++ ++#endif /* DES_DEFAULT_OPTIONS */ ++ ++#ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ ++#include <stdlib.h> ++#include <errno.h> ++#include <time.h> ++#include <io.h> ++#ifndef RAND ++#define RAND ++#endif ++#undef NOPROTO ++#endif ++ ++#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) ++#ifndef __KERNEL__ ++#include <string.h> ++#else ++#include <linux/string.h> ++#endif ++#endif ++ ++#ifndef RAND ++#define RAND ++#endif ++ ++#ifdef linux ++#undef RAND ++#endif ++ ++#ifdef MSDOS ++#define getpid() 2 ++#define RAND ++#undef NOPROTO ++#endif ++ ++#if defined(NOCONST) ++#define const ++#endif ++ ++#ifdef __STDC__ ++#undef NOPROTO ++#endif ++ ++#ifdef RAND ++#define srandom(s) srand(s) ++#define random rand ++#endif ++ ++#define ITERATIONS 16 ++#define HALF_ITERATIONS 8 ++ ++/* used in des_read and des_write */ ++#define MAXWRITE (1024*16) ++#define BSIZE (MAXWRITE+4) ++ ++#define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ ++ l|=((DES_LONG)(*((c)++)))<< 8L, \ ++ l|=((DES_LONG)(*((c)++)))<<16L, \ ++ l|=((DES_LONG)(*((c)++)))<<24L) ++ ++/* NOTE - c is not incremented as per c2l */ ++#define c2ln(c,l1,l2,n) { \ ++ c+=n; \ ++ l1=l2=0; \ ++ switch (n) { \ ++ case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ ++ case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ ++ case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ ++ case 5: l2|=((DES_LONG)(*(--(c)))); \ ++ case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ ++ case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ ++ case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ ++ case 1: l1|=((DES_LONG)(*(--(c)))); \ ++ } \ ++ } ++ ++#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ ++ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>>24L)&0xff)) ++ ++/* replacements for htonl and ntohl since I have no idea what to do ++ * when faced with machines with 8 byte longs. */ ++#define HDRSIZE 4 ++ ++#define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ ++ l|=((DES_LONG)(*((c)++)))<<16L, \ ++ l|=((DES_LONG)(*((c)++)))<< 8L, \ ++ l|=((DES_LONG)(*((c)++)))) ++ ++#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ ++ *((c)++)=(unsigned char)(((l) )&0xff)) ++ ++/* NOTE - c is not incremented as per l2c */ ++#define l2cn(l1,l2,c,n) { \ ++ c+=n; \ ++ switch (n) { \ ++ case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ ++ case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ ++ case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ ++ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ ++ case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ ++ case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ ++ case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ ++ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ ++ } \ ++ } ++ ++#if defined(WIN32) ++#define ROTATE(a,n) (_lrotr(a,n)) ++#else ++#define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) ++#endif ++ ++/* Don't worry about the LOAD_DATA() stuff, that is used by ++ * fcrypt() to add it's little bit to the front */ ++ ++#ifdef DES_FCRYPT ++ ++#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \ ++ { DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); } ++ ++#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ ++ t=R^(R>>16L); \ ++ u=t&E0; t&=E1; \ ++ tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ ++ tmp=(t<<16); t^=R^s[S+1]; t^=tmp ++#else ++#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) ++#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ ++ u=R^s[S ]; \ ++ t=R^s[S+1] ++#endif ++ ++/* The changes to this macro may help or hinder, depending on the ++ * compiler and the achitecture. gcc2 always seems to do well :-). ++ * Inspired by Dana How <how@isl.stanford.edu> ++ * DO NOT use the alternative version on machines with 8 byte longs. ++ * It does not seem to work on the Alpha, even when DES_LONG is 4 ++ * bytes, probably an issue of accessing non-word aligned objects :-( */ ++#ifdef DES_PTR ++ ++/* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there ++ * is no reason to not xor all the sub items together. This potentially ++ * saves a register since things can be xored directly into L */ ++ ++#if defined(DES_RISC1) || defined(DES_RISC2) ++#ifdef DES_RISC1 ++#define D_ENCRYPT(LL,R,S) { \ ++ unsigned int u1,u2,u3; \ ++ LOAD_DATA(R,S,u,t,E0,E1,u1); \ ++ u2=(int)u>>8L; \ ++ u1=(int)u&0xfc; \ ++ u2&=0xfc; \ ++ t=ROTATE(t,4); \ ++ u>>=16L; \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ ++ u3=(int)(u>>8L); \ ++ u1=(int)u&0xfc; \ ++ u3&=0xfc; \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+u1); \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+u3); \ ++ u2=(int)t>>8L; \ ++ u1=(int)t&0xfc; \ ++ u2&=0xfc; \ ++ t>>=16L; \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ ++ u3=(int)t>>8L; \ ++ u1=(int)t&0xfc; \ ++ u3&=0xfc; \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+u1); \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+u3); } ++#endif ++#ifdef DES_RISC2 ++#define D_ENCRYPT(LL,R,S) { \ ++ unsigned int u1,u2,s1,s2; \ ++ LOAD_DATA(R,S,u,t,E0,E1,u1); \ ++ u2=(int)u>>8L; \ ++ u1=(int)u&0xfc; \ ++ u2&=0xfc; \ ++ t=ROTATE(t,4); \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ ++ s1=(int)(u>>16L); \ ++ s2=(int)(u>>24L); \ ++ s1&=0xfc; \ ++ s2&=0xfc; \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+s1); \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+s2); \ ++ u2=(int)t>>8L; \ ++ u1=(int)t&0xfc; \ ++ u2&=0xfc; \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ ++ s1=(int)(t>>16L); \ ++ s2=(int)(t>>24L); \ ++ s1&=0xfc; \ ++ s2&=0xfc; \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+s1); \ ++ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+s2); } ++#endif ++#else ++#define D_ENCRYPT(LL,R,S) { \ ++ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ ++ t=ROTATE(t,4); \ ++ LL^= \ ++ *(DES_LONG *)((unsigned char *)des_SP +((u )&0xfc))^ \ ++ *(DES_LONG *)((unsigned char *)des_SP+0x200+((u>> 8L)&0xfc))^ \ ++ *(DES_LONG *)((unsigned char *)des_SP+0x400+((u>>16L)&0xfc))^ \ ++ *(DES_LONG *)((unsigned char *)des_SP+0x600+((u>>24L)&0xfc))^ \ ++ *(DES_LONG *)((unsigned char *)des_SP+0x100+((t )&0xfc))^ \ ++ *(DES_LONG *)((unsigned char *)des_SP+0x300+((t>> 8L)&0xfc))^ \ ++ *(DES_LONG *)((unsigned char *)des_SP+0x500+((t>>16L)&0xfc))^ \ ++ *(DES_LONG *)((unsigned char *)des_SP+0x700+((t>>24L)&0xfc)); } ++#endif ++ ++#else /* original version */ ++ ++#if defined(DES_RISC1) || defined(DES_RISC2) ++#ifdef DES_RISC1 ++#define D_ENCRYPT(LL,R,S) {\ ++ unsigned int u1,u2,u3; \ ++ LOAD_DATA(R,S,u,t,E0,E1,u1); \ ++ u>>=2L; \ ++ t=ROTATE(t,6); \ ++ u2=(int)u>>8L; \ ++ u1=(int)u&0x3f; \ ++ u2&=0x3f; \ ++ u>>=16L; \ ++ LL^=des_SPtrans[0][u1]; \ ++ LL^=des_SPtrans[2][u2]; \ ++ u3=(int)u>>8L; \ ++ u1=(int)u&0x3f; \ ++ u3&=0x3f; \ ++ LL^=des_SPtrans[4][u1]; \ ++ LL^=des_SPtrans[6][u3]; \ ++ u2=(int)t>>8L; \ ++ u1=(int)t&0x3f; \ ++ u2&=0x3f; \ ++ t>>=16L; \ ++ LL^=des_SPtrans[1][u1]; \ ++ LL^=des_SPtrans[3][u2]; \ ++ u3=(int)t>>8L; \ ++ u1=(int)t&0x3f; \ ++ u3&=0x3f; \ ++ LL^=des_SPtrans[5][u1]; \ ++ LL^=des_SPtrans[7][u3]; } ++#endif ++#ifdef DES_RISC2 ++#define D_ENCRYPT(LL,R,S) {\ ++ unsigned int u1,u2,s1,s2; \ ++ LOAD_DATA(R,S,u,t,E0,E1,u1); \ ++ u>>=2L; \ ++ t=ROTATE(t,6); \ ++ u2=(int)u>>8L; \ ++ u1=(int)u&0x3f; \ ++ u2&=0x3f; \ ++ LL^=des_SPtrans[0][u1]; \ ++ LL^=des_SPtrans[2][u2]; \ ++ s1=(int)u>>16L; \ ++ s2=(int)u>>24L; \ ++ s1&=0x3f; \ ++ s2&=0x3f; \ ++ LL^=des_SPtrans[4][s1]; \ ++ LL^=des_SPtrans[6][s2]; \ ++ u2=(int)t>>8L; \ ++ u1=(int)t&0x3f; \ ++ u2&=0x3f; \ ++ LL^=des_SPtrans[1][u1]; \ ++ LL^=des_SPtrans[3][u2]; \ ++ s1=(int)t>>16; \ ++ s2=(int)t>>24L; \ ++ s1&=0x3f; \ ++ s2&=0x3f; \ ++ LL^=des_SPtrans[5][s1]; \ ++ LL^=des_SPtrans[7][s2]; } ++#endif ++ ++#else ++ ++#define D_ENCRYPT(LL,R,S) {\ ++ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ ++ t=ROTATE(t,4); \ ++ LL^=\ ++ des_SPtrans[0][(u>> 2L)&0x3f]^ \ ++ des_SPtrans[2][(u>>10L)&0x3f]^ \ ++ des_SPtrans[4][(u>>18L)&0x3f]^ \ ++ des_SPtrans[6][(u>>26L)&0x3f]^ \ ++ des_SPtrans[1][(t>> 2L)&0x3f]^ \ ++ des_SPtrans[3][(t>>10L)&0x3f]^ \ ++ des_SPtrans[5][(t>>18L)&0x3f]^ \ ++ des_SPtrans[7][(t>>26L)&0x3f]; } ++#endif ++#endif ++ ++ /* IP and FP ++ * The problem is more of a geometric problem that random bit fiddling. ++ 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 ++ 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 ++ 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 ++ 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 ++ ++ 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 ++ 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 ++ 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 ++ 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 ++ ++ The output has been subject to swaps of the form ++ 0 1 -> 3 1 but the odd and even bits have been put into ++ 2 3 2 0 ++ different words. The main trick is to remember that ++ t=((l>>size)^r)&(mask); ++ r^=t; ++ l^=(t<<size); ++ can be used to swap and move bits between words. ++ ++ So l = 0 1 2 3 r = 16 17 18 19 ++ 4 5 6 7 20 21 22 23 ++ 8 9 10 11 24 25 26 27 ++ 12 13 14 15 28 29 30 31 ++ becomes (for size == 2 and mask == 0x3333) ++ t = 2^16 3^17 -- -- l = 0 1 16 17 r = 2 3 18 19 ++ 6^20 7^21 -- -- 4 5 20 21 6 7 22 23 ++ 10^24 11^25 -- -- 8 9 24 25 10 11 24 25 ++ 14^28 15^29 -- -- 12 13 28 29 14 15 28 29 ++ ++ Thanks for hints from Richard Outerbridge - he told me IP&FP ++ could be done in 15 xor, 10 shifts and 5 ands. ++ When I finally started to think of the problem in 2D ++ I first got ~42 operations without xors. When I remembered ++ how to use xors :-) I got it to its final state. ++ */ ++#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ ++ (b)^=(t),\ ++ (a)^=((t)<<(n))) ++ ++#define IP(l,r) \ ++ { \ ++ register DES_LONG tt; \ ++ PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ ++ PERM_OP(l,r,tt,16,0x0000ffffL); \ ++ PERM_OP(r,l,tt, 2,0x33333333L); \ ++ PERM_OP(l,r,tt, 8,0x00ff00ffL); \ ++ PERM_OP(r,l,tt, 1,0x55555555L); \ ++ } ++ ++#define FP(l,r) \ ++ { \ ++ register DES_LONG tt; \ ++ PERM_OP(l,r,tt, 1,0x55555555L); \ ++ PERM_OP(r,l,tt, 8,0x00ff00ffL); \ ++ PERM_OP(l,r,tt, 2,0x33333333L); \ ++ PERM_OP(r,l,tt,16,0x0000ffffL); \ ++ PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ ++ } ++ ++extern const DES_LONG des_SPtrans[8][64]; ++ ++#ifndef NOPROTO ++void fcrypt_body(DES_LONG *out,des_key_schedule ks, ++ DES_LONG Eswap0, DES_LONG Eswap1); ++#else ++void fcrypt_body(); ++#endif ++ ++#endif +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/des_opts.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,620 @@ ++/* crypto/des/des_opts.c */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++/* define PART1, PART2, PART3 or PART4 to build only with a few of the options. ++ * This is for machines with 64k code segment size restrictions. */ ++ ++#ifndef MSDOS ++#define TIMES ++#endif ++ ++#include <stdio.h> ++#ifndef MSDOS ++#include <unistd.h> ++#else ++#include <io.h> ++extern void exit(); ++#endif ++#include <signal.h> ++#ifndef VMS ++#ifndef _IRIX ++#include <time.h> ++#endif ++#ifdef TIMES ++#include <sys/types.h> ++#include <sys/times.h> ++#endif ++#else /* VMS */ ++#include <types.h> ++struct tms { ++ time_t tms_utime; ++ time_t tms_stime; ++ time_t tms_uchild; /* I dunno... */ ++ time_t tms_uchildsys; /* so these names are a guess :-) */ ++ } ++#endif ++#ifndef TIMES ++#include <sys/timeb.h> ++#endif ++ ++#ifdef sun ++#include <limits.h> ++#include <sys/param.h> ++#endif ++ ++#include "des_locl.h" ++#include "spr.h" ++ ++#define DES_DEFAULT_OPTIONS ++ ++#if !defined(PART1) && !defined(PART2) && !defined(PART3) && !defined(PART4) ++#define PART1 ++#define PART2 ++#define PART3 ++#define PART4 ++#endif ++ ++#ifdef PART1 ++ ++#undef DES_UNROLL ++#undef DES_RISC1 ++#undef DES_RISC2 ++#undef DES_PTR ++#undef D_ENCRYPT ++#define des_encrypt des_encrypt_u4_cisc_idx ++#define des_encrypt2 des_encrypt2_u4_cisc_idx ++#define des_encrypt3 des_encrypt3_u4_cisc_idx ++#define des_decrypt3 des_decrypt3_u4_cisc_idx ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#define DES_UNROLL ++#undef DES_RISC1 ++#undef DES_RISC2 ++#undef DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u16_cisc_idx ++#define des_encrypt2 des_encrypt2_u16_cisc_idx ++#define des_encrypt3 des_encrypt3_u16_cisc_idx ++#define des_decrypt3 des_decrypt3_u16_cisc_idx ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#undef DES_UNROLL ++#define DES_RISC1 ++#undef DES_RISC2 ++#undef DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u4_risc1_idx ++#define des_encrypt2 des_encrypt2_u4_risc1_idx ++#define des_encrypt3 des_encrypt3_u4_risc1_idx ++#define des_decrypt3 des_decrypt3_u4_risc1_idx ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#endif ++ ++#ifdef PART2 ++ ++#undef DES_UNROLL ++#undef DES_RISC1 ++#define DES_RISC2 ++#undef DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u4_risc2_idx ++#define des_encrypt2 des_encrypt2_u4_risc2_idx ++#define des_encrypt3 des_encrypt3_u4_risc2_idx ++#define des_decrypt3 des_decrypt3_u4_risc2_idx ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#define DES_UNROLL ++#define DES_RISC1 ++#undef DES_RISC2 ++#undef DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u16_risc1_idx ++#define des_encrypt2 des_encrypt2_u16_risc1_idx ++#define des_encrypt3 des_encrypt3_u16_risc1_idx ++#define des_decrypt3 des_decrypt3_u16_risc1_idx ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#define DES_UNROLL ++#undef DES_RISC1 ++#define DES_RISC2 ++#undef DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u16_risc2_idx ++#define des_encrypt2 des_encrypt2_u16_risc2_idx ++#define des_encrypt3 des_encrypt3_u16_risc2_idx ++#define des_decrypt3 des_decrypt3_u16_risc2_idx ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#endif ++ ++#ifdef PART3 ++ ++#undef DES_UNROLL ++#undef DES_RISC1 ++#undef DES_RISC2 ++#define DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u4_cisc_ptr ++#define des_encrypt2 des_encrypt2_u4_cisc_ptr ++#define des_encrypt3 des_encrypt3_u4_cisc_ptr ++#define des_decrypt3 des_decrypt3_u4_cisc_ptr ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#define DES_UNROLL ++#undef DES_RISC1 ++#undef DES_RISC2 ++#define DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u16_cisc_ptr ++#define des_encrypt2 des_encrypt2_u16_cisc_ptr ++#define des_encrypt3 des_encrypt3_u16_cisc_ptr ++#define des_decrypt3 des_decrypt3_u16_cisc_ptr ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#undef DES_UNROLL ++#define DES_RISC1 ++#undef DES_RISC2 ++#define DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u4_risc1_ptr ++#define des_encrypt2 des_encrypt2_u4_risc1_ptr ++#define des_encrypt3 des_encrypt3_u4_risc1_ptr ++#define des_decrypt3 des_decrypt3_u4_risc1_ptr ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#endif ++ ++#ifdef PART4 ++ ++#undef DES_UNROLL ++#undef DES_RISC1 ++#define DES_RISC2 ++#define DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u4_risc2_ptr ++#define des_encrypt2 des_encrypt2_u4_risc2_ptr ++#define des_encrypt3 des_encrypt3_u4_risc2_ptr ++#define des_decrypt3 des_decrypt3_u4_risc2_ptr ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#define DES_UNROLL ++#define DES_RISC1 ++#undef DES_RISC2 ++#define DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u16_risc1_ptr ++#define des_encrypt2 des_encrypt2_u16_risc1_ptr ++#define des_encrypt3 des_encrypt3_u16_risc1_ptr ++#define des_decrypt3 des_decrypt3_u16_risc1_ptr ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#define DES_UNROLL ++#undef DES_RISC1 ++#define DES_RISC2 ++#define DES_PTR ++#undef D_ENCRYPT ++#undef des_encrypt ++#undef des_encrypt2 ++#undef des_encrypt3 ++#undef des_decrypt3 ++#define des_encrypt des_encrypt_u16_risc2_ptr ++#define des_encrypt2 des_encrypt2_u16_risc2_ptr ++#define des_encrypt3 des_encrypt3_u16_risc2_ptr ++#define des_decrypt3 des_decrypt3_u16_risc2_ptr ++#undef HEADER_DES_LOCL_H ++#include "des_enc.c" ++ ++#endif ++ ++/* The following if from times(3) man page. It may need to be changed */ ++#ifndef HZ ++# ifndef CLK_TCK ++# ifndef _BSD_CLK_TCK_ /* FreeBSD fix */ ++# ifndef VMS ++# define HZ 100.0 ++# else /* VMS */ ++# define HZ 100.0 ++# endif ++# else /* _BSD_CLK_TCK_ */ ++# define HZ ((double)_BSD_CLK_TCK_) ++# endif ++# else /* CLK_TCK */ ++# define HZ ((double)CLK_TCK) ++# endif ++#endif ++ ++#define BUFSIZE ((long)1024) ++long run=0; ++ ++#ifndef NOPROTO ++double Time_F(int s); ++#else ++double Time_F(); ++#endif ++ ++#ifdef SIGALRM ++#if defined(__STDC__) || defined(sgi) ++#define SIGRETTYPE void ++#else ++#define SIGRETTYPE int ++#endif ++ ++#ifndef NOPROTO ++SIGRETTYPE sig_done(int sig); ++#else ++SIGRETTYPE sig_done(); ++#endif ++ ++SIGRETTYPE sig_done(sig) ++int sig; ++ { ++ signal(SIGALRM,sig_done); ++ run=0; ++#ifdef LINT ++ sig=sig; ++#endif ++ } ++#endif ++ ++#define START 0 ++#define STOP 1 ++ ++double Time_F(s) ++int s; ++ { ++ double ret; ++#ifdef TIMES ++ static struct tms tstart,tend; ++ ++ if (s == START) ++ { ++ times(&tstart); ++ return(0); ++ } ++ else ++ { ++ times(&tend); ++ ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; ++ return((ret == 0.0)?1e-6:ret); ++ } ++#else /* !times() */ ++ static struct timeb tstart,tend; ++ long i; ++ ++ if (s == START) ++ { ++ ftime(&tstart); ++ return(0); ++ } ++ else ++ { ++ ftime(&tend); ++ i=(long)tend.millitm-(long)tstart.millitm; ++ ret=((double)(tend.time-tstart.time))+((double)i)/1000.0; ++ return((ret == 0.0)?1e-6:ret); ++ } ++#endif ++ } ++ ++#ifdef SIGALRM ++#define print_name(name) fprintf(stderr,"Doing %s's for 10 seconds\n",name); alarm(10); ++#else ++#define print_name(name) fprintf(stderr,"Doing %s %ld times\n",name,cb); ++#endif ++ ++#define time_it(func,name,index) \ ++ print_name(name); \ ++ Time_F(START); \ ++ for (count=0,run=1; COND(cb); count++) \ ++ { \ ++ unsigned long d[2]; \ ++ func(d,&(sch[0]),DES_ENCRYPT); \ ++ } \ ++ tm[index]=Time_F(STOP); \ ++ fprintf(stderr,"%ld %s's in %.2f second\n",count,name,tm[index]); \ ++ tm[index]=((double)COUNT(cb))/tm[index]; ++ ++#define print_it(name,index) \ ++ fprintf(stderr,"%s bytes per sec = %12.2f (%5.1fuS)\n",name, \ ++ tm[index]*8,1.0e6/tm[index]); ++ ++int main(argc,argv) ++int argc; ++char **argv; ++ { ++ long count; ++ static unsigned char buf[BUFSIZE]; ++ static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}; ++ static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12}; ++ static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34}; ++ des_key_schedule sch,sch2,sch3; ++ double d,tm[16],max=0; ++ int rank[16]; ++ char *str[16]; ++ int max_idx=0,i,num=0,j; ++#ifndef SIGALARM ++ long ca,cb,cc,cd,ce; ++#endif ++ ++ for (i=0; i<12; i++) ++ { ++ tm[i]=0.0; ++ rank[i]=0; ++ } ++ ++#ifndef TIMES ++ fprintf(stderr,"To get the most acurate results, try to run this\n"); ++ fprintf(stderr,"program when this computer is idle.\n"); ++#endif ++ ++ des_set_key((C_Block *)key,sch); ++ des_set_key((C_Block *)key2,sch2); ++ des_set_key((C_Block *)key3,sch3); ++ ++#ifndef SIGALRM ++ fprintf(stderr,"First we calculate the approximate speed ...\n"); ++ des_set_key((C_Block *)key,sch); ++ count=10; ++ do { ++ long i; ++ unsigned long data[2]; ++ ++ count*=2; ++ Time_F(START); ++ for (i=count; i; i--) ++ des_encrypt(data,&(sch[0]),DES_ENCRYPT); ++ d=Time_F(STOP); ++ } while (d < 3.0); ++ ca=count; ++ cb=count*3; ++ cc=count*3*8/BUFSIZE+1; ++ cd=count*8/BUFSIZE+1; ++ ++ ce=count/20+1; ++#define COND(d) (count != (d)) ++#define COUNT(d) (d) ++#else ++#define COND(c) (run) ++#define COUNT(d) (count) ++ signal(SIGALRM,sig_done); ++ alarm(10); ++#endif ++ ++#ifdef PART1 ++ time_it(des_encrypt_u4_cisc_idx, "des_encrypt_u4_cisc_idx ", 0); ++ time_it(des_encrypt_u16_cisc_idx, "des_encrypt_u16_cisc_idx ", 1); ++ time_it(des_encrypt_u4_risc1_idx, "des_encrypt_u4_risc1_idx ", 2); ++ num+=3; ++#endif ++#ifdef PART2 ++ time_it(des_encrypt_u16_risc1_idx,"des_encrypt_u16_risc1_idx", 3); ++ time_it(des_encrypt_u4_risc2_idx, "des_encrypt_u4_risc2_idx ", 4); ++ time_it(des_encrypt_u16_risc2_idx,"des_encrypt_u16_risc2_idx", 5); ++ num+=3; ++#endif ++#ifdef PART3 ++ time_it(des_encrypt_u4_cisc_ptr, "des_encrypt_u4_cisc_ptr ", 6); ++ time_it(des_encrypt_u16_cisc_ptr, "des_encrypt_u16_cisc_ptr ", 7); ++ time_it(des_encrypt_u4_risc1_ptr, "des_encrypt_u4_risc1_ptr ", 8); ++ num+=3; ++#endif ++#ifdef PART4 ++ time_it(des_encrypt_u16_risc1_ptr,"des_encrypt_u16_risc1_ptr", 9); ++ time_it(des_encrypt_u4_risc2_ptr, "des_encrypt_u4_risc2_ptr ",10); ++ time_it(des_encrypt_u16_risc2_ptr,"des_encrypt_u16_risc2_ptr",11); ++ num+=3; ++#endif ++ ++#ifdef PART1 ++ str[0]=" 4 c i"; ++ print_it("des_encrypt_u4_cisc_idx ",0); ++ max=tm[0]; ++ max_idx=0; ++ str[1]="16 c i"; ++ print_it("des_encrypt_u16_cisc_idx ",1); ++ if (max < tm[1]) { max=tm[1]; max_idx=1; } ++ str[2]=" 4 r1 i"; ++ print_it("des_encrypt_u4_risc1_idx ",2); ++ if (max < tm[2]) { max=tm[2]; max_idx=2; } ++#endif ++#ifdef PART2 ++ str[3]="16 r1 i"; ++ print_it("des_encrypt_u16_risc1_idx",3); ++ if (max < tm[3]) { max=tm[3]; max_idx=3; } ++ str[4]=" 4 r2 i"; ++ print_it("des_encrypt_u4_risc2_idx ",4); ++ if (max < tm[4]) { max=tm[4]; max_idx=4; } ++ str[5]="16 r2 i"; ++ print_it("des_encrypt_u16_risc2_idx",5); ++ if (max < tm[5]) { max=tm[5]; max_idx=5; } ++#endif ++#ifdef PART3 ++ str[6]=" 4 c p"; ++ print_it("des_encrypt_u4_cisc_ptr ",6); ++ if (max < tm[6]) { max=tm[6]; max_idx=6; } ++ str[7]="16 c p"; ++ print_it("des_encrypt_u16_cisc_ptr ",7); ++ if (max < tm[7]) { max=tm[7]; max_idx=7; } ++ str[8]=" 4 r1 p"; ++ print_it("des_encrypt_u4_risc1_ptr ",8); ++ if (max < tm[8]) { max=tm[8]; max_idx=8; } ++#endif ++#ifdef PART4 ++ str[9]="16 r1 p"; ++ print_it("des_encrypt_u16_risc1_ptr",9); ++ if (max < tm[9]) { max=tm[9]; max_idx=9; } ++ str[10]=" 4 r2 p"; ++ print_it("des_encrypt_u4_risc2_ptr ",10); ++ if (max < tm[10]) { max=tm[10]; max_idx=10; } ++ str[11]="16 r2 p"; ++ print_it("des_encrypt_u16_risc2_ptr",11); ++ if (max < tm[11]) { max=tm[11]; max_idx=11; } ++#endif ++ printf("options des ecb/s\n"); ++ printf("%s %12.2f 100.0%%\n",str[max_idx],tm[max_idx]); ++ d=tm[max_idx]; ++ tm[max_idx]= -2.0; ++ max= -1.0; ++ for (;;) ++ { ++ for (i=0; i<12; i++) ++ { ++ if (max < tm[i]) { max=tm[i]; j=i; } ++ } ++ if (max < 0.0) break; ++ printf("%s %12.2f %4.1f%%\n",str[j],tm[j],tm[j]/d*100.0); ++ tm[j]= -2.0; ++ max= -1.0; ++ } ++ ++ switch (max_idx) ++ { ++ case 0: ++ printf("-DDES_DEFAULT_OPTIONS\n"); ++ break; ++ case 1: ++ printf("-DDES_UNROLL\n"); ++ break; ++ case 2: ++ printf("-DDES_RISC1\n"); ++ break; ++ case 3: ++ printf("-DDES_UNROLL -DDES_RISC1\n"); ++ break; ++ case 4: ++ printf("-DDES_RISC2\n"); ++ break; ++ case 5: ++ printf("-DDES_UNROLL -DDES_RISC2\n"); ++ break; ++ case 6: ++ printf("-DDES_PTR\n"); ++ break; ++ case 7: ++ printf("-DDES_UNROLL -DDES_PTR\n"); ++ break; ++ case 8: ++ printf("-DDES_RISC1 -DDES_PTR\n"); ++ break; ++ case 9: ++ printf("-DDES_UNROLL -DDES_RISC1 -DDES_PTR\n"); ++ break; ++ case 10: ++ printf("-DDES_RISC2 -DDES_PTR\n"); ++ break; ++ case 11: ++ printf("-DDES_UNROLL -DDES_RISC2 -DDES_PTR\n"); ++ break; ++ } ++ exit(0); ++#if defined(LINT) || defined(MSDOS) ++ return(0); ++#endif ++ } +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/des_ver.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,60 @@ ++/* crypto/des/des_ver.h */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++extern char *DES_version; /* SSLeay version string */ ++extern char *libdes_version; /* old libdes version string */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/destest.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,871 @@ ++/* crypto/des/destest.c */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++#if defined(WIN32) || defined(WIN16) || defined(WINDOWS) ++#ifndef MSDOS ++#define MSDOS ++#endif ++#endif ++ ++#include <stdio.h> ++#include <stdlib.h> ++#ifndef MSDOS ++#include <unistd.h> ++#else ++#include <io.h> ++#endif ++#include <string.h> ++#include "des_locl.h" ++ ++/* tisk tisk - the test keys don't all have odd parity :-( */ ++/* test data */ ++#define NUM_TESTS 34 ++static unsigned char key_data[NUM_TESTS][8]={ ++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, ++ {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, ++ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, ++ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, ++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++ {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}, ++ {0x7C,0xA1,0x10,0x45,0x4A,0x1A,0x6E,0x57}, ++ {0x01,0x31,0xD9,0x61,0x9D,0xC1,0x37,0x6E}, ++ {0x07,0xA1,0x13,0x3E,0x4A,0x0B,0x26,0x86}, ++ {0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E}, ++ {0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6}, ++ {0x01,0x13,0xB9,0x70,0xFD,0x34,0xF2,0xCE}, ++ {0x01,0x70,0xF1,0x75,0x46,0x8F,0xB5,0xE6}, ++ {0x43,0x29,0x7F,0xAD,0x38,0xE3,0x73,0xFE}, ++ {0x07,0xA7,0x13,0x70,0x45,0xDA,0x2A,0x16}, ++ {0x04,0x68,0x91,0x04,0xC2,0xFD,0x3B,0x2F}, ++ {0x37,0xD0,0x6B,0xB5,0x16,0xCB,0x75,0x46}, ++ {0x1F,0x08,0x26,0x0D,0x1A,0xC2,0x46,0x5E}, ++ {0x58,0x40,0x23,0x64,0x1A,0xBA,0x61,0x76}, ++ {0x02,0x58,0x16,0x16,0x46,0x29,0xB0,0x07}, ++ {0x49,0x79,0x3E,0xBC,0x79,0xB3,0x25,0x8F}, ++ {0x4F,0xB0,0x5E,0x15,0x15,0xAB,0x73,0xA7}, ++ {0x49,0xE9,0x5D,0x6D,0x4C,0xA2,0x29,0xBF}, ++ {0x01,0x83,0x10,0xDC,0x40,0x9B,0x26,0xD6}, ++ {0x1C,0x58,0x7F,0x1C,0x13,0x92,0x4F,0xEF}, ++ {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, ++ {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E}, ++ {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE}, ++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, ++ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, ++ {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}}; ++ ++static unsigned char plain_data[NUM_TESTS][8]={ ++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, ++ {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, ++ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, ++ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, ++ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, ++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, ++ {0x01,0xA1,0xD6,0xD0,0x39,0x77,0x67,0x42}, ++ {0x5C,0xD5,0x4C,0xA8,0x3D,0xEF,0x57,0xDA}, ++ {0x02,0x48,0xD4,0x38,0x06,0xF6,0x71,0x72}, ++ {0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A}, ++ {0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2}, ++ {0x05,0x9B,0x5E,0x08,0x51,0xCF,0x14,0x3A}, ++ {0x07,0x56,0xD8,0xE0,0x77,0x47,0x61,0xD2}, ++ {0x76,0x25,0x14,0xB8,0x29,0xBF,0x48,0x6A}, ++ {0x3B,0xDD,0x11,0x90,0x49,0x37,0x28,0x02}, ++ {0x26,0x95,0x5F,0x68,0x35,0xAF,0x60,0x9A}, ++ {0x16,0x4D,0x5E,0x40,0x4F,0x27,0x52,0x32}, ++ {0x6B,0x05,0x6E,0x18,0x75,0x9F,0x5C,0xCA}, ++ {0x00,0x4B,0xD6,0xEF,0x09,0x17,0x60,0x62}, ++ {0x48,0x0D,0x39,0x00,0x6E,0xE7,0x62,0xF2}, ++ {0x43,0x75,0x40,0xC8,0x69,0x8F,0x3C,0xFA}, ++ {0x07,0x2D,0x43,0xA0,0x77,0x07,0x52,0x92}, ++ {0x02,0xFE,0x55,0x77,0x81,0x17,0xF1,0x2A}, ++ {0x1D,0x9D,0x5C,0x50,0x18,0xF7,0x28,0xC2}, ++ {0x30,0x55,0x32,0x28,0x6D,0x6F,0x29,0x5A}, ++ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, ++ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, ++ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, ++ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, ++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}; ++ ++static unsigned char cipher_data[NUM_TESTS][8]={ ++ {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, ++ {0x73,0x59,0xB2,0x16,0x3E,0x4E,0xDC,0x58}, ++ {0x95,0x8E,0x6E,0x62,0x7A,0x05,0x55,0x7B}, ++ {0xF4,0x03,0x79,0xAB,0x9E,0x0E,0xC5,0x33}, ++ {0x17,0x66,0x8D,0xFC,0x72,0x92,0x53,0x2D}, ++ {0x8A,0x5A,0xE1,0xF8,0x1A,0xB8,0xF2,0xDD}, ++ {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, ++ {0xED,0x39,0xD9,0x50,0xFA,0x74,0xBC,0xC4}, ++ {0x69,0x0F,0x5B,0x0D,0x9A,0x26,0x93,0x9B}, ++ {0x7A,0x38,0x9D,0x10,0x35,0x4B,0xD2,0x71}, ++ {0x86,0x8E,0xBB,0x51,0xCA,0xB4,0x59,0x9A}, ++ {0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A}, ++ {0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95}, ++ {0x86,0xA5,0x60,0xF1,0x0E,0xC6,0xD8,0x5B}, ++ {0x0C,0xD3,0xDA,0x02,0x00,0x21,0xDC,0x09}, ++ {0xEA,0x67,0x6B,0x2C,0xB7,0xDB,0x2B,0x7A}, ++ {0xDF,0xD6,0x4A,0x81,0x5C,0xAF,0x1A,0x0F}, ++ {0x5C,0x51,0x3C,0x9C,0x48,0x86,0xC0,0x88}, ++ {0x0A,0x2A,0xEE,0xAE,0x3F,0xF4,0xAB,0x77}, ++ {0xEF,0x1B,0xF0,0x3E,0x5D,0xFA,0x57,0x5A}, ++ {0x88,0xBF,0x0D,0xB6,0xD7,0x0D,0xEE,0x56}, ++ {0xA1,0xF9,0x91,0x55,0x41,0x02,0x0B,0x56}, ++ {0x6F,0xBF,0x1C,0xAF,0xCF,0xFD,0x05,0x56}, ++ {0x2F,0x22,0xE4,0x9B,0xAB,0x7C,0xA1,0xAC}, ++ {0x5A,0x6B,0x61,0x2C,0xC2,0x6C,0xCE,0x4A}, ++ {0x5F,0x4C,0x03,0x8E,0xD1,0x2B,0x2E,0x41}, ++ {0x63,0xFA,0xC0,0xD0,0x34,0xD9,0xF7,0x93}, ++ {0x61,0x7B,0x3A,0x0C,0xE8,0xF0,0x71,0x00}, ++ {0xDB,0x95,0x86,0x05,0xF8,0xC8,0xC6,0x06}, ++ {0xED,0xBF,0xD1,0xC6,0x6C,0x29,0xCC,0xC7}, ++ {0x35,0x55,0x50,0xB2,0x15,0x0E,0x24,0x51}, ++ {0xCA,0xAA,0xAF,0x4D,0xEA,0xF1,0xDB,0xAE}, ++ {0xD5,0xD4,0x4F,0xF7,0x20,0x68,0x3D,0x0D}, ++ {0x2A,0x2B,0xB0,0x08,0xDF,0x97,0xC2,0xF2}}; ++ ++static unsigned char cipher_ecb2[NUM_TESTS-1][8]={ ++ {0x92,0x95,0xB5,0x9B,0xB3,0x84,0x73,0x6E}, ++ {0x19,0x9E,0x9D,0x6D,0xF3,0x9A,0xA8,0x16}, ++ {0x2A,0x4B,0x4D,0x24,0x52,0x43,0x84,0x27}, ++ {0x35,0x84,0x3C,0x01,0x9D,0x18,0xC5,0xB6}, ++ {0x4A,0x5B,0x2F,0x42,0xAA,0x77,0x19,0x25}, ++ {0xA0,0x6B,0xA9,0xB8,0xCA,0x5B,0x17,0x8A}, ++ {0xAB,0x9D,0xB7,0xFB,0xED,0x95,0xF2,0x74}, ++ {0x3D,0x25,0x6C,0x23,0xA7,0x25,0x2F,0xD6}, ++ {0xB7,0x6F,0xAB,0x4F,0xBD,0xBD,0xB7,0x67}, ++ {0x8F,0x68,0x27,0xD6,0x9C,0xF4,0x1A,0x10}, ++ {0x82,0x57,0xA1,0xD6,0x50,0x5E,0x81,0x85}, ++ {0xA2,0x0F,0x0A,0xCD,0x80,0x89,0x7D,0xFA}, ++ {0xCD,0x2A,0x53,0x3A,0xDB,0x0D,0x7E,0xF3}, ++ {0xD2,0xC2,0xBE,0x27,0xE8,0x1B,0x68,0xE3}, ++ {0xE9,0x24,0xCF,0x4F,0x89,0x3C,0x5B,0x0A}, ++ {0xA7,0x18,0xC3,0x9F,0xFA,0x9F,0xD7,0x69}, ++ {0x77,0x2C,0x79,0xB1,0xD2,0x31,0x7E,0xB1}, ++ {0x49,0xAB,0x92,0x7F,0xD0,0x22,0x00,0xB7}, ++ {0xCE,0x1C,0x6C,0x7D,0x85,0xE3,0x4A,0x6F}, ++ {0xBE,0x91,0xD6,0xE1,0x27,0xB2,0xE9,0x87}, ++ {0x70,0x28,0xAE,0x8F,0xD1,0xF5,0x74,0x1A}, ++ {0xAA,0x37,0x80,0xBB,0xF3,0x22,0x1D,0xDE}, ++ {0xA6,0xC4,0xD2,0x5E,0x28,0x93,0xAC,0xB3}, ++ {0x22,0x07,0x81,0x5A,0xE4,0xB7,0x1A,0xAD}, ++ {0xDC,0xCE,0x05,0xE7,0x07,0xBD,0xF5,0x84}, ++ {0x26,0x1D,0x39,0x2C,0xB3,0xBA,0xA5,0x85}, ++ {0xB4,0xF7,0x0F,0x72,0xFB,0x04,0xF0,0xDC}, ++ {0x95,0xBA,0xA9,0x4E,0x87,0x36,0xF2,0x89}, ++ {0xD4,0x07,0x3A,0xF1,0x5A,0x17,0x82,0x0E}, ++ {0xEF,0x6F,0xAF,0xA7,0x66,0x1A,0x7E,0x89}, ++ {0xC1,0x97,0xF5,0x58,0x74,0x8A,0x20,0xE7}, ++ {0x43,0x34,0xCF,0xDA,0x22,0xC4,0x86,0xC8}, ++ {0x08,0xD7,0xB4,0xFB,0x62,0x9D,0x08,0x85}}; ++ ++static unsigned char cbc_key [8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; ++static unsigned char cbc2_key[8]={0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87}; ++static unsigned char cbc3_key[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; ++static unsigned char cbc_iv [8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; ++static char cbc_data[40]="7654321 Now is the time for \0001"; ++ ++static unsigned char cbc_ok[32]={ ++ 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, ++ 0xac,0xd8,0xae,0xfd,0xdf,0xd8,0xa1,0xeb, ++ 0x46,0x8e,0x91,0x15,0x78,0x88,0xba,0x68, ++ 0x1d,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; ++ ++static unsigned char xcbc_ok[32]={ ++ 0x86,0x74,0x81,0x0D,0x61,0xA4,0xA5,0x48, ++ 0xB9,0x93,0x03,0xE1,0xB8,0xBB,0xBD,0xBD, ++ 0x64,0x30,0x0B,0xB9,0x06,0x65,0x81,0x76, ++ 0x04,0x1D,0x77,0x62,0x17,0xCA,0x2B,0xD2, ++ }; ++ ++static unsigned char cbc3_ok[32]={ ++ 0x3F,0xE3,0x01,0xC9,0x62,0xAC,0x01,0xD0, ++ 0x22,0x13,0x76,0x3C,0x1C,0xBD,0x4C,0xDC, ++ 0x79,0x96,0x57,0xC0,0x64,0xEC,0xF5,0xD4, ++ 0x1C,0x67,0x38,0x12,0xCF,0xDE,0x96,0x75}; ++ ++static unsigned char pcbc_ok[32]={ ++ 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, ++ 0x6d,0xec,0xb4,0x70,0xa0,0xe5,0x6b,0x15, ++ 0xae,0xa6,0xbf,0x61,0xed,0x7d,0x9c,0x9f, ++ 0xf7,0x17,0x46,0x3b,0x8a,0xb3,0xcc,0x88}; ++ ++static unsigned char cfb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; ++static unsigned char cfb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; ++static unsigned char cfb_buf1[40],cfb_buf2[40],cfb_tmp[8]; ++static unsigned char plain[24]= ++ { ++ 0x4e,0x6f,0x77,0x20,0x69,0x73, ++ 0x20,0x74,0x68,0x65,0x20,0x74, ++ 0x69,0x6d,0x65,0x20,0x66,0x6f, ++ 0x72,0x20,0x61,0x6c,0x6c,0x20 ++ }; ++static unsigned char cfb_cipher8[24]= { ++ 0xf3,0x1f,0xda,0x07,0x01,0x14, 0x62,0xee,0x18,0x7f,0x43,0xd8, ++ 0x0a,0x7c,0xd9,0xb5,0xb0,0xd2, 0x90,0xda,0x6e,0x5b,0x9a,0x87 }; ++static unsigned char cfb_cipher16[24]={ ++ 0xF3,0x09,0x87,0x87,0x7F,0x57, 0xF7,0x3C,0x36,0xB6,0xDB,0x70, ++ 0xD8,0xD5,0x34,0x19,0xD3,0x86, 0xB2,0x23,0xB7,0xB2,0xAD,0x1B }; ++static unsigned char cfb_cipher32[24]={ ++ 0xF3,0x09,0x62,0x49,0xA4,0xDF, 0xA4,0x9F,0x33,0xDC,0x7B,0xAD, ++ 0x4C,0xC8,0x9F,0x64,0xE4,0x53, 0xE5,0xEC,0x67,0x20,0xDA,0xB6 }; ++static unsigned char cfb_cipher48[24]={ ++ 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x30,0xB5,0x15,0xEC,0xBB,0x85, ++ 0x97,0x5A,0x13,0x8C,0x68,0x60, 0xE2,0x38,0x34,0x3C,0xDC,0x1F }; ++static unsigned char cfb_cipher64[24]={ ++ 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x6E,0x51,0xA6,0x9E,0x83,0x9B, ++ 0x1A,0x92,0xF7,0x84,0x03,0x46, 0x71,0x33,0x89,0x8E,0xA6,0x22 }; ++ ++static unsigned char ofb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; ++static unsigned char ofb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; ++static unsigned char ofb_buf1[24],ofb_buf2[24],ofb_tmp[8]; ++static unsigned char ofb_cipher[24]= ++ { ++ 0xf3,0x09,0x62,0x49,0xc7,0xf4,0x6e,0x51, ++ 0x35,0xf2,0x4a,0x24,0x2e,0xeb,0x3d,0x3f, ++ 0x3d,0x6d,0x5b,0xe3,0x25,0x5a,0xf8,0xc3 ++ }; ++ ++DES_LONG cbc_cksum_ret=0xB462FEF7L; ++unsigned char cbc_cksum_data[8]={0x1D,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; ++ ++#ifndef NOPROTO ++static char *pt(unsigned char *p); ++static int cfb_test(int bits, unsigned char *cfb_cipher); ++static int cfb64_test(unsigned char *cfb_cipher); ++static int ede_cfb64_test(unsigned char *cfb_cipher); ++#else ++static char *pt(); ++static int cfb_test(); ++static int cfb64_test(); ++static int ede_cfb64_test(); ++#endif ++ ++int main(argc,argv) ++int argc; ++char *argv[]; ++ { ++ int i,j,err=0; ++ des_cblock in,out,outin,iv3; ++ des_key_schedule ks,ks2,ks3; ++ unsigned char cbc_in[40]; ++ unsigned char cbc_out[40]; ++ DES_LONG cs; ++ unsigned char qret[4][4],cret[8]; ++ DES_LONG lqret[4]; ++ int num; ++ char *str; ++ ++ printf("Doing ecb\n"); ++ for (i=0; i<NUM_TESTS; i++) ++ { ++ if ((j=des_key_sched((C_Block *)(key_data[i]),ks)) != 0) ++ { ++ printf("Key error %2d:%d\n",i+1,j); ++ err=1; ++ } ++ memcpy(in,plain_data[i],8); ++ memset(out,0,8); ++ memset(outin,0,8); ++ des_ecb_encrypt((C_Block *)in,(C_Block *)out,ks,DES_ENCRYPT); ++ des_ecb_encrypt((C_Block *)out,(C_Block *)outin,ks,DES_DECRYPT); ++ ++ if (memcmp(out,cipher_data[i],8) != 0) ++ { ++ printf("Encryption error %2d\nk=%s p=%s o=%s act=%s\n", ++ i+1,pt(key_data[i]),pt(in),pt(cipher_data[i]), ++ pt(out)); ++ err=1; ++ } ++ if (memcmp(in,outin,8) != 0) ++ { ++ printf("Decryption error %2d\nk=%s p=%s o=%s act=%s\n", ++ i+1,pt(key_data[i]),pt(out),pt(in),pt(outin)); ++ err=1; ++ } ++ } ++ ++#ifndef LIBDES_LIT ++ printf("Doing ede ecb\n"); ++ for (i=0; i<(NUM_TESTS-1); i++) ++ { ++ if ((j=des_key_sched((C_Block *)(key_data[i]),ks)) != 0) ++ { ++ err=1; ++ printf("Key error %2d:%d\n",i+1,j); ++ } ++ if ((j=des_key_sched((C_Block *)(key_data[i+1]),ks2)) != 0) ++ { ++ printf("Key error %2d:%d\n",i+2,j); ++ err=1; ++ } ++ if ((j=des_key_sched((C_Block *)(key_data[i+2]),ks3)) != 0) ++ { ++ printf("Key error %2d:%d\n",i+3,j); ++ err=1; ++ } ++ memcpy(in,plain_data[i],8); ++ memset(out,0,8); ++ memset(outin,0,8); ++ des_ecb2_encrypt((C_Block *)in,(C_Block *)out,ks,ks2, ++ DES_ENCRYPT); ++ des_ecb2_encrypt((C_Block *)out,(C_Block *)outin,ks,ks2, ++ DES_DECRYPT); ++ ++ if (memcmp(out,cipher_ecb2[i],8) != 0) ++ { ++ printf("Encryption error %2d\nk=%s p=%s o=%s act=%s\n", ++ i+1,pt(key_data[i]),pt(in),pt(cipher_ecb2[i]), ++ pt(out)); ++ err=1; ++ } ++ if (memcmp(in,outin,8) != 0) ++ { ++ printf("Decryption error %2d\nk=%s p=%s o=%s act=%s\n", ++ i+1,pt(key_data[i]),pt(out),pt(in),pt(outin)); ++ err=1; ++ } ++ } ++#endif ++ ++ printf("Doing cbc\n"); ++ if ((j=des_key_sched((C_Block *)cbc_key,ks)) != 0) ++ { ++ printf("Key error %d\n",j); ++ err=1; ++ } ++ memset(cbc_out,0,40); ++ memset(cbc_in,0,40); ++ memcpy(iv3,cbc_iv,sizeof(cbc_iv)); ++ des_ncbc_encrypt((C_Block *)cbc_data,(C_Block *)cbc_out, ++ (long)strlen((char *)cbc_data)+1,ks, ++ (C_Block *)iv3,DES_ENCRYPT); ++ if (memcmp(cbc_out,cbc_ok,32) != 0) ++ printf("cbc_encrypt encrypt error\n"); ++ ++ memcpy(iv3,cbc_iv,sizeof(cbc_iv)); ++ des_ncbc_encrypt((C_Block *)cbc_out,(C_Block *)cbc_in, ++ (long)strlen((char *)cbc_data)+1,ks, ++ (C_Block *)iv3,DES_DECRYPT); ++ if (memcmp(cbc_in,cbc_data,strlen((char *)cbc_data)) != 0) ++ { ++ printf("cbc_encrypt decrypt error\n"); ++ err=1; ++ } ++ ++#ifndef LIBDES_LIT ++ printf("Doing desx cbc\n"); ++ if ((j=des_key_sched((C_Block *)cbc_key,ks)) != 0) ++ { ++ printf("Key error %d\n",j); ++ err=1; ++ } ++ memset(cbc_out,0,40); ++ memset(cbc_in,0,40); ++ memcpy(iv3,cbc_iv,sizeof(cbc_iv)); ++ des_xcbc_encrypt((C_Block *)cbc_data,(C_Block *)cbc_out, ++ (long)strlen((char *)cbc_data)+1,ks, ++ (C_Block *)iv3, ++ (C_Block *)cbc2_key, (C_Block *)cbc3_key, DES_ENCRYPT); ++ if (memcmp(cbc_out,xcbc_ok,32) != 0) ++ { ++ printf("des_xcbc_encrypt encrypt error\n"); ++ } ++ memcpy(iv3,cbc_iv,sizeof(cbc_iv)); ++ des_xcbc_encrypt((C_Block *)cbc_out,(C_Block *)cbc_in, ++ (long)strlen((char *)cbc_data)+1,ks, ++ (C_Block *)iv3, ++ (C_Block *)cbc2_key, (C_Block *)cbc3_key, DES_DECRYPT); ++ if (memcmp(cbc_in,cbc_data,strlen((char *)cbc_data)+1) != 0) ++ { ++ printf("des_xcbc_encrypt decrypt error\n"); ++ err=1; ++ } ++#endif ++ ++ printf("Doing ede cbc\n"); ++ if ((j=des_key_sched((C_Block *)cbc_key,ks)) != 0) ++ { ++ printf("Key error %d\n",j); ++ err=1; ++ } ++ if ((j=des_key_sched((C_Block *)cbc2_key,ks2)) != 0) ++ { ++ printf("Key error %d\n",j); ++ err=1; ++ } ++ if ((j=des_key_sched((C_Block *)cbc3_key,ks3)) != 0) ++ { ++ printf("Key error %d\n",j); ++ err=1; ++ } ++ memset(cbc_out,0,40); ++ memset(cbc_in,0,40); ++ i=strlen((char *)cbc_data)+1; ++ /* i=((i+7)/8)*8; */ ++ memcpy(iv3,cbc_iv,sizeof(cbc_iv)); ++ ++ des_ede3_cbc_encrypt((C_Block *)cbc_data,(C_Block *)cbc_out, ++ 16L,ks,ks2,ks3,(C_Block *)iv3,DES_ENCRYPT); ++ des_ede3_cbc_encrypt((C_Block *)&(cbc_data[16]), ++ (C_Block *)&(cbc_out[16]), ++ (long)i-16,ks,ks2,ks3,(C_Block *)iv3,DES_ENCRYPT); ++ if (memcmp(cbc_out,cbc3_ok, ++ (unsigned int)(strlen((char *)cbc_data)+1+7)/8*8) != 0) ++ { ++ printf("des_ede3_cbc_encrypt encrypt error\n"); ++ err=1; ++ } ++ ++ memcpy(iv3,cbc_iv,sizeof(cbc_iv)); ++ des_ede3_cbc_encrypt((C_Block *)cbc_out,(C_Block *)cbc_in, ++ (long)i,ks,ks2,ks3,(C_Block *)iv3,DES_DECRYPT); ++ if (memcmp(cbc_in,cbc_data,strlen(cbc_data)+1) != 0) ++ { ++ printf("des_ede3_cbc_encrypt decrypt error\n"); ++ err=1; ++ } ++ ++#ifndef LIBDES_LIT ++ printf("Doing pcbc\n"); ++ if ((j=des_key_sched((C_Block *)cbc_key,ks)) != 0) ++ { ++ printf("Key error %d\n",j); ++ err=1; ++ } ++ memset(cbc_out,0,40); ++ memset(cbc_in,0,40); ++ des_pcbc_encrypt((C_Block *)cbc_data,(C_Block *)cbc_out, ++ (long)strlen(cbc_data)+1,ks,(C_Block *)cbc_iv,DES_ENCRYPT); ++ if (memcmp(cbc_out,pcbc_ok,32) != 0) ++ { ++ printf("pcbc_encrypt encrypt error\n"); ++ err=1; ++ } ++ des_pcbc_encrypt((C_Block *)cbc_out,(C_Block *)cbc_in, ++ (long)strlen(cbc_data)+1,ks,(C_Block *)cbc_iv,DES_DECRYPT); ++ if (memcmp(cbc_in,cbc_data,strlen(cbc_data)+1) != 0) ++ { ++ printf("pcbc_encrypt decrypt error\n"); ++ err=1; ++ } ++ ++ printf("Doing "); ++ printf("cfb8 "); ++ err+=cfb_test(8,cfb_cipher8); ++ printf("cfb16 "); ++ err+=cfb_test(16,cfb_cipher16); ++ printf("cfb32 "); ++ err+=cfb_test(32,cfb_cipher32); ++ printf("cfb48 "); ++ err+=cfb_test(48,cfb_cipher48); ++ printf("cfb64 "); ++ err+=cfb_test(64,cfb_cipher64); ++ ++ printf("cfb64() "); ++ err+=cfb64_test(cfb_cipher64); ++ ++ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); ++ for (i=0; i<sizeof(plain); i++) ++ des_cfb_encrypt(&(plain[i]),&(cfb_buf1[i]), ++ 8,(long)1,ks,(C_Block *)cfb_tmp,DES_ENCRYPT); ++ if (memcmp(cfb_cipher8,cfb_buf1,sizeof(plain)) != 0) ++ { ++ printf("cfb_encrypt small encrypt error\n"); ++ err=1; ++ } ++ ++ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); ++ for (i=0; i<sizeof(plain); i++) ++ des_cfb_encrypt(&(cfb_buf1[i]),&(cfb_buf2[i]), ++ 8,(long)1,ks,(C_Block *)cfb_tmp,DES_DECRYPT); ++ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) ++ { ++ printf("cfb_encrypt small decrypt error\n"); ++ err=1; ++ } ++ ++ printf("ede_cfb64() "); ++ err+=ede_cfb64_test(cfb_cipher64); ++ ++ printf("done\n"); ++ ++ printf("Doing ofb\n"); ++ des_key_sched((C_Block *)ofb_key,ks); ++ memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv)); ++ des_ofb_encrypt(plain,ofb_buf1,64,(long)sizeof(plain)/8,ks, ++ (C_Block *)ofb_tmp); ++ if (memcmp(ofb_cipher,ofb_buf1,sizeof(ofb_buf1)) != 0) ++ { ++ printf("ofb_encrypt encrypt error\n"); ++printf("%02X %02X %02X %02X %02X %02X %02X %02X\n", ++ofb_buf1[8+0], ofb_buf1[8+1], ofb_buf1[8+2], ofb_buf1[8+3], ++ofb_buf1[8+4], ofb_buf1[8+5], ofb_buf1[8+6], ofb_buf1[8+7]); ++printf("%02X %02X %02X %02X %02X %02X %02X %02X\n", ++ofb_buf1[8+0], ofb_cipher[8+1], ofb_cipher[8+2], ofb_cipher[8+3], ++ofb_buf1[8+4], ofb_cipher[8+5], ofb_cipher[8+6], ofb_cipher[8+7]); ++ err=1; ++ } ++ memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv)); ++ des_ofb_encrypt(ofb_buf1,ofb_buf2,64,(long)sizeof(ofb_buf1)/8,ks, ++ (C_Block *)ofb_tmp); ++ if (memcmp(plain,ofb_buf2,sizeof(ofb_buf2)) != 0) ++ { ++ printf("ofb_encrypt decrypt error\n"); ++printf("%02X %02X %02X %02X %02X %02X %02X %02X\n", ++ofb_buf2[8+0], ofb_buf2[8+1], ofb_buf2[8+2], ofb_buf2[8+3], ++ofb_buf2[8+4], ofb_buf2[8+5], ofb_buf2[8+6], ofb_buf2[8+7]); ++printf("%02X %02X %02X %02X %02X %02X %02X %02X\n", ++plain[8+0], plain[8+1], plain[8+2], plain[8+3], ++plain[8+4], plain[8+5], plain[8+6], plain[8+7]); ++ err=1; ++ } ++ ++ printf("Doing ofb64\n"); ++ des_key_sched((C_Block *)ofb_key,ks); ++ memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv)); ++ memset(ofb_buf1,0,sizeof(ofb_buf1)); ++ memset(ofb_buf2,0,sizeof(ofb_buf1)); ++ num=0; ++ for (i=0; i<sizeof(plain); i++) ++ { ++ des_ofb64_encrypt(&(plain[i]),&(ofb_buf1[i]),1,ks, ++ (C_Block *)ofb_tmp,&num); ++ } ++ if (memcmp(ofb_cipher,ofb_buf1,sizeof(ofb_buf1)) != 0) ++ { ++ printf("ofb64_encrypt encrypt error\n"); ++ err=1; ++ } ++ memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv)); ++ num=0; ++ des_ofb64_encrypt(ofb_buf1,ofb_buf2,(long)sizeof(ofb_buf1),ks, ++ (C_Block *)ofb_tmp,&num); ++ if (memcmp(plain,ofb_buf2,sizeof(ofb_buf2)) != 0) ++ { ++ printf("ofb64_encrypt decrypt error\n"); ++ err=1; ++ } ++ ++ printf("Doing ede_ofb64\n"); ++ des_key_sched((C_Block *)ofb_key,ks); ++ memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv)); ++ memset(ofb_buf1,0,sizeof(ofb_buf1)); ++ memset(ofb_buf2,0,sizeof(ofb_buf1)); ++ num=0; ++ for (i=0; i<sizeof(plain); i++) ++ { ++ des_ede3_ofb64_encrypt(&(plain[i]),&(ofb_buf1[i]),1,ks,ks,ks, ++ (C_Block *)ofb_tmp,&num); ++ } ++ if (memcmp(ofb_cipher,ofb_buf1,sizeof(ofb_buf1)) != 0) ++ { ++ printf("ede_ofb64_encrypt encrypt error\n"); ++ err=1; ++ } ++ memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv)); ++ num=0; ++ des_ede3_ofb64_encrypt(ofb_buf1,ofb_buf2,(long)sizeof(ofb_buf1),ks, ++ ks,ks,(C_Block *)ofb_tmp,&num); ++ if (memcmp(plain,ofb_buf2,sizeof(ofb_buf2)) != 0) ++ { ++ printf("ede_ofb64_encrypt decrypt error\n"); ++ err=1; ++ } ++ ++ printf("Doing cbc_cksum\n"); ++ des_key_sched((C_Block *)cbc_key,ks); ++ cs=des_cbc_cksum((C_Block *)cbc_data,(C_Block *)cret, ++ (long)strlen(cbc_data),ks,(C_Block *)cbc_iv); ++ if (cs != cbc_cksum_ret) ++ { ++ printf("bad return value (%08lX), should be %08lX\n", ++ (unsigned long)cs,(unsigned long)cbc_cksum_ret); ++ err=1; ++ } ++ if (memcmp(cret,cbc_cksum_data,8) != 0) ++ { ++ printf("bad cbc_cksum block returned\n"); ++ err=1; ++ } ++ ++ printf("Doing quad_cksum\n"); ++ cs=quad_cksum((C_Block *)cbc_data,(C_Block *)qret, ++ (long)strlen(cbc_data),2,(C_Block *)cbc_iv); ++ for (i=0; i<4; i++) ++ { ++ lqret[i]=0; ++ memcpy(&(lqret[i]),&(qret[i][0]),4); ++ } ++ { /* Big-endian fix */ ++ static DES_LONG l=1; ++ static unsigned char *c=(unsigned char *)&l; ++ DES_LONG ll; ++ ++ if (!c[0]) ++ { ++ ll=lqret[0]^lqret[3]; ++ lqret[0]^=ll; ++ lqret[3]^=ll; ++ ll=lqret[1]^lqret[2]; ++ lqret[1]^=ll; ++ lqret[2]^=ll; ++ } ++ } ++ if (cs != 0x70d7a63aL) ++ { ++ printf("quad_cksum error, ret %08lx should be 70d7a63a\n", ++ (unsigned long)cs); ++ err=1; ++ } ++ if (lqret[0] != 0x327eba8dL) ++ { ++ printf("quad_cksum error, out[0] %08lx is not %08lx\n", ++ (unsigned long)lqret[0],0x327eba8dL); ++ err=1; ++ } ++ if (lqret[1] != 0x201a49ccL) ++ { ++ printf("quad_cksum error, out[1] %08lx is not %08lx\n", ++ (unsigned long)lqret[1],0x201a49ccL); ++ err=1; ++ } ++ if (lqret[2] != 0x70d7a63aL) ++ { ++ printf("quad_cksum error, out[2] %08lx is not %08lx\n", ++ (unsigned long)lqret[2],0x70d7a63aL); ++ err=1; ++ } ++ if (lqret[3] != 0x501c2c26L) ++ { ++ printf("quad_cksum error, out[3] %08lx is not %08lx\n", ++ (unsigned long)lqret[3],0x501c2c26L); ++ err=1; ++ } ++#endif ++ ++ printf("input word alignment test"); ++ for (i=0; i<4; i++) ++ { ++ printf(" %d",i); ++ des_ncbc_encrypt((C_Block *)&(cbc_out[i]),(C_Block *)cbc_in, ++ (long)strlen(cbc_data)+1,ks,(C_Block *)cbc_iv, ++ DES_ENCRYPT); ++ } ++ printf("\noutput word alignment test"); ++ for (i=0; i<4; i++) ++ { ++ printf(" %d",i); ++ des_ncbc_encrypt((C_Block *)cbc_out,(C_Block *)&(cbc_in[i]), ++ (long)strlen(cbc_data)+1,ks,(C_Block *)cbc_iv, ++ DES_ENCRYPT); ++ } ++ printf("\n"); ++ printf("fast crypt test "); ++ str=crypt("testing","ef"); ++ if (strcmp("efGnQx2725bI2",str) != 0) ++ { ++ printf("fast crypt error, %s should be efGnQx2725bI2\n",str); ++ err=1; ++ } ++ str=crypt("bca76;23","yA"); ++ if (strcmp("yA1Rp/1hZXIJk",str) != 0) ++ { ++ printf("fast crypt error, %s should be yA1Rp/1hZXIJk\n",str); ++ err=1; ++ } ++ printf("\n"); ++ exit(err); ++ return(0); ++ } ++ ++static char *pt(p) ++unsigned char *p; ++ { ++ static char bufs[10][20]; ++ static int bnum=0; ++ char *ret; ++ int i; ++ static char *f="0123456789ABCDEF"; ++ ++ ret= &(bufs[bnum++][0]); ++ bnum%=10; ++ for (i=0; i<8; i++) ++ { ++ ret[i*2]=f[(p[i]>>4)&0xf]; ++ ret[i*2+1]=f[p[i]&0xf]; ++ } ++ ret[16]='\0'; ++ return(ret); ++ } ++ ++#ifndef LIBDES_LIT ++ ++static int cfb_test(bits, cfb_cipher) ++int bits; ++unsigned char *cfb_cipher; ++ { ++ des_key_schedule ks; ++ int i,err=0; ++ ++ des_key_sched((C_Block *)cfb_key,ks); ++ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); ++ des_cfb_encrypt(plain,cfb_buf1,bits,(long)sizeof(plain),ks, ++ (C_Block *)cfb_tmp,DES_ENCRYPT); ++ if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) ++ { ++ err=1; ++ printf("cfb_encrypt encrypt error\n"); ++ for (i=0; i<24; i+=8) ++ printf("%s\n",pt(&(cfb_buf1[i]))); ++ } ++ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); ++ des_cfb_encrypt(cfb_buf1,cfb_buf2,bits,(long)sizeof(plain),ks, ++ (C_Block *)cfb_tmp,DES_DECRYPT); ++ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) ++ { ++ err=1; ++ printf("cfb_encrypt decrypt error\n"); ++ for (i=0; i<24; i+=8) ++ printf("%s\n",pt(&(cfb_buf1[i]))); ++ } ++ return(err); ++ } ++ ++static int cfb64_test(cfb_cipher) ++unsigned char *cfb_cipher; ++ { ++ des_key_schedule ks; ++ int err=0,i,n; ++ ++ des_key_sched((C_Block *)cfb_key,ks); ++ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); ++ n=0; ++ des_cfb64_encrypt(plain,cfb_buf1,(long)12,ks, ++ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); ++ des_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), ++ (long)sizeof(plain)-12,ks, ++ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); ++ if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) ++ { ++ err=1; ++ printf("cfb_encrypt encrypt error\n"); ++ for (i=0; i<24; i+=8) ++ printf("%s\n",pt(&(cfb_buf1[i]))); ++ } ++ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); ++ n=0; ++ des_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks, ++ (C_Block *)cfb_tmp,&n,DES_DECRYPT); ++ des_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), ++ (long)sizeof(plain)-17,ks, ++ (C_Block *)cfb_tmp,&n,DES_DECRYPT); ++ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) ++ { ++ err=1; ++ printf("cfb_encrypt decrypt error\n"); ++ for (i=0; i<24; i+=8) ++ printf("%s\n",pt(&(cfb_buf2[i]))); ++ } ++ return(err); ++ } ++ ++static int ede_cfb64_test(cfb_cipher) ++unsigned char *cfb_cipher; ++ { ++ des_key_schedule ks; ++ int err=0,i,n; ++ ++ des_key_sched((C_Block *)cfb_key,ks); ++ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); ++ n=0; ++ des_ede3_cfb64_encrypt(plain,cfb_buf1,(long)12,ks,ks,ks, ++ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); ++ des_ede3_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), ++ (long)sizeof(plain)-12,ks,ks,ks, ++ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); ++ if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) ++ { ++ err=1; ++ printf("ede_cfb_encrypt encrypt error\n"); ++ for (i=0; i<24; i+=8) ++ printf("%s\n",pt(&(cfb_buf1[i]))); ++ } ++ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); ++ n=0; ++ des_ede3_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks,ks,ks, ++ (C_Block *)cfb_tmp,&n,DES_DECRYPT); ++ des_ede3_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), ++ (long)sizeof(plain)-17,ks,ks,ks, ++ (C_Block *)cfb_tmp,&n,DES_DECRYPT); ++ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) ++ { ++ err=1; ++ printf("ede_cfb_encrypt decrypt error\n"); ++ for (i=0; i<24; i+=8) ++ printf("%s\n",pt(&(cfb_buf2[i]))); ++ } ++ return(err); ++ } ++ ++#endif ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/dx86unix.S Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,3160 @@ ++/* ++ * This file was originally generated by Michael Richardson <mcr@freeswan.org> ++ * via the perl scripts found in the ASM subdir. It remains copyright of ++ * Eric Young, see the file COPYRIGHT. ++ * ++ * This was last done on October 9, 2002. ++ * ++ * While this file does not need to go through cpp, we pass it through ++ * CPP by naming it dx86unix.S instead of dx86unix.s because there is ++ * a bug in Rules.make for .s builds - specifically it references EXTRA_CFLAGS ++ * which may contain stuff that AS doesn't understand instead of ++ * referencing EXTRA_AFLAGS. ++ */ ++ ++ .file "dx86unix.S" ++ .version "01.01" ++.text ++ .align 16 ++.globl des_encrypt ++ .type des_encrypt , @function ++des_encrypt: ++ pushl %esi ++ pushl %edi ++ ++ ++ movl 12(%esp), %esi ++ xorl %ecx, %ecx ++ pushl %ebx ++ pushl %ebp ++ movl (%esi), %eax ++ movl 28(%esp), %ebx ++ movl 4(%esi), %edi ++ ++ ++ roll $4, %eax ++ movl %eax, %esi ++ xorl %edi, %eax ++ andl $0xf0f0f0f0, %eax ++ xorl %eax, %esi ++ xorl %eax, %edi ++ ++ roll $20, %edi ++ movl %edi, %eax ++ xorl %esi, %edi ++ andl $0xfff0000f, %edi ++ xorl %edi, %eax ++ xorl %edi, %esi ++ ++ roll $14, %eax ++ movl %eax, %edi ++ xorl %esi, %eax ++ andl $0x33333333, %eax ++ xorl %eax, %edi ++ xorl %eax, %esi ++ ++ roll $22, %esi ++ movl %esi, %eax ++ xorl %edi, %esi ++ andl $0x03fc03fc, %esi ++ xorl %esi, %eax ++ xorl %esi, %edi ++ ++ roll $9, %eax ++ movl %eax, %esi ++ xorl %edi, %eax ++ andl $0xaaaaaaaa, %eax ++ xorl %eax, %esi ++ xorl %eax, %edi ++ ++.byte 209 ++.byte 199 ++ movl 24(%esp), %ebp ++ cmpl $0, %ebx ++ je .L000start_decrypt ++ ++ ++ movl (%ebp), %eax ++ xorl %ebx, %ebx ++ movl 4(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 8(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 12(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 16(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 20(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 24(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 28(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 32(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 36(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 40(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 44(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 48(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 52(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 56(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 60(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 64(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 68(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 72(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 76(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 80(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 84(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 88(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 92(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 96(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 100(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 104(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 108(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 112(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 116(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 120(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 124(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ jmp .L001end ++.L000start_decrypt: ++ ++ ++ movl 120(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 124(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 112(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 116(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 104(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 108(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 96(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 100(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 88(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 92(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 80(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 84(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 72(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 76(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 64(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 68(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 56(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 60(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 48(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 52(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 40(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 44(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 32(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 36(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 24(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 28(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 16(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 20(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 8(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 12(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl (%ebp), %eax ++ xorl %ebx, %ebx ++ movl 4(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++.L001end: ++ ++ ++ movl 20(%esp), %edx ++.byte 209 ++.byte 206 ++ movl %edi, %eax ++ xorl %esi, %edi ++ andl $0xaaaaaaaa, %edi ++ xorl %edi, %eax ++ xorl %edi, %esi ++ ++ roll $23, %eax ++ movl %eax, %edi ++ xorl %esi, %eax ++ andl $0x03fc03fc, %eax ++ xorl %eax, %edi ++ xorl %eax, %esi ++ ++ roll $10, %edi ++ movl %edi, %eax ++ xorl %esi, %edi ++ andl $0x33333333, %edi ++ xorl %edi, %eax ++ xorl %edi, %esi ++ ++ roll $18, %esi ++ movl %esi, %edi ++ xorl %eax, %esi ++ andl $0xfff0000f, %esi ++ xorl %esi, %edi ++ xorl %esi, %eax ++ ++ roll $12, %edi ++ movl %edi, %esi ++ xorl %eax, %edi ++ andl $0xf0f0f0f0, %edi ++ xorl %edi, %esi ++ xorl %edi, %eax ++ ++ rorl $4, %eax ++ movl %eax, (%edx) ++ movl %esi, 4(%edx) ++ popl %ebp ++ popl %ebx ++ popl %edi ++ popl %esi ++ ret ++.des_encrypt_end: ++ .size des_encrypt , .des_encrypt_end-des_encrypt ++.ident "desasm.pl" ++.text ++ .align 16 ++.globl des_encrypt2 ++ .type des_encrypt2 , @function ++des_encrypt2: ++ pushl %esi ++ pushl %edi ++ ++ ++ movl 12(%esp), %eax ++ xorl %ecx, %ecx ++ pushl %ebx ++ pushl %ebp ++ movl (%eax), %esi ++ movl 28(%esp), %ebx ++ roll $3, %esi ++ movl 4(%eax), %edi ++ roll $3, %edi ++ movl 24(%esp), %ebp ++ cmpl $0, %ebx ++ je .L002start_decrypt ++ ++ ++ movl (%ebp), %eax ++ xorl %ebx, %ebx ++ movl 4(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 8(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 12(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 16(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 20(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 24(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 28(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 32(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 36(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 40(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 44(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 48(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 52(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 56(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 60(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 64(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 68(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 72(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 76(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 80(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 84(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 88(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 92(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 96(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 100(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 104(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 108(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 112(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 116(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 120(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 124(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ jmp .L003end ++.L002start_decrypt: ++ ++ ++ movl 120(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 124(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 112(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 116(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 104(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 108(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 96(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 100(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 88(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 92(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 80(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 84(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 72(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 76(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 64(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 68(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 56(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 60(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 48(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 52(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 40(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 44(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 32(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 36(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 24(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 28(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl 16(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 20(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++ ++ ++ movl 8(%ebp), %eax ++ xorl %ebx, %ebx ++ movl 12(%ebp), %edx ++ xorl %esi, %eax ++ xorl %esi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %edi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %edi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %edi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %edi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %edi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %edi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %edi ++ ++ ++ movl (%ebp), %eax ++ xorl %ebx, %ebx ++ movl 4(%ebp), %edx ++ xorl %edi, %eax ++ xorl %edi, %edx ++ andl $0xfcfcfcfc, %eax ++ andl $0xcfcfcfcf, %edx ++ movb %al, %bl ++ movb %ah, %cl ++ rorl $4, %edx ++ movl des_SPtrans(%ebx),%ebp ++ movb %dl, %bl ++ xorl %ebp, %esi ++ movl 0x200+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movb %dh, %cl ++ shrl $16, %eax ++ movl 0x100+des_SPtrans(%ebx),%ebp ++ xorl %ebp, %esi ++ movb %ah, %bl ++ shrl $16, %edx ++ movl 0x300+des_SPtrans(%ecx),%ebp ++ xorl %ebp, %esi ++ movl 24(%esp), %ebp ++ movb %dh, %cl ++ andl $0xff, %eax ++ andl $0xff, %edx ++ movl 0x600+des_SPtrans(%ebx),%ebx ++ xorl %ebx, %esi ++ movl 0x700+des_SPtrans(%ecx),%ebx ++ xorl %ebx, %esi ++ movl 0x400+des_SPtrans(%eax),%ebx ++ xorl %ebx, %esi ++ movl 0x500+des_SPtrans(%edx),%ebx ++ xorl %ebx, %esi ++.L003end: ++ ++ ++ rorl $3, %edi ++ movl 20(%esp), %eax ++ rorl $3, %esi ++ movl %edi, (%eax) ++ movl %esi, 4(%eax) ++ popl %ebp ++ popl %ebx ++ popl %edi ++ popl %esi ++ ret ++.des_encrypt2_end: ++ .size des_encrypt2 , .des_encrypt2_end-des_encrypt2 ++.ident "desasm.pl" ++.text ++ .align 16 ++.globl des_encrypt3 ++ .type des_encrypt3 , @function ++des_encrypt3: ++ pushl %ebx ++ movl 8(%esp), %ebx ++ pushl %ebp ++ pushl %esi ++ pushl %edi ++ ++ ++ movl (%ebx), %edi ++ movl 4(%ebx), %esi ++ subl $12, %esp ++ ++ ++ roll $4, %edi ++ movl %edi, %edx ++ xorl %esi, %edi ++ andl $0xf0f0f0f0, %edi ++ xorl %edi, %edx ++ xorl %edi, %esi ++ ++ roll $20, %esi ++ movl %esi, %edi ++ xorl %edx, %esi ++ andl $0xfff0000f, %esi ++ xorl %esi, %edi ++ xorl %esi, %edx ++ ++ roll $14, %edi ++ movl %edi, %esi ++ xorl %edx, %edi ++ andl $0x33333333, %edi ++ xorl %edi, %esi ++ xorl %edi, %edx ++ ++ roll $22, %edx ++ movl %edx, %edi ++ xorl %esi, %edx ++ andl $0x03fc03fc, %edx ++ xorl %edx, %edi ++ xorl %edx, %esi ++ ++ roll $9, %edi ++ movl %edi, %edx ++ xorl %esi, %edi ++ andl $0xaaaaaaaa, %edi ++ xorl %edi, %edx ++ xorl %edi, %esi ++ ++ rorl $3, %edx ++ rorl $2, %esi ++ movl %esi, 4(%ebx) ++ movl 36(%esp), %eax ++ movl %edx, (%ebx) ++ movl 40(%esp), %edi ++ movl 44(%esp), %esi ++ movl $1, 8(%esp) ++ movl %eax, 4(%esp) ++ movl %ebx, (%esp) ++ call des_encrypt2 ++ movl $0, 8(%esp) ++ movl %edi, 4(%esp) ++ movl %ebx, (%esp) ++ call des_encrypt2 ++ movl $1, 8(%esp) ++ movl %esi, 4(%esp) ++ movl %ebx, (%esp) ++ call des_encrypt2 ++ addl $12, %esp ++ movl (%ebx), %edi ++ movl 4(%ebx), %esi ++ ++ ++ roll $2, %esi ++ roll $3, %edi ++ movl %edi, %eax ++ xorl %esi, %edi ++ andl $0xaaaaaaaa, %edi ++ xorl %edi, %eax ++ xorl %edi, %esi ++ ++ roll $23, %eax ++ movl %eax, %edi ++ xorl %esi, %eax ++ andl $0x03fc03fc, %eax ++ xorl %eax, %edi ++ xorl %eax, %esi ++ ++ roll $10, %edi ++ movl %edi, %eax ++ xorl %esi, %edi ++ andl $0x33333333, %edi ++ xorl %edi, %eax ++ xorl %edi, %esi ++ ++ roll $18, %esi ++ movl %esi, %edi ++ xorl %eax, %esi ++ andl $0xfff0000f, %esi ++ xorl %esi, %edi ++ xorl %esi, %eax ++ ++ roll $12, %edi ++ movl %edi, %esi ++ xorl %eax, %edi ++ andl $0xf0f0f0f0, %edi ++ xorl %edi, %esi ++ xorl %edi, %eax ++ ++ rorl $4, %eax ++ movl %eax, (%ebx) ++ movl %esi, 4(%ebx) ++ popl %edi ++ popl %esi ++ popl %ebp ++ popl %ebx ++ ret ++.des_encrypt3_end: ++ .size des_encrypt3 , .des_encrypt3_end-des_encrypt3 ++.ident "desasm.pl" ++.text ++ .align 16 ++.globl des_decrypt3 ++ .type des_decrypt3 , @function ++des_decrypt3: ++ pushl %ebx ++ movl 8(%esp), %ebx ++ pushl %ebp ++ pushl %esi ++ pushl %edi ++ ++ ++ movl (%ebx), %edi ++ movl 4(%ebx), %esi ++ subl $12, %esp ++ ++ ++ roll $4, %edi ++ movl %edi, %edx ++ xorl %esi, %edi ++ andl $0xf0f0f0f0, %edi ++ xorl %edi, %edx ++ xorl %edi, %esi ++ ++ roll $20, %esi ++ movl %esi, %edi ++ xorl %edx, %esi ++ andl $0xfff0000f, %esi ++ xorl %esi, %edi ++ xorl %esi, %edx ++ ++ roll $14, %edi ++ movl %edi, %esi ++ xorl %edx, %edi ++ andl $0x33333333, %edi ++ xorl %edi, %esi ++ xorl %edi, %edx ++ ++ roll $22, %edx ++ movl %edx, %edi ++ xorl %esi, %edx ++ andl $0x03fc03fc, %edx ++ xorl %edx, %edi ++ xorl %edx, %esi ++ ++ roll $9, %edi ++ movl %edi, %edx ++ xorl %esi, %edi ++ andl $0xaaaaaaaa, %edi ++ xorl %edi, %edx ++ xorl %edi, %esi ++ ++ rorl $3, %edx ++ rorl $2, %esi ++ movl %esi, 4(%ebx) ++ movl 36(%esp), %esi ++ movl %edx, (%ebx) ++ movl 40(%esp), %edi ++ movl 44(%esp), %eax ++ movl $0, 8(%esp) ++ movl %eax, 4(%esp) ++ movl %ebx, (%esp) ++ call des_encrypt2 ++ movl $1, 8(%esp) ++ movl %edi, 4(%esp) ++ movl %ebx, (%esp) ++ call des_encrypt2 ++ movl $0, 8(%esp) ++ movl %esi, 4(%esp) ++ movl %ebx, (%esp) ++ call des_encrypt2 ++ addl $12, %esp ++ movl (%ebx), %edi ++ movl 4(%ebx), %esi ++ ++ ++ roll $2, %esi ++ roll $3, %edi ++ movl %edi, %eax ++ xorl %esi, %edi ++ andl $0xaaaaaaaa, %edi ++ xorl %edi, %eax ++ xorl %edi, %esi ++ ++ roll $23, %eax ++ movl %eax, %edi ++ xorl %esi, %eax ++ andl $0x03fc03fc, %eax ++ xorl %eax, %edi ++ xorl %eax, %esi ++ ++ roll $10, %edi ++ movl %edi, %eax ++ xorl %esi, %edi ++ andl $0x33333333, %edi ++ xorl %edi, %eax ++ xorl %edi, %esi ++ ++ roll $18, %esi ++ movl %esi, %edi ++ xorl %eax, %esi ++ andl $0xfff0000f, %esi ++ xorl %esi, %edi ++ xorl %esi, %eax ++ ++ roll $12, %edi ++ movl %edi, %esi ++ xorl %eax, %edi ++ andl $0xf0f0f0f0, %edi ++ xorl %edi, %esi ++ xorl %edi, %eax ++ ++ rorl $4, %eax ++ movl %eax, (%ebx) ++ movl %esi, 4(%ebx) ++ popl %edi ++ popl %esi ++ popl %ebp ++ popl %ebx ++ ret ++.des_decrypt3_end: ++ .size des_decrypt3 , .des_decrypt3_end-des_decrypt3 ++.ident "desasm.pl" ++.text ++ .align 16 ++.globl des_ncbc_encrypt ++ .type des_ncbc_encrypt , @function ++des_ncbc_encrypt: ++ ++ pushl %ebp ++ pushl %ebx ++ pushl %esi ++ pushl %edi ++ movl 28(%esp), %ebp ++ ++ movl 36(%esp), %ebx ++ movl (%ebx), %esi ++ movl 4(%ebx), %edi ++ pushl %edi ++ pushl %esi ++ pushl %edi ++ pushl %esi ++ movl %esp, %ebx ++ movl 36(%esp), %esi ++ movl 40(%esp), %edi ++ ++ movl 56(%esp), %ecx ++ ++ pushl %ecx ++ ++ movl 52(%esp), %eax ++ pushl %eax ++ pushl %ebx ++ cmpl $0, %ecx ++ jz .L004decrypt ++ andl $4294967288, %ebp ++ movl 12(%esp), %eax ++ movl 16(%esp), %ebx ++ jz .L005encrypt_finish ++.L006encrypt_loop: ++ movl (%esi), %ecx ++ movl 4(%esi), %edx ++ xorl %ecx, %eax ++ xorl %edx, %ebx ++ movl %eax, 12(%esp) ++ movl %ebx, 16(%esp) ++ call des_encrypt ++ movl 12(%esp), %eax ++ movl 16(%esp), %ebx ++ movl %eax, (%edi) ++ movl %ebx, 4(%edi) ++ addl $8, %esi ++ addl $8, %edi ++ subl $8, %ebp ++ jnz .L006encrypt_loop ++.L005encrypt_finish: ++ movl 56(%esp), %ebp ++ andl $7, %ebp ++ jz .L007finish ++ xorl %ecx, %ecx ++ xorl %edx, %edx ++ movl .L008cbc_enc_jmp_table(,%ebp,4),%ebp ++ jmp *%ebp ++.L009ej7: ++ movb 6(%esi), %dh ++ sall $8, %edx ++.L010ej6: ++ movb 5(%esi), %dh ++.L011ej5: ++ movb 4(%esi), %dl ++.L012ej4: ++ movl (%esi), %ecx ++ jmp .L013ejend ++.L014ej3: ++ movb 2(%esi), %ch ++ sall $8, %ecx ++.L015ej2: ++ movb 1(%esi), %ch ++.L016ej1: ++ movb (%esi), %cl ++.L013ejend: ++ xorl %ecx, %eax ++ xorl %edx, %ebx ++ movl %eax, 12(%esp) ++ movl %ebx, 16(%esp) ++ call des_encrypt ++ movl 12(%esp), %eax ++ movl 16(%esp), %ebx ++ movl %eax, (%edi) ++ movl %ebx, 4(%edi) ++ jmp .L007finish ++.align 16 ++.L004decrypt: ++ andl $4294967288, %ebp ++ movl 20(%esp), %eax ++ movl 24(%esp), %ebx ++ jz .L017decrypt_finish ++.L018decrypt_loop: ++ movl (%esi), %eax ++ movl 4(%esi), %ebx ++ movl %eax, 12(%esp) ++ movl %ebx, 16(%esp) ++ call des_encrypt ++ movl 12(%esp), %eax ++ movl 16(%esp), %ebx ++ movl 20(%esp), %ecx ++ movl 24(%esp), %edx ++ xorl %eax, %ecx ++ xorl %ebx, %edx ++ movl (%esi), %eax ++ movl 4(%esi), %ebx ++ movl %ecx, (%edi) ++ movl %edx, 4(%edi) ++ movl %eax, 20(%esp) ++ movl %ebx, 24(%esp) ++ addl $8, %esi ++ addl $8, %edi ++ subl $8, %ebp ++ jnz .L018decrypt_loop ++.L017decrypt_finish: ++ movl 56(%esp), %ebp ++ andl $7, %ebp ++ jz .L007finish ++ movl (%esi), %eax ++ movl 4(%esi), %ebx ++ movl %eax, 12(%esp) ++ movl %ebx, 16(%esp) ++ call des_encrypt ++ movl 12(%esp), %eax ++ movl 16(%esp), %ebx ++ movl 20(%esp), %ecx ++ movl 24(%esp), %edx ++ xorl %eax, %ecx ++ xorl %ebx, %edx ++ movl (%esi), %eax ++ movl 4(%esi), %ebx ++.L019dj7: ++ rorl $16, %edx ++ movb %dl, 6(%edi) ++ shrl $16, %edx ++.L020dj6: ++ movb %dh, 5(%edi) ++.L021dj5: ++ movb %dl, 4(%edi) ++.L022dj4: ++ movl %ecx, (%edi) ++ jmp .L023djend ++.L024dj3: ++ rorl $16, %ecx ++ movb %cl, 2(%edi) ++ sall $16, %ecx ++.L025dj2: ++ movb %ch, 1(%esi) ++.L026dj1: ++ movb %cl, (%esi) ++.L023djend: ++ jmp .L007finish ++.align 16 ++.L007finish: ++ movl 64(%esp), %ecx ++ addl $28, %esp ++ movl %eax, (%ecx) ++ movl %ebx, 4(%ecx) ++ popl %edi ++ popl %esi ++ popl %ebx ++ popl %ebp ++ ret ++.align 16 ++.L008cbc_enc_jmp_table: ++ .long 0 ++ .long .L016ej1 ++ .long .L015ej2 ++ .long .L014ej3 ++ .long .L012ej4 ++ .long .L011ej5 ++ .long .L010ej6 ++ .long .L009ej7 ++.align 16 ++.L027cbc_dec_jmp_table: ++ .long 0 ++ .long .L026dj1 ++ .long .L025dj2 ++ .long .L024dj3 ++ .long .L022dj4 ++ .long .L021dj5 ++ .long .L020dj6 ++ .long .L019dj7 ++.des_ncbc_encrypt_end: ++ .size des_ncbc_encrypt , .des_ncbc_encrypt_end-des_ncbc_encrypt ++.ident "desasm.pl" ++.text ++ .align 16 ++.globl des_ede3_cbc_encrypt ++ .type des_ede3_cbc_encrypt , @function ++des_ede3_cbc_encrypt: ++ ++ pushl %ebp ++ pushl %ebx ++ pushl %esi ++ pushl %edi ++ movl 28(%esp), %ebp ++ ++ movl 44(%esp), %ebx ++ movl (%ebx), %esi ++ movl 4(%ebx), %edi ++ pushl %edi ++ pushl %esi ++ pushl %edi ++ pushl %esi ++ movl %esp, %ebx ++ movl 36(%esp), %esi ++ movl 40(%esp), %edi ++ ++ movl 64(%esp), %ecx ++ ++ movl 56(%esp), %eax ++ pushl %eax ++ ++ movl 56(%esp), %eax ++ pushl %eax ++ ++ movl 56(%esp), %eax ++ pushl %eax ++ pushl %ebx ++ cmpl $0, %ecx ++ jz .L028decrypt ++ andl $4294967288, %ebp ++ movl 16(%esp), %eax ++ movl 20(%esp), %ebx ++ jz .L029encrypt_finish ++.L030encrypt_loop: ++ movl (%esi), %ecx ++ movl 4(%esi), %edx ++ xorl %ecx, %eax ++ xorl %edx, %ebx ++ movl %eax, 16(%esp) ++ movl %ebx, 20(%esp) ++ call des_encrypt3 ++ movl 16(%esp), %eax ++ movl 20(%esp), %ebx ++ movl %eax, (%edi) ++ movl %ebx, 4(%edi) ++ addl $8, %esi ++ addl $8, %edi ++ subl $8, %ebp ++ jnz .L030encrypt_loop ++.L029encrypt_finish: ++ movl 60(%esp), %ebp ++ andl $7, %ebp ++ jz .L031finish ++ xorl %ecx, %ecx ++ xorl %edx, %edx ++ movl .L032cbc_enc_jmp_table(,%ebp,4),%ebp ++ jmp *%ebp ++.L033ej7: ++ movb 6(%esi), %dh ++ sall $8, %edx ++.L034ej6: ++ movb 5(%esi), %dh ++.L035ej5: ++ movb 4(%esi), %dl ++.L036ej4: ++ movl (%esi), %ecx ++ jmp .L037ejend ++.L038ej3: ++ movb 2(%esi), %ch ++ sall $8, %ecx ++.L039ej2: ++ movb 1(%esi), %ch ++.L040ej1: ++ movb (%esi), %cl ++.L037ejend: ++ xorl %ecx, %eax ++ xorl %edx, %ebx ++ movl %eax, 16(%esp) ++ movl %ebx, 20(%esp) ++ call des_encrypt3 ++ movl 16(%esp), %eax ++ movl 20(%esp), %ebx ++ movl %eax, (%edi) ++ movl %ebx, 4(%edi) ++ jmp .L031finish ++.align 16 ++.L028decrypt: ++ andl $4294967288, %ebp ++ movl 24(%esp), %eax ++ movl 28(%esp), %ebx ++ jz .L041decrypt_finish ++.L042decrypt_loop: ++ movl (%esi), %eax ++ movl 4(%esi), %ebx ++ movl %eax, 16(%esp) ++ movl %ebx, 20(%esp) ++ call des_decrypt3 ++ movl 16(%esp), %eax ++ movl 20(%esp), %ebx ++ movl 24(%esp), %ecx ++ movl 28(%esp), %edx ++ xorl %eax, %ecx ++ xorl %ebx, %edx ++ movl (%esi), %eax ++ movl 4(%esi), %ebx ++ movl %ecx, (%edi) ++ movl %edx, 4(%edi) ++ movl %eax, 24(%esp) ++ movl %ebx, 28(%esp) ++ addl $8, %esi ++ addl $8, %edi ++ subl $8, %ebp ++ jnz .L042decrypt_loop ++.L041decrypt_finish: ++ movl 60(%esp), %ebp ++ andl $7, %ebp ++ jz .L031finish ++ movl (%esi), %eax ++ movl 4(%esi), %ebx ++ movl %eax, 16(%esp) ++ movl %ebx, 20(%esp) ++ call des_decrypt3 ++ movl 16(%esp), %eax ++ movl 20(%esp), %ebx ++ movl 24(%esp), %ecx ++ movl 28(%esp), %edx ++ xorl %eax, %ecx ++ xorl %ebx, %edx ++ movl (%esi), %eax ++ movl 4(%esi), %ebx ++.L043dj7: ++ rorl $16, %edx ++ movb %dl, 6(%edi) ++ shrl $16, %edx ++.L044dj6: ++ movb %dh, 5(%edi) ++.L045dj5: ++ movb %dl, 4(%edi) ++.L046dj4: ++ movl %ecx, (%edi) ++ jmp .L047djend ++.L048dj3: ++ rorl $16, %ecx ++ movb %cl, 2(%edi) ++ sall $16, %ecx ++.L049dj2: ++ movb %ch, 1(%esi) ++.L050dj1: ++ movb %cl, (%esi) ++.L047djend: ++ jmp .L031finish ++.align 16 ++.L031finish: ++ movl 76(%esp), %ecx ++ addl $32, %esp ++ movl %eax, (%ecx) ++ movl %ebx, 4(%ecx) ++ popl %edi ++ popl %esi ++ popl %ebx ++ popl %ebp ++ ret ++.align 16 ++.L032cbc_enc_jmp_table: ++ .long 0 ++ .long .L040ej1 ++ .long .L039ej2 ++ .long .L038ej3 ++ .long .L036ej4 ++ .long .L035ej5 ++ .long .L034ej6 ++ .long .L033ej7 ++.align 16 ++.L051cbc_dec_jmp_table: ++ .long 0 ++ .long .L050dj1 ++ .long .L049dj2 ++ .long .L048dj3 ++ .long .L046dj4 ++ .long .L045dj5 ++ .long .L044dj6 ++ .long .L043dj7 ++.des_ede3_cbc_encrypt_end: ++ .size des_ede3_cbc_encrypt , .des_ede3_cbc_encrypt_end-des_ede3_cbc_encrypt ++.ident "desasm.pl" +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/ecb_enc.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,128 @@ ++/* crypto/des/ecb_enc.c */ ++/* Copyright (C) 1995-1997 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 "des_locl.h" ++#include "spr.h" ++ ++char *libdes_version="libdes v 3.24 - 20-Apr-1996 - eay"; ++char *DES_version="DES part of SSLeay 0.8.2b 08-Jan-1998"; ++ ++/* RCSID $Id: ecb_enc.c,v 1.6 2002/04/24 07:36:38 mcr Exp $ */ ++/* This function ifdef'ed out for FreeS/WAN project. */ ++#ifdef notdef ++char *des_options() ++ { ++ static int init=1; ++ static char buf[32]; ++ ++ if (init) ++ { ++ char *ptr,*unroll,*risc,*size; ++ ++ init=0; ++#ifdef DES_PTR ++ ptr="ptr"; ++#else ++ ptr="idx"; ++#endif ++#if defined(DES_RISC1) || defined(DES_RISC2) ++#ifdef DES_RISC1 ++ risc="risc1"; ++#endif ++#ifdef DES_RISC2 ++ risc="risc2"; ++#endif ++#else ++ risc="cisc"; ++#endif ++#ifdef DES_UNROLL ++ unroll="16"; ++#else ++ unroll="4"; ++#endif ++ if (sizeof(DES_LONG) != sizeof(long)) ++ size="int"; ++ else ++ size="long"; ++ sprintf(buf,"des(%s,%s,%s,%s)",ptr,risc,unroll,size); ++ } ++ return(buf); ++ } ++#endif ++ ++ ++void des_ecb_encrypt(input, output, ks, enc) ++des_cblock (*input); ++des_cblock (*output); ++des_key_schedule ks; ++int enc; ++ { ++ register DES_LONG l; ++ register unsigned char *in,*out; ++ DES_LONG ll[2]; ++ ++ in=(unsigned char *)input; ++ out=(unsigned char *)output; ++ c2l(in,l); ll[0]=l; ++ c2l(in,l); ll[1]=l; ++ des_encrypt(ll,ks,enc); ++ l=ll[0]; l2c(l,out); ++ l=ll[1]; l2c(l,out); ++ l=ll[0]=ll[1]=0; ++ } ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/fcrypt.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,152 @@ ++/* NOCW */ ++ ++/* This version of crypt has been developed from my MIT compatable ++ * DES library. ++ * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au ++ * Eric Young (eay@cryptsoft.com) ++ */ ++ ++/* Modification by Jens Kupferschmidt (Cu) ++ * I have included directive PARA for shared memory computers. ++ * I have included a directive LONGCRYPT to using this routine to cipher ++ * passwords with more then 8 bytes like HP-UX 10.x it used. The MAXPLEN ++ * definition is the maximum of lenght of password and can changed. I have ++ * defined 24. ++ */ ++ ++#include "des_locl.h" ++ ++/* Added more values to handle illegal salt values the way normal ++ * crypt() implementations do. The patch was sent by ++ * Bjorn Gronvall <bg@sics.se> ++ */ ++static unsigned const char con_salt[128]={ ++0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9, ++0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1, ++0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, ++0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1, ++0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9, ++0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01, ++0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, ++0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A, ++0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12, ++0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A, ++0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22, ++0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24, ++0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C, ++0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34, ++0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C, ++0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44, ++}; ++ ++static unsigned const char cov_2char[64]={ ++0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35, ++0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44, ++0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C, ++0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54, ++0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62, ++0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A, ++0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72, ++0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A ++}; ++ ++#ifndef NOPROTO ++void fcrypt_body(DES_LONG *out,des_key_schedule ks, ++ DES_LONG Eswap0, DES_LONG Eswap1); ++ ++#ifdef PERL5 ++char *des_crypt(const char *buf,const char *salt); ++#else ++char *crypt(const char *buf,const char *salt); ++#endif ++#else ++void fcrypt_body(); ++#ifdef PERL5 ++char *des_crypt(); ++#else ++char *crypt(); ++#endif ++#endif ++ ++#ifdef PERL5 ++char *des_crypt(buf,salt) ++#else ++char *crypt(buf,salt) ++#endif ++const char *buf; ++const char *salt; ++ { ++ static char buff[14]; ++ ++ return(des_fcrypt(buf,salt,buff)); ++ } ++ ++ ++char *des_fcrypt(buf,salt,ret) ++const char *buf; ++const char *salt; ++char *ret; ++ { ++ unsigned int i,j,x,y; ++ DES_LONG Eswap0,Eswap1; ++ DES_LONG out[2],ll; ++ des_cblock key; ++ des_key_schedule ks; ++ unsigned char bb[9]; ++ unsigned char *b=bb; ++ unsigned char c,u; ++ ++ /* eay 25/08/92 ++ * If you call crypt("pwd","*") as often happens when you ++ * have * as the pwd field in /etc/passwd, the function ++ * returns *\0XXXXXXXXX ++ * The \0 makes the string look like * so the pwd "*" would ++ * crypt to "*". This was found when replacing the crypt in ++ * our shared libraries. People found that the disbled ++ * accounts effectivly had no passwd :-(. */ ++ x=ret[0]=((salt[0] == '\0')?'A':salt[0]); ++ Eswap0=con_salt[x]<<2; ++ x=ret[1]=((salt[1] == '\0')?'A':salt[1]); ++ Eswap1=con_salt[x]<<6; ++ ++/* EAY ++r=strlen(buf); ++r=(r+7)/8; ++*/ ++ for (i=0; i<8; i++) ++ { ++ c= *(buf++); ++ if (!c) break; ++ key[i]=(c<<1); ++ } ++ for (; i<8; i++) ++ key[i]=0; ++ ++ des_set_key((des_cblock *)(key),ks); ++ fcrypt_body(&(out[0]),ks,Eswap0,Eswap1); ++ ++ ll=out[0]; l2c(ll,b); ++ ll=out[1]; l2c(ll,b); ++ y=0; ++ u=0x80; ++ bb[8]=0; ++ for (i=2; i<13; i++) ++ { ++ c=0; ++ for (j=0; j<6; j++) ++ { ++ c<<=1; ++ if (bb[y] & u) c|=1; ++ u>>=1; ++ if (!u) ++ { ++ y++; ++ u=0x80; ++ } ++ } ++ ret[i]=cov_2char[c]; ++ } ++ ret[13]='\0'; ++ return(ret); ++ } ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/fcrypt_b.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,148 @@ ++/* crypto/des/fcrypt_b.c */ ++/* Copyright (C) 1995-1997 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 <stdio.h> */ ++ ++/* This version of crypt has been developed from my MIT compatable ++ * DES library. ++ * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au ++ * Eric Young (eay@cryptsoft.com) ++ */ ++ ++#define DES_FCRYPT ++#include "des_locl.h" ++#undef DES_FCRYPT ++ ++#undef PERM_OP ++#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ ++ (b)^=(t),\ ++ (a)^=((t)<<(n))) ++ ++#undef HPERM_OP ++#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ ++ (a)=(a)^(t)^(t>>(16-(n))))\ ++ ++void fcrypt_body(out, ks, Eswap0, Eswap1) ++DES_LONG *out; ++des_key_schedule ks; ++DES_LONG Eswap0; ++DES_LONG Eswap1; ++ { ++ register DES_LONG l,r,t,u; ++#ifdef DES_PTR ++ register unsigned char *des_SP=(unsigned char *)des_SPtrans; ++#endif ++ register DES_LONG *s; ++ register int j; ++ register DES_LONG E0,E1; ++ ++ l=0; ++ r=0; ++ ++ s=(DES_LONG *)ks; ++ E0=Eswap0; ++ E1=Eswap1; ++ ++ for (j=0; j<25; j++) ++ { ++#ifdef DES_UNROLL ++ register int i; ++ ++ for (i=0; i<32; i+=8) ++ { ++ D_ENCRYPT(l,r,i+0); /* 1 */ ++ D_ENCRYPT(r,l,i+2); /* 2 */ ++ D_ENCRYPT(l,r,i+4); /* 1 */ ++ D_ENCRYPT(r,l,i+6); /* 2 */ ++ } ++#else ++ D_ENCRYPT(l,r, 0); /* 1 */ ++ D_ENCRYPT(r,l, 2); /* 2 */ ++ D_ENCRYPT(l,r, 4); /* 3 */ ++ D_ENCRYPT(r,l, 6); /* 4 */ ++ D_ENCRYPT(l,r, 8); /* 5 */ ++ D_ENCRYPT(r,l,10); /* 6 */ ++ D_ENCRYPT(l,r,12); /* 7 */ ++ D_ENCRYPT(r,l,14); /* 8 */ ++ D_ENCRYPT(l,r,16); /* 9 */ ++ D_ENCRYPT(r,l,18); /* 10 */ ++ D_ENCRYPT(l,r,20); /* 11 */ ++ D_ENCRYPT(r,l,22); /* 12 */ ++ D_ENCRYPT(l,r,24); /* 13 */ ++ D_ENCRYPT(r,l,26); /* 14 */ ++ D_ENCRYPT(l,r,28); /* 15 */ ++ D_ENCRYPT(r,l,30); /* 16 */ ++#endif ++ ++ t=l; ++ l=r; ++ r=t; ++ } ++ l=ROTATE(l,3)&0xffffffffL; ++ r=ROTATE(r,3)&0xffffffffL; ++ ++ PERM_OP(l,r,t, 1,0x55555555L); ++ PERM_OP(r,l,t, 8,0x00ff00ffL); ++ PERM_OP(l,r,t, 2,0x33333333L); ++ PERM_OP(r,l,t,16,0x0000ffffL); ++ PERM_OP(l,r,t, 4,0x0f0f0f0fL); ++ ++ out[0]=r; ++ out[1]=l; ++ } ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/options.txt Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,39 @@ ++Note that the UNROLL option makes the 'inner' des loop unroll all 16 rounds ++instead of the default 4. ++RISC1 and RISC2 are 2 alternatives for the inner loop and ++PTR means to use pointers arithmatic instead of arrays. ++ ++FreeBSD - Pentium Pro 200mhz - gcc 2.7.2.2 - assembler 577,000 4620k/s ++IRIX 6.2 - R10000 195mhz - cc (-O3 -n32) - UNROLL RISC2 PTR 496,000 3968k/s ++solaris 2.5.1 usparc 167mhz?? - SC4.0 - UNROLL RISC1 PTR [1] 459,400 3672k/s ++FreeBSD - Pentium Pro 200mhz - gcc 2.7.2.2 - UNROLL RISC1 433,000 3468k/s ++solaris 2.5.1 usparc 167mhz?? - gcc 2.7.2 - UNROLL 380,000 3041k/s ++linux - pentium 100mhz - gcc 2.7.0 - assembler 281,000 2250k/s ++NT 4.0 - pentium 100mhz - VC 4.2 - assembler 281,000 2250k/s ++AIX 4.1? - PPC604 100mhz - cc - UNROLL 275,000 2200k/s ++IRIX 5.3 - R4400 200mhz - gcc 2.6.3 - UNROLL RISC2 PTR 235,300 1882k/s ++IRIX 5.3 - R4400 200mhz - cc - UNROLL RISC2 PTR 233,700 1869k/s ++NT 4.0 - pentium 100mhz - VC 4.2 - UNROLL RISC1 PTR 191,000 1528k/s ++DEC Alpha 165mhz?? - cc - RISC2 PTR [2] 181,000 1448k/s ++linux - pentium 100mhz - gcc 2.7.0 - UNROLL RISC1 PTR 158,500 1268k/s ++HPUX 10 - 9000/887 - cc - UNROLL [3] 148,000 1190k/s ++solaris 2.5.1 - sparc 10 50mhz - gcc 2.7.2 - UNROLL 123,600 989k/s ++IRIX 5.3 - R4000 100mhz - cc - UNROLL RISC2 PTR 101,000 808k/s ++DGUX - 88100 50mhz(?) - gcc 2.6.3 - UNROLL 81,000 648k/s ++solaris 2.4 486 50mhz - gcc 2.6.3 - assembler 65,000 522k/s ++HPUX 10 - 9000/887 - k&r cc (default compiler) - UNROLL PTR 76,000 608k/s ++solaris 2.4 486 50mhz - gcc 2.6.3 - UNROLL RISC2 43,500 344k/s ++AIX - old slow one :-) - cc - 39,000 312k/s ++ ++Notes. ++[1] For the ultra sparc, SunC 4.0 ++ cc -xtarget=ultra -xarch=v8plus -Xa -xO5, running 'des_opts' ++ gives a speed of 344,000 des/s while 'speed' gives 459,000 des/s. ++ I'll record the higher since it is coming from the library but it ++ is all rather weird. ++[2] Similar to the ultra sparc ([1]), 181,000 for 'des_opts' vs 175,000. ++[3] I was unable to get access to this machine when it was not heavily loaded. ++ As such, my timing program was never able to get more that %30 of the CPU. ++ This would cause the program to give much lower speed numbers because ++ it would be 'fighting' to stay in the cache with the other CPU burning ++ processes. +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/podd.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,75 @@ ++/* crypto/des/podd.h */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++static const unsigned char odd_parity[256]={ ++ 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, ++ 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, ++ 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, ++ 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, ++ 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, ++ 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, ++ 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, ++112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, ++128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, ++145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, ++161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, ++176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, ++193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, ++208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, ++224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, ++241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/set_key.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,246 @@ ++/* crypto/des/set_key.c */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++/* set_key.c v 1.4 eay 24/9/91 ++ * 1.4 Speed up by 400% :-) ++ * 1.3 added register declarations. ++ * 1.2 unrolled make_key_sched a bit more ++ * 1.1 added norm_expand_bits ++ * 1.0 First working version ++ */ ++#include "des_locl.h" ++#include "podd.h" ++#include "sk.h" ++ ++#ifndef NOPROTO ++static int check_parity(des_cblock (*key)); ++#else ++static int check_parity(); ++#endif ++ ++int des_check_key=0; ++ ++void des_set_odd_parity(key) ++des_cblock (*key); ++ { ++ int i; ++ ++ for (i=0; i<DES_KEY_SZ; i++) ++ (*key)[i]=odd_parity[(*key)[i]]; ++ } ++ ++static int check_parity(key) ++des_cblock (*key); ++ { ++ int i; ++ ++ for (i=0; i<DES_KEY_SZ; i++) ++ { ++ if ((*key)[i] != odd_parity[(*key)[i]]) ++ return(0); ++ } ++ return(1); ++ } ++ ++/* Weak and semi week keys as take from ++ * %A D.W. Davies ++ * %A W.L. Price ++ * %T Security for Computer Networks ++ * %I John Wiley & Sons ++ * %D 1984 ++ * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference ++ * (and actual cblock values). ++ */ ++#define NUM_WEAK_KEY 16 ++static des_cblock weak_keys[NUM_WEAK_KEY]={ ++ /* weak keys */ ++ {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, ++ {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE}, ++ {0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}, ++ {0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0}, ++ /* semi-weak keys */ ++ {0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE}, ++ {0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01}, ++ {0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1}, ++ {0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E}, ++ {0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1}, ++ {0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01}, ++ {0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE}, ++ {0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E}, ++ {0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E}, ++ {0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01}, ++ {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE}, ++ {0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}}; ++ ++int des_is_weak_key(key) ++des_cblock (*key); ++ { ++ int i; ++ ++ for (i=0; i<NUM_WEAK_KEY; i++) ++ /* Added == 0 to comparision, I obviously don't run ++ * this section very often :-(, thanks to ++ * engineering@MorningStar.Com for the fix ++ * eay 93/06/29 ++ * Another problem, I was comparing only the first 4 ++ * bytes, 97/03/18 */ ++ if (memcmp(weak_keys[i],key,sizeof(des_cblock)) == 0) return(1); ++ return(0); ++ } ++ ++/* NOW DEFINED IN des_local.h ++ * See ecb_encrypt.c for a pseudo description of these macros. ++ * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ ++ * (b)^=(t),\ ++ * (a)=((a)^((t)<<(n)))) ++ */ ++ ++#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ ++ (a)=(a)^(t)^(t>>(16-(n)))) ++ ++/* return 0 if key parity is odd (correct), ++ * return -1 if key parity error, ++ * return -2 if illegal weak key. ++ */ ++int des_set_key(key, schedule) ++des_cblock (*key); ++des_key_schedule schedule; ++ { ++ static int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; ++ register DES_LONG c,d,t,s,t2; ++ register unsigned char *in; ++ register DES_LONG *k; ++ register int i; ++ ++ if (des_check_key) ++ { ++ if (!check_parity(key)) ++ return(-1); ++ ++ if (des_is_weak_key(key)) ++ return(-2); ++ } ++ ++ k=(DES_LONG *)schedule; ++ in=(unsigned char *)key; ++ ++ c2l(in,c); ++ c2l(in,d); ++ ++ /* do PC1 in 60 simple operations */ ++/* PERM_OP(d,c,t,4,0x0f0f0f0fL); ++ HPERM_OP(c,t,-2, 0xcccc0000L); ++ HPERM_OP(c,t,-1, 0xaaaa0000L); ++ HPERM_OP(c,t, 8, 0x00ff0000L); ++ HPERM_OP(c,t,-1, 0xaaaa0000L); ++ HPERM_OP(d,t,-8, 0xff000000L); ++ HPERM_OP(d,t, 8, 0x00ff0000L); ++ HPERM_OP(d,t, 2, 0x33330000L); ++ d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L); ++ d=(d>>8)|((c&0xf0000000L)>>4); ++ c&=0x0fffffffL; */ ++ ++ /* I now do it in 47 simple operations :-) ++ * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) ++ * for the inspiration. :-) */ ++ PERM_OP (d,c,t,4,0x0f0f0f0fL); ++ HPERM_OP(c,t,-2,0xcccc0000L); ++ HPERM_OP(d,t,-2,0xcccc0000L); ++ PERM_OP (d,c,t,1,0x55555555L); ++ PERM_OP (c,d,t,8,0x00ff00ffL); ++ PERM_OP (d,c,t,1,0x55555555L); ++ d= (((d&0x000000ffL)<<16L)| (d&0x0000ff00L) | ++ ((d&0x00ff0000L)>>16L)|((c&0xf0000000L)>>4L)); ++ c&=0x0fffffffL; ++ ++ for (i=0; i<ITERATIONS; i++) ++ { ++ if (shifts2[i]) ++ { c=((c>>2L)|(c<<26L)); d=((d>>2L)|(d<<26L)); } ++ else ++ { c=((c>>1L)|(c<<27L)); d=((d>>1L)|(d<<27L)); } ++ c&=0x0fffffffL; ++ d&=0x0fffffffL; ++ /* could be a few less shifts but I am to lazy at this ++ * point in time to investigate */ ++ s= des_skb[0][ (c )&0x3f ]| ++ des_skb[1][((c>> 6)&0x03)|((c>> 7L)&0x3c)]| ++ des_skb[2][((c>>13)&0x0f)|((c>>14L)&0x30)]| ++ des_skb[3][((c>>20)&0x01)|((c>>21L)&0x06) | ++ ((c>>22L)&0x38)]; ++ t= des_skb[4][ (d )&0x3f ]| ++ des_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]| ++ des_skb[6][ (d>>15L)&0x3f ]| ++ des_skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)]; ++ ++ /* table contained 0213 4657 */ ++ t2=((t<<16L)|(s&0x0000ffffL))&0xffffffffL; ++ *(k++)=ROTATE(t2,30)&0xffffffffL; ++ ++ t2=((s>>16L)|(t&0xffff0000L)); ++ *(k++)=ROTATE(t2,26)&0xffffffffL; ++ } ++ return(0); ++ } ++ ++int des_key_sched(key, schedule) ++des_cblock (*key); ++des_key_schedule schedule; ++ { ++ return(des_set_key(key,schedule)); ++ } +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/sk.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,204 @@ ++/* crypto/des/sk.h */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++static const DES_LONG des_skb[8][64]={ ++{ ++/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ ++0x00000000L,0x00000010L,0x20000000L,0x20000010L, ++0x00010000L,0x00010010L,0x20010000L,0x20010010L, ++0x00000800L,0x00000810L,0x20000800L,0x20000810L, ++0x00010800L,0x00010810L,0x20010800L,0x20010810L, ++0x00000020L,0x00000030L,0x20000020L,0x20000030L, ++0x00010020L,0x00010030L,0x20010020L,0x20010030L, ++0x00000820L,0x00000830L,0x20000820L,0x20000830L, ++0x00010820L,0x00010830L,0x20010820L,0x20010830L, ++0x00080000L,0x00080010L,0x20080000L,0x20080010L, ++0x00090000L,0x00090010L,0x20090000L,0x20090010L, ++0x00080800L,0x00080810L,0x20080800L,0x20080810L, ++0x00090800L,0x00090810L,0x20090800L,0x20090810L, ++0x00080020L,0x00080030L,0x20080020L,0x20080030L, ++0x00090020L,0x00090030L,0x20090020L,0x20090030L, ++0x00080820L,0x00080830L,0x20080820L,0x20080830L, ++0x00090820L,0x00090830L,0x20090820L,0x20090830L, ++},{ ++/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ ++0x00000000L,0x02000000L,0x00002000L,0x02002000L, ++0x00200000L,0x02200000L,0x00202000L,0x02202000L, ++0x00000004L,0x02000004L,0x00002004L,0x02002004L, ++0x00200004L,0x02200004L,0x00202004L,0x02202004L, ++0x00000400L,0x02000400L,0x00002400L,0x02002400L, ++0x00200400L,0x02200400L,0x00202400L,0x02202400L, ++0x00000404L,0x02000404L,0x00002404L,0x02002404L, ++0x00200404L,0x02200404L,0x00202404L,0x02202404L, ++0x10000000L,0x12000000L,0x10002000L,0x12002000L, ++0x10200000L,0x12200000L,0x10202000L,0x12202000L, ++0x10000004L,0x12000004L,0x10002004L,0x12002004L, ++0x10200004L,0x12200004L,0x10202004L,0x12202004L, ++0x10000400L,0x12000400L,0x10002400L,0x12002400L, ++0x10200400L,0x12200400L,0x10202400L,0x12202400L, ++0x10000404L,0x12000404L,0x10002404L,0x12002404L, ++0x10200404L,0x12200404L,0x10202404L,0x12202404L, ++},{ ++/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ ++0x00000000L,0x00000001L,0x00040000L,0x00040001L, ++0x01000000L,0x01000001L,0x01040000L,0x01040001L, ++0x00000002L,0x00000003L,0x00040002L,0x00040003L, ++0x01000002L,0x01000003L,0x01040002L,0x01040003L, ++0x00000200L,0x00000201L,0x00040200L,0x00040201L, ++0x01000200L,0x01000201L,0x01040200L,0x01040201L, ++0x00000202L,0x00000203L,0x00040202L,0x00040203L, ++0x01000202L,0x01000203L,0x01040202L,0x01040203L, ++0x08000000L,0x08000001L,0x08040000L,0x08040001L, ++0x09000000L,0x09000001L,0x09040000L,0x09040001L, ++0x08000002L,0x08000003L,0x08040002L,0x08040003L, ++0x09000002L,0x09000003L,0x09040002L,0x09040003L, ++0x08000200L,0x08000201L,0x08040200L,0x08040201L, ++0x09000200L,0x09000201L,0x09040200L,0x09040201L, ++0x08000202L,0x08000203L,0x08040202L,0x08040203L, ++0x09000202L,0x09000203L,0x09040202L,0x09040203L, ++},{ ++/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ ++0x00000000L,0x00100000L,0x00000100L,0x00100100L, ++0x00000008L,0x00100008L,0x00000108L,0x00100108L, ++0x00001000L,0x00101000L,0x00001100L,0x00101100L, ++0x00001008L,0x00101008L,0x00001108L,0x00101108L, ++0x04000000L,0x04100000L,0x04000100L,0x04100100L, ++0x04000008L,0x04100008L,0x04000108L,0x04100108L, ++0x04001000L,0x04101000L,0x04001100L,0x04101100L, ++0x04001008L,0x04101008L,0x04001108L,0x04101108L, ++0x00020000L,0x00120000L,0x00020100L,0x00120100L, ++0x00020008L,0x00120008L,0x00020108L,0x00120108L, ++0x00021000L,0x00121000L,0x00021100L,0x00121100L, ++0x00021008L,0x00121008L,0x00021108L,0x00121108L, ++0x04020000L,0x04120000L,0x04020100L,0x04120100L, ++0x04020008L,0x04120008L,0x04020108L,0x04120108L, ++0x04021000L,0x04121000L,0x04021100L,0x04121100L, ++0x04021008L,0x04121008L,0x04021108L,0x04121108L, ++},{ ++/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ ++0x00000000L,0x10000000L,0x00010000L,0x10010000L, ++0x00000004L,0x10000004L,0x00010004L,0x10010004L, ++0x20000000L,0x30000000L,0x20010000L,0x30010000L, ++0x20000004L,0x30000004L,0x20010004L,0x30010004L, ++0x00100000L,0x10100000L,0x00110000L,0x10110000L, ++0x00100004L,0x10100004L,0x00110004L,0x10110004L, ++0x20100000L,0x30100000L,0x20110000L,0x30110000L, ++0x20100004L,0x30100004L,0x20110004L,0x30110004L, ++0x00001000L,0x10001000L,0x00011000L,0x10011000L, ++0x00001004L,0x10001004L,0x00011004L,0x10011004L, ++0x20001000L,0x30001000L,0x20011000L,0x30011000L, ++0x20001004L,0x30001004L,0x20011004L,0x30011004L, ++0x00101000L,0x10101000L,0x00111000L,0x10111000L, ++0x00101004L,0x10101004L,0x00111004L,0x10111004L, ++0x20101000L,0x30101000L,0x20111000L,0x30111000L, ++0x20101004L,0x30101004L,0x20111004L,0x30111004L, ++},{ ++/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ ++0x00000000L,0x08000000L,0x00000008L,0x08000008L, ++0x00000400L,0x08000400L,0x00000408L,0x08000408L, ++0x00020000L,0x08020000L,0x00020008L,0x08020008L, ++0x00020400L,0x08020400L,0x00020408L,0x08020408L, ++0x00000001L,0x08000001L,0x00000009L,0x08000009L, ++0x00000401L,0x08000401L,0x00000409L,0x08000409L, ++0x00020001L,0x08020001L,0x00020009L,0x08020009L, ++0x00020401L,0x08020401L,0x00020409L,0x08020409L, ++0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, ++0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, ++0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, ++0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, ++0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, ++0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, ++0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, ++0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, ++},{ ++/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ ++0x00000000L,0x00000100L,0x00080000L,0x00080100L, ++0x01000000L,0x01000100L,0x01080000L,0x01080100L, ++0x00000010L,0x00000110L,0x00080010L,0x00080110L, ++0x01000010L,0x01000110L,0x01080010L,0x01080110L, ++0x00200000L,0x00200100L,0x00280000L,0x00280100L, ++0x01200000L,0x01200100L,0x01280000L,0x01280100L, ++0x00200010L,0x00200110L,0x00280010L,0x00280110L, ++0x01200010L,0x01200110L,0x01280010L,0x01280110L, ++0x00000200L,0x00000300L,0x00080200L,0x00080300L, ++0x01000200L,0x01000300L,0x01080200L,0x01080300L, ++0x00000210L,0x00000310L,0x00080210L,0x00080310L, ++0x01000210L,0x01000310L,0x01080210L,0x01080310L, ++0x00200200L,0x00200300L,0x00280200L,0x00280300L, ++0x01200200L,0x01200300L,0x01280200L,0x01280300L, ++0x00200210L,0x00200310L,0x00280210L,0x00280310L, ++0x01200210L,0x01200310L,0x01280210L,0x01280310L, ++},{ ++/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ ++0x00000000L,0x04000000L,0x00040000L,0x04040000L, ++0x00000002L,0x04000002L,0x00040002L,0x04040002L, ++0x00002000L,0x04002000L,0x00042000L,0x04042000L, ++0x00002002L,0x04002002L,0x00042002L,0x04042002L, ++0x00000020L,0x04000020L,0x00040020L,0x04040020L, ++0x00000022L,0x04000022L,0x00040022L,0x04040022L, ++0x00002020L,0x04002020L,0x00042020L,0x04042020L, ++0x00002022L,0x04002022L,0x00042022L,0x04042022L, ++0x00000800L,0x04000800L,0x00040800L,0x04040800L, ++0x00000802L,0x04000802L,0x00040802L,0x04040802L, ++0x00002800L,0x04002800L,0x00042800L,0x04042800L, ++0x00002802L,0x04002802L,0x00042802L,0x04042802L, ++0x00000820L,0x04000820L,0x00040820L,0x04040820L, ++0x00000822L,0x04000822L,0x00040822L,0x04040822L, ++0x00002820L,0x04002820L,0x00042820L,0x04042820L, ++0x00002822L,0x04002822L,0x00042822L,0x04042822L, ++}}; +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/speed.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,329 @@ ++/* crypto/des/speed.c */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++/* 11-Sep-92 Andrew Daviel Support for Silicon Graphics IRIX added */ ++/* 06-Apr-92 Luke Brennan Support for VMS and add extra signal calls */ ++ ++#ifndef MSDOS ++#define TIMES ++#endif ++ ++#include <stdio.h> ++#ifndef MSDOS ++#include <unistd.h> ++#else ++#include <io.h> ++extern int exit(); ++#endif ++#include <signal.h> ++#ifndef VMS ++#ifndef _IRIX ++#include <time.h> ++#endif ++#ifdef TIMES ++#include <sys/types.h> ++#include <sys/times.h> ++#endif ++#else /* VMS */ ++#include <types.h> ++struct tms { ++ time_t tms_utime; ++ time_t tms_stime; ++ time_t tms_uchild; /* I dunno... */ ++ time_t tms_uchildsys; /* so these names are a guess :-) */ ++ } ++#endif ++#ifndef TIMES ++#include <sys/timeb.h> ++#endif ++ ++#ifdef sun ++#include <limits.h> ++#include <sys/param.h> ++#endif ++ ++#include "des_locl.h" ++ ++/* The following if from times(3) man page. It may need to be changed */ ++#ifndef HZ ++# ifndef CLK_TCK ++# ifndef _BSD_CLK_TCK_ /* FreeBSD fix */ ++# ifndef VMS ++# define HZ 100.0 ++# else /* VMS */ ++# define HZ 100.0 ++# endif ++# else /* _BSD_CLK_TCK_ */ ++# define HZ ((double)_BSD_CLK_TCK_) ++# endif ++# else /* CLK_TCK */ ++# define HZ ((double)CLK_TCK) ++# endif ++#endif ++ ++#define BUFSIZE ((long)1024) ++long run=0; ++ ++#ifndef NOPROTO ++double Time_F(int s); ++#else ++double Time_F(); ++#endif ++ ++#ifdef SIGALRM ++#if defined(__STDC__) || defined(sgi) || defined(_AIX) ++#define SIGRETTYPE void ++#else ++#define SIGRETTYPE int ++#endif ++ ++#ifndef NOPROTO ++SIGRETTYPE sig_done(int sig); ++#else ++SIGRETTYPE sig_done(); ++#endif ++ ++SIGRETTYPE sig_done(sig) ++int sig; ++ { ++ signal(SIGALRM,sig_done); ++ run=0; ++#ifdef LINT ++ sig=sig; ++#endif ++ } ++#endif ++ ++#define START 0 ++#define STOP 1 ++ ++double Time_F(s) ++int s; ++ { ++ double ret; ++#ifdef TIMES ++ static struct tms tstart,tend; ++ ++ if (s == START) ++ { ++ times(&tstart); ++ return(0); ++ } ++ else ++ { ++ times(&tend); ++ ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; ++ return((ret == 0.0)?1e-6:ret); ++ } ++#else /* !times() */ ++ static struct timeb tstart,tend; ++ long i; ++ ++ if (s == START) ++ { ++ ftime(&tstart); ++ return(0); ++ } ++ else ++ { ++ ftime(&tend); ++ i=(long)tend.millitm-(long)tstart.millitm; ++ ret=((double)(tend.time-tstart.time))+((double)i)/1e3; ++ return((ret == 0.0)?1e-6:ret); ++ } ++#endif ++ } ++ ++int main(argc,argv) ++int argc; ++char **argv; ++ { ++ long count; ++ static unsigned char buf[BUFSIZE]; ++ static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}; ++ static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12}; ++ static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34}; ++ des_key_schedule sch,sch2,sch3; ++ double a,b,c,d,e; ++#ifndef SIGALRM ++ long ca,cb,cc,cd,ce; ++#endif ++ ++#ifndef TIMES ++ printf("To get the most acurate results, try to run this\n"); ++ printf("program when this computer is idle.\n"); ++#endif ++ ++ des_set_key((C_Block *)key2,sch2); ++ des_set_key((C_Block *)key3,sch3); ++ ++#ifndef SIGALRM ++ printf("First we calculate the approximate speed ...\n"); ++ des_set_key((C_Block *)key,sch); ++ count=10; ++ do { ++ long i; ++ DES_LONG data[2]; ++ ++ count*=2; ++ Time_F(START); ++ for (i=count; i; i--) ++ des_encrypt(data,&(sch[0]),DES_ENCRYPT); ++ d=Time_F(STOP); ++ } while (d < 3.0); ++ ca=count; ++ cb=count*3; ++ cc=count*3*8/BUFSIZE+1; ++ cd=count*8/BUFSIZE+1; ++ ce=count/20+1; ++ printf("Doing set_key %ld times\n",ca); ++#define COND(d) (count != (d)) ++#define COUNT(d) (d) ++#else ++#define COND(c) (run) ++#define COUNT(d) (count) ++ signal(SIGALRM,sig_done); ++ printf("Doing set_key for 10 seconds\n"); ++ alarm(10); ++#endif ++ ++ Time_F(START); ++ for (count=0,run=1; COND(ca); count++) ++ des_set_key((C_Block *)key,sch); ++ d=Time_F(STOP); ++ printf("%ld set_key's in %.2f seconds\n",count,d); ++ a=((double)COUNT(ca))/d; ++ ++#ifdef SIGALRM ++ printf("Doing des_encrypt's for 10 seconds\n"); ++ alarm(10); ++#else ++ printf("Doing des_encrypt %ld times\n",cb); ++#endif ++ Time_F(START); ++ for (count=0,run=1; COND(cb); count++) ++ { ++ DES_LONG data[2]; ++ ++ des_encrypt(data,&(sch[0]),DES_ENCRYPT); ++ } ++ d=Time_F(STOP); ++ printf("%ld des_encrypt's in %.2f second\n",count,d); ++ b=((double)COUNT(cb)*8)/d; ++ ++#ifdef SIGALRM ++ printf("Doing des_cbc_encrypt on %ld byte blocks for 10 seconds\n", ++ BUFSIZE); ++ alarm(10); ++#else ++ printf("Doing des_cbc_encrypt %ld times on %ld byte blocks\n",cc, ++ BUFSIZE); ++#endif ++ Time_F(START); ++ for (count=0,run=1; COND(cc); count++) ++ des_ncbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE,&(sch[0]), ++ (C_Block *)&(key[0]),DES_ENCRYPT); ++ d=Time_F(STOP); ++ printf("%ld des_cbc_encrypt's of %ld byte blocks in %.2f second\n", ++ count,BUFSIZE,d); ++ c=((double)COUNT(cc)*BUFSIZE)/d; ++ ++#ifdef SIGALRM ++ printf("Doing des_ede_cbc_encrypt on %ld byte blocks for 10 seconds\n", ++ BUFSIZE); ++ alarm(10); ++#else ++ printf("Doing des_ede_cbc_encrypt %ld times on %ld byte blocks\n",cd, ++ BUFSIZE); ++#endif ++ Time_F(START); ++ for (count=0,run=1; COND(cd); count++) ++ des_ede3_cbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE, ++ &(sch[0]), ++ &(sch2[0]), ++ &(sch3[0]), ++ (C_Block *)&(key[0]), ++ DES_ENCRYPT); ++ d=Time_F(STOP); ++ printf("%ld des_ede_cbc_encrypt's of %ld byte blocks in %.2f second\n", ++ count,BUFSIZE,d); ++ d=((double)COUNT(cd)*BUFSIZE)/d; ++ ++#ifdef SIGALRM ++ printf("Doing crypt for 10 seconds\n"); ++ alarm(10); ++#else ++ printf("Doing crypt %ld times\n",ce); ++#endif ++ Time_F(START); ++ for (count=0,run=1; COND(ce); count++) ++ crypt("testing1","ef"); ++ e=Time_F(STOP); ++ printf("%ld crypts in %.2f second\n",count,e); ++ e=((double)COUNT(ce))/e; ++ ++ printf("set_key per sec = %12.2f (%9.3fuS)\n",a,1.0e6/a); ++ printf("DES raw ecb bytes per sec = %12.2f (%9.3fuS)\n",b,8.0e6/b); ++ printf("DES cbc bytes per sec = %12.2f (%9.3fuS)\n",c,8.0e6/c); ++ printf("DES ede cbc bytes per sec = %12.2f (%9.3fuS)\n",d,8.0e6/d); ++ printf("crypt per sec = %12.2f (%9.3fuS)\n",e,1.0e6/e); ++ exit(0); ++#if defined(LINT) || defined(MSDOS) ++ return(0); ++#endif ++ } +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/crypto/ciphers/des/spr.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,204 @@ ++/* crypto/des/spr.h */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++const DES_LONG des_SPtrans[8][64]={ ++{ ++/* nibble 0 */ ++0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, ++0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L, ++0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L, ++0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L, ++0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, ++0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, ++0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L, ++0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L, ++0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L, ++0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, ++0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, ++0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L, ++0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L, ++0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L, ++0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, ++0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, ++},{ ++/* nibble 1 */ ++0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, ++0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L, ++0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L, ++0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L, ++0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, ++0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, ++0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L, ++0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L, ++0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L, ++0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, ++0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, ++0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L, ++0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L, ++0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L, ++0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, ++0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, ++},{ ++/* nibble 2 */ ++0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, ++0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L, ++0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L, ++0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L, ++0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, ++0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, ++0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L, ++0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L, ++0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L, ++0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, ++0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, ++0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L, ++0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L, ++0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L, ++0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, ++0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, ++},{ ++/* nibble 3 */ ++0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, ++0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L, ++0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L, ++0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L, ++0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, ++0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, ++0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L, ++0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L, ++0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L, ++0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, ++0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, ++0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L, ++0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L, ++0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L, ++0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, ++0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, ++},{ ++/* nibble 4 */ ++0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, ++0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L, ++0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L, ++0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L, ++0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, ++0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, ++0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L, ++0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L, ++0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L, ++0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, ++0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, ++0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L, ++0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L, ++0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L, ++0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, ++0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, ++},{ ++/* nibble 5 */ ++0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, ++0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L, ++0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L, ++0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L, ++0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, ++0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, ++0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L, ++0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L, ++0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L, ++0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, ++0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, ++0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L, ++0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L, ++0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L, ++0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, ++0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, ++},{ ++/* nibble 6 */ ++0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, ++0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L, ++0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L, ++0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L, ++0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, ++0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, ++0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L, ++0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L, ++0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L, ++0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, ++0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, ++0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L, ++0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L, ++0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L, ++0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, ++0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, ++},{ ++/* nibble 7 */ ++0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, ++0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L, ++0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L, ++0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L, ++0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, ++0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, ++0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L, ++0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L, ++0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L, ++0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, ++0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, ++0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L, ++0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L, ++0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L, ++0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, ++0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, ++}}; +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/crypto/aes.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,97 @@ ++// I retain copyright in this code but I encourage its free use provided ++// that I don't carry any responsibility for the results. I am especially ++// happy to see it used in free and open source software. If you do use ++// it I would appreciate an acknowledgement of its origin in the code or ++// the product that results and I would also appreciate knowing a little ++// about the use to which it is being put. I am grateful to Frank Yellin ++// for some ideas that are used in this implementation. ++// ++// Dr B. R. Gladman <brg@gladman.uk.net> 6th April 2001. ++// ++// This is an implementation of the AES encryption algorithm (Rijndael) ++// designed by Joan Daemen and Vincent Rijmen. This version is designed ++// to provide both fixed and dynamic block and key lengths and can also ++// run with either big or little endian internal byte order (see aes.h). ++// It inputs block and key lengths in bytes with the legal values being ++// 16, 24 and 32. ++ ++/* ++ * Modified by Jari Ruusu, May 1 2001 ++ * - Fixed some compile warnings, code was ok but gcc warned anyway. ++ * - Changed basic types: byte -> unsigned char, word -> u_int32_t ++ * - Major name space cleanup: Names visible to outside now begin ++ * with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c ++ * - Removed C++ and DLL support as part of name space cleanup. ++ * - Eliminated unnecessary recomputation of tables. (actual bug fix) ++ * - Merged precomputed constant tables to aes.c file. ++ * - Removed data alignment restrictions for portability reasons. ++ * - Made block and key lengths accept bit count (128/192/256) ++ * as well byte count (16/24/32). ++ * - Removed all error checks. This change also eliminated the need ++ * to preinitialize the context struct to zero. ++ * - Removed some totally unused constants. ++ */ ++ ++#ifndef _AES_H ++#define _AES_H ++ ++#if defined(__linux__) && defined(__KERNEL__) ++# include <linux/types.h> ++#else ++# include <sys/types.h> ++#endif ++ ++// CONFIGURATION OPTIONS (see also aes.c) ++// ++// Define AES_BLOCK_SIZE to set the cipher block size (16, 24 or 32) or ++// leave this undefined for dynamically variable block size (this will ++// result in much slower code). ++// IMPORTANT NOTE: AES_BLOCK_SIZE is in BYTES (16, 24, 32 or undefined). If ++// left undefined a slower version providing variable block length is compiled ++ ++#define AES_BLOCK_SIZE 16 ++ ++// The number of key schedule words for different block and key lengths ++// allowing for method of computation which requires the length to be a ++// multiple of the key length ++// ++// Nk = 4 6 8 ++// ------------- ++// Nb = 4 | 60 60 64 ++// 6 | 96 90 96 ++// 8 | 120 120 120 ++ ++#if !defined(AES_BLOCK_SIZE) || (AES_BLOCK_SIZE == 32) ++#define AES_KS_LENGTH 120 ++#define AES_RC_LENGTH 29 ++#else ++#define AES_KS_LENGTH 4 * AES_BLOCK_SIZE ++#define AES_RC_LENGTH (9 * AES_BLOCK_SIZE) / 8 - 8 ++#endif ++ ++typedef struct ++{ ++ u_int32_t aes_Nkey; // the number of words in the key input block ++ u_int32_t aes_Nrnd; // the number of cipher rounds ++ u_int32_t aes_e_key[AES_KS_LENGTH]; // the encryption key schedule ++ u_int32_t aes_d_key[AES_KS_LENGTH]; // the decryption key schedule ++#if !defined(AES_BLOCK_SIZE) ++ u_int32_t aes_Ncol; // the number of columns in the cipher state ++#endif ++} aes_context; ++ ++// THE CIPHER INTERFACE ++ ++#if !defined(AES_BLOCK_SIZE) ++extern void aes_set_blk(aes_context *, const int); ++#endif ++extern void aes_set_key(aes_context *, const unsigned char [], const int, const int); ++extern void aes_encrypt(const aes_context *, const unsigned char [], unsigned char []); ++extern void aes_decrypt(const aes_context *, const unsigned char [], unsigned char []); ++ ++// The block length inputs to aes_set_block and aes_set_key are in numbers ++// of bytes or bits. The calls to subroutines must be made in the above ++// order but multiple calls can be made without repeating earlier calls ++// if their parameters have not changed. ++ ++#endif // _AES_H +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/crypto/aes_cbc.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,4 @@ ++/* Glue header */ ++#include "aes.h" ++int AES_set_key(aes_context *aes_ctx, const u_int8_t * key, int keysize); ++int AES_cbc_encrypt(aes_context *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt); +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/crypto/aes_xcbc_mac.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,12 @@ ++#ifndef _AES_XCBC_MAC_H ++#define _AES_XCBC_MAC_H ++ ++typedef u_int32_t aes_block[4]; ++typedef struct { ++ aes_context ctx_k1; ++ aes_block k2; ++ aes_block k3; ++} aes_context_mac; ++int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen); ++int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]); ++#endif /* _AES_XCBC_MAC_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/crypto/cbc_generic.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,110 @@ ++#ifndef _CBC_GENERIC_H ++#define _CBC_GENERIC_H ++/* ++ * CBC macro helpers ++ * ++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++ ++/* ++ * Heavily inspired in loop_AES ++ */ ++#define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \ ++int name(ctx_type *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \ ++ int ret=ilen, pos; \ ++ const u_int32_t *iv_i; \ ++ if ((ilen) % 16) return 0; \ ++ if (encrypt) { \ ++ pos=0; \ ++ while(pos<ilen) { \ ++ if (pos==0) \ ++ iv_i=(const u_int32_t*) iv; \ ++ else \ ++ iv_i=(const u_int32_t*) (out-16); \ ++ *((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \ ++ *((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \ ++ *((u_int32_t *)(&out[ 8])) = iv_i[2]^*((const u_int32_t *)(&in[ 8])); \ ++ *((u_int32_t *)(&out[12])) = iv_i[3]^*((const u_int32_t *)(&in[12])); \ ++ enc_func(ctx, (addr_type) out, (addr_type) out); \ ++ in+=16; \ ++ out+=16; \ ++ pos+=16; \ ++ } \ ++ } else { \ ++ pos=ilen-16; \ ++ in+=pos; \ ++ out+=pos; \ ++ while(pos>=0) { \ ++ dec_func(ctx, (const addr_type) in, (addr_type) out); \ ++ if (pos==0) \ ++ iv_i=(const u_int32_t*) (iv); \ ++ else \ ++ iv_i=(const u_int32_t*) (in-16); \ ++ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ ++ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ ++ *((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \ ++ *((u_int32_t *)(&out[12])) ^= iv_i[3]; \ ++ in-=16; \ ++ out-=16; \ ++ pos-=16; \ ++ } \ ++ } \ ++ return ret; \ ++} ++#define CBC_IMPL_BLK8(name, ctx_type, addr_type, enc_func, dec_func) \ ++int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \ ++ int ret=ilen, pos; \ ++ const u_int32_t *iv_i; \ ++ if ((ilen) % 8) return 0; \ ++ if (encrypt) { \ ++ pos=0; \ ++ while(pos<ilen) { \ ++ if (pos==0) \ ++ iv_i=(const u_int32_t*) iv; \ ++ else \ ++ iv_i=(const u_int32_t*) (out-8); \ ++ *((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \ ++ *((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \ ++ enc_func(ctx, (addr_type)out, (addr_type)out); \ ++ in+=8; \ ++ out+=8; \ ++ pos+=8; \ ++ } \ ++ } else { \ ++ pos=ilen-8; \ ++ in+=pos; \ ++ out+=pos; \ ++ while(pos>=0) { \ ++ dec_func(ctx, (const addr_type)in, (addr_type)out); \ ++ if (pos==0) \ ++ iv_i=(const u_int32_t*) (iv); \ ++ else \ ++ iv_i=(const u_int32_t*) (in-8); \ ++ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ ++ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ ++ in-=8; \ ++ out-=8; \ ++ pos-=8; \ ++ } \ ++ } \ ++ return ret; \ ++} ++#define CBC_DECL(name, ctx_type) \ ++int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) ++/* ++Eg.: ++CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); ++CBC_DECL(AES_cbc_encrypt, aes_context); ++*/ ++#endif /* _CBC_GENERIC_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/crypto/des.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,298 @@ ++/* crypto/des/des.org */ ++/* Copyright (C) 1995-1997 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.] ++ */ ++ ++/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ++ * ++ * Always modify des.org since des.h is automatically generated from ++ * it during SSLeay configuration. ++ * ++ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ++ */ ++ ++#ifndef HEADER_DES_H ++#define HEADER_DES_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++ ++/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a ++ * %20 speed up (longs are 8 bytes, int's are 4). */ ++/* Must be unsigned int on ia64/Itanium or DES breaks badly */ ++ ++#ifdef __KERNEL__ ++#include <linux/types.h> ++#else ++#include <sys/types.h> ++#endif ++ ++#ifndef DES_LONG ++#define DES_LONG u_int32_t ++#endif ++ ++typedef unsigned char des_cblock[8]; ++typedef struct { des_cblock ks; } des_key_schedule[16]; ++ ++#define DES_KEY_SZ (sizeof(des_cblock)) ++#define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) ++ ++#define DES_ENCRYPT 1 ++#define DES_DECRYPT 0 ++ ++#define DES_CBC_MODE 0 ++#define DES_PCBC_MODE 1 ++ ++#define des_ecb2_encrypt(i,o,k1,k2,e) \ ++ des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) ++ ++#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ ++ des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) ++ ++#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ ++ des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) ++ ++#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ ++ des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) ++ ++#define C_Block des_cblock ++#define Key_schedule des_key_schedule ++#ifdef KERBEROS ++#define ENCRYPT DES_ENCRYPT ++#define DECRYPT DES_DECRYPT ++#endif ++#define KEY_SZ DES_KEY_SZ ++#define string_to_key des_string_to_key ++#define read_pw_string des_read_pw_string ++#define random_key des_random_key ++#define pcbc_encrypt des_pcbc_encrypt ++#define set_key des_set_key ++#define key_sched des_key_sched ++#define ecb_encrypt des_ecb_encrypt ++#define cbc_encrypt des_cbc_encrypt ++#define ncbc_encrypt des_ncbc_encrypt ++#define xcbc_encrypt des_xcbc_encrypt ++#define cbc_cksum des_cbc_cksum ++#define quad_cksum des_quad_cksum ++ ++/* For compatibility with the MIT lib - eay 20/05/92 */ ++typedef des_key_schedule bit_64; ++#define des_fixup_key_parity des_set_odd_parity ++#define des_check_key_parity check_parity ++ ++extern int des_check_key; /* defaults to false */ ++extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ ++ ++/* The next line is used to disable full ANSI prototypes, if your ++ * compiler has problems with the prototypes, make sure this line always ++ * evaluates to true :-) */ ++#if defined(MSDOS) || defined(__STDC__) ++#undef NOPROTO ++#endif ++#ifndef NOPROTO ++char *des_options(void); ++void des_ecb3_encrypt(des_cblock *input,des_cblock *output, ++ des_key_schedule ks1,des_key_schedule ks2, ++ des_key_schedule ks3, int enc); ++DES_LONG des_cbc_cksum(des_cblock *input,des_cblock *output, ++ long length,des_key_schedule schedule,des_cblock *ivec); ++void des_cbc_encrypt(des_cblock *input,des_cblock *output,long length, ++ des_key_schedule schedule,des_cblock *ivec,int enc); ++void des_ncbc_encrypt(des_cblock *input,des_cblock *output,long length, ++ des_key_schedule schedule,des_cblock *ivec,int enc); ++void des_xcbc_encrypt(des_cblock *input,des_cblock *output,long length, ++ des_key_schedule schedule,des_cblock *ivec, ++ des_cblock *inw,des_cblock *outw,int enc); ++void des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits, ++ long length,des_key_schedule schedule,des_cblock *ivec,int enc); ++void des_ecb_encrypt(des_cblock *input,des_cblock *output, ++ des_key_schedule ks,int enc); ++void des_encrypt(DES_LONG *data,des_key_schedule ks, int enc); ++void des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc); ++void des_encrypt3(DES_LONG *data, des_key_schedule ks1, ++ des_key_schedule ks2, des_key_schedule ks3); ++void des_decrypt3(DES_LONG *data, des_key_schedule ks1, ++ des_key_schedule ks2, des_key_schedule ks3); ++void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, ++ long length, des_key_schedule ks1, des_key_schedule ks2, ++ des_key_schedule ks3, des_cblock *ivec, int enc); ++void des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, ++ long length, des_key_schedule ks1, des_key_schedule ks2, ++ des_key_schedule ks3, des_cblock *ivec, int *num, int enc); ++void des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, ++ long length, des_key_schedule ks1, des_key_schedule ks2, ++ des_key_schedule ks3, des_cblock *ivec, int *num); ++ ++void des_xwhite_in2out(des_cblock (*des_key), des_cblock (*in_white), ++ des_cblock (*out_white)); ++ ++int des_enc_read(int fd,char *buf,int len,des_key_schedule sched, ++ des_cblock *iv); ++int des_enc_write(int fd,char *buf,int len,des_key_schedule sched, ++ des_cblock *iv); ++char *des_fcrypt(const char *buf,const char *salt, char *ret); ++#ifdef PERL5 ++char *des_crypt(const char *buf,const char *salt); ++#else ++/* some stupid compilers complain because I have declared char instead ++ * of const char */ ++#ifndef __KERNEL__ ++#ifdef HEADER_DES_LOCL_H ++char *crypt(const char *buf,const char *salt); ++#else /* HEADER_DES_LOCL_H */ ++char *crypt(void); ++#endif /* HEADER_DES_LOCL_H */ ++#endif /* __KERNEL__ */ ++#endif /* PERL5 */ ++void des_ofb_encrypt(unsigned char *in,unsigned char *out, ++ int numbits,long length,des_key_schedule schedule,des_cblock *ivec); ++void des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length, ++ des_key_schedule schedule,des_cblock *ivec,int enc); ++DES_LONG des_quad_cksum(des_cblock *input,des_cblock *output, ++ long length,int out_count,des_cblock *seed); ++void des_random_seed(des_cblock key); ++void des_random_key(des_cblock ret); ++int des_read_password(des_cblock *key,char *prompt,int verify); ++int des_read_2passwords(des_cblock *key1,des_cblock *key2, ++ char *prompt,int verify); ++int des_read_pw_string(char *buf,int length,char *prompt,int verify); ++void des_set_odd_parity(des_cblock *key); ++int des_is_weak_key(des_cblock *key); ++int des_set_key(des_cblock *key,des_key_schedule schedule); ++int des_key_sched(des_cblock *key,des_key_schedule schedule); ++void des_string_to_key(char *str,des_cblock *key); ++void des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2); ++void des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, ++ des_key_schedule schedule, des_cblock *ivec, int *num, int enc); ++void des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, ++ des_key_schedule schedule, des_cblock *ivec, int *num); ++int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify); ++ ++/* Extra functions from Mark Murray <mark@grondar.za> */ ++/* The following functions are not in the normal unix build or the ++ * SSLeay build. When using the SSLeay build, use RAND_seed() ++ * and RAND_bytes() instead. */ ++int des_new_random_key(des_cblock *key); ++void des_init_random_number_generator(des_cblock *key); ++void des_set_random_generator_seed(des_cblock *key); ++void des_set_sequence_number(des_cblock new_sequence_number); ++void des_generate_random_block(des_cblock *block); ++ ++#else ++ ++char *des_options(); ++void des_ecb3_encrypt(); ++DES_LONG des_cbc_cksum(); ++void des_cbc_encrypt(); ++void des_ncbc_encrypt(); ++void des_xcbc_encrypt(); ++void des_cfb_encrypt(); ++void des_ede3_cfb64_encrypt(); ++void des_ede3_ofb64_encrypt(); ++void des_ecb_encrypt(); ++void des_encrypt(); ++void des_encrypt2(); ++void des_encrypt3(); ++void des_decrypt3(); ++void des_ede3_cbc_encrypt(); ++int des_enc_read(); ++int des_enc_write(); ++char *des_fcrypt(); ++#ifdef PERL5 ++char *des_crypt(); ++#else ++char *crypt(); ++#endif ++void des_ofb_encrypt(); ++void des_pcbc_encrypt(); ++DES_LONG des_quad_cksum(); ++void des_random_seed(); ++void des_random_key(); ++int des_read_password(); ++int des_read_2passwords(); ++int des_read_pw_string(); ++void des_set_odd_parity(); ++int des_is_weak_key(); ++int des_set_key(); ++int des_key_sched(); ++void des_string_to_key(); ++void des_string_to_2keys(); ++void des_cfb64_encrypt(); ++void des_ofb64_encrypt(); ++int des_read_pw(); ++void des_xwhite_in2out(); ++ ++/* Extra functions from Mark Murray <mark@grondar.za> */ ++/* The following functions are not in the normal unix build or the ++ * SSLeay build. When using the SSLeay build, use RAND_seed() ++ * and RAND_bytes() instead. */ ++#ifdef FreeBSD ++int des_new_random_key(); ++void des_init_random_number_generator(); ++void des_set_random_generator_seed(); ++void des_set_sequence_number(); ++void des_generate_random_block(); ++#endif ++ ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/mast.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,33 @@ ++struct mast_callbacks { ++ int (*packet_encap)(struct device *mast, void *context, ++ struct sk_buff *skb, int flowref); ++ int (*link_inquire)(struct device *mast, void *context); ++}; ++ ++ ++struct device *mast_init (int family, ++ struct mast_callbacks *callbacks, ++ unsigned int flags, ++ unsigned int desired_unit, ++ unsigned int max_flowref, ++ void *context); ++ ++int mast_destroy(struct device *mast); ++ ++int mast_recv(struct device *mast, struct sk_buff *skb, int flowref); ++ ++/* free this skb as being useless, increment failure count. */ ++int mast_toast(struct device *mast, struct sk_buff *skb, int flowref); ++ ++int mast_linkstat (struct device *mast, int flowref, ++ int status); ++ ++int mast_setreference (struct device *mast, ++ int defaultSA); ++ ++int mast_setneighbor (struct device *mast, ++ struct sockaddr *source, ++ struct sockaddr *destination, ++ int flowref); ++ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,513 @@ ++#ifndef _OPENSWAN_H ++/* ++ * header file for FreeS/WAN library functions ++ * Copyright (C) 1998, 1999, 2000 Henry Spencer. ++ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: openswan.h,v 1.89 2004/06/08 00:53:13 mcr Exp $ ++ */ ++#define _OPENSWAN_H /* seen it, no need to see it again */ ++ ++ ++ ++/* ++ * We've just got to have some datatypes defined... And annoyingly, just ++ * where we get them depends on whether we're in userland or not. ++ */ ++/* things that need to come from one place or the other, depending */ ++#ifdef __KERNEL__ ++#include <linux/types.h> ++#include <linux/socket.h> ++#include <linux/in.h> ++#include <linux/string.h> ++#include <linux/ctype.h> ++#define assert(foo) /* nothing */ ++#else ++#include <sys/types.h> ++#include <netinet/in.h> ++#include <string.h> ++#include <ctype.h> ++#include <assert.h> ++#include <stdio.h> ++ ++# define uint8_t u_int8_t ++# define uint16_t u_int16_t ++# define uint32_t u_int32_t ++# define uint64_t u_int64_t ++ ++ ++# define DEBUG_NO_STATIC static ++ ++#endif ++ ++#include <openswan/ipsec_param.h> ++ ++ ++/* ++ * Grab the kernel version to see if we have NET_21, and therefore ++ * IPv6. Some of this is repeated from ipsec_kversions.h. Of course, ++ * we aren't really testing if the kernel has IPv6, but rather if the ++ * the include files do. ++ */ ++#include <linux/version.h> ++#ifndef KERNEL_VERSION ++#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) ++#define NET_21 ++#endif ++ ++#ifndef IPPROTO_COMP ++# define IPPROTO_COMP 108 ++#endif /* !IPPROTO_COMP */ ++ ++#ifndef IPPROTO_INT ++# define IPPROTO_INT 61 ++#endif /* !IPPROTO_INT */ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++#ifndef DEBUG_NO_STATIC ++# define DEBUG_NO_STATIC ++#endif ++#else /* CONFIG_IPSEC_DEBUG */ ++#ifndef DEBUG_NO_STATIC ++# define DEBUG_NO_STATIC static ++#endif ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL /* KERNEL ifdef */ ++#ifndef NAT_TRAVERSAL ++#define NAT_TRAVERSAL ++#endif ++#endif ++#ifdef NAT_TRAVERSAL ++#define ESPINUDP_WITH_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ ++#define ESPINUDP_WITH_NON_ESP 2 /* draft-ietf-ipsec-nat-t-ike-02 */ ++#endif ++ ++/* ++ * Basic data types for the address-handling functions. ++ * ip_address and ip_subnet are supposed to be opaque types; do not ++ * use their definitions directly, they are subject to change! ++ */ ++ ++/* first, some quick fakes in case we're on an old system with no IPv6 */ ++#ifndef s6_addr16 ++struct in6_addr { ++ union ++ { ++ __u8 u6_addr8[16]; ++ __u16 u6_addr16[8]; ++ __u32 u6_addr32[4]; ++ } in6_u; ++#define s6_addr in6_u.u6_addr8 ++#define s6_addr16 in6_u.u6_addr16 ++#define s6_addr32 in6_u.u6_addr32 ++}; ++struct sockaddr_in6 { ++ unsigned short int sin6_family; /* AF_INET6 */ ++ __u16 sin6_port; /* Transport layer port # */ ++ __u32 sin6_flowinfo; /* IPv6 flow information */ ++ struct in6_addr sin6_addr; /* IPv6 address */ ++ __u32 sin6_scope_id; /* scope id (new in RFC2553) */ ++}; ++#endif /* !s6_addr16 */ ++ ++/* then the main types */ ++typedef struct { ++ union { ++ struct sockaddr_in v4; ++ struct sockaddr_in6 v6; ++ } u; ++} ip_address; ++typedef struct { ++ ip_address addr; ++ int maskbits; ++} ip_subnet; ++ ++/* and the SA ID stuff */ ++#ifdef __KERNEL__ ++typedef __u32 ipsec_spi_t; ++#else ++typedef u_int32_t ipsec_spi_t; ++#endif ++typedef struct { /* to identify an SA, we need: */ ++ ip_address dst; /* A. destination host */ ++ ipsec_spi_t spi; /* B. 32-bit SPI, assigned by dest. host */ ++# define SPI_PASS 256 /* magic values... */ ++# define SPI_DROP 257 /* ...for use... */ ++# define SPI_REJECT 258 /* ...with SA_INT */ ++# define SPI_HOLD 259 ++# define SPI_TRAP 260 ++# define SPI_TRAPSUBNET 261 ++ int proto; /* C. protocol */ ++# define SA_ESP 50 /* IPPROTO_ESP */ ++# define SA_AH 51 /* IPPROTO_AH */ ++# define SA_IPIP 4 /* IPPROTO_IPIP */ ++# define SA_COMP 108 /* IPPROTO_COMP */ ++# define SA_INT 61 /* IANA reserved for internal use */ ++} ip_said; ++ ++/* misc */ ++typedef const char *err_t; /* error message, or NULL for success */ ++struct prng { /* pseudo-random-number-generator guts */ ++ unsigned char sbox[256]; ++ int i, j; ++ unsigned long count; ++}; ++ ++ ++/* ++ * definitions for user space, taken from freeswan/ipsec_sa.h ++ */ ++typedef uint32_t IPsecSAref_t; ++ ++#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t)) ++ ++#define IPsecSAref2NFmark(x) ((x) << (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) ++#define NFmark2IPsecSAref(x) ((x) >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) ++ ++#define IPSEC_SAREF_NULL (~((IPsecSAref_t)0)) ++ ++/* GCC magic for use in function definitions! */ ++#ifdef GCC_LINT ++# define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n+1))) ++# define NEVER_RETURNS __attribute__ ((noreturn)) ++# define UNUSED __attribute__ ((unused)) ++# define BLANK_FORMAT " " /* GCC_LINT whines about empty formats */ ++#else ++# define PRINTF_LIKE(n) /* ignore */ ++# define NEVER_RETURNS /* ignore */ ++# define UNUSED /* ignore */ ++# define BLANK_FORMAT "" ++#endif ++ ++ ++ ++ ++ ++/* ++ * new IPv6-compatible functions ++ */ ++ ++/* text conversions */ ++err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst); ++size_t ultot(unsigned long src, int format, char *buf, size_t buflen); ++#define ULTOT_BUF (22+1) /* holds 64 bits in octal */ ++err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst); ++err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst); ++size_t addrtot(const ip_address *src, int format, char *buf, size_t buflen); ++/* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */ ++#define ADDRTOT_BUF (32*2 + 3 + 1 + 3 + 1 + 1) ++err_t ttosubnet(const char *src, size_t srclen, int af, ip_subnet *dst); ++size_t subnettot(const ip_subnet *src, int format, char *buf, size_t buflen); ++#define SUBNETTOT_BUF (ADDRTOT_BUF + 1 + 3) ++size_t subnetporttot(const ip_subnet *src, int format, char *buf, size_t buflen); ++#define SUBNETPROTOTOT_BUF (SUBNETTOTO_BUF + ULTOT_BUF) ++err_t ttosa(const char *src, size_t srclen, ip_said *dst); ++size_t satot(const ip_said *src, int format, char *bufptr, size_t buflen); ++#define SATOT_BUF (5 + ULTOA_BUF + 1 + ADDRTOT_BUF) ++err_t ttodata(const char *src, size_t srclen, int base, char *buf, ++ size_t buflen, size_t *needed); ++err_t ttodatav(const char *src, size_t srclen, int base, ++ char *buf, size_t buflen, size_t *needed, ++ char *errp, size_t errlen, unsigned int flags); ++#define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */ ++#define TTODATAV_IGNORESPACE (1<<1) /* ignore spaces in base64 encodings*/ ++#define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */ ++ ++size_t datatot(const char *src, size_t srclen, int format, char *buf, ++ size_t buflen); ++size_t keyblobtoid(const unsigned char *src, size_t srclen, char *dst, ++ size_t dstlen); ++size_t splitkeytoid(const unsigned char *e, size_t elen, const unsigned char *m, ++ size_t mlen, char *dst, size_t dstlen); ++#define KEYID_BUF 10 /* up to 9 text digits plus NUL */ ++err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port, ++ int *has_port_wildcard); ++ ++/* initializations */ ++void initsaid(const ip_address *addr, ipsec_spi_t spi, int proto, ip_said *dst); ++err_t loopbackaddr(int af, ip_address *dst); ++err_t unspecaddr(int af, ip_address *dst); ++err_t anyaddr(int af, ip_address *dst); ++err_t initaddr(const unsigned char *src, size_t srclen, int af, ip_address *dst); ++err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst); ++err_t addrtosubnet(const ip_address *addr, ip_subnet *dst); ++ ++/* misc. conversions and related */ ++err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst); ++int addrtypeof(const ip_address *src); ++int subnettypeof(const ip_subnet *src); ++size_t addrlenof(const ip_address *src); ++size_t addrbytesptr(const ip_address *src, const unsigned char **dst); ++size_t addrbytesof(const ip_address *src, unsigned char *dst, size_t dstlen); ++int masktocount(const ip_address *src); ++void networkof(const ip_subnet *src, ip_address *dst); ++void maskof(const ip_subnet *src, ip_address *dst); ++ ++/* tests */ ++int sameaddr(const ip_address *a, const ip_address *b); ++int addrcmp(const ip_address *a, const ip_address *b); ++int samesubnet(const ip_subnet *a, const ip_subnet *b); ++int addrinsubnet(const ip_address *a, const ip_subnet *s); ++int subnetinsubnet(const ip_subnet *a, const ip_subnet *b); ++int subnetishost(const ip_subnet *s); ++int samesaid(const ip_said *a, const ip_said *b); ++int sameaddrtype(const ip_address *a, const ip_address *b); ++int samesubnettype(const ip_subnet *a, const ip_subnet *b); ++int isanyaddr(const ip_address *src); ++int isunspecaddr(const ip_address *src); ++int isloopbackaddr(const ip_address *src); ++ ++/* low-level grot */ ++int portof(const ip_address *src); ++void setportof(int port, ip_address *dst); ++struct sockaddr *sockaddrof(ip_address *src); ++size_t sockaddrlenof(const ip_address *src); ++ ++/* PRNG */ ++void prng_init(struct prng *prng, const unsigned char *key, size_t keylen); ++void prng_bytes(struct prng *prng, unsigned char *dst, size_t dstlen); ++unsigned long prng_count(struct prng *prng); ++void prng_final(struct prng *prng); ++ ++/* odds and ends */ ++const char *ipsec_version_code(void); ++const char *ipsec_version_string(void); ++const char **ipsec_copyright_notice(void); ++ ++const char *dns_string_rr(int rr, char *buf, int bufsize); ++const char *dns_string_datetime(time_t seconds, ++ char *buf, ++ int bufsize); ++ ++ ++/* ++ * old functions, to be deleted eventually ++ */ ++ ++/* unsigned long */ ++const char * /* NULL for success, else string literal */ ++atoul( ++ const char *src, ++ size_t srclen, /* 0 means strlen(src) */ ++ int base, /* 0 means figure it out */ ++ unsigned long *resultp ++); ++size_t /* space needed for full conversion */ ++ultoa( ++ unsigned long n, ++ int base, ++ char *dst, ++ size_t dstlen ++); ++#define ULTOA_BUF 21 /* just large enough for largest result, */ ++ /* assuming 64-bit unsigned long! */ ++ ++/* Internet addresses */ ++const char * /* NULL for success, else string literal */ ++atoaddr( ++ const char *src, ++ size_t srclen, /* 0 means strlen(src) */ ++ struct in_addr *addr ++); ++size_t /* space needed for full conversion */ ++addrtoa( ++ struct in_addr addr, ++ int format, /* character; 0 means default */ ++ char *dst, ++ size_t dstlen ++); ++#define ADDRTOA_BUF 16 /* just large enough for largest result */ ++ ++/* subnets */ ++const char * /* NULL for success, else string literal */ ++atosubnet( ++ const char *src, ++ size_t srclen, /* 0 means strlen(src) */ ++ struct in_addr *addr, ++ struct in_addr *mask ++); ++size_t /* space needed for full conversion */ ++subnettoa( ++ struct in_addr addr, ++ struct in_addr mask, ++ int format, /* character; 0 means default */ ++ char *dst, ++ size_t dstlen ++); ++#define SUBNETTOA_BUF 32 /* large enough for worst case result */ ++ ++/* ranges */ ++const char * /* NULL for success, else string literal */ ++atoasr( ++ const char *src, ++ size_t srclen, /* 0 means strlen(src) */ ++ char *type, /* 'a', 's', 'r' */ ++ struct in_addr *addrs /* two-element array */ ++); ++size_t /* space needed for full conversion */ ++rangetoa( ++ struct in_addr *addrs, /* two-element array */ ++ int format, /* character; 0 means default */ ++ char *dst, ++ size_t dstlen ++); ++#define RANGETOA_BUF 34 /* large enough for worst case result */ ++ ++/* data types for SA conversion functions */ ++ ++/* generic data, e.g. keys */ ++const char * /* NULL for success, else string literal */ ++atobytes( ++ const char *src, ++ size_t srclen, /* 0 means strlen(src) */ ++ char *dst, ++ size_t dstlen, ++ size_t *lenp /* NULL means don't bother telling me */ ++); ++size_t /* 0 failure, else true size */ ++bytestoa( ++ const char *src, ++ size_t srclen, ++ int format, /* character; 0 means default */ ++ char *dst, ++ size_t dstlen ++); ++ ++/* old versions of generic-data functions; deprecated */ ++size_t /* 0 failure, else true size */ ++atodata( ++ const char *src, ++ size_t srclen, /* 0 means strlen(src) */ ++ char *dst, ++ size_t dstlen ++); ++size_t /* 0 failure, else true size */ ++datatoa( ++ const char *src, ++ size_t srclen, ++ int format, /* character; 0 means default */ ++ char *dst, ++ size_t dstlen ++); ++ ++/* part extraction and special addresses */ ++struct in_addr ++subnetof( ++ struct in_addr addr, ++ struct in_addr mask ++); ++struct in_addr ++hostof( ++ struct in_addr addr, ++ struct in_addr mask ++); ++struct in_addr ++broadcastof( ++ struct in_addr addr, ++ struct in_addr mask ++); ++ ++/* mask handling */ ++int ++goodmask( ++ struct in_addr mask ++); ++int ++masktobits( ++ struct in_addr mask ++); ++struct in_addr ++bitstomask( ++ int n ++); ++ ++ ++ ++/* ++ * general utilities ++ */ ++ ++#ifndef __KERNEL__ ++/* option pickup from files (userland only because of use of FILE) */ ++const char *optionsfrom(const char *filename, int *argcp, char ***argvp, ++ int optind, FILE *errorreport); ++ ++/* sanitize a string */ ++extern size_t sanitize_string(char *buf, size_t size); ++ ++#endif ++ ++ ++/* ++ * ENUM of klips debugging values. Not currently used in klips. ++ * debug flag is actually 32 -bits, but only one bit is ever used, ++ * so we can actually pack it all into a single 32-bit word. ++ */ ++enum klips_debug_flags { ++ KDF_VERBOSE = 0, ++ KDF_XMIT = 1, ++ KDF_NETLINK = 2, /* obsolete */ ++ KDF_XFORM = 3, ++ KDF_EROUTE = 4, ++ KDF_SPI = 5, ++ KDF_RADIJ = 6, ++ KDF_ESP = 7, ++ KDF_AH = 8, /* obsolete */ ++ KDF_RCV = 9, ++ KDF_TUNNEL = 10, ++ KDF_PFKEY = 11, ++ KDF_COMP = 12 ++}; ++ ++ ++/* ++ * Debugging levels for pfkey_lib_debug ++ */ ++#define PF_KEY_DEBUG_PARSE_NONE 0 ++#define PF_KEY_DEBUG_PARSE_PROBLEM 1 ++#define PF_KEY_DEBUG_PARSE_STRUCT 2 ++#define PF_KEY_DEBUG_PARSE_FLOW 4 ++#define PF_KEY_DEBUG_BUILD 8 ++#define PF_KEY_DEBUG_PARSE_MAX 15 ++ ++extern unsigned int pfkey_lib_debug; /* bits selecting what to report */ ++ ++/* ++ * pluto and lwdnsq need to know the maximum size of the commands to, ++ * and replies from lwdnsq. ++ */ ++ ++#define LWDNSQ_CMDBUF_LEN 1024 ++#define LWDNSQ_RESULT_LEN_MAX 4096 ++ ++ ++/* syntax for passthrough SA */ ++#ifndef PASSTHROUGHNAME ++#define PASSTHROUGHNAME "%passthrough" ++#define PASSTHROUGH4NAME "%passthrough4" ++#define PASSTHROUGH6NAME "%passthrough6" ++#define PASSTHROUGHIS "tun0@0.0.0.0" ++#define PASSTHROUGH4IS "tun0@0.0.0.0" ++#define PASSTHROUGH6IS "tun0@::" ++#define PASSTHROUGHTYPE "tun" ++#define PASSTHROUGHSPI 0 ++#define PASSTHROUGHDST 0 ++#endif ++ ++ ++ ++#endif /* _OPENSWAN_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipcomp.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,61 @@ ++/* ++ * IPCOMP zlib interface code. ++ * Copyright (C) 2000 Svenning Soerensen <svenning@post5.tele.dk> ++ * Copyright (C) 2000, 2001 Richard Guy Briggs <rgb@conscoop.ottawa.on.ca> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ ++ RCSID $Id: ipcomp.h,v 1.13 2004/04/05 19:55:04 mcr Exp $ ++ ++ */ ++ ++/* SSS */ ++ ++#ifndef _IPCOMP_H ++#define _IPCOMP_H ++ ++/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */ ++#ifndef IPCOMP_PREFIX ++#define IPCOMP_PREFIX ++#endif /* IPCOMP_PREFIX */ ++ ++#ifndef IPPROTO_COMP ++#define IPPROTO_COMP 108 ++#endif /* IPPROTO_COMP */ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++extern int sysctl_ipsec_debug_ipcomp; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++struct ipcomphdr { /* IPCOMP header */ ++ __u8 ipcomp_nh; /* Next header (protocol) */ ++ __u8 ipcomp_flags; /* Reserved, must be 0 */ ++ __u16 ipcomp_cpi; /* Compression Parameter Index */ ++}; ++ ++extern struct inet_protocol comp_protocol; ++extern int sysctl_ipsec_debug_ipcomp; ++ ++#define IPCOMP_UNCOMPRESSABLE 0x000000001 ++#define IPCOMP_COMPRESSIONERROR 0x000000002 ++#define IPCOMP_PARMERROR 0x000000004 ++#define IPCOMP_DECOMPRESSIONERROR 0x000000008 ++ ++#define IPCOMP_ADAPT_INITIAL_TRIES 8 ++#define IPCOMP_ADAPT_INITIAL_SKIP 4 ++#define IPCOMP_ADAPT_SUBSEQ_TRIES 2 ++#define IPCOMP_ADAPT_SUBSEQ_SKIP 8 ++ ++/* Function prototypes */ ++struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); ++struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); ++ ++#endif /* _IPCOMP_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_ah.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,190 @@ ++/* ++ * Authentication Header declarations ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_ah.h,v 1.23 2004/04/05 19:55:04 mcr Exp $ ++ */ ++ ++#include "ipsec_md5h.h" ++#include "ipsec_sha1.h" ++ ++#ifndef IPPROTO_AH ++#define IPPROTO_AH 51 ++#endif /* IPPROTO_AH */ ++ ++#include "ipsec_auth.h" ++ ++#ifdef __KERNEL__ ++ ++extern struct inet_protocol ah_protocol; ++ ++struct options; ++ ++struct ahhdr /* Generic AH header */ ++{ ++ __u8 ah_nh; /* Next header (protocol) */ ++ __u8 ah_hl; /* AH length, in 32-bit words */ ++ __u16 ah_rv; /* reserved, must be 0 */ ++ __u32 ah_spi; /* Security Parameters Index */ ++ __u32 ah_rpl; /* Replay prevention */ ++ __u8 ah_data[AHHMAC_HASHLEN];/* Authentication hash */ ++}; ++#define AH_BASIC_LEN 8 /* basic AH header is 8 bytes, nh,hl,rv,spi ++ * and the ah_hl, says how many bytes after that ++ * to cover. */ ++ ++extern struct xform_functions ah_xform_funcs[]; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++extern int debug_ah; ++#endif /* CONFIG_IPSEC_DEBUG */ ++#endif /* __KERNEL__ */ ++ ++/* ++ * $Log: ipsec_ah.h,v $ ++ * Revision 1.23 2004/04/05 19:55:04 mcr ++ * Moved from linux/include/freeswan/ipsec_ah.h,v ++ * ++ * Revision 1.22 2004/04/05 19:41:05 mcr ++ * merged alg-branch code. ++ * ++ * Revision 1.21 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.22 2003/12/11 20:14:58 mcr ++ * refactored the xmit code, to move all encapsulation ++ * code into protocol functions. Note that all functions ++ * are essentially done by a single function, which is probably ++ * wrong. ++ * the rcv_functions structures are renamed xform_functions. ++ * ++ * Revision 1.21 2003/12/06 21:21:19 mcr ++ * split up receive path into per-transform files, for ++ * easier later removal. ++ * ++ * Revision 1.20.8.1 2003/12/22 15:25:52 jjo ++ * Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.20 2003/02/06 02:21:34 rgb ++ * ++ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . ++ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". ++ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. ++ * ++ * Revision 1.19 2002/09/16 21:19:13 mcr ++ * fixes for west-ah-icmp-01 - length of AH header must be ++ * calculated properly, and next_header field properly copied. ++ * ++ * Revision 1.18 2002/05/14 02:37:02 rgb ++ * Change reference from _TDB to _IPSA. ++ * ++ * Revision 1.17 2002/04/24 07:36:46 mcr ++ * Moved from ./klips/net/ipsec/ipsec_ah.h,v ++ * ++ * Revision 1.16 2002/02/20 01:27:06 rgb ++ * Ditched a pile of structs only used by the old Netlink interface. ++ * ++ * Revision 1.15 2001/12/11 02:35:57 rgb ++ * Change "struct net_device" to "struct device" for 2.2 compatibility. ++ * ++ * Revision 1.14 2001/11/26 09:23:47 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.13.2.1 2001/09/25 02:18:24 mcr ++ * replace "struct device" with "struct netdevice" ++ * ++ * Revision 1.13 2001/06/14 19:35:08 rgb ++ * Update copyright date. ++ * ++ * Revision 1.12 2000/09/12 03:21:20 rgb ++ * Cleared out unused htonq. ++ * ++ * Revision 1.11 2000/09/08 19:12:55 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.10 2000/01/21 06:13:10 rgb ++ * Tidied up spacing. ++ * Added macros for HMAC padding magic numbers.(kravietz) ++ * ++ * Revision 1.9 1999/12/07 18:16:23 rgb ++ * Fixed comments at end of #endif lines. ++ * ++ * Revision 1.8 1999/04/11 00:28:56 henry ++ * GPL boilerplate ++ * ++ * Revision 1.7 1999/04/06 04:54:25 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.6 1999/01/26 02:06:01 rgb ++ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. ++ * ++ * Revision 1.5 1999/01/22 06:17:49 rgb ++ * Updated macro comments. ++ * Added context types to support algorithm switch code. ++ * 64-bit clean-up -- converting 'u long long' to __u64. ++ * ++ * Revision 1.4 1998/07/14 15:54:56 rgb ++ * Add #ifdef __KERNEL__ to protect kernel-only structures. ++ * ++ * Revision 1.3 1998/06/30 18:05:16 rgb ++ * Comment out references to htonq. ++ * ++ * Revision 1.2 1998/06/25 19:33:46 rgb ++ * Add prototype for protocol receive function. ++ * Rearrange for more logical layout. ++ * ++ * Revision 1.1 1998/06/18 21:27:43 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.4 1998/05/18 22:28:43 rgb ++ * Disable key printing facilities from /proc/net/ipsec_*. ++ * ++ * Revision 1.3 1998/04/21 21:29:07 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.2 1998/04/12 22:03:17 rgb ++ * Updated ESP-3DES-HMAC-MD5-96, ++ * ESP-DES-HMAC-MD5-96, ++ * AH-HMAC-MD5-96, ++ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository ++ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. ++ * ++ * Fixed eroute references in /proc/net/ipsec*. ++ * ++ * Started to patch module unloading memory leaks in ipsec_netlink and ++ * radij tree unloading. ++ * ++ * Revision 1.1 1998/04/09 03:05:55 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:02 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * Added definitions for new AH transforms. ++ * ++ * Revision 0.3 1996/11/20 14:35:48 ji ++ * Minor Cleanup. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_alg.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,260 @@ ++/* ++ * Modular extensions service and registration functions interface ++ * ++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar> ++ * ++ * ipsec_alg.h,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp ++ * ++ */ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++#ifndef IPSEC_ALG_H ++#define IPSEC_ALG_H ++ ++/* ++ * gcc >= 3.2 has removed __FUNCTION__, replaced by C99 __func__ ++ * *BUT* its a compiler variable. ++ */ ++#if (__GNUC__ >= 3) ++#ifndef __FUNCTION__ ++#define __FUNCTION__ __func__ ++#endif ++#endif ++ ++/* Version 0.8.1-0 */ ++#define IPSEC_ALG_VERSION 0x00080100 ++ ++#include <linux/types.h> ++#include <linux/list.h> ++#include <asm/atomic.h> ++/* ++ * The following structs are used via pointers in ipsec_alg object to ++ * avoid ipsec_alg.h coupling with freeswan headers, thus simplifying ++ * module development ++ */ ++struct ipsec_sa; ++struct esp; ++ ++/************************************** ++ * ++ * Main registration object ++ * ++ *************************************/ ++#define IPSEC_ALG_VERSION_QUAD(v) \ ++ (v>>24),((v>>16)&0xff),((v>>8)&0xff),(v&0xff) ++/* ++ * Main ipsec_alg objects: "OOPrograming wannabe" ++ * Hierachy (carefully handled with _minimal_ cast'ing): ++ * ++ * ipsec_alg+ ++ * +->ipsec_alg_enc (ixt_alg_type=SADB_EXT_SUPPORTED_ENCRYPT) ++ * +->ipsec_alg_auth (ixt_alg_type=SADB_EXT_SUPPORTED_AUTH) ++ */ ++ ++/*************************************************************** ++ * ++ * INTERFACE object: struct ipsec_alg ++ * ++ ***************************************************************/ ++ ++/* ++ * common part for every struct ipsec_alg_* ++ * (sortof poor's man OOP) ++ */ ++#define IPSEC_ALG_STRUCT_COMMON \ ++ unsigned ixt_version; /* only allow this version (or 'near')*/ \ ++ struct list_head ixt_list; /* dlinked list */ \ ++ struct module *ixt_module; /* THIS_MODULE */ \ ++ unsigned ixt_state; /* state flags */ \ ++ atomic_t ixt_refcnt; /* ref. count when pointed from ipsec_sa */ \ ++ char ixt_name[16]; /* descriptive short name, eg. "3des" */ \ ++ void *ixt_data; /* private for algo implementation */ \ ++ uint8_t ixt_blocksize; /* blocksize in bytes */ \ ++ \ ++ /* THIS IS A COPY of struct supported (lib/pfkey.h) \ ++ * please keep in sync until we migrate 'supported' stuff \ ++ * to ipsec_alg \ ++ */ \ ++ uint16_t ixt_alg_type; /* correspond to IPSEC_ALG_{ENCRYPT,AUTH} */ \ ++ uint8_t ixt_alg_id; /* enc. alg. number, eg. ESP_3DES */ \ ++ uint8_t ixt_ivlen; /* ivlen in bits, expected to be multiple of 8! */ \ ++ uint16_t ixt_keyminbits;/* min. keybits (of entropy) */ \ ++ uint16_t ixt_keymaxbits;/* max. keybits (of entropy) */ ++ ++#define ixt_support ixt_alg_type ++ ++#define IPSEC_ALG_ST_SUPP 0x01 ++#define IPSEC_ALG_ST_REGISTERED 0x02 ++#define IPSEC_ALG_ST_EXCL 0x04 ++struct ipsec_alg { ++ IPSEC_ALG_STRUCT_COMMON ++}; ++/* ++ * Note the const in cbc_encrypt IV arg: ++ * some ciphers like to toast passed IV (eg. 3DES): make a local IV copy ++ */ ++struct ipsec_alg_enc { ++ IPSEC_ALG_STRUCT_COMMON ++ unsigned ixt_e_keylen; /* raw key length in bytes */ ++ unsigned ixt_e_ctx_size; /* sa_p->key_e_size */ ++ int (*ixt_e_set_key)(struct ipsec_alg_enc *alg, __u8 *key_e, const __u8 *key, size_t keysize); ++ __u8 *(*ixt_e_new_key)(struct ipsec_alg_enc *alg, const __u8 *key, size_t keysize); ++ void (*ixt_e_destroy_key)(struct ipsec_alg_enc *alg, __u8 *key_e); ++ int (*ixt_e_cbc_encrypt)(struct ipsec_alg_enc *alg, __u8 *key_e, __u8 *in, int ilen, const __u8 *iv, int encrypt); ++}; ++struct ipsec_alg_auth { ++ IPSEC_ALG_STRUCT_COMMON ++ unsigned ixt_a_keylen; /* raw key length in bytes */ ++ unsigned ixt_a_ctx_size; /* sa_p->key_a_size */ ++ unsigned ixt_a_authlen; /* 'natural' auth. hash len (bytes) */ ++ int (*ixt_a_hmac_set_key)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *key, int keylen); ++ int (*ixt_a_hmac_hash)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *dat, int len, __u8 *hash, int hashlen); ++}; ++/* ++ * These are _copies_ of SADB_EXT_SUPPORTED_{AUTH,ENCRYPT}, ++ * to avoid header coupling for true constants ++ * about headers ... "cp is your friend" --Linus ++ */ ++#define IPSEC_ALG_TYPE_AUTH 14 ++#define IPSEC_ALG_TYPE_ENCRYPT 15 ++ ++/*************************************************************** ++ * ++ * INTERFACE for module loading,testing, and unloading ++ * ++ ***************************************************************/ ++/* - registration calls */ ++int register_ipsec_alg(struct ipsec_alg *); ++int unregister_ipsec_alg(struct ipsec_alg *); ++/* - optional (simple test) for algos */ ++int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int testparm); ++/* inline wrappers (usefull for type validation */ ++static inline int register_ipsec_alg_enc(struct ipsec_alg_enc *ixt) { ++ return register_ipsec_alg((struct ipsec_alg*)ixt); ++} ++static inline int unregister_ipsec_alg_enc(struct ipsec_alg_enc *ixt) { ++ return unregister_ipsec_alg((struct ipsec_alg*)ixt); ++} ++static inline int register_ipsec_alg_auth(struct ipsec_alg_auth *ixt) { ++ return register_ipsec_alg((struct ipsec_alg*)ixt); ++} ++static inline int unregister_ipsec_alg_auth(struct ipsec_alg_auth *ixt) { ++ return unregister_ipsec_alg((struct ipsec_alg*)ixt); ++} ++ ++/***************************************************************** ++ * ++ * INTERFACE for ENC services: key creation, encrypt function ++ * ++ *****************************************************************/ ++ ++#define IPSEC_ALG_ENCRYPT 1 ++#define IPSEC_ALG_DECRYPT 0 ++ ++/* encryption key context creation function */ ++int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p); ++/* ++ * ipsec_alg_esp_encrypt(): encrypt ilen bytes in idat returns ++ * 0 or ERR<0 ++ */ ++int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 *idat, int ilen, const __u8 *iv, int action); ++ ++/*************************************************************** ++ * ++ * INTERFACE for AUTH services: key creation, hash functions ++ * ++ ***************************************************************/ ++int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p); ++int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) ; ++#define ipsec_alg_sa_esp_update(c,k,l) ipsec_alg_sa_esp_hash(c,k,l,NULL,0) ++ ++/* only called from ipsec_init.c */ ++int ipsec_alg_init(void); ++ ++/* algo module glue for static algos */ ++void ipsec_alg_static_init(void); ++typedef int (*ipsec_alg_init_func_t) (void); ++ ++/********************************************** ++ * ++ * INTERFACE for ipsec_sa init and wipe ++ * ++ **********************************************/ ++ ++/* returns true if ipsec_sa has ipsec_alg obj attached */ ++/* ++ * Initializes ipsec_sa's ipsec_alg object, using already loaded ++ * proto, authalg, encalg.; links ipsec_alg objects (enc, auth) ++ */ ++int ipsec_alg_sa_init(struct ipsec_sa *sa_p); ++/* ++ * Destroys ipsec_sa's ipsec_alg object ++ * unlinking ipsec_alg objects ++ */ ++int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p); ++ ++#define IPSEC_ALG_MODULE_INIT_MOD( func_name ) \ ++ static int func_name(void); \ ++ module_init(func_name); \ ++ static int __init func_name(void) ++#define IPSEC_ALG_MODULE_EXIT_MOD( func_name ) \ ++ static void func_name(void); \ ++ module_exit(func_name); \ ++ static void __exit func_name(void) ++ ++#define IPSEC_ALG_MODULE_INIT_STATIC( func_name ) \ ++ extern int func_name(void); \ ++ int func_name(void) ++#define IPSEC_ALG_MODULE_EXIT_STATIC( func_name ) \ ++ extern void func_name(void); \ ++ void func_name(void) ++ ++/********************************************** ++ * ++ * 2.2 backport for some 2.4 useful module stuff ++ * ++ **********************************************/ ++#ifdef MODULE ++#ifndef THIS_MODULE ++#define THIS_MODULE (&__this_module) ++#endif ++#ifndef module_init ++typedef int (*__init_module_func_t)(void); ++typedef void (*__cleanup_module_func_t)(void); ++ ++#define module_init(x) \ ++ int init_module(void) __attribute__((alias(#x))); \ ++ static inline __init_module_func_t __init_module_inline(void) \ ++ { return x; } ++#define module_exit(x) \ ++ void cleanup_module(void) __attribute__((alias(#x))); \ ++ static inline __cleanup_module_func_t __cleanup_module_inline(void) \ ++ { return x; } ++#endif ++#define IPSEC_ALG_MODULE_INIT( func_name ) IPSEC_ALG_MODULE_INIT_MOD( func_name ) ++#define IPSEC_ALG_MODULE_EXIT( func_name ) IPSEC_ALG_MODULE_EXIT_MOD( func_name ) ++ ++#else /* not MODULE */ ++#ifndef THIS_MODULE ++#define THIS_MODULE NULL ++#endif ++/* ++ * I only want module_init() magic ++ * when algo.c file *is THE MODULE*, in all other ++ * cases, initialization is called explicitely from ipsec_alg_init() ++ */ ++#define IPSEC_ALG_MODULE_INIT( func_name ) IPSEC_ALG_MODULE_INIT_STATIC(func_name) ++#define IPSEC_ALG_MODULE_EXIT( func_name ) IPSEC_ALG_MODULE_EXIT_STATIC(func_name) ++#endif ++ ++#endif /* IPSEC_ALG_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_auth.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,100 @@ ++/* ++ * Authentication Header declarations ++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_auth.h,v 1.3 2004/04/06 02:49:08 mcr Exp $ ++ */ ++ ++#include "ipsec_md5h.h" ++#include "ipsec_sha1.h" ++ ++#ifndef IPSEC_AUTH_H ++#define IPSEC_AUTH_H ++ ++#define AH_FLENGTH 12 /* size of fixed part */ ++#define AHMD5_KMAX 64 /* MD5 max 512 bits key */ ++#define AHMD5_AMAX 12 /* MD5 96 bits of authenticator */ ++ ++#define AHMD596_KLEN 16 /* MD5 128 bits key */ ++#define AHSHA196_KLEN 20 /* SHA1 160 bits key */ ++ ++#define AHMD596_ALEN 16 /* MD5 128 bits authentication length */ ++#define AHSHA196_ALEN 20 /* SHA1 160 bits authentication length */ ++ ++#define AHMD596_BLKLEN 64 /* MD5 block length */ ++#define AHSHA196_BLKLEN 64 /* SHA1 block length */ ++#define AHSHA2_256_BLKLEN 64 /* SHA2-256 block length */ ++#define AHSHA2_384_BLKLEN 128 /* SHA2-384 block length (?) */ ++#define AHSHA2_512_BLKLEN 128 /* SHA2-512 block length */ ++ ++#define AH_BLKLEN_MAX 128 /* keep up to date! */ ++ ++ ++#define AH_AMAX AHSHA196_ALEN /* keep up to date! */ ++#define AHHMAC_HASHLEN 12 /* authenticator length of 96bits */ ++#define AHHMAC_RPLLEN 4 /* 32 bit replay counter */ ++ ++#define DB_AH_PKTRX 0x0001 ++#define DB_AH_PKTRX2 0x0002 ++#define DB_AH_DMP 0x0004 ++#define DB_AH_IPSA 0x0010 ++#define DB_AH_XF 0x0020 ++#define DB_AH_INAU 0x0040 ++#define DB_AH_REPLAY 0x0100 ++ ++#ifdef __KERNEL__ ++ ++/* General HMAC algorithm is described in RFC 2104 */ ++ ++#define HMAC_IPAD 0x36 ++#define HMAC_OPAD 0x5C ++ ++struct md5_ctx { ++ MD5_CTX ictx; /* context after H(K XOR ipad) */ ++ MD5_CTX octx; /* context after H(K XOR opad) */ ++}; ++ ++struct sha1_ctx { ++ SHA1_CTX ictx; /* context after H(K XOR ipad) */ ++ SHA1_CTX octx; /* context after H(K XOR opad) */ ++}; ++ ++struct auth_alg { ++ void (*init)(void *ctx); ++ void (*update)(void *ctx, unsigned char *bytes, __u32 len); ++ void (*final)(unsigned char *hash, void *ctx); ++ int hashlen; ++}; ++ ++struct options; ++ ++#endif /* __KERNEL__ */ ++#endif /* IPSEC_AUTH_H */ ++ ++/* ++ * $Log: ipsec_auth.h,v $ ++ * Revision 1.3 2004/04/06 02:49:08 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.2 2004/04/05 19:55:04 mcr ++ * Moved from linux/include/freeswan/ipsec_auth.h,v ++ * ++ * Revision 1.1 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.1 2003/12/06 21:21:19 mcr ++ * split up receive path into per-transform files, for ++ * easier later removal. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_encap.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,149 @@ ++/* ++ * declarations relevant to encapsulation-like operations ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_encap.h,v 1.19 2004/04/05 19:55:04 mcr Exp $ ++ */ ++ ++#ifndef _IPSEC_ENCAP_H_ ++ ++#define SENT_IP4 16 /* data is two struct in_addr + proto + ports*/ ++ /* (2 * sizeof(struct in_addr)) */ ++ /* sizeof(struct sockaddr_encap) ++ - offsetof(struct sockaddr_encap, Sen.Sip4.Src) */ ++ ++struct sockaddr_encap ++{ ++ __u8 sen_len; /* length */ ++ __u8 sen_family; /* AF_ENCAP */ ++ __u16 sen_type; /* see SENT_* */ ++ union ++ { ++ struct /* SENT_IP4 */ ++ { ++ struct in_addr Src; ++ struct in_addr Dst; ++ __u8 Proto; ++ __u16 Sport; ++ __u16 Dport; ++ } Sip4; ++ } Sen; ++}; ++ ++#define sen_ip_src Sen.Sip4.Src ++#define sen_ip_dst Sen.Sip4.Dst ++#define sen_proto Sen.Sip4.Proto ++#define sen_sport Sen.Sip4.Sport ++#define sen_dport Sen.Sip4.Dport ++ ++#ifndef AF_ENCAP ++#define AF_ENCAP 26 ++#endif /* AF_ENCAP */ ++ ++#define _IPSEC_ENCAP_H_ ++#endif /* _IPSEC_ENCAP_H_ */ ++ ++/* ++ * $Log: ipsec_encap.h,v $ ++ * Revision 1.19 2004/04/05 19:55:04 mcr ++ * Moved from linux/include/freeswan/ipsec_encap.h,v ++ * ++ * Revision 1.18 2003/10/31 02:27:05 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.17.30.1 2003/09/21 13:59:38 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.17 2002/04/24 07:36:46 mcr ++ * Moved from ./klips/net/ipsec/ipsec_encap.h,v ++ * ++ * Revision 1.16 2001/11/26 09:23:47 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.15.2.1 2001/09/25 02:18:54 mcr ++ * struct eroute moved to ipsec_eroute.h ++ * ++ * Revision 1.15 2001/09/14 16:58:36 rgb ++ * Added support for storing the first and last packets through a HOLD. ++ * ++ * Revision 1.14 2001/09/08 21:13:31 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.13 2001/06/14 19:35:08 rgb ++ * Update copyright date. ++ * ++ * Revision 1.12 2001/05/27 06:12:10 rgb ++ * Added structures for pid, packet count and last access time to eroute. ++ * Added packet count to beginning of /proc/net/ipsec_eroute. ++ * ++ * Revision 1.11 2000/09/08 19:12:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.10 2000/03/22 16:15:36 rgb ++ * Fixed renaming of dev_get (MB). ++ * ++ * Revision 1.9 2000/01/21 06:13:26 rgb ++ * Added a macro for AF_ENCAP ++ * ++ * Revision 1.8 1999/12/31 14:56:55 rgb ++ * MB fix for 2.3 dev-use-count. ++ * ++ * Revision 1.7 1999/11/18 04:09:18 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * ++ * Revision 1.6 1999/09/24 00:34:13 rgb ++ * Add Marc Boucher's support for 2.3.xx+. ++ * ++ * Revision 1.5 1999/04/11 00:28:57 henry ++ * GPL boilerplate ++ * ++ * Revision 1.4 1999/04/06 04:54:25 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.3 1998/10/19 14:44:28 rgb ++ * Added inclusion of freeswan.h. ++ * sa_id structure implemented and used: now includes protocol. ++ * ++ * Revision 1.2 1998/07/14 18:19:33 rgb ++ * Added #ifdef __KERNEL__ directives to restrict scope of header. ++ * ++ * Revision 1.1 1998/06/18 21:27:44 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.2 1998/04/21 21:29:10 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.1 1998/04/09 03:05:58 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:02 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * Minor cosmetic changes. ++ * ++ * Revision 0.3 1996/11/20 14:35:48 ji ++ * Minor Cleanup. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_eroute.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,112 @@ ++/* ++ * @(#) declarations of eroute structures ++ * ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs <rgb@freeswan.org> ++ * Copyright (C) 2001 Michael Richardson <mcr@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_eroute.h,v 1.5 2004/04/05 19:55:05 mcr Exp $ ++ * ++ * derived from ipsec_encap.h 1.15 on 2001/9/18 by mcr. ++ * ++ */ ++ ++#ifndef _IPSEC_EROUTE_H_ ++ ++#include "radij.h" ++#include "ipsec_encap.h" ++#include "ipsec_radij.h" ++ ++/* ++ * The "type" is really part of the address as far as the routing ++ * system is concerned. By using only one bit in the type field ++ * for each type, we sort-of make sure that different types of ++ * encapsulation addresses won't be matched against the wrong type. ++ */ ++ ++/* ++ * An entry in the radix tree ++ */ ++ ++struct rjtentry ++{ ++ struct radij_node rd_nodes[2]; /* tree glue, and other values */ ++#define rd_key(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_key)) ++#define rd_mask(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_mask)) ++ short rd_flags; ++ short rd_count; ++}; ++ ++struct ident ++{ ++ __u16 type; /* identity type */ ++ __u64 id; /* identity id */ ++ __u8 len; /* identity len */ ++ caddr_t data; /* identity data */ ++}; ++ ++/* ++ * An encapsulation route consists of a pointer to a ++ * radix tree entry and a SAID (a destination_address/SPI/protocol triple). ++ */ ++ ++struct eroute ++{ ++ struct rjtentry er_rjt; ++ ip_said er_said; ++ uint32_t er_pid; ++ uint32_t er_count; ++ uint64_t er_lasttime; ++ struct sockaddr_encap er_eaddr; /* MCR get rid of _encap, it is silly*/ ++ struct sockaddr_encap er_emask; ++ struct ident er_ident_s; ++ struct ident er_ident_d; ++ struct sk_buff* er_first; ++ struct sk_buff* er_last; ++}; ++ ++#define er_dst er_said.dst ++#define er_spi er_said.spi ++ ++#define _IPSEC_EROUTE_H_ ++#endif /* _IPSEC_EROUTE_H_ */ ++ ++/* ++ * $Log: ipsec_eroute.h,v $ ++ * Revision 1.5 2004/04/05 19:55:05 mcr ++ * Moved from linux/include/freeswan/ipsec_eroute.h,v ++ * ++ * Revision 1.4 2003/10/31 02:27:05 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.3.30.2 2003/10/29 01:10:19 mcr ++ * elimited "struct sa_id" ++ * ++ * Revision 1.3.30.1 2003/09/21 13:59:38 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.3 2002/04/24 07:36:46 mcr ++ * Moved from ./klips/net/ipsec/ipsec_eroute.h,v ++ * ++ * Revision 1.2 2001/11/26 09:16:13 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.1.2.1 2001/09/25 02:18:54 mcr ++ * struct eroute moved to ipsec_eroute.h ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_errs.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,53 @@ ++/* ++ * @(#) definition of ipsec_errs structure ++ * ++ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org> ++ * and Michael Richardson <mcr@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_errs.h,v 1.4 2004/04/05 19:55:05 mcr Exp $ ++ * ++ */ ++ ++/* ++ * This file describes the errors/statistics that FreeSWAN collects. ++ * ++ */ ++ ++struct ipsec_errs { ++ __u32 ips_alg_errs; /* number of algorithm errors */ ++ __u32 ips_auth_errs; /* # of authentication errors */ ++ __u32 ips_encsize_errs; /* # of encryption size errors*/ ++ __u32 ips_encpad_errs; /* # of encryption pad errors*/ ++ __u32 ips_replaywin_errs; /* # of pkt sequence errors */ ++}; ++ ++/* ++ * $Log: ipsec_errs.h,v $ ++ * Revision 1.4 2004/04/05 19:55:05 mcr ++ * Moved from linux/include/freeswan/ipsec_errs.h,v ++ * ++ * Revision 1.3 2002/04/24 07:36:46 mcr ++ * Moved from ./klips/net/ipsec/ipsec_errs.h,v ++ * ++ * Revision 1.2 2001/11/26 09:16:13 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.1.2.1 2001/09/25 02:25:57 mcr ++ * lifetime structure created and common functions created. ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_esp.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,147 @@ ++/* ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_esp.h,v 1.25 2004/04/06 02:49:08 mcr Exp $ ++ */ ++ ++#include "openswan/ipsec_md5h.h" ++#include "openswan/ipsec_sha1.h" ++ ++#include "crypto/des.h" ++ ++#ifndef IPPROTO_ESP ++#define IPPROTO_ESP 50 ++#endif /* IPPROTO_ESP */ ++ ++#define ESP_HEADER_LEN 8 /* 64 bits header (spi+rpl)*/ ++ ++#define EMT_ESPDESCBC_ULEN 20 /* coming from user mode */ ++#define EMT_ESPDES_KMAX 64 /* 512 bit secret key enough? */ ++#define EMT_ESPDES_KEY_SZ 8 /* 56 bit secret key with parity = 64 bits */ ++#define EMT_ESP3DES_KEY_SZ 24 /* 168 bit secret key with parity = 192 bits */ ++#define EMT_ESPDES_IV_SZ 8 /* IV size */ ++#define ESP_DESCBC_BLKLEN 8 /* DES-CBC block size */ ++ ++#define ESP_IV_MAXSZ 16 /* This is _critical_ */ ++#define ESP_IV_MAXSZ_INT (ESP_IV_MAXSZ/sizeof(int)) ++ ++#define DB_ES_PKTRX 0x0001 ++#define DB_ES_PKTRX2 0x0002 ++#define DB_ES_IPSA 0x0010 ++#define DB_ES_XF 0x0020 ++#define DB_ES_IPAD 0x0040 ++#define DB_ES_INAU 0x0080 ++#define DB_ES_OINFO 0x0100 ++#define DB_ES_OINFO2 0x0200 ++#define DB_ES_OH 0x0400 ++#define DB_ES_REPLAY 0x0800 ++ ++#ifdef __KERNEL__ ++struct des_eks { ++ des_key_schedule ks; ++}; ++ ++extern struct inet_protocol esp_protocol; ++ ++struct options; ++ ++struct esphdr ++{ ++ __u32 esp_spi; /* Security Parameters Index */ ++ __u32 esp_rpl; /* Replay counter */ ++ __u8 esp_iv[8]; /* iv */ ++}; ++ ++extern struct xform_functions esp_xform_funcs[]; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++extern int debug_esp; ++#endif /* CONFIG_IPSEC_DEBUG */ ++#endif /* __KERNEL__ */ ++ ++/* ++ * $Log: ipsec_esp.h,v $ ++ * Revision 1.25 2004/04/06 02:49:08 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.24 2004/04/05 19:55:05 mcr ++ * Moved from linux/include/freeswan/ipsec_esp.h,v ++ * ++ * Revision 1.23 2004/04/05 19:41:05 mcr ++ * merged alg-branch code. ++ * ++ * Revision 1.22 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.23 2003/12/11 20:14:58 mcr ++ * refactored the xmit code, to move all encapsulation ++ * code into protocol functions. Note that all functions ++ * are essentially done by a single function, which is probably ++ * wrong. ++ * the rcv_functions structures are renamed xform_functions. ++ * ++ * Revision 1.22 2003/12/06 21:21:19 mcr ++ * split up receive path into per-transform files, for ++ * easier later removal. ++ * ++ * Revision 1.21.8.1 2003/12/22 15:25:52 jjo ++ * Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.21 2003/02/06 02:21:34 rgb ++ * ++ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . ++ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". ++ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. ++ * ++ * Revision 1.20 2002/05/14 02:37:02 rgb ++ * Change reference from _TDB to _IPSA. ++ * ++ * Revision 1.19 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.18 2002/04/24 07:36:46 mcr ++ * Moved from ./klips/net/ipsec/ipsec_esp.h,v ++ * ++ * Revision 1.17 2002/02/20 01:27:07 rgb ++ * Ditched a pile of structs only used by the old Netlink interface. ++ * ++ * Revision 1.16 2001/12/11 02:35:57 rgb ++ * Change "struct net_device" to "struct device" for 2.2 compatibility. ++ * ++ * Revision 1.15 2001/11/26 09:23:48 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.14.2.3 2001/10/23 04:16:42 mcr ++ * get definition of des_key_schedule from des.h ++ * ++ * Revision 1.14.2.2 2001/10/22 20:33:13 mcr ++ * use "des_key_schedule" structure instead of cooking our own. ++ * ++ * Revision 1.14.2.1 2001/09/25 02:18:25 mcr ++ * replace "struct device" with "struct netdevice" ++ * ++ * Revision 1.14 2001/06/14 19:35:08 rgb ++ * Update copyright date. ++ * ++ * Revision 1.13 2000/09/08 19:12:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.12 2000/08/01 14:51:50 rgb ++ * Removed _all_ remaining traces of DES. ++ * ++ * Revision 1.11 2000/01/10 16:36:20 rgb ++ * Ditch last of EME option flags, including initiator. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_ipcomp.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,91 @@ ++/* ++ * IP compression header declations ++ * ++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_ipcomp.h,v 1.3 2004/04/06 02:49:08 mcr Exp $ ++ */ ++ ++#ifndef IPSEC_IPCOMP_H ++#define IPSEC_IPCOMP_H ++ ++#include "openswan/ipsec_auth.h" ++ ++/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */ ++#ifndef IPCOMP_PREFIX ++#define IPCOMP_PREFIX ++#endif /* IPCOMP_PREFIX */ ++ ++#ifndef IPPROTO_COMP ++#define IPPROTO_COMP 108 ++#endif /* IPPROTO_COMP */ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++extern int sysctl_ipsec_debug_ipcomp; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++struct ipcomphdr { /* IPCOMP header */ ++ __u8 ipcomp_nh; /* Next header (protocol) */ ++ __u8 ipcomp_flags; /* Reserved, must be 0 */ ++ __u16 ipcomp_cpi; /* Compression Parameter Index */ ++}; ++ ++extern struct inet_protocol comp_protocol; ++extern int sysctl_ipsec_debug_ipcomp; ++ ++#define IPCOMP_UNCOMPRESSABLE 0x000000001 ++#define IPCOMP_COMPRESSIONERROR 0x000000002 ++#define IPCOMP_PARMERROR 0x000000004 ++#define IPCOMP_DECOMPRESSIONERROR 0x000000008 ++ ++#define IPCOMP_ADAPT_INITIAL_TRIES 8 ++#define IPCOMP_ADAPT_INITIAL_SKIP 4 ++#define IPCOMP_ADAPT_SUBSEQ_TRIES 2 ++#define IPCOMP_ADAPT_SUBSEQ_SKIP 8 ++ ++/* Function prototypes */ ++struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); ++struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); ++ ++extern struct xform_functions ipcomp_xform_funcs[]; ++ ++#endif /* IPSEC_IPCOMP_H */ ++ ++/* ++ * $Log: ipsec_ipcomp.h,v $ ++ * Revision 1.3 2004/04/06 02:49:08 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.2 2004/04/05 19:55:05 mcr ++ * Moved from linux/include/freeswan/ipsec_ipcomp.h,v ++ * ++ * Revision 1.1 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.2 2003/12/11 20:14:58 mcr ++ * refactored the xmit code, to move all encapsulation ++ * code into protocol functions. Note that all functions ++ * are essentially done by a single function, which is probably ++ * wrong. ++ * the rcv_functions structures are renamed xform_functions. ++ * ++ * Revision 1.1 2003/12/06 21:21:19 mcr ++ * split up receive path into per-transform files, for ++ * easier later removal. ++ * ++ * ++ * ++ */ ++ ++ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_ipe4.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,68 @@ ++/* ++ * IP-in-IP Header declarations ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_ipe4.h,v 1.6 2004/04/05 19:55:05 mcr Exp $ ++ */ ++ ++/* The packet header is an IP header! */ ++ ++struct ipe4_xdata /* transform table data */ ++{ ++ struct in_addr i4_src; ++ struct in_addr i4_dst; ++}; ++ ++#define EMT_IPE4_ULEN 8 /* coming from user mode */ ++ ++ ++/* ++ * $Log: ipsec_ipe4.h,v $ ++ * Revision 1.6 2004/04/05 19:55:05 mcr ++ * Moved from linux/include/freeswan/ipsec_ipe4.h,v ++ * ++ * Revision 1.5 2002/04/24 07:36:46 mcr ++ * Moved from ./klips/net/ipsec/ipsec_ipe4.h,v ++ * ++ * Revision 1.4 2001/06/14 19:35:08 rgb ++ * Update copyright date. ++ * ++ * Revision 1.3 1999/04/11 00:28:57 henry ++ * GPL boilerplate ++ * ++ * Revision 1.2 1999/04/06 04:54:25 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.1 1998/06/18 21:27:47 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.1 1998/04/09 03:06:07 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:03 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * No changes. ++ * ++ * Revision 0.3 1996/11/20 14:48:53 ji ++ * Release update only. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_ipip.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_ipip.h,v 1.2 2004/04/05 19:55:05 mcr Exp $ ++ */ ++ ++#ifndef _IPSEC_IPIP_H_ ++ ++#ifndef IPPROTO_IPIP ++#define IPPROTO_IPIP 4 ++#endif /* IPPROTO_ESP */ ++ ++extern struct xform_functions ipip_xform_funcs[]; ++ ++#define _IPSEC_IPIP_H_ ++ ++#endif /* _IPSEC_IPIP_H_ */ ++ ++/* ++ * $Log: ipsec_ipip.h,v $ ++ * Revision 1.2 2004/04/05 19:55:05 mcr ++ * Moved from linux/include/freeswan/ipsec_ipip.h,v ++ * ++ * Revision 1.1 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.1 2003/12/11 20:14:58 mcr ++ * refactored the xmit code, to move all encapsulation ++ * code into protocol functions. Note that all functions ++ * are essentially done by a single function, which is probably ++ * wrong. ++ * the rcv_functions structures are renamed xform_functions. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_kversion.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,239 @@ ++#ifndef _FREESWAN_KVERSIONS_H ++/* ++ * header file for FreeS/WAN library functions ++ * Copyright (C) 1998, 1999, 2000 Henry Spencer. ++ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: ipsec_kversion.h,v 1.9 2004/04/05 19:55:05 mcr Exp $ ++ */ ++#define _FREESWAN_KVERSIONS_H /* seen it, no need to see it again */ ++ ++/* ++ * this file contains a series of atomic defines that depend upon ++ * kernel version numbers. The kernel versions are arranged ++ * in version-order number (which is often not chronological) ++ * and each clause enables or disables a feature. ++ */ ++ ++/* ++ * First, assorted kernel-version-dependent trickery. ++ */ ++#include <linux/version.h> ++#ifndef KERNEL_VERSION ++#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) ++#define HEADER_CACHE_BIND_21 ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) ++#define SPINLOCK ++#define PROC_FS_21 ++#define NETLINK_SOCK ++#define NET_21 ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,19) ++#define net_device_stats enet_statistics ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ++#define SPINLOCK_23 ++#define NETDEV_23 ++# ifndef CONFIG_IP_ALIAS ++# define CONFIG_IP_ALIAS ++# endif ++#include <linux/socket.h> ++#include <linux/skbuff.h> ++#include <linux/netlink.h> ++# ifdef NETLINK_XFRM ++# define NETDEV_25 ++# endif ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,25) ++#define PROC_FS_2325 ++#undef PROC_FS_21 ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) ++#define PROC_NO_DUMMY ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,35) ++#define SKB_COPY_EXPAND ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,37) ++#define IP_SELECT_IDENT ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,50)) && defined(CONFIG_NETFILTER) ++#define SKB_RESET_NFCT ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,2) ++#define IP_SELECT_IDENT_NEW ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) ++#define IPH_is_SKB_PULLED ++#define SKB_COW_NEW ++#define PROTO_HANDLER_SINGLE_PARM ++#define IP_FRAGMENT_LINEARIZE 1 ++#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */ ++# ifdef REDHAT_BOGOSITY ++# define IP_SELECT_IDENT_NEW ++# define IPH_is_SKB_PULLED ++# define SKB_COW_NEW ++# define PROTO_HANDLER_SINGLE_PARM ++# endif /* REDHAT_BOGOSITY */ ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) ++#define MALLOC_SLAB ++#define LINUX_KERNEL_HAS_SNPRINTF ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ++#define HAVE_NETDEV_PRINTK 1 ++#endif ++ ++#ifdef NET_21 ++# include <linux/in6.h> ++#else ++ /* old kernel in.h has some IPv6 stuff, but not quite enough */ ++# define s6_addr16 s6_addr ++# define AF_INET6 10 ++# define uint8_t __u8 ++# define uint16_t __u16 ++# define uint32_t __u32 ++# define uint64_t __u64 ++#endif ++ ++#ifdef NET_21 ++# define ipsec_kfree_skb(a) kfree_skb(a) ++#else /* NET_21 */ ++# define ipsec_kfree_skb(a) kfree_skb(a, FREE_WRITE) ++#endif /* NET_21 */ ++ ++#ifdef NETDEV_23 ++# define device net_device ++# define ipsec_dev_get dev_get_by_name ++# define __ipsec_dev_get __dev_get_by_name ++# define ipsec_dev_put(x) dev_put(x) ++# define __ipsec_dev_put(x) __dev_put(x) ++# define ipsec_dev_hold(x) dev_hold(x) ++#else /* NETDEV_23 */ ++# define ipsec_dev_get dev_get ++# define __ipsec_dev_put(x) ++# define ipsec_dev_put(x) ++# define ipsec_dev_hold(x) ++#endif /* NETDEV_23 */ ++ ++#ifndef SPINLOCK ++# include <linux/bios32.h> ++ /* simulate spin locks and read/write locks */ ++ typedef struct { ++ volatile char lock; ++ } spinlock_t; ++ ++ typedef struct { ++ volatile unsigned int lock; ++ } rwlock_t; ++ ++# define spin_lock_init(x) { (x)->lock = 0;} ++# define rw_lock_init(x) { (x)->lock = 0; } ++ ++# define spin_lock(x) { while ((x)->lock) barrier(); (x)->lock=1;} ++# define spin_lock_irq(x) { cli(); spin_lock(x);} ++# define spin_lock_irqsave(x,flags) { save_flags(flags); spin_lock_irq(x);} ++ ++# define spin_unlock(x) { (x)->lock=0;} ++# define spin_unlock_irq(x) { spin_unlock(x); sti();} ++# define spin_unlock_irqrestore(x,flags) { spin_unlock(x); restore_flags(flags);} ++ ++# define read_lock(x) spin_lock(x) ++# define read_lock_irq(x) spin_lock_irq(x) ++# define read_lock_irqsave(x,flags) spin_lock_irqsave(x,flags) ++ ++# define read_unlock(x) spin_unlock(x) ++# define read_unlock_irq(x) spin_unlock_irq(x) ++# define read_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags) ++ ++# define write_lock(x) spin_lock(x) ++# define write_lock_irq(x) spin_lock_irq(x) ++# define write_lock_irqsave(x,flags) spin_lock_irqsave(x,flags) ++ ++# define write_unlock(x) spin_unlock(x) ++# define write_unlock_irq(x) spin_unlock_irq(x) ++# define write_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags) ++#endif /* !SPINLOCK */ ++ ++#ifndef SPINLOCK_23 ++# define spin_lock_bh(x) spin_lock_irq(x) ++# define spin_unlock_bh(x) spin_unlock_irq(x) ++ ++# define read_lock_bh(x) read_lock_irq(x) ++# define read_unlock_bh(x) read_unlock_irq(x) ++ ++# define write_lock_bh(x) write_lock_irq(x) ++# define write_unlock_bh(x) write_unlock_irq(x) ++#endif /* !SPINLOCK_23 */ ++ ++#ifndef HAVE_NETDEV_PRINTK ++#define netdev_printk(sevlevel, netdev, msglevel, format, arg...) \ ++ printk(sevlevel "%s: " format , netdev->name , ## arg) ++#endif ++ ++#endif /* _FREESWAN_KVERSIONS_H */ ++ ++/* ++ * $Log: ipsec_kversion.h,v $ ++ * Revision 1.9 2004/04/05 19:55:05 mcr ++ * Moved from linux/include/freeswan/ipsec_kversion.h,v ++ * ++ * Revision 1.8 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.7 2003/07/31 22:48:08 mcr ++ * derive NET25-ness from presence of NETLINK_XFRM macro. ++ * ++ * Revision 1.6 2003/06/24 20:22:32 mcr ++ * added new global: ipsecdevices[] so that we can keep track of ++ * the ipsecX devices. They will be referenced with dev_hold(), ++ * so 2.2 may need this as well. ++ * ++ * Revision 1.5 2003/04/03 17:38:09 rgb ++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. ++ * ++ * Revision 1.4 2002/04/24 07:36:46 mcr ++ * Moved from ./klips/net/ipsec/ipsec_kversion.h,v ++ * ++ * Revision 1.3 2002/04/12 03:21:17 mcr ++ * three parameter version of ip_select_ident appears first ++ * in 2.4.2 (RH7.1) not 2.4.4. ++ * ++ * Revision 1.2 2002/03/08 21:35:22 rgb ++ * Defined LINUX_KERNEL_HAS_SNPRINTF to shut up compiler warnings after ++ * 2.4.9. (Andreas Piesk). ++ * ++ * Revision 1.1 2002/01/29 02:11:42 mcr ++ * removal of kversions.h - sources that needed it now use ipsec_param.h. ++ * updating of IPv6 structures to match latest in6.h version. ++ * removed dead code from freeswan.h that also duplicated kversions.h ++ * code. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_life.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,112 @@ ++/* ++ * Definitions relevant to IPSEC lifetimes ++ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org> ++ * and Michael Richardson <mcr@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_life.h,v 1.4 2004/04/05 19:55:05 mcr Exp $ ++ * ++ * This file derived from ipsec_xform.h on 2001/9/18 by mcr. ++ * ++ */ ++ ++/* ++ * This file describes the book keeping fields for the ++ * IPsec Security Association Structure. ("ipsec_sa") ++ * ++ * This structure is never allocated directly by kernel code, ++ * (it is always a static/auto or is part of a structure) ++ * so it does not have a reference count. ++ * ++ */ ++ ++#ifndef _IPSEC_LIFE_H_ ++ ++/* ++ * _count is total count. ++ * _hard is hard limit (kill SA after this number) ++ * _soft is soft limit (try to renew SA after this number) ++ * _last is used in some special cases. ++ * ++ */ ++ ++struct ipsec_lifetime64 ++{ ++ __u64 ipl_count; ++ __u64 ipl_soft; ++ __u64 ipl_hard; ++ __u64 ipl_last; ++}; ++ ++struct ipsec_lifetimes ++{ ++ /* number of bytes processed */ ++ struct ipsec_lifetime64 ipl_bytes; ++ ++ /* number of packets processed */ ++ struct ipsec_lifetime64 ipl_packets; ++ ++ /* time since SA was added */ ++ struct ipsec_lifetime64 ipl_addtime; ++ ++ /* time since SA was first used */ ++ struct ipsec_lifetime64 ipl_usetime; ++ ++ /* from rfc2367: ++ * For CURRENT, the number of different connections, ++ * endpoints, or flows that the association has been ++ * allocated towards. For HARD and SOFT, the number of ++ * these the association may be allocated towards ++ * before it expires. The concept of a connection, ++ * flow, or endpoint is system specific. ++ * ++ * mcr(2001-9-18) it is unclear what purpose these serve for FreeSWAN. ++ * They are maintained for PF_KEY compatibility. ++ */ ++ struct ipsec_lifetime64 ipl_allocations; ++}; ++ ++enum ipsec_life_alive { ++ ipsec_life_harddied = -1, ++ ipsec_life_softdied = 0, ++ ipsec_life_okay = 1 ++}; ++ ++enum ipsec_life_type { ++ ipsec_life_timebased = 1, ++ ipsec_life_countbased= 0 ++}; ++ ++#define _IPSEC_LIFE_H_ ++#endif /* _IPSEC_LIFE_H_ */ ++ ++ ++/* ++ * $Log: ipsec_life.h,v $ ++ * Revision 1.4 2004/04/05 19:55:05 mcr ++ * Moved from linux/include/freeswan/ipsec_life.h,v ++ * ++ * Revision 1.3 2002/04/24 07:36:46 mcr ++ * Moved from ./klips/net/ipsec/ipsec_life.h,v ++ * ++ * Revision 1.2 2001/11/26 09:16:14 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.1.2.1 2001/09/25 02:25:58 mcr ++ * lifetime structure created and common functions created. ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_md5h.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,140 @@ ++/* ++ * RCSID $Id: ipsec_md5h.h,v 1.9 2004/04/05 19:55:05 mcr Exp $ ++ */ ++ ++/* ++ * The rest of this file is Copyright RSA DSI. See the following comments ++ * for the full Copyright notice. ++ */ ++ ++#ifndef _IPSEC_MD5H_H_ ++#define _IPSEC_MD5H_H_ ++ ++/* GLOBAL.H - RSAREF types and constants ++ */ ++ ++/* PROTOTYPES should be set to one if and only if the compiler supports ++ function argument prototyping. ++ The following makes PROTOTYPES default to 0 if it has not already ++ been defined with C compiler flags. ++ */ ++#ifndef PROTOTYPES ++#define PROTOTYPES 1 ++#endif /* !PROTOTYPES */ ++ ++/* POINTER defines a generic pointer type */ ++typedef __u8 *POINTER; ++ ++/* UINT2 defines a two byte word */ ++typedef __u16 UINT2; ++ ++/* UINT4 defines a four byte word */ ++typedef __u32 UINT4; ++ ++/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. ++ If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it ++ returns an empty list. ++ */ ++ ++#if PROTOTYPES ++#define PROTO_LIST(list) list ++#else /* PROTOTYPES */ ++#define PROTO_LIST(list) () ++#endif /* PROTOTYPES */ ++ ++ ++/* MD5.H - header file for MD5C.C ++ */ ++ ++/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All ++rights reserved. ++ ++License to copy and use this software is granted provided that it ++is identified as the "RSA Data Security, Inc. MD5 Message-Digest ++Algorithm" in all material mentioning or referencing this software ++or this function. ++ ++License is also granted to make and use derivative works provided ++that such works are identified as "derived from the RSA Data ++Security, Inc. MD5 Message-Digest Algorithm" in all material ++mentioning or referencing the derived work. ++ ++RSA Data Security, Inc. makes no representations concerning either ++the merchantability of this software or the suitability of this ++software for any particular purpose. It is provided "as is" ++without express or implied warranty of any kind. ++ ++These notices must be retained in any copies of any part of this ++documentation and/or software. ++ */ ++ ++/* MD5 context. */ ++typedef struct { ++ UINT4 state[4]; /* state (ABCD) */ ++ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ ++ unsigned char buffer[64]; /* input buffer */ ++} MD5_CTX; ++ ++void MD5Init PROTO_LIST ((void *)); ++void MD5Update PROTO_LIST ++ ((void *, unsigned char *, __u32)); ++void MD5Final PROTO_LIST ((unsigned char [16], void *)); ++ ++#endif /* _IPSEC_MD5H_H_ */ ++ ++/* ++ * $Log: ipsec_md5h.h,v $ ++ * Revision 1.9 2004/04/05 19:55:05 mcr ++ * Moved from linux/include/freeswan/ipsec_md5h.h,v ++ * ++ * Revision 1.8 2002/09/10 01:45:09 mcr ++ * changed type of MD5_CTX and SHA1_CTX to void * so that ++ * the function prototypes would match, and could be placed ++ * into a pointer to a function. ++ * ++ * Revision 1.7 2002/04/24 07:36:46 mcr ++ * Moved from ./klips/net/ipsec/ipsec_md5h.h,v ++ * ++ * Revision 1.6 1999/12/13 13:59:13 rgb ++ * Quick fix to argument size to Update bugs. ++ * ++ * Revision 1.5 1999/12/07 18:16:23 rgb ++ * Fixed comments at end of #endif lines. ++ * ++ * Revision 1.4 1999/04/06 04:54:26 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.3 1999/01/22 06:19:58 rgb ++ * 64-bit clean-up. ++ * ++ * Revision 1.2 1998/11/30 13:22:54 rgb ++ * Rationalised all the klips kernel file headers. They are much shorter ++ * now and won't conflict under RH5.2. ++ * ++ * Revision 1.1 1998/06/18 21:27:48 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.2 1998/04/23 20:54:03 rgb ++ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when ++ * verified. ++ * ++ * Revision 1.1 1998/04/09 03:04:21 henry ++ * sources moved up from linux/net/ipsec ++ * these two include files modified not to include others except in kernel ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:03 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * No changes. ++ * ++ * Revision 0.3 1996/11/20 14:48:53 ji ++ * Release update only. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_param.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,333 @@ ++/* ++ * @(#) FreeSWAN tunable paramaters ++ * ++ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org> ++ * and Michael Richardson <mcr@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_param.h,v 1.24 2004/04/05 19:55:06 mcr Exp $ ++ * ++ */ ++ ++/* ++ * This file provides a set of #define's which may be tuned by various ++ * people/configurations. It keeps all compile-time tunables in one place. ++ * ++ * This file should be included before all other IPsec kernel-only files. ++ * ++ */ ++ ++#ifndef _IPSEC_PARAM_H_ ++ ++#ifdef __KERNEL__ ++#include "ipsec_kversion.h" ++ ++/* Set number of ipsecX virtual devices here. */ ++/* This must be < exp(field width of IPSEC_DEV_FORMAT) */ ++/* It must also be reasonable so as not to overload the memory and CPU */ ++/* constraints of the host. */ ++#define IPSEC_NUM_IF 4 ++/* The field width must be < IF_NAM_SIZ - strlen("ipsec") - 1. */ ++/* With "ipsec" being 5 characters, that means 10 is the max field width */ ++/* but machine memory and CPU constraints are not likely to tollerate */ ++/* more than 3 digits. The default is one digit. */ ++/* Update: userland scripts get upset if they can't find "ipsec0", so */ ++/* for now, no "0"-padding should be used (which would have been helpful */ ++/* to make text-searches work */ ++#define IPSEC_DEV_FORMAT "ipsec%d" ++/* For, say, 500 virtual ipsec devices, I would recommend: */ ++/* #define IPSEC_NUM_IF 500 */ ++/* #define IPSEC_DEV_FORMAT "ipsec%03d" */ ++/* Note that the "interfaces=" line in /etc/ipsec.conf would be, um, challenging. */ ++ ++/* use dynamic ipsecX device allocation */ ++#ifndef CONFIG_IPSEC_DYNDEV ++#define CONFIG_IPSEC_DYNDEV 1 ++#endif /* CONFIG_IPSEC_DYNDEV */ ++ ++ ++#ifdef CONFIG_IPSEC_BIGGATE ++# define SADB_HASHMOD 8069 ++#else /* CONFIG_IPSEC_BIGGATE */ ++# define SADB_HASHMOD 257 ++#endif /* CONFIG_IPSEC_BIGGATE */ ++#endif /* __KERNEL__ */ ++ ++/* ++ * This is for the SA reference table. This number is related to the ++ * maximum number of SAs that KLIPS can concurrently deal with, plus enough ++ * space for keeping expired SAs around. ++ * ++ * TABLE_MAX_WIDTH is the number of bits that we will use. ++ * MAIN_TABLE_WIDTH is the number of bits used for the primary index table. ++ * ++ */ ++#ifndef IPSEC_SA_REF_TABLE_IDX_WIDTH ++# define IPSEC_SA_REF_TABLE_IDX_WIDTH 16 ++#endif ++ ++#ifndef IPSEC_SA_REF_MAINTABLE_IDX_WIDTH ++# define IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 4 ++#endif ++ ++#ifndef IPSEC_SA_REF_FREELIST_NUM_ENTRIES ++# define IPSEC_SA_REF_FREELIST_NUM_ENTRIES 256 ++#endif ++ ++#ifndef IPSEC_SA_REF_CODE ++# define IPSEC_SA_REF_CODE 1 ++#endif ++ ++#ifdef __KERNEL__ ++/* This is defined for 2.4, but not 2.2.... */ ++#ifndef ARPHRD_VOID ++# define ARPHRD_VOID 0xFFFF ++#endif ++ ++/* ++ * Worry about PROC_FS stuff ++ */ ++#if defined(PROC_FS_2325) ++/* kernel 2.4 */ ++# define IPSEC_PROC_LAST_ARG ,int *eof,void *data ++# define IPSEC_PROCFS_DEBUG_NO_STATIC ++# define IPSEC_PROC_SUBDIRS ++#else ++/* kernel <2.4 */ ++# define IPSEC_PROCFS_DEBUG_NO_STATIC DEBUG_NO_STATIC ++ ++# ifndef PROC_NO_DUMMY ++# define IPSEC_PROC_LAST_ARG , int dummy ++# else ++# define IPSEC_PROC_LAST_ARG ++# endif /* !PROC_NO_DUMMY */ ++#endif /* PROC_FS_2325 */ ++ ++#if !defined(LINUX_KERNEL_HAS_SNPRINTF) ++/* GNU CPP specific! */ ++# define snprintf(buf, len, fmt...) sprintf(buf, ##fmt) ++#endif /* !LINUX_KERNEL_HAS_SNPRINTF */ ++ ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++ ++#ifndef KLIPS_FIXES_DES_PARITY ++# define KLIPS_FIXES_DES_PARITY 1 ++#endif /* !KLIPS_FIXES_DES_PARITY */ ++ ++/* we don't really want to print these unless there are really big problems */ ++#ifndef KLIPS_DIVULGE_CYPHER_KEY ++# define KLIPS_DIVULGE_CYPHER_KEY 0 ++#endif /* !KLIPS_DIVULGE_CYPHER_KEY */ ++ ++#ifndef KLIPS_DIVULGE_HMAC_KEY ++# define KLIPS_DIVULGE_HMAC_KEY 0 ++#endif /* !KLIPS_DIVULGE_HMAC_KEY */ ++ ++#ifndef IPSEC_DISALLOW_IPOPTIONS ++# define IPSEC_DISALLOW_IPOPTIONS 1 ++#endif /* !KLIPS_DIVULGE_HMAC_KEY */ ++ ++/* extra toggles for regression testing */ ++#ifdef CONFIG_IPSEC_REGRESS ++ ++/* ++ * should pfkey_acquire() become 100% lossy? ++ * ++ */ ++extern int sysctl_ipsec_regress_pfkey_lossage; ++#ifndef KLIPS_PFKEY_ACQUIRE_LOSSAGE ++# ifdef CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE ++# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 100 ++# else /* CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE */ ++/* not by default! */ ++# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0 ++# endif /* CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE */ ++#endif /* KLIPS_PFKEY_ACQUIRE_LOSSAGE */ ++ ++#endif /* CONFIG_IPSEC_REGRESS */ ++ ++ ++/* ++ * debugging routines. ++ */ ++#ifdef CONFIG_IPSEC_DEBUG ++extern void ipsec_print_ip(struct iphdr *ip); ++ ++ #define KLIPS_PRINT(flag, format, args...) \ ++ ((flag) ? printk(KERN_INFO format , ## args) : 0) ++ #define KLIPS_PRINTMORE(flag, format, args...) \ ++ ((flag) ? printk(format , ## args) : 0) ++ #define KLIPS_IP_PRINT(flag, ip) \ ++ ((flag) ? ipsec_print_ip(ip) : 0) ++#else /* CONFIG_IPSEC_DEBUG */ ++ #define KLIPS_PRINT(flag, format, args...) do ; while(0) ++ #define KLIPS_PRINTMORE(flag, format, args...) do ; while(0) ++ #define KLIPS_IP_PRINT(flag, ip) do ; while(0) ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ ++/* ++ * Stupid kernel API differences in APIs. Not only do some ++ * kernels not have ip_select_ident, but some have differing APIs, ++ * and SuSE has one with one parameter, but no way of checking to ++ * see what is really what. ++ */ ++ ++#ifdef SUSE_LINUX_2_4_19_IS_STUPID ++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph) ++#else ++ ++/* simplest case, nothing */ ++#if !defined(IP_SELECT_IDENT) ++#define KLIPS_IP_SELECT_IDENT(iph, skb) do { iph->id = htons(ip_id_count++); } while(0) ++#endif ++ ++/* kernels > 2.3.37-ish */ ++#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW) ++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst) ++#endif ++ ++/* kernels > 2.4.2 */ ++#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW) ++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL) ++#endif ++ ++#endif /* SUSE_LINUX_2_4_19_IS_STUPID */ ++ ++/* ++ * make klips fail test:east-espiv-01. ++ * exploit is at testing/attacks/espiv ++ * ++ */ ++#define KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK 0 ++ ++ ++/* IP_FRAGMENT_LINEARIZE is set in freeswan.h if Kernel > 2.4.4 */ ++#ifndef IP_FRAGMENT_LINEARIZE ++# define IP_FRAGMENT_LINEARIZE 0 ++#endif /* IP_FRAGMENT_LINEARIZE */ ++#endif /* __KERNEL__ */ ++ ++#define _IPSEC_PARAM_H_ ++#endif /* _IPSEC_PARAM_H_ */ ++ ++/* ++ * $Log: ipsec_param.h,v $ ++ * Revision 1.24 2004/04/05 19:55:06 mcr ++ * Moved from linux/include/freeswan/ipsec_param.h,v ++ * ++ * Revision 1.23 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.22 2003/10/31 02:27:05 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.21.4.1 2003/10/29 01:10:19 mcr ++ * elimited "struct sa_id" ++ * ++ * Revision 1.21 2003/04/03 17:38:18 rgb ++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. ++ * Change indentation for readability. ++ * ++ * Revision 1.20 2003/03/14 08:09:26 rgb ++ * Fixed up CONFIG_IPSEC_DYNDEV definitions. ++ * ++ * Revision 1.19 2003/01/30 02:31:43 rgb ++ * ++ * Rename SAref table macro names for clarity. ++ * ++ * Revision 1.18 2002/09/30 19:06:26 rgb ++ * Reduce default table to 16 bits width. ++ * ++ * Revision 1.17 2002/09/20 15:40:29 rgb ++ * Define switch to activate new SAref code. ++ * Prefix macros with "IPSEC_". ++ * Rework saref freelist. ++ * Restrict some bits to kernel context for use to klips utils. ++ * ++ * Revision 1.16 2002/09/20 05:00:31 rgb ++ * Define switch to divulge hmac keys for debugging. ++ * Added IPOPTIONS switch. ++ * ++ * Revision 1.15 2002/09/19 02:34:24 mcr ++ * define IPSEC_PROC_SUBDIRS if we are 2.4, and use that in ipsec_proc.c ++ * to decide if we are to create /proc/net/ipsec/. ++ * ++ * Revision 1.14 2002/08/30 01:20:54 mcr ++ * reorganized 2.0/2.2/2.4 procfs support macro so match ++ * 2.4 values/typedefs. ++ * ++ * Revision 1.13 2002/07/28 22:03:28 mcr ++ * added some documentation to SA_REF_* ++ * turned on fix for ESPIV attack, now that we have the attack code. ++ * ++ * Revision 1.12 2002/07/26 08:48:31 rgb ++ * Added SA ref table code. ++ * ++ * Revision 1.11 2002/07/23 02:57:45 rgb ++ * Define ARPHRD_VOID for < 2.4 kernels. ++ * ++ * Revision 1.10 2002/05/27 21:37:28 rgb ++ * Set the defaults sanely for those adventurous enough to try more than 1 ++ * digit of ipsec devices. ++ * ++ * Revision 1.9 2002/05/27 18:56:07 rgb ++ * Convert to dynamic ipsec device allocation. ++ * ++ * Revision 1.8 2002/04/24 07:36:47 mcr ++ * Moved from ./klips/net/ipsec/ipsec_param.h,v ++ * ++ * Revision 1.7 2002/04/20 00:12:25 rgb ++ * Added esp IV CBC attack fix, disabled. ++ * ++ * Revision 1.6 2002/01/29 02:11:42 mcr ++ * removal of kversions.h - sources that needed it now use ipsec_param.h. ++ * updating of IPv6 structures to match latest in6.h version. ++ * removed dead code from freeswan.h that also duplicated kversions.h ++ * code. ++ * ++ * Revision 1.5 2002/01/28 19:22:01 mcr ++ * by default, turn off LINEARIZE option ++ * (let kversions.h turn it on) ++ * ++ * Revision 1.4 2002/01/20 20:19:36 mcr ++ * renamed option to IP_FRAGMENT_LINEARIZE. ++ * ++ * Revision 1.3 2002/01/12 02:57:25 mcr ++ * first regression test causes acquire messages to be lost ++ * 100% of the time. This is to help testing of pluto. ++ * ++ * Revision 1.2 2001/11/26 09:16:14 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.1.2.3 2001/10/23 04:40:16 mcr ++ * added #define for DIVULGING session keys in debug output. ++ * ++ * Revision 1.1.2.2 2001/10/22 20:53:25 mcr ++ * added a define to control forcing of DES parity. ++ * ++ * Revision 1.1.2.1 2001/09/25 02:20:19 mcr ++ * many common kernel configuration questions centralized. ++ * more things remain that should be moved from freeswan.h. ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_policy.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,216 @@ ++#ifndef _IPSEC_POLICY_H ++/* ++ * policy interface file between pluto and applications ++ * Copyright (C) 2003 Michael Richardson <mcr@freeswan.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: ipsec_policy.h,v 1.5 2004/06/17 04:23:33 mcr Exp $ ++ */ ++#define _IPSEC_POLICY_H /* seen it, no need to see it again */ ++ ++ ++/* ++ * this file defines an interface between an application (or rather an ++ * application library) and a key/policy daemon. It provides for inquiries ++ * as to the current state of a connected socket, as well as for general ++ * questions. ++ * ++ * In general, the interface is defined as a series of functional interfaces, ++ * and the policy messages should be internal. However, because this is in ++ * fact an ABI between pieces of the system that may get compiled and revised ++ * seperately, this ABI must be public and revision controlled. ++ * ++ * It is expected that the daemon will always support previous versions. ++ */ ++ ++#define IPSEC_POLICY_MSG_REVISION (unsigned)200305061 ++ ++enum ipsec_policy_command { ++ IPSEC_CMD_QUERY_FD = 1, ++ IPSEC_CMD_QUERY_HOSTPAIR = 2, ++ IPSEC_CMD_QUERY_DSTONLY = 3, ++}; ++ ++struct ipsec_policy_msg_head { ++ u_int32_t ipm_version; ++ u_int32_t ipm_msg_len; ++ u_int32_t ipm_msg_type; ++ u_int32_t ipm_msg_seq; ++}; ++ ++enum ipsec_privacy_quality { ++ IPSEC_PRIVACY_NONE = 0, ++ IPSEC_PRIVACY_INTEGRAL = 4, /* not private at all. AH-like */ ++ IPSEC_PRIVACY_UNKNOWN = 8, /* something is claimed, but details unavail */ ++ IPSEC_PRIVACY_ROT13 = 12, /* trivially breakable, i.e. 1DES */ ++ IPSEC_PRIVACY_GAK = 16, /* known eavesdroppers */ ++ IPSEC_PRIVACY_PRIVATE = 32, /* secure for at least a decade */ ++ IPSEC_PRIVACY_STRONG = 64, /* ridiculously secure */ ++ IPSEC_PRIVACY_TORTOISE = 192, /* even stronger, but very slow */ ++ IPSEC_PRIVACY_OTP = 224, /* some kind of *true* one time pad */ ++}; ++ ++enum ipsec_bandwidth_quality { ++ IPSEC_QOS_UNKNOWN = 0, /* unknown bandwidth */ ++ IPSEC_QOS_INTERACTIVE = 16, /* reasonably moderate jitter, moderate fast. ++ Good enough for telnet/ssh. */ ++ IPSEC_QOS_VOIP = 32, /* faster crypto, predicable jitter */ ++ IPSEC_QOS_FTP = 64, /* higher throughput crypto, perhaps hardware ++ offloaded, but latency/jitter may be bad */ ++ IPSEC_QOS_WIRESPEED = 128, /* expect to be able to fill your pipe */ ++}; ++ ++/* moved from programs/pluto/constants.h */ ++/* IPsec AH transform values ++ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.3 ++ * and in http://www.iana.org/assignments/isakmp-registry ++ */ ++enum ipsec_authentication_algo { ++ AH_MD5=2, ++ AH_SHA=3, ++ AH_DES=4, ++ AH_SHA2_256=5, ++ AH_SHA2_384=6, ++ AH_SHA2_512=7 ++}; ++ ++/* IPsec ESP transform values ++ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.4 ++ * and from http://www.iana.org/assignments/isakmp-registry ++ */ ++ ++enum ipsec_cipher_algo { ++ ESP_reserved=0, ++ ESP_DES_IV64=1, ++ ESP_DES=2, ++ ESP_3DES=3, ++ ESP_RC5=4, ++ ESP_IDEA=5, ++ ESP_CAST=6, ++ ESP_BLOWFISH=7, ++ ESP_3IDEA=8, ++ ESP_DES_IV32=9, ++ ESP_RC4=10, ++ ESP_NULL=11, ++ ESP_AES=12, ++}; ++ ++/* IPCOMP transform values ++ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.5 ++ */ ++ ++enum ipsec_comp_algo { ++ IPCOMP_OUI= 1, ++ IPCOMP_DEFLATE= 2, ++ IPCOMP_LZS= 3, ++ IPCOMP_V42BIS= 4 ++}; ++ ++/* Identification type values ++ * RFC 2407 The Internet IP security Domain of Interpretation for ISAKMP 4.6.2.1 ++ */ ++ ++enum ipsec_id_type { ++ ID_IMPOSSIBLE= (-2), /* private to Pluto */ ++ ID_MYID= (-1), /* private to Pluto */ ++ ID_NONE= 0, /* private to Pluto */ ++ ID_IPV4_ADDR= 1, ++ ID_FQDN= 2, ++ ID_USER_FQDN= 3, ++ ID_IPV4_ADDR_SUBNET= 4, ++ ID_IPV6_ADDR= 5, ++ ID_IPV6_ADDR_SUBNET= 6, ++ ID_IPV4_ADDR_RANGE= 7, ++ ID_IPV6_ADDR_RANGE= 8, ++ ID_DER_ASN1_DN= 9, ++ ID_DER_ASN1_GN= 10, ++ ID_KEY_ID= 11 ++}; ++ ++/* Certificate type values ++ * RFC 2408 ISAKMP, chapter 3.9 ++ */ ++enum ipsec_cert_type { ++ CERT_NONE= 0, /* none, or guess from file contents */ ++ CERT_PKCS7_WRAPPED_X509= 1, /* self-signed certificate from disk */ ++ CERT_PGP= 2, ++ CERT_DNS_SIGNED_KEY= 3, /* KEY RR from DNS */ ++ CERT_X509_SIGNATURE= 4, ++ CERT_X509_KEY_EXCHANGE= 5, ++ CERT_KERBEROS_TOKENS= 6, ++ CERT_CRL= 7, ++ CERT_ARL= 8, ++ CERT_SPKI= 9, ++ CERT_X509_ATTRIBUTE= 10, ++ CERT_RAW_RSA= 11, /* raw RSA from config file */ ++}; ++ ++/* a SIG record in ASCII */ ++struct ipsec_dns_sig { ++ char fqdn[256]; ++ char dns_sig[768]; /* empty string if not signed */ ++}; ++ ++struct ipsec_raw_key { ++ char id_name[256]; ++ char fs_keyid[8]; ++}; ++ ++struct ipsec_identity { ++ enum ipsec_id_type ii_type; ++ enum ipsec_cert_type ii_format; ++ union { ++ struct ipsec_dns_sig ipsec_dns_signed; ++ /* some thing for PGP */ ++ /* some thing for PKIX */ ++ struct ipsec_raw_key ipsec_raw_key; ++ } ii_credential; ++}; ++ ++#define IPSEC_MAX_CREDENTIALS 32 ++ ++struct ipsec_policy_cmd_query { ++ struct ipsec_policy_msg_head head; ++ ++ /* Query section */ ++ ip_address query_local; /* us */ ++ ip_address query_remote; /* them */ ++ u_short src_port, dst_port; ++ ++ /* Answer section */ ++ enum ipsec_privacy_quality strength; ++ enum ipsec_bandwidth_quality bandwidth; ++ enum ipsec_authentication_algo auth_detail; ++ enum ipsec_cipher_algo esp_detail; ++ enum ipsec_comp_algo comp_detail; ++ ++ int credential_count; ++ ++ struct ipsec_identity credentials[IPSEC_MAX_CREDENTIALS]; ++}; ++ ++#define IPSEC_POLICY_SOCKET "/var/run/pluto.info" ++ ++/* prototypes */ ++extern err_t ipsec_policy_lookup(int fd, struct ipsec_policy_cmd_query *result); ++extern err_t ipsec_policy_init(void); ++extern err_t ipsec_policy_final(void); ++extern err_t ipsec_policy_readmsg(int policysock, ++ unsigned char *buf, size_t buflen); ++extern err_t ipsec_policy_sendrecv(unsigned char *buf, size_t buflen); ++extern err_t ipsec_policy_cgilookup(struct ipsec_policy_cmd_query *result); ++ ++ ++extern const char *ipsec_policy_version_code(void); ++extern const char *ipsec_policy_version_string(void); ++ ++#endif /* _IPSEC_POLICY_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_proto.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,151 @@ ++/* ++ * @(#) prototypes for FreeSWAN functions ++ * ++ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org> ++ * and Michael Richardson <mcr@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_proto.h,v 1.8 2004/04/05 19:55:06 mcr Exp $ ++ * ++ */ ++ ++#ifndef _IPSEC_PROTO_H_ ++ ++#include "ipsec_param.h" ++ ++/* ++ * This file is a kernel only file that declares prototypes for ++ * all intra-module function calls and global data structures. ++ * ++ * Include this file last. ++ * ++ */ ++ ++/* ipsec_init.c */ ++extern struct prng ipsec_prng; ++ ++/* ipsec_sa.c */ ++extern struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD]; ++extern spinlock_t tdb_lock; ++extern int ipsec_sadb_init(void); ++ ++extern struct ipsec_sa *ipsec_sa_getbyid(ip_said *); ++extern int ipsec_sa_put(struct ipsec_sa *); ++extern /* void */ int ipsec_sa_del(struct ipsec_sa *); ++extern /* void */ int ipsec_sa_delchain(struct ipsec_sa *); ++extern /* void */ int ipsec_sa_add(struct ipsec_sa *); ++ ++extern int ipsec_sadb_cleanup(__u8); ++extern int ipsec_sa_wipe(struct ipsec_sa *); ++ ++/* debug declarations */ ++ ++/* ipsec_proc.c */ ++extern int ipsec_proc_init(void); ++extern void ipsec_proc_cleanup(void); ++ ++/* ipsec_radij.c */ ++extern int ipsec_makeroute(struct sockaddr_encap *ea, ++ struct sockaddr_encap *em, ++ ip_said said, ++ uint32_t pid, ++ struct sk_buff *skb, ++ struct ident *ident_s, ++ struct ident *ident_d); ++ ++extern int ipsec_breakroute(struct sockaddr_encap *ea, ++ struct sockaddr_encap *em, ++ struct sk_buff **first, ++ struct sk_buff **last); ++ ++int ipsec_radijinit(void); ++int ipsec_cleareroutes(void); ++int ipsec_radijcleanup(void); ++ ++/* ipsec_life.c */ ++extern enum ipsec_life_alive ipsec_lifetime_check(struct ipsec_lifetime64 *il64, ++ const char *lifename, ++ const char *saname, ++ enum ipsec_life_type ilt, ++ enum ipsec_direction idir, ++ struct ipsec_sa *ips); ++ ++ ++extern int ipsec_lifetime_format(char *buffer, ++ int buflen, ++ char *lifename, ++ enum ipsec_life_type timebaselife, ++ struct ipsec_lifetime64 *lifetime); ++ ++extern void ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime, ++ __u64 newvalue); ++ ++extern void ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime, ++ __u64 newvalue); ++ ++ ++ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ ++extern int debug_xform; ++extern int debug_eroute; ++extern int debug_spi; ++extern int debug_netlink; ++ ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ ++ ++ ++#define _IPSEC_PROTO_H ++#endif /* _IPSEC_PROTO_H_ */ ++ ++/* ++ * $Log: ipsec_proto.h,v $ ++ * Revision 1.8 2004/04/05 19:55:06 mcr ++ * Moved from linux/include/freeswan/ipsec_proto.h,v ++ * ++ * Revision 1.7 2003/10/31 02:27:05 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.6.30.1 2003/10/29 01:10:19 mcr ++ * elimited "struct sa_id" ++ * ++ * Revision 1.6 2002/05/23 07:13:48 rgb ++ * Added ipsec_sa_put() for releasing an ipsec_sa refcount. ++ * ++ * Revision 1.5 2002/05/14 02:36:40 rgb ++ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion ++ * with "put" usage in the kernel. ++ * ++ * Revision 1.4 2002/04/24 07:36:47 mcr ++ * Moved from ./klips/net/ipsec/ipsec_proto.h,v ++ * ++ * Revision 1.3 2002/04/20 00:12:25 rgb ++ * Added esp IV CBC attack fix, disabled. ++ * ++ * Revision 1.2 2001/11/26 09:16:15 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.1.2.1 2001/09/25 02:21:01 mcr ++ * ipsec_proto.h created to keep prototypes rather than deal with ++ * cyclic dependancies of structures and prototypes in .h files. ++ * ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_radij.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,176 @@ ++/* ++ * @(#) Definitions relevant to the IPSEC <> radij tree interfacing ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_radij.h,v 1.21 2004/04/29 11:06:42 ken Exp $ ++ */ ++ ++#ifndef _IPSEC_RADIJ_H ++ ++#include <openswan.h> ++ ++int ipsec_walk(char *); ++ ++int ipsec_rj_walker_procprint(struct radij_node *, void *); ++int ipsec_rj_walker_delete(struct radij_node *, void *); ++ ++/* This structure is used to pass information between ++ * ipsec_eroute_get_info and ipsec_rj_walker_procprint ++ * (through rj_walktree) and between calls of ipsec_rj_walker_procprint. ++ */ ++struct wsbuf ++{ ++ /* from caller of ipsec_eroute_get_info: */ ++ char *const buffer; /* start of buffer provided */ ++ const int length; /* length of buffer provided */ ++ const off_t offset; /* file position of first character of interest */ ++ /* accumulated by ipsec_rj_walker_procprint: */ ++ int len; /* number of character filled into buffer */ ++ off_t begin; /* file position contained in buffer[0] (<=offset) */ ++}; ++ ++extern struct radij_node_head *rnh; ++extern spinlock_t eroute_lock; ++ ++struct eroute * ipsec_findroute(struct sockaddr_encap *); ++ ++#define O1(x) (int)(((x)>>24)&0xff) ++#define O2(x) (int)(((x)>>16)&0xff) ++#define O3(x) (int)(((x)>>8)&0xff) ++#define O4(x) (int)(((x))&0xff) ++ ++#ifdef CONFIG_IPSEC_DEBUG ++extern int debug_radij; ++void rj_dumptrees(void); ++ ++#define DB_RJ_DUMPTREES 0x0001 ++#define DB_RJ_FINDROUTE 0x0002 ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++#define _IPSEC_RADIJ_H ++#endif ++ ++/* ++ * $Log: ipsec_radij.h,v $ ++ * Revision 1.21 2004/04/29 11:06:42 ken ++ * Last bits from 2.06 procfs updates ++ * ++ * Revision 1.20 2004/04/06 02:49:08 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.19 2004/04/05 19:55:06 mcr ++ * Moved from linux/include/freeswan/ipsec_radij.h,v ++ * ++ * Revision 1.18 2002/04/24 07:36:47 mcr ++ * Moved from ./klips/net/ipsec/ipsec_radij.h,v ++ * ++ * Revision 1.17 2001/11/26 09:23:49 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.16.2.1 2001/09/25 02:21:17 mcr ++ * ipsec_proto.h created to keep prototypes rather than deal with ++ * cyclic dependancies of structures and prototypes in .h files. ++ * ++ * Revision 1.16 2001/09/15 16:24:04 rgb ++ * Re-inject first and last HOLD packet when an eroute REPLACE is done. ++ * ++ * Revision 1.15 2001/09/14 16:58:37 rgb ++ * Added support for storing the first and last packets through a HOLD. ++ * ++ * Revision 1.14 2001/09/08 21:13:32 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.13 2001/06/14 19:35:09 rgb ++ * Update copyright date. ++ * ++ * Revision 1.12 2001/05/27 06:12:11 rgb ++ * Added structures for pid, packet count and last access time to eroute. ++ * Added packet count to beginning of /proc/net/ipsec_eroute. ++ * ++ * Revision 1.11 2000/09/08 19:12:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.10 1999/11/17 15:53:39 rgb ++ * Changed all occurrences of #include "../../../lib/freeswan.h" ++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the ++ * klips/net/ipsec/Makefile. ++ * ++ * Revision 1.9 1999/10/01 00:01:23 rgb ++ * Added eroute structure locking. ++ * ++ * Revision 1.8 1999/04/11 00:28:59 henry ++ * GPL boilerplate ++ * ++ * Revision 1.7 1999/04/06 04:54:26 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.6 1999/01/22 06:23:26 rgb ++ * Cruft clean-out. ++ * ++ * Revision 1.5 1998/10/25 02:42:08 rgb ++ * Change return type on ipsec_breakroute and ipsec_makeroute and add an ++ * argument to be able to transmit more infomation about errors. ++ * ++ * Revision 1.4 1998/10/19 14:44:29 rgb ++ * Added inclusion of freeswan.h. ++ * sa_id structure implemented and used: now includes protocol. ++ * ++ * Revision 1.3 1998/07/28 00:03:31 rgb ++ * Comment out temporary inet_nto4u() kluge. ++ * ++ * Revision 1.2 1998/07/14 18:22:00 rgb ++ * Add function to clear the eroute table. ++ * ++ * Revision 1.1 1998/06/18 21:27:49 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.5 1998/05/25 20:30:38 rgb ++ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. ++ * ++ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and ++ * add ipsec_rj_walker_delete. ++ * ++ * Revision 1.4 1998/05/21 13:02:56 rgb ++ * Imported definitions from ipsec_radij.c and radij.c to support /proc 3k ++ * limit fix. ++ * ++ * Revision 1.3 1998/04/21 21:29:09 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.2 1998/04/14 17:30:39 rgb ++ * Fix up compiling errors for radij tree memory reclamation. ++ * ++ * Revision 1.1 1998/04/09 03:06:10 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:04 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * No changes. ++ * ++ * Revision 0.3 1996/11/20 14:39:04 ji ++ * Minor cleanups. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_rcv.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,279 @@ ++/* ++ * ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_rcv.h,v 1.21 2004/04/06 02:49:08 mcr Exp $ ++ */ ++ ++#ifndef IPSEC_RCV_H ++#define IPSEC_RCV_H ++ ++#include "openswan/ipsec_auth.h" ++ ++#define DB_RX_PKTRX 0x0001 ++#define DB_RX_PKTRX2 0x0002 ++#define DB_RX_DMP 0x0004 ++#define DB_RX_IPSA 0x0010 ++#define DB_RX_XF 0x0020 ++#define DB_RX_IPAD 0x0040 ++#define DB_RX_INAU 0x0080 ++#define DB_RX_OINFO 0x0100 ++#define DB_RX_OINFO2 0x0200 ++#define DB_RX_OH 0x0400 ++#define DB_RX_REPLAY 0x0800 ++ ++#ifdef __KERNEL__ ++/* struct options; */ ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/config.h> /* for CONFIG_IP_FORWARD */ ++#include <linux/version.h> ++#include <openswan.h> ++ ++#define IPSEC_BIRTH_TEMPLATE_MAXLEN 256 ++ ++struct ipsec_birth_reply { ++ int packet_template_len; ++ unsigned char packet_template[IPSEC_BIRTH_TEMPLATE_MAXLEN]; ++}; ++ ++extern struct ipsec_birth_reply ipsec_ipv4_birth_packet; ++extern struct ipsec_birth_reply ipsec_ipv6_birth_packet; ++ ++enum ipsec_rcv_value { ++ IPSEC_RCV_LASTPROTO=1, ++ IPSEC_RCV_OK=0, ++ IPSEC_RCV_BADPROTO=-1, ++ IPSEC_RCV_BADLEN=-2, ++ IPSEC_RCV_ESP_BADALG=-3, ++ IPSEC_RCV_3DES_BADBLOCKING=-4, ++ IPSEC_RCV_ESP_DECAPFAIL=-5, ++ IPSEC_RCV_DECAPFAIL=-6, ++ IPSEC_RCV_SAIDNOTFOUND=-7, ++ IPSEC_RCV_IPCOMPALONE=-8, ++ IPSEC_RCV_IPCOMPFAILED=-10, ++ IPSEC_RCV_SAIDNOTLIVE=-11, ++ IPSEC_RCV_FAILEDINBOUND=-12, ++ IPSEC_RCV_LIFETIMEFAILED=-13, ++ IPSEC_RCV_BADAUTH=-14, ++ IPSEC_RCV_REPLAYFAILED=-15, ++ IPSEC_RCV_AUTHFAILED=-16, ++ IPSEC_RCV_REPLAYROLLED=-17, ++ IPSEC_RCV_BAD_DECRYPT=-18 ++}; ++ ++struct ipsec_rcv_state { ++ struct sk_buff *skb; ++ struct net_device_stats *stats; ++ struct iphdr *ipp; ++ struct ipsec_sa *ipsp; ++ int len; ++ int ilen; ++ int authlen; ++ int hard_header_len; ++ int iphlen; ++ struct auth_alg *authfuncs; ++ ip_said said; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ __u8 next_header; ++ __u8 hash[AH_AMAX]; ++ char ipsaddr_txt[ADDRTOA_BUF]; ++ char ipdaddr_txt[ADDRTOA_BUF]; ++ __u8 *octx; ++ __u8 *ictx; ++ int ictx_len; ++ int octx_len; ++ union { ++ struct { ++ struct esphdr *espp; ++ } espstuff; ++ struct { ++ struct ahhdr *ahp; ++ } ahstuff; ++ struct { ++ struct ipcomphdr *compp; ++ } ipcompstuff; ++ } protostuff; ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ __u8 natt_type; ++ __u16 natt_sport; ++ __u16 natt_dport; ++ int natt_len; ++#endif ++}; ++ ++extern int ++#ifdef PROTO_HANDLER_SINGLE_PARM ++ipsec_rcv(struct sk_buff *skb); ++#else /* PROTO_HANDLER_SINGLE_PARM */ ++ipsec_rcv(struct sk_buff *skb, ++#ifdef NET_21 ++ unsigned short xlen); ++#else /* NET_21 */ ++ struct device *dev, ++ struct options *opt, ++ __u32 daddr, ++ unsigned short len, ++ __u32 saddr, ++ int redo, ++ struct inet_protocol *protocol); ++#endif /* NET_21 */ ++#endif /* PROTO_HANDLER_SINGLE_PARM */ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++extern int debug_rcv; ++#endif /* CONFIG_IPSEC_DEBUG */ ++#define ipsec_rcv_dmp(_x,_y, _z) if (debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp(_x,_y,_z) ++ ++extern int sysctl_ipsec_inbound_policy_check; ++#endif /* __KERNEL__ */ ++ ++#endif /* IPSEC_RCV_H */ ++ ++/* ++ * $Log: ipsec_rcv.h,v $ ++ * Revision 1.21 2004/04/06 02:49:08 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.20 2004/04/05 19:55:06 mcr ++ * Moved from linux/include/freeswan/ipsec_rcv.h,v ++ * ++ * Revision 1.19 2003/12/15 18:13:09 mcr ++ * when compiling with NAT traversal, don't assume that the ++ * kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP ++ * is set. ++ * ++ * Revision 1.18 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.17 2002/09/03 16:32:32 mcr ++ * definitions of ipsec_birth_reply. ++ * ++ * Revision 1.16 2002/05/14 02:36:00 rgb ++ * Change references to _TDB to _IPSA. ++ * ++ * Revision 1.15 2002/04/24 07:36:47 mcr ++ * Moved from ./klips/net/ipsec/ipsec_rcv.h,v ++ * ++ * Revision 1.14 2001/09/07 22:15:48 rgb ++ * Fix for removal of transport layer protocol handler arg in 2.4.4. ++ * ++ * Revision 1.13 2001/06/14 19:35:09 rgb ++ * Update copyright date. ++ * ++ * Revision 1.12 2001/03/16 07:36:44 rgb ++ * Fixed #endif comment to sate compiler. ++ * ++ * Revision 1.11 2000/09/21 04:34:21 rgb ++ * Moved declaration of sysctl_ipsec_inbound_policy_check outside ++ * CONFIG_IPSEC_DEBUG. (MB) ++ * ++ * Revision 1.10 2000/09/18 02:36:10 rgb ++ * Exported sysctl_ipsec_inbound_policy_check for skb_decompress(). ++ * ++ * Revision 1.9 2000/09/08 19:12:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.8 1999/11/18 04:09:19 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * ++ * Revision 1.7 1999/05/25 01:45:37 rgb ++ * Fix version macros for 2.0.x as a module. ++ * ++ * Revision 1.6 1999/05/08 21:24:27 rgb ++ * Add includes for 2.2.x include into net/ipv4/protocol.c ++ * ++ * Revision 1.5 1999/05/05 22:02:32 rgb ++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>. ++ * ++ * Revision 1.4 1999/04/11 00:28:59 henry ++ * GPL boilerplate ++ * ++ * Revision 1.3 1999/04/06 04:54:27 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.2 1999/01/22 20:06:59 rgb ++ * Fixed cut-and-paste error from ipsec_esp.h. ++ * ++ * Revision 1.1 1999/01/21 20:29:12 rgb ++ * Converted from transform switching to algorithm switching. ++ * ++ * Log: ipsec_esp.h,v ++ * Revision 1.4 1998/08/12 00:07:32 rgb ++ * Added data structures for new xforms: null, {,3}dessha1. ++ * ++ * Revision 1.3 1998/07/14 15:57:01 rgb ++ * Add #ifdef __KERNEL__ to protect kernel-only structures. ++ * ++ * Revision 1.2 1998/06/25 19:33:46 rgb ++ * Add prototype for protocol receive function. ++ * Rearrange for more logical layout. ++ * ++ * Revision 1.1 1998/06/18 21:27:45 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.6 1998/06/05 02:28:08 rgb ++ * Minor comment fix. ++ * ++ * Revision 1.5 1998/05/27 22:34:00 rgb ++ * Changed structures to accomodate key separation. ++ * ++ * Revision 1.4 1998/05/18 22:28:43 rgb ++ * Disable key printing facilities from /proc/net/ipsec_*. ++ * ++ * Revision 1.3 1998/04/21 21:29:07 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.2 1998/04/12 22:03:20 rgb ++ * Updated ESP-3DES-HMAC-MD5-96, ++ * ESP-DES-HMAC-MD5-96, ++ * AH-HMAC-MD5-96, ++ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository ++ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. ++ * ++ * Fixed eroute references in /proc/net/ipsec*. ++ * ++ * Started to patch module unloading memory leaks in ipsec_netlink and ++ * radij tree unloading. ++ * ++ * Revision 1.1 1998/04/09 03:06:00 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:02 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.5 1997/06/03 04:24:48 ji ++ * Added ESP-3DES-MD5-96 transform. ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * Added definitions for new ESP transforms. ++ * ++ * Revision 0.3 1996/11/20 14:35:48 ji ++ * Minor Cleanup. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ ++ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_sa.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,341 @@ ++/* ++ * @(#) Definitions of IPsec Security Association (ipsec_sa) ++ * ++ * Copyright (C) 2001, 2002, 2003 ++ * Richard Guy Briggs <rgb@freeswan.org> ++ * and Michael Richardson <mcr@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_sa.h,v 1.19 2004/04/05 19:55:06 mcr Exp $ ++ * ++ * This file derived from ipsec_xform.h on 2001/9/18 by mcr. ++ * ++ */ ++ ++/* ++ * This file describes the IPsec Security Association Structure. ++ * ++ * This structure keeps track of a single transform that may be done ++ * to a set of packets. It can describe applying the transform or ++ * apply the reverse. (e.g. compression vs expansion). However, it ++ * only describes one at a time. To describe both, two structures would ++ * be used, but since the sides of the transform are performed ++ * on different machines typically it is usual to have only one side ++ * of each association. ++ * ++ */ ++ ++#ifndef _IPSEC_SA_H_ ++ ++#ifdef __KERNEL__ ++#include "ipsec_stats.h" ++#include "ipsec_life.h" ++#include "ipsec_eroute.h" ++#endif /* __KERNEL__ */ ++#include "ipsec_param.h" ++ ++ ++/* SAs are held in a table. ++ * Entries in this table are referenced by IPsecSAref_t values. ++ * IPsecSAref_t values are conceptually subscripts. Because ++ * we want to allocate the table piece-meal, the subscripting ++ * is implemented with two levels, a bit like paged virtual memory. ++ * This representation mechanism is known as an Iliffe Vector. ++ * ++ * The Main table (AKA the refTable) consists of 2^IPSEC_SA_REF_MAINTABLE_IDX_WIDTH ++ * pointers to subtables. ++ * Each subtable has 2^IPSEC_SA_REF_SUBTABLE_IDX_WIDTH entries, each of which ++ * is a pointer to an SA. ++ * ++ * An IPsecSAref_t contains either an exceptional value (signified by the ++ * high-order bit being on) or a reference to a table entry. A table entry ++ * reference has the subtable subscript in the low-order ++ * IPSEC_SA_REF_SUBTABLE_IDX_WIDTH bits and the Main table subscript ++ * in the next lowest IPSEC_SA_REF_MAINTABLE_IDX_WIDTH bits. ++ * ++ * The Maintable entry for an IPsecSAref_t x, a pointer to its subtable, is ++ * IPsecSAref2table(x). It is of type struct IPsecSArefSubTable *. ++ * ++ * The pointer to the SA for x is IPsecSAref2SA(x). It is of type ++ * struct ipsec_sa*. The macro definition clearly shows the two-level ++ * access needed to find the SA pointer. ++ * ++ * The Maintable is allocated when IPsec is initialized. ++ * Each subtable is allocated when needed, but the first is allocated ++ * when IPsec is initialized. ++ * ++ * IPsecSAref_t is designed to be smaller than an NFmark so that ++ * they can be stored in NFmarks and still leave a few bits for other ++ * purposes. The spare bits are in the low order of the NFmark ++ * but in the high order of the IPsecSAref_t, so conversion is required. ++ * We pick the upper bits of NFmark on the theory that they are less likely to ++ * interfere with more pedestrian uses of nfmark. ++ */ ++ ++ ++typedef unsigned short int IPsecRefTableUnusedCount; ++ ++#define IPSEC_SA_REF_TABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH) ++ ++#ifdef __KERNEL__ ++#if ((IPSEC_SA_REF_TABLE_IDX_WIDTH - (1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) < 0) ++#error "IPSEC_SA_REF_TABLE_IDX_WIDTH("IPSEC_SA_REF_TABLE_IDX_WIDTH") MUST be < 1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH("IPSEC_SA_REF_MAINTABLE_IDX_WIDTH")" ++#endif ++ ++#define IPSEC_SA_REF_SUBTABLE_IDX_WIDTH (IPSEC_SA_REF_TABLE_IDX_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) ++ ++#define IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) ++#define IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) ++ ++#ifdef CONFIG_NETFILTER ++#define IPSEC_SA_REF_HOST_FIELD(x) ((struct sk_buff*)(x))->nfmark ++#define IPSEC_SA_REF_HOST_FIELD_TYPE typeof(IPSEC_SA_REF_HOST_FIELD(NULL)) ++#else /* CONFIG_NETFILTER */ ++/* just make it work for now, it doesn't matter, since there is no nfmark */ ++#define IPSEC_SA_REF_HOST_FIELD_TYPE unsigned long ++#endif /* CONFIG_NETFILTER */ ++#define IPSEC_SA_REF_HOST_FIELD_WIDTH (8 * sizeof(IPSEC_SA_REF_HOST_FIELD_TYPE)) ++#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t)) ++ ++#define IPSEC_SA_REF_MASK (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) ++#define IPSEC_SA_REF_TABLE_MASK ((IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) ++#define IPSEC_SA_REF_ENTRY_MASK (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)) ++ ++#define IPsecSAref2table(x) (((x) & IPSEC_SA_REF_TABLE_MASK) >> IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) ++#define IPsecSAref2entry(x) ((x) & IPSEC_SA_REF_ENTRY_MASK) ++#define IPsecSArefBuild(x,y) (((x) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) + (y)) ++ ++#define IPsecSAref2SA(x) (ipsec_sadb.refTable[IPsecSAref2table(x)]->entry[IPsecSAref2entry(x)]) ++#define IPsecSA2SAref(x) ((x)->ips_ref) ++ ++#define EMT_INBOUND 0x01 /* SA direction, 1=inbound */ ++ ++/* 'struct ipsec_sa' should be 64bit aligned when allocated. */ ++struct ipsec_sa ++{ ++ IPsecSAref_t ips_ref; /* reference table entry number */ ++ atomic_t ips_refcount; /* reference count for this struct */ ++ struct ipsec_sa *ips_hnext; /* next in hash chain */ ++ struct ipsec_sa *ips_inext; /* pointer to next xform */ ++ struct ipsec_sa *ips_onext; /* pointer to prev xform */ ++ ++ struct ifnet *ips_rcvif; /* related rcv encap interface */ ++ ++ ip_said ips_said; /* SA ID */ ++ ++ __u32 ips_seq; /* seq num of msg that initiated this SA */ ++ __u32 ips_pid; /* PID of process that initiated this SA */ ++ __u8 ips_authalg; /* auth algorithm for this SA */ ++ __u8 ips_encalg; /* enc algorithm for this SA */ ++ ++ struct ipsec_stats ips_errs; ++ ++ __u8 ips_replaywin; /* replay window size */ ++ __u8 ips_state; /* state of SA */ ++ __u32 ips_replaywin_lastseq; /* last pkt sequence num */ ++ __u64 ips_replaywin_bitmap; /* bitmap of received pkts */ ++ __u32 ips_replaywin_maxdiff; /* max pkt sequence difference */ ++ ++ __u32 ips_flags; /* generic xform flags */ ++ ++ ++ struct ipsec_lifetimes ips_life; /* lifetime records */ ++ ++ /* selector information */ ++ __u8 ips_transport_protocol; /* protocol for this SA, if ports are involved */ ++ struct sockaddr*ips_addr_s; /* src sockaddr */ ++ struct sockaddr*ips_addr_d; /* dst sockaddr */ ++ struct sockaddr*ips_addr_p; /* proxy sockaddr */ ++ __u16 ips_addr_s_size; ++ __u16 ips_addr_d_size; ++ __u16 ips_addr_p_size; ++ ip_address ips_flow_s; ++ ip_address ips_flow_d; ++ ip_address ips_mask_s; ++ ip_address ips_mask_d; ++ ++ __u16 ips_key_bits_a; /* size of authkey in bits */ ++ __u16 ips_auth_bits; /* size of authenticator in bits */ ++ __u16 ips_key_bits_e; /* size of enckey in bits */ ++ __u16 ips_iv_bits; /* size of IV in bits */ ++ __u8 ips_iv_size; ++ __u16 ips_key_a_size; ++ __u16 ips_key_e_size; ++ ++ caddr_t ips_key_a; /* authentication key */ ++ caddr_t ips_key_e; /* encryption key */ ++ caddr_t ips_iv; /* Initialisation Vector */ ++ ++ struct ident ips_ident_s; /* identity src */ ++ struct ident ips_ident_d; /* identity dst */ ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++ __u16 ips_comp_adapt_tries; /* ipcomp self-adaption tries */ ++ __u16 ips_comp_adapt_skip; /* ipcomp self-adaption to-skip */ ++ __u64 ips_comp_ratio_cbytes; /* compressed bytes */ ++ __u64 ips_comp_ratio_dbytes; /* decompressed (or uncompressed) bytes */ ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ __u8 ips_natt_type; ++ __u8 ips_natt_reserved[3]; ++ __u16 ips_natt_sport; ++ __u16 ips_natt_dport; ++ ++ struct sockaddr *ips_natt_oa; ++ __u16 ips_natt_oa_size; ++ __u16 ips_natt_reserved2; ++#endif ++ ++#if 0 ++ __u32 ips_sens_dpd; ++ __u8 ips_sens_sens_level; ++ __u8 ips_sens_sens_len; ++ __u64* ips_sens_sens_bitmap; ++ __u8 ips_sens_integ_level; ++ __u8 ips_sens_integ_len; ++ __u64* ips_sens_integ_bitmap; ++#endif ++ struct ipsec_alg_enc *ips_alg_enc; ++ struct ipsec_alg_auth *ips_alg_auth; ++ IPsecSAref_t ips_ref_rel; ++}; ++ ++struct IPsecSArefSubTable ++{ ++ struct ipsec_sa* entry[IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES]; ++}; ++ ++struct ipsec_sadb { ++ struct IPsecSArefSubTable* refTable[IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES]; ++ IPsecSAref_t refFreeList[IPSEC_SA_REF_FREELIST_NUM_ENTRIES]; ++ int refFreeListHead; ++ int refFreeListTail; ++ IPsecSAref_t refFreeListCont; ++ IPsecSAref_t said_hash[SADB_HASHMOD]; ++ spinlock_t sadb_lock; ++}; ++ ++extern struct ipsec_sadb ipsec_sadb; ++ ++extern int ipsec_SAref_recycle(void); ++extern int ipsec_SArefSubTable_alloc(unsigned table); ++extern int ipsec_saref_freelist_init(void); ++extern int ipsec_sadb_init(void); ++extern struct ipsec_sa *ipsec_sa_alloc(int*error); /* pass in error var by pointer */ ++extern IPsecSAref_t ipsec_SAref_alloc(int*erorr); /* pass in error var by pointer */ ++extern int ipsec_sa_free(struct ipsec_sa* ips); ++extern int ipsec_sa_put(struct ipsec_sa *ips); ++extern int ipsec_sa_add(struct ipsec_sa *ips); ++extern int ipsec_sa_del(struct ipsec_sa *ips); ++extern int ipsec_sa_delchain(struct ipsec_sa *ips); ++extern int ipsec_sadb_cleanup(__u8 proto); ++extern int ipsec_sadb_free(void); ++extern int ipsec_sa_wipe(struct ipsec_sa *ips); ++#endif /* __KERNEL__ */ ++ ++enum ipsec_direction { ++ ipsec_incoming = 1, ++ ipsec_outgoing = 2 ++}; ++ ++#define _IPSEC_SA_H_ ++#endif /* _IPSEC_SA_H_ */ ++ ++/* ++ * $Log: ipsec_sa.h,v $ ++ * Revision 1.19 2004/04/05 19:55:06 mcr ++ * Moved from linux/include/freeswan/ipsec_sa.h,v ++ * ++ * Revision 1.18 2004/04/05 19:41:05 mcr ++ * merged alg-branch code. ++ * ++ * Revision 1.17.2.1 2003/12/22 15:25:52 jjo ++ * . Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.17 2003/12/10 01:20:06 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.16 2003/10/31 02:27:05 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.15.4.1 2003/10/29 01:10:19 mcr ++ * elimited "struct sa_id" ++ * ++ * Revision 1.15 2003/05/11 00:53:09 mcr ++ * IPsecSAref_t and macros were moved to freeswan.h. ++ * ++ * Revision 1.14 2003/02/12 19:31:55 rgb ++ * Fixed bug in "file seen" machinery. ++ * Updated copyright year. ++ * ++ * Revision 1.13 2003/01/30 02:31:52 rgb ++ * ++ * Re-wrote comments describing SAref system for accuracy. ++ * Rename SAref table macro names for clarity. ++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. ++ * Transmit error code through to caller from callee for better diagnosis of problems. ++ * Enclose all macro arguments in parens to avoid any possible obscrure bugs. ++ * ++ * Revision 1.12 2002/10/07 18:31:19 rgb ++ * Change comment to reflect the flexible nature of the main and sub-table widths. ++ * Added a counter for the number of unused entries in each subtable. ++ * Further break up host field type macro to host field. ++ * Move field width sanity checks to ipsec_sa.c ++ * Define a mask for an entire saref. ++ * ++ * Revision 1.11 2002/09/20 15:40:33 rgb ++ * Re-write most of the SAref macros and types to eliminate any pointer references to Entrys. ++ * Fixed SAref/nfmark macros. ++ * Rework saref freeslist. ++ * Place all ipsec sadb globals into one struct. ++ * Restrict some bits to kernel context for use to klips utils. ++ * ++ * Revision 1.10 2002/09/20 05:00:34 rgb ++ * Update copyright date. ++ * ++ * Revision 1.9 2002/09/17 17:19:29 mcr ++ * make it compile even if there is no netfilter - we lost ++ * functionality, but it works, especially on 2.2. ++ * ++ * Revision 1.8 2002/07/28 22:59:53 mcr ++ * clarified/expanded one comment. ++ * ++ * Revision 1.7 2002/07/26 08:48:31 rgb ++ * Added SA ref table code. ++ * ++ * Revision 1.6 2002/05/31 17:27:48 rgb ++ * Comment fix. ++ * ++ * Revision 1.5 2002/05/27 18:55:03 rgb ++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. ++ * ++ * Revision 1.4 2002/05/23 07:13:36 rgb ++ * Convert "usecount" to "refcount" to remove ambiguity. ++ * ++ * Revision 1.3 2002/04/24 07:36:47 mcr ++ * Moved from ./klips/net/ipsec/ipsec_sa.h,v ++ * ++ * Revision 1.2 2001/11/26 09:16:15 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.1.2.1 2001/09/25 02:24:58 mcr ++ * struct tdb -> struct ipsec_sa. ++ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c ++ * ipsec_xform.c removed. header file still contains useful things. ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_sha1.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,79 @@ ++/* ++ * RCSID $Id: ipsec_sha1.h,v 1.8 2004/04/05 19:55:07 mcr Exp $ ++ */ ++ ++/* ++ * Here is the original comment from the distribution: ++ ++SHA-1 in C ++By Steve Reid <steve@edmweb.com> ++100% Public Domain ++ ++ * Adapted for use by the IPSEC code by John Ioannidis ++ */ ++ ++ ++#ifndef _IPSEC_SHA1_H_ ++#define _IPSEC_SHA1_H_ ++ ++typedef struct ++{ ++ __u32 state[5]; ++ __u32 count[2]; ++ __u8 buffer[64]; ++} SHA1_CTX; ++ ++void SHA1Transform(__u32 state[5], __u8 buffer[64]); ++void SHA1Init(void *context); ++void SHA1Update(void *context, unsigned char *data, __u32 len); ++void SHA1Final(unsigned char digest[20], void *context); ++ ++ ++#endif /* _IPSEC_SHA1_H_ */ ++ ++/* ++ * $Log: ipsec_sha1.h,v $ ++ * Revision 1.8 2004/04/05 19:55:07 mcr ++ * Moved from linux/include/freeswan/ipsec_sha1.h,v ++ * ++ * Revision 1.7 2002/09/10 01:45:09 mcr ++ * changed type of MD5_CTX and SHA1_CTX to void * so that ++ * the function prototypes would match, and could be placed ++ * into a pointer to a function. ++ * ++ * Revision 1.6 2002/04/24 07:36:47 mcr ++ * Moved from ./klips/net/ipsec/ipsec_sha1.h,v ++ * ++ * Revision 1.5 1999/12/13 13:59:13 rgb ++ * Quick fix to argument size to Update bugs. ++ * ++ * Revision 1.4 1999/12/07 18:16:23 rgb ++ * Fixed comments at end of #endif lines. ++ * ++ * Revision 1.3 1999/04/06 04:54:27 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.2 1998/11/30 13:22:54 rgb ++ * Rationalised all the klips kernel file headers. They are much shorter ++ * now and won't conflict under RH5.2. ++ * ++ * Revision 1.1 1998/06/18 21:27:50 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.2 1998/04/23 20:54:05 rgb ++ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when ++ * verified. ++ * ++ * Revision 1.1 1998/04/09 03:04:21 henry ++ * sources moved up from linux/net/ipsec ++ * these two include files modified not to include others except in kernel ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:04 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * New transform ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_stats.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,75 @@ ++/* ++ * @(#) definition of ipsec_stats structure ++ * ++ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org> ++ * and Michael Richardson <mcr@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_stats.h,v 1.6 2004/04/05 19:55:07 mcr Exp $ ++ * ++ */ ++ ++/* ++ * This file describes the errors/statistics that FreeSWAN collects. ++ */ ++ ++#ifndef _IPSEC_STATS_H_ ++ ++struct ipsec_stats { ++ __u32 ips_alg_errs; /* number of algorithm errors */ ++ __u32 ips_auth_errs; /* # of authentication errors */ ++ __u32 ips_encsize_errs; /* # of encryption size errors*/ ++ __u32 ips_encpad_errs; /* # of encryption pad errors*/ ++ __u32 ips_replaywin_errs; /* # of pkt sequence errors */ ++}; ++ ++extern int ipsec_snprintf(char * buf, ssize_t size, const char *fmt, ...); ++ ++#define _IPSEC_STATS_H_ ++#endif /* _IPSEC_STATS_H_ */ ++ ++/* ++ * $Log: ipsec_stats.h,v $ ++ * Revision 1.6 2004/04/05 19:55:07 mcr ++ * Moved from linux/include/freeswan/ipsec_stats.h,v ++ * ++ * Revision 1.5 2004/04/05 19:41:05 mcr ++ * merged alg-branch code. ++ * ++ * Revision 1.4 2004/03/28 20:27:19 paul ++ * Included tested and confirmed fixes mcr made and dhr verified for ++ * snprint statements. Changed one other snprintf to use ipsec_snprintf ++ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with ++ * dhr. (thanks dhr!) ++ * ++ * Revision 1.4 2004/03/24 01:58:31 mcr ++ * sprintf->snprintf for formatting into proc buffer. ++ * ++ * Revision 1.3.34.1 2004/04/05 04:30:46 mcr ++ * patches for alg-branch to compile/work with 2.x openswan ++ * ++ * Revision 1.3 2002/04/24 07:36:47 mcr ++ * Moved from ./klips/net/ipsec/ipsec_stats.h,v ++ * ++ * Revision 1.2 2001/11/26 09:16:16 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.1.2.1 2001/09/25 02:27:00 mcr ++ * statistics moved to seperate structure. ++ * ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_tunnel.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,265 @@ ++/* ++ * IPSEC tunneling code ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_tunnel.h,v 1.29 2004/04/05 19:55:07 mcr Exp $ ++ */ ++ ++ ++#ifdef NET_21 ++# define DEV_QUEUE_XMIT(skb, device, pri) {\ ++ skb->dev = device; \ ++ neigh_compat_output(skb); \ ++ /* skb->dst->output(skb); */ \ ++ } ++# define ICMP_SEND(skb_in, type, code, info, dev) \ ++ icmp_send(skb_in, type, code, htonl(info)) ++# define IP_SEND(skb, dev) \ ++ ip_send(skb); ++#else /* NET_21 */ ++# define DEV_QUEUE_XMIT(skb, device, pri) {\ ++ dev_queue_xmit(skb, device, pri); \ ++ } ++# define ICMP_SEND(skb_in, type, code, info, dev) \ ++ icmp_send(skb_in, type, code, info, dev) ++# define IP_SEND(skb, dev) \ ++ if(ntohs(iph->tot_len) > physmtu) { \ ++ ip_fragment(NULL, skb, dev, 0); \ ++ ipsec_kfree_skb(skb); \ ++ } else { \ ++ dev_queue_xmit(skb, dev, SOPRI_NORMAL); \ ++ } ++#endif /* NET_21 */ ++ ++ ++/* ++ * Heavily based on drivers/net/new_tunnel.c. Lots ++ * of ideas also taken from the 2.1.x version of drivers/net/shaper.c ++ */ ++ ++struct ipsectunnelconf ++{ ++ __u32 cf_cmd; ++ union ++ { ++ char cfu_name[12]; ++ } cf_u; ++#define cf_name cf_u.cfu_name ++}; ++ ++#define IPSEC_SET_DEV (SIOCDEVPRIVATE) ++#define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1) ++#define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2) ++ ++#ifdef __KERNEL__ ++#include <linux/version.h> ++#ifndef KERNEL_VERSION ++# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) ++#endif ++struct ipsecpriv ++{ ++ struct sk_buff_head sendq; ++ struct device *dev; ++ struct wait_queue *wait_queue; ++ char locked; ++ int (*hard_start_xmit) (struct sk_buff *skb, ++ struct device *dev); ++ int (*hard_header) (struct sk_buff *skb, ++ struct device *dev, ++ unsigned short type, ++ void *daddr, ++ void *saddr, ++ unsigned len); ++#ifdef NET_21 ++ int (*rebuild_header)(struct sk_buff *skb); ++#else /* NET_21 */ ++ int (*rebuild_header)(void *buff, struct device *dev, ++ unsigned long raddr, struct sk_buff *skb); ++#endif /* NET_21 */ ++ int (*set_mac_address)(struct device *dev, void *addr); ++#ifndef NET_21 ++ void (*header_cache_bind)(struct hh_cache **hhp, struct device *dev, ++ unsigned short htype, __u32 daddr); ++#endif /* !NET_21 */ ++ void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char * haddr); ++ struct net_device_stats *(*get_stats)(struct device *dev); ++ struct net_device_stats mystats; ++ int mtu; /* What is the desired MTU? */ ++}; ++ ++extern char ipsec_tunnel_c_version[]; ++ ++extern struct device *ipsecdevices[IPSEC_NUM_IF]; ++ ++int ipsec_tunnel_init_devices(void); ++ ++/* void */ int ipsec_tunnel_cleanup_devices(void); ++ ++extern /* void */ int ipsec_init(void); ++ ++extern int ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev); ++ ++#ifdef CONFIG_IPSEC_DEBUG ++extern int debug_tunnel; ++extern int sysctl_ipsec_debug_verbose; ++#endif /* CONFIG_IPSEC_DEBUG */ ++#endif /* __KERNEL__ */ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++#define DB_TN_INIT 0x0001 ++#define DB_TN_PROCFS 0x0002 ++#define DB_TN_XMIT 0x0010 ++#define DB_TN_OHDR 0x0020 ++#define DB_TN_CROUT 0x0040 ++#define DB_TN_OXFS 0x0080 ++#define DB_TN_REVEC 0x0100 ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++/* ++ * $Log: ipsec_tunnel.h,v $ ++ * Revision 1.29 2004/04/05 19:55:07 mcr ++ * Moved from linux/include/freeswan/ipsec_tunnel.h,v ++ * ++ * Revision 1.28 2003/06/24 20:22:32 mcr ++ * added new global: ipsecdevices[] so that we can keep track of ++ * the ipsecX devices. They will be referenced with dev_hold(), ++ * so 2.2 may need this as well. ++ * ++ * Revision 1.27 2003/04/03 17:38:09 rgb ++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. ++ * ++ * Revision 1.26 2003/02/12 19:32:20 rgb ++ * Updated copyright year. ++ * ++ * Revision 1.25 2002/05/27 18:56:07 rgb ++ * Convert to dynamic ipsec device allocation. ++ * ++ * Revision 1.24 2002/04/24 07:36:48 mcr ++ * Moved from ./klips/net/ipsec/ipsec_tunnel.h,v ++ * ++ * Revision 1.23 2001/11/06 19:50:44 rgb ++ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for ++ * use also by pfkey_v2_parser.c ++ * ++ * Revision 1.22 2001/09/15 16:24:05 rgb ++ * Re-inject first and last HOLD packet when an eroute REPLACE is done. ++ * ++ * Revision 1.21 2001/06/14 19:35:10 rgb ++ * Update copyright date. ++ * ++ * Revision 1.20 2000/09/15 11:37:02 rgb ++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk> ++ * IPCOMP zlib deflate code. ++ * ++ * Revision 1.19 2000/09/08 19:12:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.18 2000/07/28 13:50:54 rgb ++ * Changed enet_statistics to net_device_stats and added back compatibility ++ * for pre-2.1.19. ++ * ++ * Revision 1.17 1999/11/19 01:12:15 rgb ++ * Purge unneeded proc_info prototypes, now that static linking uses ++ * dynamic proc_info registration. ++ * ++ * Revision 1.16 1999/11/18 18:51:00 rgb ++ * Changed all device registrations for static linking to ++ * dynamic to reduce the number and size of patches. ++ * ++ * Revision 1.15 1999/11/18 04:14:21 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * Added CONFIG_PROC_FS compiler directives in case it is shut off. ++ * Added Marc Boucher's 2.3.25 proc patches. ++ * ++ * Revision 1.14 1999/05/25 02:50:10 rgb ++ * Fix kernel version macros for 2.0.x static linking. ++ * ++ * Revision 1.13 1999/05/25 02:41:06 rgb ++ * Add ipsec_klipsdebug support for static linking. ++ * ++ * Revision 1.12 1999/05/05 22:02:32 rgb ++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>. ++ * ++ * Revision 1.11 1999/04/29 15:19:50 rgb ++ * Add return values to init and cleanup functions. ++ * ++ * Revision 1.10 1999/04/16 16:02:39 rgb ++ * Bump up macro to 4 ipsec I/Fs. ++ * ++ * Revision 1.9 1999/04/15 15:37:25 rgb ++ * Forward check changes from POST1_00 branch. ++ * ++ * Revision 1.5.2.1 1999/04/02 04:26:14 rgb ++ * Backcheck from HEAD, pre1.0. ++ * ++ * Revision 1.8 1999/04/11 00:29:01 henry ++ * GPL boilerplate ++ * ++ * Revision 1.7 1999/04/06 04:54:28 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.6 1999/03/31 05:44:48 rgb ++ * Keep PMTU reduction private. ++ * ++ * Revision 1.5 1999/02/10 22:31:20 rgb ++ * Change rebuild_header member to reflect generality of link layer. ++ * ++ * Revision 1.4 1998/12/01 13:22:04 rgb ++ * Added support for debug printing of version info. ++ * ++ * Revision 1.3 1998/07/29 20:42:46 rgb ++ * Add a macro for clearing all tunnel devices. ++ * Rearrange structures and declarations for sharing with userspace. ++ * ++ * Revision 1.2 1998/06/25 20:01:45 rgb ++ * Make prototypes available for ipsec_init and ipsec proc_dir_entries ++ * for static linking. ++ * ++ * Revision 1.1 1998/06/18 21:27:50 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.3 1998/05/18 21:51:50 rgb ++ * Added macros for num of I/F's and a procfs debug switch. ++ * ++ * Revision 1.2 1998/04/21 21:29:09 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.1 1998/04/09 03:06:13 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:05 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.5 1997/06/03 04:24:48 ji ++ * Added transport mode. ++ * Changed the way routing is done. ++ * Lots of bug fixes. ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * No changes. ++ * ++ * Revision 0.3 1996/11/20 14:39:04 ji ++ * Minor cleanups. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_xform.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,254 @@ ++/* ++ * Definitions relevant to IPSEC transformations ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * COpyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_xform.h,v 1.40 2004/04/06 02:49:08 mcr Exp $ ++ */ ++ ++#ifndef _IPSEC_XFORM_H_ ++ ++#include <openswan.h> ++ ++#define XF_NONE 0 /* No transform set */ ++#define XF_IP4 1 /* IPv4 inside IPv4 */ ++#define XF_AHMD5 2 /* AH MD5 */ ++#define XF_AHSHA 3 /* AH SHA */ ++#define XF_ESP3DES 5 /* ESP DES3-CBC */ ++#define XF_AHHMACMD5 6 /* AH-HMAC-MD5 with opt replay prot */ ++#define XF_AHHMACSHA1 7 /* AH-HMAC-SHA1 with opt replay prot */ ++#define XF_ESP3DESMD5 9 /* triple DES, HMAC-MD-5, 128-bits of authentication */ ++#define XF_ESP3DESMD596 10 /* triple DES, HMAC-MD-5, 96-bits of authentication */ ++#define XF_ESPNULLMD596 12 /* NULL, HMAC-MD-5 with 96-bits of authentication */ ++#define XF_ESPNULLSHA196 13 /* NULL, HMAC-SHA-1 with 96-bits of authentication */ ++#define XF_ESP3DESSHA196 14 /* triple DES, HMAC-SHA-1, 96-bits of authentication */ ++#define XF_IP6 15 /* IPv6 inside IPv6 */ ++#define XF_COMPDEFLATE 16 /* IPCOMP deflate */ ++ ++#define XF_CLR 126 /* Clear SA table */ ++#define XF_DEL 127 /* Delete SA */ ++ ++/* IPsec AH transform values ++ * RFC 2407 ++ * draft-ietf-ipsec-doi-tc-mib-02.txt ++ */ ++ ++#define AH_NONE 0 ++#define AH_MD5 2 ++#define AH_SHA 3 ++/* draft-ietf-ipsec-ciph-aes-cbc-03.txt */ ++#define AH_SHA2_256 5 ++#define AH_SHA2_384 6 ++#define AH_SHA2_512 7 ++#define AH_RIPEMD 8 ++#define AH_MAX 15 ++ ++/* IPsec ESP transform values */ ++ ++#define ESP_NONE 0 ++#define ESP_DES 2 ++#define ESP_3DES 3 ++#define ESP_RC5 4 ++#define ESP_IDEA 5 ++#define ESP_CAST 6 ++#define ESP_BLOWFISH 7 ++#define ESP_3IDEA 8 ++#define ESP_RC4 10 ++#define ESP_NULL 11 ++#define ESP_AES 12 ++ ++/* as draft-ietf-ipsec-ciph-aes-cbc-02.txt */ ++#define ESP_MARS 249 ++#define ESP_RC6 250 ++#define ESP_SERPENT 252 ++#define ESP_TWOFISH 253 ++ ++/* IPCOMP transform values */ ++ ++#define IPCOMP_NONE 0 ++#define IPCOMP_OUI 1 ++#define IPCOMP_DEFLAT 2 ++#define IPCOMP_LZS 3 ++#define IPCOMP_V42BIS 4 ++ ++#define XFT_AUTH 0x0001 ++#define XFT_CONF 0x0100 ++ ++/* available if CONFIG_IPSEC_DEBUG is defined */ ++#define DB_XF_INIT 0x0001 ++ ++#define PROTO2TXT(x) \ ++ (x) == IPPROTO_AH ? "AH" : \ ++ (x) == IPPROTO_ESP ? "ESP" : \ ++ (x) == IPPROTO_IPIP ? "IPIP" : \ ++ (x) == IPPROTO_COMP ? "COMP" : \ ++ "UNKNOWN_proto" ++static inline const char *enc_name_id (unsigned id) { ++ static char buf[16]; ++ snprintf(buf, sizeof(buf), "_ID%d", id); ++ return buf; ++} ++static inline const char *auth_name_id (unsigned id) { ++ static char buf[16]; ++ snprintf(buf, sizeof(buf), "_ID%d", id); ++ return buf; ++} ++#define IPS_XFORM_NAME(x) \ ++ PROTO2TXT((x)->ips_said.proto), \ ++ (x)->ips_said.proto == IPPROTO_COMP ? \ ++ ((x)->ips_encalg == SADB_X_CALG_DEFLATE ? \ ++ "_DEFLATE" : "_UNKNOWN_comp") : \ ++ (x)->ips_encalg == ESP_NONE ? "" : \ ++ (x)->ips_encalg == ESP_3DES ? "_3DES" : \ ++ (x)->ips_encalg == ESP_AES ? "_AES" : \ ++ (x)->ips_encalg == ESP_SERPENT ? "_SERPENT" : \ ++ (x)->ips_encalg == ESP_TWOFISH ? "_TWOFISH" : \ ++ enc_name_id(x->ips_encalg)/* "_UNKNOWN_encr" */, \ ++ (x)->ips_authalg == AH_NONE ? "" : \ ++ (x)->ips_authalg == AH_MD5 ? "_HMAC_MD5" : \ ++ (x)->ips_authalg == AH_SHA ? "_HMAC_SHA1" : \ ++ (x)->ips_authalg == AH_SHA2_256 ? "_HMAC_SHA2_256" : \ ++ (x)->ips_authalg == AH_SHA2_384 ? "_HMAC_SHA2_384" : \ ++ (x)->ips_authalg == AH_SHA2_512 ? "_HMAC_SHA2_512" : \ ++ auth_name_id(x->ips_authalg) /* "_UNKNOWN_auth" */ \ ++ ++#ifdef __KERNEL__ ++struct ipsec_rcv_state; ++struct ipsec_xmit_state; ++ ++struct xform_functions { ++ enum ipsec_rcv_value (*rcv_checks)(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb); ++ enum ipsec_rcv_value (*rcv_decrypt)(struct ipsec_rcv_state *irs); ++ ++ enum ipsec_rcv_value (*rcv_setup_auth)(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb, ++ __u32 *replay, ++ unsigned char **authenticator); ++ enum ipsec_rcv_value (*rcv_calc_auth)(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb); ++ ++ enum ipsec_xmit_value (*xmit_setup)(struct ipsec_xmit_state *ixs); ++ enum ipsec_xmit_value (*xmit_encrypt)(struct ipsec_xmit_state *ixs); ++ ++ enum ipsec_xmit_value (*xmit_setup_auth)(struct ipsec_xmit_state *ixs, ++ struct sk_buff *skb, ++ __u32 *replay, ++ unsigned char **authenticator); ++ enum ipsec_xmit_value (*xmit_calc_auth)(struct ipsec_xmit_state *ixs, ++ struct sk_buff *skb); ++ int xmit_headroom; ++ int xmit_needtailroom; ++}; ++ ++#endif /* __KERNEL__ */ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++extern void ipsec_dmp(char *s, caddr_t bb, int len); ++#else /* CONFIG_IPSEC_DEBUG */ ++#define ipsec_dmp(_x, _y, _z) ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ ++#define _IPSEC_XFORM_H_ ++#endif /* _IPSEC_XFORM_H_ */ ++ ++/* ++ * $Log: ipsec_xform.h,v $ ++ * Revision 1.40 2004/04/06 02:49:08 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.39 2004/04/05 19:55:07 mcr ++ * Moved from linux/include/freeswan/ipsec_xform.h,v ++ * ++ * Revision 1.38 2004/04/05 19:41:05 mcr ++ * merged alg-branch code. ++ * ++ * Revision 1.37 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.36.34.1 2003/12/22 15:25:52 jjo ++ * Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.36 2002/04/24 07:36:48 mcr ++ * Moved from ./klips/net/ipsec/ipsec_xform.h,v ++ * ++ * Revision 1.35 2001/11/26 09:23:51 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.33.2.1 2001/09/25 02:24:58 mcr ++ * struct tdb -> struct ipsec_sa. ++ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c ++ * ipsec_xform.c removed. header file still contains useful things. ++ * ++ * Revision 1.34 2001/11/06 19:47:17 rgb ++ * Changed lifetime_packets to uint32 from uint64. ++ * ++ * Revision 1.33 2001/09/08 21:13:34 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.32 2001/07/06 07:40:01 rgb ++ * Reformatted for readability. ++ * Added inbound policy checking fields for use with IPIP SAs. ++ * ++ * Revision 1.31 2001/06/14 19:35:11 rgb ++ * Update copyright date. ++ * ++ * Revision 1.30 2001/05/30 08:14:03 rgb ++ * Removed vestiges of esp-null transforms. ++ * ++ * Revision 1.29 2001/01/30 23:42:47 rgb ++ * Allow pfkey msgs from pid other than user context required for ACQUIRE ++ * and subsequent ADD or UDATE. ++ * ++ * Revision 1.28 2000/11/06 04:30:40 rgb ++ * Add Svenning's adaptive content compression. ++ * ++ * Revision 1.27 2000/09/19 00:38:25 rgb ++ * Fixed algorithm name bugs introduced for ipcomp. ++ * ++ * Revision 1.26 2000/09/17 21:36:48 rgb ++ * Added proto2txt macro. ++ * ++ * Revision 1.25 2000/09/17 18:56:47 rgb ++ * Added IPCOMP support. ++ * ++ * Revision 1.24 2000/09/12 19:34:12 rgb ++ * Defined XF_IP6 from Gerhard for ipv6 tunnel support. ++ * ++ * Revision 1.23 2000/09/12 03:23:14 rgb ++ * Cleaned out now unused tdb_xform and tdb_xdata members of struct tdb. ++ * ++ * Revision 1.22 2000/09/08 19:12:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.21 2000/09/01 18:32:43 rgb ++ * Added (disabled) sensitivity members to tdb struct. ++ * ++ * Revision 1.20 2000/08/30 05:31:01 rgb ++ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst. ++ * Kill remainder of tdb_xform, tdb_xdata, xformsw. ++ * ++ * Revision 1.19 2000/08/01 14:51:52 rgb ++ * Removed _all_ remaining traces of DES. ++ * ++ * Revision 1.18 2000/01/21 06:17:45 rgb ++ * Tidied up spacing. ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/ipsec_xmit.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,176 @@ ++/* ++ * IPSEC tunneling code ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_xmit.h,v 1.9 2004/04/06 02:49:08 mcr Exp $ ++ */ ++ ++#include "openswan/ipsec_sa.h" ++ ++enum ipsec_xmit_value ++{ ++ IPSEC_XMIT_STOLEN=2, ++ IPSEC_XMIT_PASS=1, ++ IPSEC_XMIT_OK=0, ++ IPSEC_XMIT_ERRMEMALLOC=-1, ++ IPSEC_XMIT_ESP_BADALG=-2, ++ IPSEC_XMIT_BADPROTO=-3, ++ IPSEC_XMIT_ESP_PUSHPULLERR=-4, ++ IPSEC_XMIT_BADLEN=-5, ++ IPSEC_XMIT_AH_BADALG=-6, ++ IPSEC_XMIT_SAIDNOTFOUND=-7, ++ IPSEC_XMIT_SAIDNOTLIVE=-8, ++ IPSEC_XMIT_REPLAYROLLED=-9, ++ IPSEC_XMIT_LIFETIMEFAILED=-10, ++ IPSEC_XMIT_CANNOTFRAG=-11, ++ IPSEC_XMIT_MSSERR=-12, ++ IPSEC_XMIT_ERRSKBALLOC=-13, ++ IPSEC_XMIT_ENCAPFAIL=-14, ++ IPSEC_XMIT_NODEV=-15, ++ IPSEC_XMIT_NOPRIVDEV=-16, ++ IPSEC_XMIT_NOPHYSDEV=-17, ++ IPSEC_XMIT_NOSKB=-18, ++ IPSEC_XMIT_NOIPV6=-19, ++ IPSEC_XMIT_NOIPOPTIONS=-20, ++ IPSEC_XMIT_TTLEXPIRED=-21, ++ IPSEC_XMIT_BADHHLEN=-22, ++ IPSEC_XMIT_PUSHPULLERR=-23, ++ IPSEC_XMIT_ROUTEERR=-24, ++ IPSEC_XMIT_RECURSDETECT=-25, ++ IPSEC_XMIT_IPSENDFAILURE=-26, ++ IPSEC_XMIT_ESPUDP=-27, ++ IPSEC_XMIT_ESPUDP_BADTYPE=-28, ++}; ++ ++struct ipsec_xmit_state ++{ ++ struct sk_buff *skb; /* working skb pointer */ ++ struct device *dev; /* working dev pointer */ ++ struct ipsecpriv *prv; /* Our device' private space */ ++ struct sk_buff *oskb; /* Original skb pointer */ ++ struct net_device_stats *stats; /* This device's statistics */ ++ struct iphdr *iph; /* Our new IP header */ ++ __u32 newdst; /* The other SG's IP address */ ++ __u32 orgdst; /* Original IP destination address */ ++ __u32 orgedst; /* 1st SG's IP address */ ++ __u32 newsrc; /* The new source SG's IP address */ ++ __u32 orgsrc; /* Original IP source address */ ++ __u32 innersrc; /* Innermost IP source address */ ++ int iphlen; /* IP header length */ ++ int pyldsz; /* upper protocol payload size */ ++ int headroom; ++ int tailroom; ++ int authlen; ++ int max_headroom; /* The extra header space needed */ ++ int max_tailroom; /* The extra stuffing needed */ ++ int ll_headroom; /* The extra link layer hard_header space needed */ ++ int tot_headroom; /* The total header space needed */ ++ int tot_tailroom; /* The totalstuffing needed */ ++ __u8 *saved_header; /* saved copy of the hard header */ ++ unsigned short sport, dport; ++ ++ struct sockaddr_encap matcher; /* eroute search key */ ++ struct eroute *eroute; ++ struct ipsec_sa *ipsp, *ipsq; /* ipsec_sa pointers */ ++ char sa_txt[SATOT_BUF]; ++ size_t sa_len; ++ int hard_header_stripped; /* has the hard header been removed yet? */ ++ int hard_header_len; ++ struct device *physdev; ++/* struct device *virtdev; */ ++ short physmtu; ++ short mtudiff; ++#ifdef NET_21 ++ struct rtable *route; ++#endif /* NET_21 */ ++ ip_said outgoing_said; ++#ifdef NET_21 ++ int pass; ++#endif /* NET_21 */ ++ int error; ++ uint32_t eroute_pid; ++ struct ipsec_sa ips; ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ uint8_t natt_type; ++ uint8_t natt_head; ++ uint16_t natt_sport; ++ uint16_t natt_dport; ++#endif ++}; ++ ++enum ipsec_xmit_value ++ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs); ++ ++enum ipsec_xmit_value ++ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs); ++ ++enum ipsec_xmit_value ++ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs); ++ ++extern void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er); ++ ++ ++extern int ipsec_xmit_trap_count; ++extern int ipsec_xmit_trap_sendcount; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++extern int debug_tunnel; ++extern int sysctl_ipsec_debug_verbose; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++#define debug_xmit debug_tunnel ++ ++#define ipsec_xmit_dmp(_x,_y, _z) if (debug_xmit && sysctl_ipsec_debug_verbose) ipsec_dmp(_x,_y,_z) ++ ++extern int sysctl_ipsec_icmp; ++extern int sysctl_ipsec_tos; ++ ++ ++/* ++ * $Log: ipsec_xmit.h,v $ ++ * Revision 1.9 2004/04/06 02:49:08 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.8 2004/04/05 19:55:07 mcr ++ * Moved from linux/include/freeswan/ipsec_xmit.h,v ++ * ++ * Revision 1.7 2004/02/03 03:11:40 mcr ++ * new xmit type if the UDP encapsulation is wrong. ++ * ++ * Revision 1.6 2003/12/13 19:10:16 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.5 2003/12/10 01:20:06 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.4 2003/12/06 16:37:04 mcr ++ * 1.4.7a X.509 patch applied. ++ * ++ * Revision 1.3 2003/10/31 02:27:05 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.2.4.2 2003/10/29 01:10:19 mcr ++ * elimited "struct sa_id" ++ * ++ * Revision 1.2.4.1 2003/09/21 13:59:38 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.2 2003/06/20 01:42:13 mcr ++ * added counters to measure how many ACQUIREs we send to pluto, ++ * and how many are successfully sent. ++ * ++ * Revision 1.1 2003/02/12 19:31:03 rgb ++ * Refactored from ipsec_tunnel.c ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/passert.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,64 @@ ++/* ++ * sanitize a string into a printable format. ++ * ++ * Copyright (C) 1998-2002 D. Hugh Redelmeier. ++ * Copyright (C) 2003 Michael Richardson <mcr@freeswan.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: passert.h,v 1.4 2004/04/06 02:49:08 mcr Exp $ ++ */ ++ ++#include "openswan.h" ++ ++/* our versions of assert: log result */ ++ ++#ifdef DEBUG ++ ++extern void passert_fail(const char *pred_str ++ , const char *file_str, unsigned long line_no) NEVER_RETURNS; ++ ++extern void pexpect_log(const char *pred_str ++ , const char *file_str, unsigned long line_no); ++ ++# define impossible() passert_fail("impossible", __FILE__, __LINE__) ++ ++extern void switch_fail(int n ++ , const char *file_str, unsigned long line_no) NEVER_RETURNS; ++ ++# define bad_case(n) switch_fail((int) n, __FILE__, __LINE__) ++ ++# define passert(pred) { \ ++ if (!(pred)) \ ++ passert_fail(#pred, __FILE__, __LINE__); \ ++ } ++ ++# define pexpect(pred) { \ ++ if (!(pred)) \ ++ pexpect_log(#pred, __FILE__, __LINE__); \ ++ } ++ ++/* assert that an err_t is NULL; evaluate exactly once */ ++# define happy(x) { \ ++ err_t ugh = x; \ ++ if (ugh != NULL) \ ++ passert_fail(ugh, __FILE__, __LINE__); \ ++ } ++ ++#else /*!DEBUG*/ ++ ++# define impossible() abort() ++# define bad_case(n) abort() ++# define passert(pred) { } /* do nothing */ ++# define happy(x) { (void) x; } /* evaluate non-judgementally */ ++ ++#endif /*!DEBUG*/ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/pfkey_debug.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,54 @@ ++/* ++ * sanitize a string into a printable format. ++ * ++ * Copyright (C) 1998-2002 D. Hugh Redelmeier. ++ * Copyright (C) 2003 Michael Richardson <mcr@freeswan.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: pfkey_debug.h,v 1.3 2004/04/05 19:55:07 mcr Exp $ ++ */ ++ ++#ifndef _FREESWAN_PFKEY_DEBUG_H ++#define _FREESWAN_PFKEY_DEBUG_H ++ ++#ifdef __KERNEL__ ++ ++/* note, kernel version ignores pfkey levels */ ++# define DEBUGGING(level,args...) \ ++ KLIPS_PRINT(debug_pfkey, "klips_debug:" args) ++ ++# define ERROR(args...) printk(KERN_ERR "klips:" args) ++ ++#else ++ ++extern unsigned int pfkey_lib_debug; ++ ++extern void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); ++extern void (*pfkey_error_func)(const char *message, ...) PRINTF_LIKE(1); ++ ++#define DEBUGGING(level,args...) if(pfkey_lib_debug & level) { \ ++ if(pfkey_debug_func != NULL) { \ ++ (*pfkey_debug_func)("pfkey_lib_debug:" args); \ ++ } else { \ ++ printf("pfkey_lib_debug:" args); \ ++ } } ++ ++#define ERROR(args...) if(pfkey_error_func != NULL) { \ ++ (*pfkey_error_func)("pfkey_lib_debug:" args); \ ++ } ++ ++# define MALLOC(size) malloc(size) ++# define FREE(obj) free(obj) ++ ++#endif ++ ++#endif +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/openswan/radij.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,280 @@ ++/* ++ * RCSID $Id: radij.h,v 1.13 2004/04/05 19:55:08 mcr Exp $ ++ */ ++ ++/* ++ * This file is defived from ${SRC}/sys/net/radix.h of BSD 4.4lite ++ * ++ * Variable and procedure names have been modified so that they don't ++ * conflict with the original BSD code, as a small number of modifications ++ * have been introduced and we may want to reuse this code in BSD. ++ * ++ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek ++ * chi or a German ch sound (as `doch', not as in `milch'), or even a ++ * spanish j as in Juan. It is not as far back in the throat like ++ * the corresponding Hebrew sound, nor is it a soft breath like the English h. ++ * It has nothing to do with the Dutch ij sound. ++ * ++ * Here is the appropriate copyright notice: ++ */ ++ ++/* ++ * Copyright (c) 1988, 1989, 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. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the University of ++ * California, Berkeley and its contributors. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)radix.h 8.1 (Berkeley) 6/10/93 ++ */ ++ ++#ifndef _RADIJ_H_ ++#define _RADIJ_H_ ++ ++/* ++#define RJ_DEBUG ++*/ ++ ++#ifdef __KERNEL__ ++ ++#ifndef __P ++#ifdef __STDC__ ++#define __P(x) x ++#else ++#define __P(x) () ++#endif ++#endif ++ ++/* ++ * Radix search tree node layout. ++ */ ++ ++struct radij_node ++{ ++ struct radij_mask *rj_mklist; /* list of masks contained in subtree */ ++ struct radij_node *rj_p; /* parent */ ++ short rj_b; /* bit offset; -1-index(netmask) */ ++ char rj_bmask; /* node: mask for bit test*/ ++ u_char rj_flags; /* enumerated next */ ++#define RJF_NORMAL 1 /* leaf contains normal route */ ++#define RJF_ROOT 2 /* leaf is root leaf for tree */ ++#define RJF_ACTIVE 4 /* This node is alive (for rtfree) */ ++ union { ++ struct { /* leaf only data: */ ++ caddr_t rj_Key; /* object of search */ ++ caddr_t rj_Mask; /* netmask, if present */ ++ struct radij_node *rj_Dupedkey; ++ } rj_leaf; ++ struct { /* node only data: */ ++ int rj_Off; /* where to start compare */ ++ struct radij_node *rj_L;/* progeny */ ++ struct radij_node *rj_R;/* progeny */ ++ }rj_node; ++ } rj_u; ++#ifdef RJ_DEBUG ++ int rj_info; ++ struct radij_node *rj_twin; ++ struct radij_node *rj_ybro; ++#endif ++}; ++ ++#define rj_dupedkey rj_u.rj_leaf.rj_Dupedkey ++#define rj_key rj_u.rj_leaf.rj_Key ++#define rj_mask rj_u.rj_leaf.rj_Mask ++#define rj_off rj_u.rj_node.rj_Off ++#define rj_l rj_u.rj_node.rj_L ++#define rj_r rj_u.rj_node.rj_R ++ ++/* ++ * Annotations to tree concerning potential routes applying to subtrees. ++ */ ++ ++extern struct radij_mask { ++ short rm_b; /* bit offset; -1-index(netmask) */ ++ char rm_unused; /* cf. rj_bmask */ ++ u_char rm_flags; /* cf. rj_flags */ ++ struct radij_mask *rm_mklist; /* more masks to try */ ++ caddr_t rm_mask; /* the mask */ ++ int rm_refs; /* # of references to this struct */ ++} *rj_mkfreelist; ++ ++#define MKGet(m) {\ ++ if (rj_mkfreelist) {\ ++ m = rj_mkfreelist; \ ++ rj_mkfreelist = (m)->rm_mklist; \ ++ } else \ ++ R_Malloc(m, struct radij_mask *, sizeof (*(m))); }\ ++ ++#define MKFree(m) { (m)->rm_mklist = rj_mkfreelist; rj_mkfreelist = (m);} ++ ++struct radij_node_head { ++ struct radij_node *rnh_treetop; ++ int rnh_addrsize; /* permit, but not require fixed keys */ ++ int rnh_pktsize; /* permit, but not require fixed keys */ ++#if 0 ++ struct radij_node *(*rnh_addaddr) /* add based on sockaddr */ ++ __P((void *v, void *mask, ++ struct radij_node_head *head, struct radij_node nodes[])); ++#endif ++ int (*rnh_addaddr) /* add based on sockaddr */ ++ __P((void *v, void *mask, ++ struct radij_node_head *head, struct radij_node nodes[])); ++ struct radij_node *(*rnh_addpkt) /* add based on packet hdr */ ++ __P((void *v, void *mask, ++ struct radij_node_head *head, struct radij_node nodes[])); ++#if 0 ++ struct radij_node *(*rnh_deladdr) /* remove based on sockaddr */ ++ __P((void *v, void *mask, struct radij_node_head *head)); ++#endif ++ int (*rnh_deladdr) /* remove based on sockaddr */ ++ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node **node)); ++ struct radij_node *(*rnh_delpkt) /* remove based on packet hdr */ ++ __P((void *v, void *mask, struct radij_node_head *head)); ++ struct radij_node *(*rnh_matchaddr) /* locate based on sockaddr */ ++ __P((void *v, struct radij_node_head *head)); ++ struct radij_node *(*rnh_matchpkt) /* locate based on packet hdr */ ++ __P((void *v, struct radij_node_head *head)); ++ int (*rnh_walktree) /* traverse tree */ ++ __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w)); ++ struct radij_node rnh_nodes[3]; /* empty tree for common case */ ++}; ++ ++ ++#define Bcmp(a, b, n) memcmp(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) ++#define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) ++#define Bzero(p, n) memset((caddr_t)(p), 0, (unsigned)(n)) ++#define R_Malloc(p, t, n) ((p = (t) kmalloc((size_t)(n), GFP_ATOMIC)), Bzero((p),(n))) ++#define Free(p) kfree((caddr_t)p); ++ ++void rj_init __P((void)); ++int rj_inithead __P((void **, int)); ++int rj_refines __P((void *, void *)); ++int rj_walktree __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w)); ++struct radij_node ++ *rj_addmask __P((void *, int, int)) /* , rgb */ ; ++int /* * */ rj_addroute __P((void *, void *, struct radij_node_head *, ++ struct radij_node [2])) /* , rgb */ ; ++int /* * */ rj_delete __P((void *, void *, struct radij_node_head *, struct radij_node **)) /* , rgb */ ; ++struct radij_node /* rgb */ ++ *rj_insert __P((void *, struct radij_node_head *, int *, ++ struct radij_node [2])), ++ *rj_match __P((void *, struct radij_node_head *)), ++ *rj_newpair __P((void *, int, struct radij_node[2])), ++ *rj_search __P((void *, struct radij_node *)), ++ *rj_search_m __P((void *, struct radij_node *, void *)); ++ ++void rj_deltree(struct radij_node_head *); ++void rj_delnodes(struct radij_node *); ++void rj_free_mkfreelist(void); ++int radijcleartree(void); ++int radijcleanup(void); ++ ++extern struct radij_node_head *mask_rjhead; ++extern int maj_keylen; ++#endif /* __KERNEL__ */ ++ ++#endif /* _RADIJ_H_ */ ++ ++ ++/* ++ * $Log: radij.h,v $ ++ * Revision 1.13 2004/04/05 19:55:08 mcr ++ * Moved from linux/include/freeswan/radij.h,v ++ * ++ * Revision 1.12 2002/04/24 07:36:48 mcr ++ * Moved from ./klips/net/ipsec/radij.h,v ++ * ++ * Revision 1.11 2001/09/20 15:33:00 rgb ++ * Min/max cleanup. ++ * ++ * Revision 1.10 1999/11/18 04:09:20 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * ++ * Revision 1.9 1999/05/05 22:02:33 rgb ++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>. ++ * ++ * Revision 1.8 1999/04/29 15:24:58 rgb ++ * Add check for existence of macros min/max. ++ * ++ * Revision 1.7 1999/04/11 00:29:02 henry ++ * GPL boilerplate ++ * ++ * Revision 1.6 1999/04/06 04:54:29 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.5 1999/01/22 06:30:32 rgb ++ * 64-bit clean-up. ++ * ++ * Revision 1.4 1998/11/30 13:22:55 rgb ++ * Rationalised all the klips kernel file headers. They are much shorter ++ * now and won't conflict under RH5.2. ++ * ++ * Revision 1.3 1998/10/25 02:43:27 rgb ++ * Change return type on rj_addroute and rj_delete and add and argument ++ * to the latter to be able to transmit more infomation about errors. ++ * ++ * Revision 1.2 1998/07/14 18:09:51 rgb ++ * Add a routine to clear eroute table. ++ * Added #ifdef __KERNEL__ directives to restrict scope of header. ++ * ++ * Revision 1.1 1998/06/18 21:30:22 henry ++ * move sources from klips/src to klips/net/ipsec to keep stupid kernel ++ * build scripts happier about symlinks ++ * ++ * Revision 1.4 1998/05/25 20:34:16 rgb ++ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. ++ * ++ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and ++ * add ipsec_rj_walker_delete. ++ * ++ * Recover memory for eroute table on unload of module. ++ * ++ * Revision 1.3 1998/04/22 16:51:37 rgb ++ * Tidy up radij debug code from recent rash of modifications to debug code. ++ * ++ * Revision 1.2 1998/04/14 17:30:38 rgb ++ * Fix up compiling errors for radij tree memory reclamation. ++ * ++ * Revision 1.1 1998/04/09 03:06:16 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:04 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * No changes. ++ * ++ * Revision 0.3 1996/11/20 14:44:45 ji ++ * Release update only. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/pfkey.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,509 @@ ++/* ++ * FreeS/WAN specific PF_KEY headers ++ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: pfkey.h,v 1.45 2004/04/06 02:49:00 mcr Exp $ ++ */ ++ ++#ifndef __NET_IPSEC_PF_KEY_H ++#define __NET_IPSEC_PF_KEY_H ++#ifdef __KERNEL__ ++extern struct proto_ops pfkey_proto_ops; ++typedef struct sock pfkey_sock; ++extern int debug_pfkey; ++ ++extern /* void */ int pfkey_init(void); ++extern /* void */ int pfkey_cleanup(void); ++ ++extern struct sock *pfkey_sock_list; ++struct socket_list ++{ ++ struct socket *socketp; ++ struct socket_list *next; ++}; ++extern int pfkey_list_insert_socket(struct socket*, struct socket_list**); ++extern int pfkey_list_remove_socket(struct socket*, struct socket_list**); ++extern struct socket_list *pfkey_open_sockets; ++extern struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1]; ++ ++struct supported ++{ ++ uint16_t supported_alg_exttype; ++ uint8_t supported_alg_id; ++ uint8_t supported_alg_ivlen; ++ uint16_t supported_alg_minbits; ++ uint16_t supported_alg_maxbits; ++}; ++ ++extern struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1]; ++struct supported_list ++{ ++ struct supported *supportedp; ++ struct supported_list *next; ++}; ++extern int pfkey_list_insert_supported(struct supported*, struct supported_list**); ++extern int pfkey_list_remove_supported(struct supported*, struct supported_list**); ++ ++struct sockaddr_key ++{ ++ uint16_t key_family; /* PF_KEY */ ++ uint16_t key_pad; /* not used */ ++ uint32_t key_pid; /* process ID */ ++}; ++ ++struct pfkey_extracted_data ++{ ++ struct ipsec_sa* ips; ++ struct ipsec_sa* ips2; ++ struct eroute *eroute; ++}; ++ ++extern int ++pfkey_alloc_eroute(struct eroute** eroute); ++ ++extern int ++pfkey_sa_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_lifetime_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_address_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_key_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_ident_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_sens_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_prop_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_supported_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_spirange_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_x_satype_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int ++pfkey_x_debug_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data* extr); ++ ++extern int pfkey_upmsg(struct socket *, struct sadb_msg *); ++extern int pfkey_expire(struct ipsec_sa *, int); ++extern int pfkey_acquire(struct ipsec_sa *); ++#else /* ! __KERNEL__ */ ++ ++extern void (*pfkey_debug_func)(const char *message, ...); ++extern void (*pfkey_error_func)(const char *message, ...); ++extern void pfkey_print(struct sadb_msg *msg, FILE *out); ++ ++ ++#endif /* __KERNEL__ */ ++ ++extern uint8_t satype2proto(uint8_t satype); ++extern uint8_t proto2satype(uint8_t proto); ++extern char* satype2name(uint8_t satype); ++extern char* proto2name(uint8_t proto); ++ ++struct key_opt ++{ ++ uint32_t key_pid; /* process ID */ ++ struct sock *sk; ++}; ++ ++#define key_pid(sk) ((struct key_opt*)&((sk)->protinfo))->key_pid ++ ++/* XXX-mcr this is not an alignment, this is because the count is in 64-bit ++ * words. ++ */ ++#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t)/sizeof(uint8_t)) ++#define BITS_PER_OCTET 8 ++#define OCTETBITS 8 ++#define PFKEYBITS 64 ++#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */ ++#define ALIGN_N(x,y) (DIVUP(x,y) * y) /* align on y boundary */ ++ ++#define IPSEC_PFKEYv2_LEN(x) ((x) * IPSEC_PFKEYv2_ALIGN) ++#define IPSEC_PFKEYv2_WORDS(x) ((x) / IPSEC_PFKEYv2_ALIGN) ++ ++ ++#define PFKEYv2_MAX_MSGSIZE 4096 ++ ++/* ++ * PF_KEYv2 permitted and required extensions in and out bitmaps ++ */ ++struct pf_key_ext_parsers_def { ++ int (*parser)(struct sadb_ext*); ++ char *parser_name; ++}; ++ ++ ++extern unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/]; ++#define EXT_BITS_IN 0 ++#define EXT_BITS_OUT 1 ++#define EXT_BITS_PERM 0 ++#define EXT_BITS_REQ 1 ++ ++extern void pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]); ++extern void pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]); ++extern void pfkey_msg_free(struct sadb_msg **pfkey_msg); ++ ++extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg, ++ struct pf_key_ext_parsers_def *ext_parsers[], ++ struct sadb_ext **extensions, ++ int dir); ++ ++extern int pfkey_register_reply(int satype, struct sadb_msg *sadb_msg); ++ ++/* ++ * PF_KEYv2 build function prototypes ++ */ ++ ++int ++pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext, ++ uint8_t msg_type, ++ uint8_t satype, ++ uint8_t msg_errno, ++ uint32_t seq, ++ uint32_t pid); ++ ++int ++pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext, ++ uint16_t exttype, ++ uint32_t spi, /* in network order */ ++ uint8_t replay_window, ++ uint8_t sa_state, ++ uint8_t auth, ++ uint8_t encrypt, ++ uint32_t flags, ++ uint32_t/*IPsecSAref_t*/ ref); ++ ++int ++pfkey_sa_build(struct sadb_ext ** pfkey_ext, ++ uint16_t exttype, ++ uint32_t spi, /* in network order */ ++ uint8_t replay_window, ++ uint8_t sa_state, ++ uint8_t auth, ++ uint8_t encrypt, ++ uint32_t flags); ++ ++int ++pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, ++ uint16_t exttype, ++ uint32_t allocations, ++ uint64_t bytes, ++ uint64_t addtime, ++ uint64_t usetime, ++ uint32_t packets); ++ ++int ++pfkey_address_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint8_t proto, ++ uint8_t prefixlen, ++ struct sockaddr* address); ++ ++int ++pfkey_key_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint16_t key_bits, ++ char* key); ++ ++int ++pfkey_ident_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint16_t ident_type, ++ uint64_t ident_id, ++ uint8_t ident_len, ++ char* ident_string); ++ ++#ifdef NAT_TRAVERSAL ++#ifdef __KERNEL__ ++extern int pfkey_nat_t_new_mapping(struct ipsec_sa *, struct sockaddr *, __u16); ++extern int pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr); ++extern int pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr); ++#endif /* __KERNEL__ */ ++int ++pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext, ++ uint8_t type); ++int ++pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint16_t port); ++#endif ++ ++int ++pfkey_sens_build(struct sadb_ext** pfkey_ext, ++ uint32_t dpd, ++ uint8_t sens_level, ++ uint8_t sens_len, ++ uint64_t* sens_bitmap, ++ uint8_t integ_level, ++ uint8_t integ_len, ++ uint64_t* integ_bitmap); ++ ++int pfkey_x_protocol_build(struct sadb_ext **, uint8_t); ++ ++ ++int ++pfkey_prop_build(struct sadb_ext** pfkey_ext, ++ uint8_t replay, ++ unsigned int comb_num, ++ struct sadb_comb* comb); ++ ++int ++pfkey_supported_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ unsigned int alg_num, ++ struct sadb_alg* alg); ++ ++int ++pfkey_spirange_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint32_t min, ++ uint32_t max); ++ ++int ++pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext); ++ ++int ++pfkey_x_satype_build(struct sadb_ext** pfkey_ext, ++ uint8_t satype); ++ ++int ++pfkey_x_debug_build(struct sadb_ext** pfkey_ext, ++ uint32_t tunnel, ++ uint32_t netlink, ++ uint32_t xform, ++ uint32_t eroute, ++ uint32_t spi, ++ uint32_t radij, ++ uint32_t esp, ++ uint32_t ah, ++ uint32_t rcv, ++ uint32_t pfkey, ++ uint32_t ipcomp, ++ uint32_t verbose); ++ ++int ++pfkey_msg_build(struct sadb_msg** pfkey_msg, ++ struct sadb_ext* extensions[], ++ int dir); ++ ++/* in pfkey_v2_debug.c - routines to decode numbers -> strings */ ++const char * ++pfkey_v2_sadb_ext_string(int extnum); ++ ++const char * ++pfkey_v2_sadb_type_string(int sadb_type); ++ ++ ++#endif /* __NET_IPSEC_PF_KEY_H */ ++ ++/* ++ * $Log: pfkey.h,v $ ++ * Revision 1.45 2004/04/06 02:49:00 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.44 2003/12/10 01:20:01 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.43 2003/10/31 02:26:44 mcr ++ * pulled up port-selector patches. ++ * ++ * Revision 1.42.2.2 2003/10/29 01:09:32 mcr ++ * added debugging for pfkey library. ++ * ++ * Revision 1.42.2.1 2003/09/21 13:59:34 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.42 2003/08/25 22:08:19 mcr ++ * removed pfkey_proto_init() from pfkey.h for 2.6 support. ++ * ++ * Revision 1.41 2003/05/07 17:28:57 mcr ++ * new function pfkey_debug_func added for us in debugging from ++ ++ * pfkey library. ++ * ++ * Revision 1.40 2003/01/30 02:31:34 rgb ++ * ++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. ++ * ++ * Revision 1.39 2002/09/20 15:40:21 rgb ++ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). ++ * Added ref parameter to pfkey_sa_build(). ++ * Cleaned out unused cruft. ++ * ++ * Revision 1.38 2002/05/14 02:37:24 rgb ++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, ++ * ipsec_sa or ipsec_sa. ++ * Added function prototypes for the functions moved to ++ * pfkey_v2_ext_process.c. ++ * ++ * Revision 1.37 2002/04/24 07:36:49 mcr ++ * Moved from ./lib/pfkey.h,v ++ * ++ * Revision 1.36 2002/01/20 20:34:49 mcr ++ * added pfkey_v2_sadb_type_string to decode sadb_type to string. ++ * ++ * Revision 1.35 2001/11/27 05:27:47 mcr ++ * pfkey parses are now maintained by a structure ++ * that includes their name for debug purposes. ++ * ++ * Revision 1.34 2001/11/26 09:23:53 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.33 2001/11/06 19:47:47 rgb ++ * Added packet parameter to lifetime and comb structures. ++ * ++ * Revision 1.32 2001/09/08 21:13:34 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.31 2001/06/14 19:35:16 rgb ++ * Update copyright date. ++ * ++ * Revision 1.30 2001/02/27 07:04:52 rgb ++ * Added satype2name prototype. ++ * ++ * Revision 1.29 2001/02/26 19:59:33 rgb ++ * Ditch unused sadb_satype2proto[], replaced by satype2proto(). ++ * ++ * Revision 1.28 2000/10/10 20:10:19 rgb ++ * Added support for debug_ipcomp and debug_verbose to klipsdebug. ++ * ++ * Revision 1.27 2000/09/21 04:20:45 rgb ++ * Fixed array size off-by-one error. (Thanks Svenning!) ++ * ++ * Revision 1.26 2000/09/12 03:26:05 rgb ++ * Added pfkey_acquire prototype. ++ * ++ * Revision 1.25 2000/09/08 19:21:28 rgb ++ * Fix pfkey_prop_build() parameter to be only single indirection. ++ * ++ * Revision 1.24 2000/09/01 18:46:42 rgb ++ * Added a supported algorithms array lists, one per satype and registered ++ * existing algorithms. ++ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to ++ * list. ++ * ++ * Revision 1.23 2000/08/27 01:55:26 rgb ++ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code. ++ * ++ * Revision 1.22 2000/08/20 21:39:23 rgb ++ * Added kernel prototypes for kernel funcitions pfkey_upmsg() and ++ * pfkey_expire(). ++ * ++ * Revision 1.21 2000/08/15 17:29:23 rgb ++ * Fixes from SZI to untested pfkey_prop_build(). ++ * ++ * Revision 1.20 2000/05/10 20:14:19 rgb ++ * Fleshed out sensitivity, proposal and supported extensions. ++ * ++ * Revision 1.19 2000/03/16 14:07:23 rgb ++ * Renamed ALIGN macro to avoid fighting with others in kernel. ++ * ++ * Revision 1.18 2000/01/22 23:24:06 rgb ++ * Added prototypes for proto2satype(), satype2proto() and proto2name(). ++ * ++ * Revision 1.17 2000/01/21 06:26:59 rgb ++ * Converted from double tdb arguments to one structure (extr) ++ * containing pointers to all temporary information structures. ++ * Added klipsdebug switching capability. ++ * Dropped unused argument to pfkey_x_satype_build(). ++ * ++ * Revision 1.16 1999/12/29 21:17:41 rgb ++ * Changed pfkey_msg_build() I/F to include a struct sadb_msg** ++ * parameter for cleaner manipulation of extensions[] and to guard ++ * against potential memory leaks. ++ * Changed the I/F to pfkey_msg_free() for the same reason. ++ * ++ * Revision 1.15 1999/12/09 23:12:54 rgb ++ * Added macro for BITS_PER_OCTET. ++ * Added argument to pfkey_sa_build() to do eroutes. ++ * ++ * Revision 1.14 1999/12/08 20:33:25 rgb ++ * Changed sa_family_t to uint16_t for 2.0.xx compatibility. ++ * ++ * Revision 1.13 1999/12/07 19:53:40 rgb ++ * Removed unused first argument from extension parsers. ++ * Changed __u* types to uint* to avoid use of asm/types.h and ++ * sys/types.h in userspace code. ++ * Added function prototypes for pfkey message and extensions ++ * initialisation and cleanup. ++ * ++ * Revision 1.12 1999/12/01 22:19:38 rgb ++ * Change pfkey_sa_build to accept an SPI in network byte order. ++ * ++ * Revision 1.11 1999/11/27 11:55:26 rgb ++ * Added extern sadb_satype2proto to enable moving protocol lookup table ++ * to lib/pfkey_v2_parse.c. ++ * Delete unused, moved typedefs. ++ * Add argument to pfkey_msg_parse() for direction. ++ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. ++ * ++ * Revision 1.10 1999/11/23 22:29:21 rgb ++ * This file has been moved in the distribution from klips/net/ipsec to ++ * lib. ++ * Add macros for dealing with alignment and rounding up more opaquely. ++ * The uint<n>_t type defines have been moved to freeswan.h to avoid ++ * chicken-and-egg problems. ++ * Add macros for dealing with alignment and rounding up more opaque. ++ * Added prototypes for using extention header bitmaps. ++ * Added prototypes of all the build functions. ++ * ++ * Revision 1.9 1999/11/20 21:59:48 rgb ++ * Moved socketlist type declarations and prototypes for shared use. ++ * Slightly modified scope of sockaddr_key declaration. ++ * ++ * Revision 1.8 1999/11/17 14:34:25 rgb ++ * Protect sa_family_t from being used in userspace with GLIBC<2. ++ * ++ * Revision 1.7 1999/10/27 19:40:35 rgb ++ * Add a maximum PFKEY packet size macro. ++ * ++ * Revision 1.6 1999/10/26 16:58:58 rgb ++ * Created a sockaddr_key and key_opt socket extension structures. ++ * ++ * Revision 1.5 1999/06/10 05:24:41 rgb ++ * Renamed variables to reduce confusion. ++ * ++ * Revision 1.4 1999/04/29 15:21:11 rgb ++ * Add pfkey support to debugging. ++ * Add return values to init and cleanup functions. ++ * ++ * Revision 1.3 1999/04/15 17:58:07 rgb ++ * Add RCSID labels. ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/pfkeyv2.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,467 @@ ++/* ++ * RCSID $Id: pfkeyv2.h,v 1.30 2004/04/06 02:49:00 mcr Exp $ ++ */ ++ ++/* ++RFC 2367 PF_KEY Key Management API July 1998 ++ ++ ++Appendix D: Sample Header File ++ ++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_GRPSA 13 ++#define SADB_X_ADDFLOW 14 ++#define SADB_X_DELFLOW 15 ++#define SADB_X_DEBUG 16 ++#define SADB_X_NAT_T_NEW_MAPPING 17 ++#define SADB_MAX 17 ++ ++struct sadb_msg { ++ uint8_t sadb_msg_version; ++ uint8_t sadb_msg_type; ++ uint8_t sadb_msg_errno; ++ uint8_t sadb_msg_satype; ++ uint16_t sadb_msg_len; ++ uint16_t sadb_msg_reserved; ++ uint32_t sadb_msg_seq; ++ uint32_t sadb_msg_pid; ++}; ++ ++struct sadb_ext { ++ uint16_t sadb_ext_len; ++ uint16_t sadb_ext_type; ++}; ++ ++struct sadb_sa { ++ uint16_t sadb_sa_len; ++ uint16_t sadb_sa_exttype; ++ uint32_t sadb_sa_spi; ++ uint8_t sadb_sa_replay; ++ uint8_t sadb_sa_state; ++ uint8_t sadb_sa_auth; ++ uint8_t sadb_sa_encrypt; ++ uint32_t sadb_sa_flags; ++ uint32_t /*IPsecSAref_t*/ sadb_x_sa_ref; /* 32 bits */ ++ uint8_t sadb_x_reserved[4]; ++}; ++ ++struct sadb_sa_v1 { ++ uint16_t sadb_sa_len; ++ uint16_t sadb_sa_exttype; ++ uint32_t sadb_sa_spi; ++ uint8_t sadb_sa_replay; ++ uint8_t sadb_sa_state; ++ uint8_t sadb_sa_auth; ++ uint8_t sadb_sa_encrypt; ++ uint32_t sadb_sa_flags; ++}; ++ ++struct sadb_lifetime { ++ uint16_t sadb_lifetime_len; ++ uint16_t sadb_lifetime_exttype; ++ uint32_t sadb_lifetime_allocations; ++ uint64_t sadb_lifetime_bytes; ++ uint64_t sadb_lifetime_addtime; ++ uint64_t sadb_lifetime_usetime; ++ uint32_t sadb_x_lifetime_packets; ++ uint32_t sadb_x_lifetime_reserved; ++}; ++ ++struct sadb_address { ++ uint16_t sadb_address_len; ++ uint16_t sadb_address_exttype; ++ uint8_t sadb_address_proto; ++ uint8_t sadb_address_prefixlen; ++ uint16_t sadb_address_reserved; ++}; ++ ++struct sadb_key { ++ uint16_t sadb_key_len; ++ uint16_t sadb_key_exttype; ++ uint16_t sadb_key_bits; ++ uint16_t sadb_key_reserved; ++}; ++ ++struct sadb_ident { ++ uint16_t sadb_ident_len; ++ uint16_t sadb_ident_exttype; ++ uint16_t sadb_ident_type; ++ uint16_t sadb_ident_reserved; ++ uint64_t sadb_ident_id; ++}; ++ ++struct sadb_sens { ++ uint16_t sadb_sens_len; ++ uint16_t sadb_sens_exttype; ++ uint32_t sadb_sens_dpd; ++ uint8_t sadb_sens_sens_level; ++ uint8_t sadb_sens_sens_len; ++ uint8_t sadb_sens_integ_level; ++ uint8_t sadb_sens_integ_len; ++ uint32_t sadb_sens_reserved; ++}; ++ ++struct sadb_prop { ++ uint16_t sadb_prop_len; ++ uint16_t sadb_prop_exttype; ++ uint8_t sadb_prop_replay; ++ uint8_t sadb_prop_reserved[3]; ++}; ++ ++struct sadb_comb { ++ uint8_t sadb_comb_auth; ++ uint8_t sadb_comb_encrypt; ++ uint16_t sadb_comb_flags; ++ uint16_t sadb_comb_auth_minbits; ++ uint16_t sadb_comb_auth_maxbits; ++ uint16_t sadb_comb_encrypt_minbits; ++ uint16_t sadb_comb_encrypt_maxbits; ++ uint32_t sadb_comb_reserved; ++ uint32_t sadb_comb_soft_allocations; ++ uint32_t sadb_comb_hard_allocations; ++ uint64_t sadb_comb_soft_bytes; ++ uint64_t sadb_comb_hard_bytes; ++ uint64_t sadb_comb_soft_addtime; ++ uint64_t sadb_comb_hard_addtime; ++ uint64_t sadb_comb_soft_usetime; ++ uint64_t sadb_comb_hard_usetime; ++ uint32_t sadb_x_comb_soft_packets; ++ uint32_t sadb_x_comb_hard_packets; ++}; ++ ++struct sadb_supported { ++ uint16_t sadb_supported_len; ++ uint16_t sadb_supported_exttype; ++ uint32_t sadb_supported_reserved; ++}; ++ ++struct sadb_alg { ++ uint8_t sadb_alg_id; ++ uint8_t sadb_alg_ivlen; ++ uint16_t sadb_alg_minbits; ++ uint16_t sadb_alg_maxbits; ++ uint16_t sadb_alg_reserved; ++}; ++ ++struct sadb_spirange { ++ uint16_t sadb_spirange_len; ++ uint16_t sadb_spirange_exttype; ++ uint32_t sadb_spirange_min; ++ uint32_t sadb_spirange_max; ++ uint32_t sadb_spirange_reserved; ++}; ++ ++struct sadb_x_kmprivate { ++ uint16_t sadb_x_kmprivate_len; ++ uint16_t sadb_x_kmprivate_exttype; ++ uint32_t sadb_x_kmprivate_reserved; ++}; ++ ++struct sadb_x_satype { ++ uint16_t sadb_x_satype_len; ++ uint16_t sadb_x_satype_exttype; ++ uint8_t sadb_x_satype_satype; ++ uint8_t sadb_x_satype_reserved[3]; ++}; ++ ++struct sadb_x_policy { ++ uint16_t sadb_x_policy_len; ++ uint16_t sadb_x_policy_exttype; ++ uint16_t sadb_x_policy_type; ++ uint8_t sadb_x_policy_dir; ++ uint8_t sadb_x_policy_reserved; ++ uint32_t sadb_x_policy_id; ++ uint32_t sadb_x_policy_reserved2; ++}; ++ ++struct sadb_x_debug { ++ uint16_t sadb_x_debug_len; ++ uint16_t sadb_x_debug_exttype; ++ uint32_t sadb_x_debug_tunnel; ++ uint32_t sadb_x_debug_netlink; ++ uint32_t sadb_x_debug_xform; ++ uint32_t sadb_x_debug_eroute; ++ uint32_t sadb_x_debug_spi; ++ uint32_t sadb_x_debug_radij; ++ uint32_t sadb_x_debug_esp; ++ uint32_t sadb_x_debug_ah; ++ uint32_t sadb_x_debug_rcv; ++ uint32_t sadb_x_debug_pfkey; ++ uint32_t sadb_x_debug_ipcomp; ++ uint32_t sadb_x_debug_verbose; ++ uint8_t sadb_x_debug_reserved[4]; ++}; ++ ++struct sadb_x_nat_t_type { ++ uint16_t sadb_x_nat_t_type_len; ++ uint16_t sadb_x_nat_t_type_exttype; ++ uint8_t sadb_x_nat_t_type_type; ++ uint8_t sadb_x_nat_t_type_reserved[3]; ++}; ++struct sadb_x_nat_t_port { ++ uint16_t sadb_x_nat_t_port_len; ++ uint16_t sadb_x_nat_t_port_exttype; ++ uint16_t sadb_x_nat_t_port_port; ++ uint16_t sadb_x_nat_t_port_reserved; ++}; ++ ++/* ++ * A protocol structure for passing through the transport level ++ * protocol. It contains more fields than are actually used/needed ++ * but it is this way to be compatible with the structure used in ++ * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h) ++ */ ++struct sadb_protocol { ++ uint16_t sadb_protocol_len; ++ uint16_t sadb_protocol_exttype; ++ uint8_t sadb_protocol_proto; ++ uint8_t sadb_protocol_direction; ++ uint8_t sadb_protocol_flags; ++ uint8_t sadb_protocol_reserved2; ++}; ++ ++#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_SATYPE2 18 ++#ifdef KERNEL26_HAS_KAME_DUPLICATES ++#define SADB_X_EXT_POLICY 18 ++#endif ++#define SADB_X_EXT_SA2 19 ++#define SADB_X_EXT_ADDRESS_DST2 20 ++#define SADB_X_EXT_ADDRESS_SRC_FLOW 21 ++#define SADB_X_EXT_ADDRESS_DST_FLOW 22 ++#define SADB_X_EXT_ADDRESS_SRC_MASK 23 ++#define SADB_X_EXT_ADDRESS_DST_MASK 24 ++#define SADB_X_EXT_DEBUG 25 ++#define SADB_X_EXT_PROTOCOL 26 ++#define SADB_X_EXT_NAT_T_TYPE 27 ++#define SADB_X_EXT_NAT_T_SPORT 28 ++#define SADB_X_EXT_NAT_T_DPORT 29 ++#define SADB_X_EXT_NAT_T_OA 30 ++#define SADB_EXT_MAX 30 ++ ++/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */ ++#define SADB_X_EXT_ADDRESS_DELFLOW \ ++ ( (1<<SADB_X_EXT_ADDRESS_SRC_FLOW) \ ++ | (1<<SADB_X_EXT_ADDRESS_DST_FLOW) \ ++ | (1<<SADB_X_EXT_ADDRESS_SRC_MASK) \ ++ | (1<<SADB_X_EXT_ADDRESS_DST_MASK)) ++ ++#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_IPIP 9 ++#ifdef KERNEL26_HAS_KAME_DUPLICATES ++#define SADB_X_SATYPE_IPCOMP 9 /* ICK! */ ++#endif ++#define SADB_X_SATYPE_COMP 10 ++#define SADB_X_SATYPE_INT 11 ++#define SADB_SATYPE_MAX 11 ++ ++#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 ++#define SADB_X_SAFLAGS_REPLACEFLOW 2 ++#define SADB_X_SAFLAGS_CLEARFLOW 4 ++#define SADB_X_SAFLAGS_INFLOW 8 ++ ++/* not obvious, but these are the same values as used in isakmp, ++ * and in freeswan/ipsec_policy.h. If you need to add any, they ++ * should be added as according to ++ * http://www.iana.org/assignments/isakmp-registry ++ * ++ * and if not, then please try to use a private-use value, and ++ * consider asking IANA to assign a value. ++ */ ++#define SADB_AALG_NONE 0 ++#define SADB_AALG_MD5HMAC 2 ++#define SADB_AALG_SHA1HMAC 3 ++#define SADB_X_AALG_SHA2_256HMAC 5 ++#define SADB_X_AALG_SHA2_384HMAC 6 ++#define SADB_X_AALG_SHA2_512HMAC 7 ++#define SADB_X_AALG_RIPEMD160HMAC 8 ++#define SADB_X_AALG_NULL 251 /* kame */ ++#define SADB_AALG_MAX 251 ++ ++#define SADB_EALG_NONE 0 ++#define SADB_EALG_DESCBC 2 ++#define SADB_EALG_3DESCBC 3 ++#define SADB_X_EALG_CASTCBC 6 ++#define SADB_X_EALG_BLOWFISHCBC 7 ++#define SADB_EALG_NULL 11 ++#define SADB_X_EALG_AESCBC 12 ++#define SADB_EALG_MAX 255 ++ ++#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_V42BIS 4 ++#ifdef KERNEL26_HAS_KAME_DUPLICATES ++#define SADB_X_CALG_LZJH 4 ++#endif ++#define SADB_X_CALG_MAX 4 ++ ++#define SADB_X_TALG_NONE 0 ++#define SADB_X_TALG_IPv4_in_IPv4 1 ++#define SADB_X_TALG_IPv6_in_IPv4 2 ++#define SADB_X_TALG_IPv4_in_IPv6 3 ++#define SADB_X_TALG_IPv6_in_IPv6 4 ++#define SADB_X_TALG_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_CONNECTION 4 ++#define SADB_IDENTTYPE_MAX 4 ++ ++#define SADB_KEY_FLAGS_MAX 0 ++#endif /* __PFKEY_V2_H */ ++ ++/* ++ * $Log: pfkeyv2.h,v $ ++ * Revision 1.30 2004/04/06 02:49:00 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.29 2003/12/22 21:35:58 mcr ++ * new patches from Dr{Who}. ++ * ++ * Revision 1.28 2003/12/22 19:33:15 mcr ++ * added 0.6c NAT-T patch. ++ * ++ * Revision 1.27 2003/12/10 01:20:01 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.26 2003/10/31 02:26:44 mcr ++ * pulled up port-selector patches. ++ * ++ * Revision 1.25.4.1 2003/09/21 13:59:34 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.25 2003/07/31 23:59:17 mcr ++ * re-introduce kernel 2.6 duplicate values for now. ++ * hope to get them changed! ++ * ++ * Revision 1.24 2003/07/31 22:55:27 mcr ++ * added some definitions to keep pfkeyv2.h files in sync. ++ * ++ * Revision 1.23 2003/05/11 00:43:48 mcr ++ * added comment about origin of values used ++ * ++ * Revision 1.22 2003/01/30 02:31:34 rgb ++ * ++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. ++ * ++ * Revision 1.21 2002/12/16 19:26:49 mcr ++ * added definition of FS 1.xx sadb structure ++ * ++ * Revision 1.20 2002/09/20 15:40:25 rgb ++ * Added sadb_x_sa_ref to struct sadb_sa. ++ * ++ * Revision 1.19 2002/04/24 07:36:49 mcr ++ * Moved from ./lib/pfkeyv2.h,v ++ * ++ * Revision 1.18 2001/11/06 19:47:47 rgb ++ * Added packet parameter to lifetime and comb structures. ++ * ++ * Revision 1.17 2001/09/08 21:13:35 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.16 2001/07/06 19:49:46 rgb ++ * Added SADB_X_SAFLAGS_INFLOW for supporting incoming policy checks. ++ * ++ * Revision 1.15 2001/02/26 20:00:43 rgb ++ * Added internal IP protocol 61 for magic SAs. ++ * ++ * Revision 1.14 2001/02/08 18:51:05 rgb ++ * Include RFC document title and appendix subsection title. ++ * ++ * Revision 1.13 2000/10/10 20:10:20 rgb ++ * Added support for debug_ipcomp and debug_verbose to klipsdebug. ++ * ++ * Revision 1.12 2000/09/15 06:41:50 rgb ++ * Added V42BIS constant. ++ * ++ * Revision 1.11 2000/09/12 22:35:37 rgb ++ * Restructured to remove unused extensions from CLEARFLOW messages. ++ * ++ * Revision 1.10 2000/09/12 18:50:09 rgb ++ * Added IPIP tunnel types as algo support. ++ * ++ * Revision 1.9 2000/08/21 16:47:19 rgb ++ * Added SADB_X_CALG_* macros for IPCOMP. ++ * ++ * Revision 1.8 2000/08/09 20:43:34 rgb ++ * Fixed bitmask value for SADB_X_SAFLAGS_CLEAREROUTE. ++ * ++ * Revision 1.7 2000/01/21 06:28:37 rgb ++ * Added flow add/delete message type macros. ++ * Added flow address extension type macros. ++ * Tidied up spacing. ++ * Added klipsdebug switching capability. ++ * ++ * Revision 1.6 1999/11/27 11:56:08 rgb ++ * Add SADB_X_SATYPE_COMP for compression, eventually. ++ * ++ * Revision 1.5 1999/11/23 22:23:16 rgb ++ * This file has been moved in the distribution from klips/net/ipsec to ++ * lib. ++ * ++ * Revision 1.4 1999/04/29 15:23:29 rgb ++ * Add GRPSA support. ++ * Add support for a second SATYPE, SA and DST_ADDRESS. ++ * Add IPPROTO_IPIP support. ++ * ++ * Revision 1.3 1999/04/15 17:58:08 rgb ++ * Add RCSID labels. ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/zlib/zlib.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,893 @@ ++/* zlib.h -- interface of the 'zlib' general purpose compression library ++ version 1.1.4, March 11th, 2002 ++ ++ Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler ++ ++ This software is provided 'as-is', without any express or implied ++ warranty. In no event will the authors be held liable for any damages ++ arising from the use of this software. ++ ++ Permission is granted to anyone to use this software for any purpose, ++ including commercial applications, and to alter it and redistribute it ++ freely, subject to the following restrictions: ++ ++ 1. The origin of this software must not be misrepresented; you must not ++ claim that you wrote the original software. If you use this software ++ in a product, an acknowledgment in the product documentation would be ++ appreciated but is not required. ++ 2. Altered source versions must be plainly marked as such, and must not be ++ misrepresented as being the original software. ++ 3. This notice may not be removed or altered from any source distribution. ++ ++ Jean-loup Gailly Mark Adler ++ jloup@gzip.org madler@alumni.caltech.edu ++ ++ ++ The data format used by the zlib library is described by RFCs (Request for ++ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt ++ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). ++*/ ++ ++#ifndef _ZLIB_H ++#define _ZLIB_H ++ ++#include "zconf.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define ZLIB_VERSION "1.1.4" ++ ++/* ++ The 'zlib' compression library provides in-memory compression and ++ decompression functions, including integrity checks of the uncompressed ++ data. This version of the library supports only one compression method ++ (deflation) but other algorithms will be added later and will have the same ++ stream interface. ++ ++ Compression can be done in a single step if the buffers are large ++ enough (for example if an input file is mmap'ed), or can be done by ++ repeated calls of the compression function. In the latter case, the ++ application must provide more input and/or consume the output ++ (providing more output space) before each call. ++ ++ The library also supports reading and writing files in gzip (.gz) format ++ with an interface similar to that of stdio. ++ ++ The library does not install any signal handler. The decoder checks ++ the consistency of the compressed data, so the library should never ++ crash even in case of corrupted input. ++*/ ++ ++typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); ++typedef void (*free_func) OF((voidpf opaque, voidpf address)); ++ ++struct internal_state; ++ ++typedef struct z_stream_s { ++ Bytef *next_in; /* next input byte */ ++ uInt avail_in; /* number of bytes available at next_in */ ++ uLong total_in; /* total nb of input bytes read so far */ ++ ++ Bytef *next_out; /* next output byte should be put there */ ++ uInt avail_out; /* remaining free space at next_out */ ++ uLong total_out; /* total nb of bytes output so far */ ++ ++ const char *msg; /* last error message, NULL if no error */ ++ struct internal_state FAR *state; /* not visible by applications */ ++ ++ alloc_func zalloc; /* used to allocate the internal state */ ++ free_func zfree; /* used to free the internal state */ ++ voidpf opaque; /* private data object passed to zalloc and zfree */ ++ ++ int data_type; /* best guess about the data type: ascii or binary */ ++ uLong adler; /* adler32 value of the uncompressed data */ ++ uLong reserved; /* reserved for future use */ ++} z_stream; ++ ++typedef z_stream FAR *z_streamp; ++ ++/* ++ The application must update next_in and avail_in when avail_in has ++ dropped to zero. It must update next_out and avail_out when avail_out ++ has dropped to zero. The application must initialize zalloc, zfree and ++ opaque before calling the init function. All other fields are set by the ++ compression library and must not be updated by the application. ++ ++ The opaque value provided by the application will be passed as the first ++ parameter for calls of zalloc and zfree. This can be useful for custom ++ memory management. The compression library attaches no meaning to the ++ opaque value. ++ ++ zalloc must return Z_NULL if there is not enough memory for the object. ++ If zlib is used in a multi-threaded application, zalloc and zfree must be ++ thread safe. ++ ++ On 16-bit systems, the functions zalloc and zfree must be able to allocate ++ exactly 65536 bytes, but will not be required to allocate more than this ++ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, ++ pointers returned by zalloc for objects of exactly 65536 bytes *must* ++ have their offset normalized to zero. The default allocation function ++ provided by this library ensures this (see zutil.c). To reduce memory ++ requirements and avoid any allocation of 64K objects, at the expense of ++ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). ++ ++ The fields total_in and total_out can be used for statistics or ++ progress reports. After compression, total_in holds the total size of ++ the uncompressed data and may be saved for use in the decompressor ++ (particularly if the decompressor wants to decompress everything in ++ a single step). ++*/ ++ ++ /* constants */ ++ ++#define Z_NO_FLUSH 0 ++#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ ++#define Z_SYNC_FLUSH 2 ++#define Z_FULL_FLUSH 3 ++#define Z_FINISH 4 ++/* Allowed flush values; see deflate() below for details */ ++ ++#define Z_OK 0 ++#define Z_STREAM_END 1 ++#define Z_NEED_DICT 2 ++#define Z_ERRNO (-1) ++#define Z_STREAM_ERROR (-2) ++#define Z_DATA_ERROR (-3) ++#define Z_MEM_ERROR (-4) ++#define Z_BUF_ERROR (-5) ++#define Z_VERSION_ERROR (-6) ++/* Return codes for the compression/decompression functions. Negative ++ * values are errors, positive values are used for special but normal events. ++ */ ++ ++#define Z_NO_COMPRESSION 0 ++#define Z_BEST_SPEED 1 ++#define Z_BEST_COMPRESSION 9 ++#define Z_DEFAULT_COMPRESSION (-1) ++/* compression levels */ ++ ++#define Z_FILTERED 1 ++#define Z_HUFFMAN_ONLY 2 ++#define Z_DEFAULT_STRATEGY 0 ++/* compression strategy; see deflateInit2() below for details */ ++ ++#define Z_BINARY 0 ++#define Z_ASCII 1 ++#define Z_UNKNOWN 2 ++/* Possible values of the data_type field */ ++ ++#define Z_DEFLATED 8 ++/* The deflate compression method (the only one supported in this version) */ ++ ++#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ ++ ++#define zlib_version zlibVersion() ++/* for compatibility with versions < 1.0.2 */ ++ ++ /* basic functions */ ++ ++ZEXTERN const char * ZEXPORT zlibVersion OF((void)); ++/* The application can compare zlibVersion and ZLIB_VERSION for consistency. ++ If the first character differs, the library code actually used is ++ not compatible with the zlib.h header file used by the application. ++ This check is automatically made by deflateInit and inflateInit. ++ */ ++ ++/* ++ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); ++ ++ Initializes the internal stream state for compression. The fields ++ zalloc, zfree and opaque must be initialized before by the caller. ++ If zalloc and zfree are set to Z_NULL, deflateInit updates them to ++ use default allocation functions. ++ ++ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: ++ 1 gives best speed, 9 gives best compression, 0 gives no compression at ++ all (the input data is simply copied a block at a time). ++ Z_DEFAULT_COMPRESSION requests a default compromise between speed and ++ compression (currently equivalent to level 6). ++ ++ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not ++ enough memory, Z_STREAM_ERROR if level is not a valid compression level, ++ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible ++ with the version assumed by the caller (ZLIB_VERSION). ++ msg is set to null if there is no error message. deflateInit does not ++ perform any compression: this will be done by deflate(). ++*/ ++ ++ ++ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); ++/* ++ deflate compresses as much data as possible, and stops when the input ++ buffer becomes empty or the output buffer becomes full. It may introduce some ++ output latency (reading input without producing any output) except when ++ forced to flush. ++ ++ The detailed semantics are as follows. deflate performs one or both of the ++ following actions: ++ ++ - Compress more input starting at next_in and update next_in and avail_in ++ accordingly. If not all input can be processed (because there is not ++ enough room in the output buffer), next_in and avail_in are updated and ++ processing will resume at this point for the next call of deflate(). ++ ++ - Provide more output starting at next_out and update next_out and avail_out ++ accordingly. This action is forced if the parameter flush is non zero. ++ Forcing flush frequently degrades the compression ratio, so this parameter ++ should be set only when necessary (in interactive applications). ++ Some output may be provided even if flush is not set. ++ ++ Before the call of deflate(), the application should ensure that at least ++ one of the actions is possible, by providing more input and/or consuming ++ more output, and updating avail_in or avail_out accordingly; avail_out ++ should never be zero before the call. The application can consume the ++ compressed output when it wants, for example when the output buffer is full ++ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK ++ and with zero avail_out, it must be called again after making room in the ++ output buffer because there might be more output pending. ++ ++ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is ++ flushed to the output buffer and the output is aligned on a byte boundary, so ++ that the decompressor can get all input data available so far. (In particular ++ avail_in is zero after the call if enough output space has been provided ++ before the call.) Flushing may degrade compression for some compression ++ algorithms and so it should be used only when necessary. ++ ++ If flush is set to Z_FULL_FLUSH, all output is flushed as with ++ Z_SYNC_FLUSH, and the compression state is reset so that decompression can ++ restart from this point if previous compressed data has been damaged or if ++ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade ++ the compression. ++ ++ If deflate returns with avail_out == 0, this function must be called again ++ with the same value of the flush parameter and more output space (updated ++ avail_out), until the flush is complete (deflate returns with non-zero ++ avail_out). ++ ++ If the parameter flush is set to Z_FINISH, pending input is processed, ++ pending output is flushed and deflate returns with Z_STREAM_END if there ++ was enough output space; if deflate returns with Z_OK, this function must be ++ called again with Z_FINISH and more output space (updated avail_out) but no ++ more input data, until it returns with Z_STREAM_END or an error. After ++ deflate has returned Z_STREAM_END, the only possible operations on the ++ stream are deflateReset or deflateEnd. ++ ++ Z_FINISH can be used immediately after deflateInit if all the compression ++ is to be done in a single step. In this case, avail_out must be at least ++ 0.1% larger than avail_in plus 12 bytes. If deflate does not return ++ Z_STREAM_END, then it must be called again as described above. ++ ++ deflate() sets strm->adler to the adler32 checksum of all input read ++ so far (that is, total_in bytes). ++ ++ deflate() may update data_type if it can make a good guess about ++ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered ++ binary. This field is only for information purposes and does not affect ++ the compression algorithm in any manner. ++ ++ deflate() returns Z_OK if some progress has been made (more input ++ processed or more output produced), Z_STREAM_END if all input has been ++ consumed and all output has been produced (only when flush is set to ++ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example ++ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible ++ (for example avail_in or avail_out was zero). ++*/ ++ ++ ++ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); ++/* ++ All dynamically allocated data structures for this stream are freed. ++ This function discards any unprocessed input and does not flush any ++ pending output. ++ ++ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the ++ stream state was inconsistent, Z_DATA_ERROR if the stream was freed ++ prematurely (some input or output was discarded). In the error case, ++ msg may be set but then points to a static string (which must not be ++ deallocated). ++*/ ++ ++ ++/* ++ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); ++ ++ Initializes the internal stream state for decompression. The fields ++ next_in, avail_in, zalloc, zfree and opaque must be initialized before by ++ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact ++ value depends on the compression method), inflateInit determines the ++ compression method from the zlib header and allocates all data structures ++ accordingly; otherwise the allocation will be deferred to the first call of ++ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to ++ use default allocation functions. ++ ++ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough ++ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the ++ version assumed by the caller. msg is set to null if there is no error ++ message. inflateInit does not perform any decompression apart from reading ++ the zlib header if present: this will be done by inflate(). (So next_in and ++ avail_in may be modified, but next_out and avail_out are unchanged.) ++*/ ++ ++ ++ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); ++/* ++ inflate decompresses as much data as possible, and stops when the input ++ buffer becomes empty or the output buffer becomes full. It may some ++ introduce some output latency (reading input without producing any output) ++ except when forced to flush. ++ ++ The detailed semantics are as follows. inflate performs one or both of the ++ following actions: ++ ++ - Decompress more input starting at next_in and update next_in and avail_in ++ accordingly. If not all input can be processed (because there is not ++ enough room in the output buffer), next_in is updated and processing ++ will resume at this point for the next call of inflate(). ++ ++ - Provide more output starting at next_out and update next_out and avail_out ++ accordingly. inflate() provides as much output as possible, until there ++ is no more input data or no more space in the output buffer (see below ++ about the flush parameter). ++ ++ Before the call of inflate(), the application should ensure that at least ++ one of the actions is possible, by providing more input and/or consuming ++ more output, and updating the next_* and avail_* values accordingly. ++ The application can consume the uncompressed output when it wants, for ++ example when the output buffer is full (avail_out == 0), or after each ++ call of inflate(). If inflate returns Z_OK and with zero avail_out, it ++ must be called again after making room in the output buffer because there ++ might be more output pending. ++ ++ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much ++ output as possible to the output buffer. The flushing behavior of inflate is ++ not specified for values of the flush parameter other than Z_SYNC_FLUSH ++ and Z_FINISH, but the current implementation actually flushes as much output ++ as possible anyway. ++ ++ inflate() should normally be called until it returns Z_STREAM_END or an ++ error. However if all decompression is to be performed in a single step ++ (a single call of inflate), the parameter flush should be set to ++ Z_FINISH. In this case all pending input is processed and all pending ++ output is flushed; avail_out must be large enough to hold all the ++ uncompressed data. (The size of the uncompressed data may have been saved ++ by the compressor for this purpose.) The next operation on this stream must ++ be inflateEnd to deallocate the decompression state. The use of Z_FINISH ++ is never required, but can be used to inform inflate that a faster routine ++ may be used for the single inflate() call. ++ ++ If a preset dictionary is needed at this point (see inflateSetDictionary ++ below), inflate sets strm-adler to the adler32 checksum of the ++ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise ++ it sets strm->adler to the adler32 checksum of all output produced ++ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or ++ an error code as described below. At the end of the stream, inflate() ++ checks that its computed adler32 checksum is equal to that saved by the ++ compressor and returns Z_STREAM_END only if the checksum is correct. ++ ++ inflate() returns Z_OK if some progress has been made (more input processed ++ or more output produced), Z_STREAM_END if the end of the compressed data has ++ been reached and all uncompressed output has been produced, Z_NEED_DICT if a ++ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was ++ corrupted (input stream not conforming to the zlib format or incorrect ++ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent ++ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not ++ enough memory, Z_BUF_ERROR if no progress is possible or if there was not ++ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR ++ case, the application may then call inflateSync to look for a good ++ compression block. ++*/ ++ ++ ++ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); ++/* ++ All dynamically allocated data structures for this stream are freed. ++ This function discards any unprocessed input and does not flush any ++ pending output. ++ ++ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state ++ was inconsistent. In the error case, msg may be set but then points to a ++ static string (which must not be deallocated). ++*/ ++ ++ /* Advanced functions */ ++ ++/* ++ The following functions are needed only in some special applications. ++*/ ++ ++/* ++ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, ++ int level, ++ int method, ++ int windowBits, ++ int memLevel, ++ int strategy)); ++ ++ This is another version of deflateInit with more compression options. The ++ fields next_in, zalloc, zfree and opaque must be initialized before by ++ the caller. ++ ++ The method parameter is the compression method. It must be Z_DEFLATED in ++ this version of the library. ++ ++ The windowBits parameter is the base two logarithm of the window size ++ (the size of the history buffer). It should be in the range 8..15 for this ++ version of the library. Larger values of this parameter result in better ++ compression at the expense of memory usage. The default value is 15 if ++ deflateInit is used instead. ++ ++ The memLevel parameter specifies how much memory should be allocated ++ for the internal compression state. memLevel=1 uses minimum memory but ++ is slow and reduces compression ratio; memLevel=9 uses maximum memory ++ for optimal speed. The default value is 8. See zconf.h for total memory ++ usage as a function of windowBits and memLevel. ++ ++ The strategy parameter is used to tune the compression algorithm. Use the ++ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a ++ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no ++ string match). Filtered data consists mostly of small values with a ++ somewhat random distribution. In this case, the compression algorithm is ++ tuned to compress them better. The effect of Z_FILTERED is to force more ++ Huffman coding and less string matching; it is somewhat intermediate ++ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects ++ the compression ratio but not the correctness of the compressed output even ++ if it is not set appropriately. ++ ++ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough ++ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid ++ method). msg is set to null if there is no error message. deflateInit2 does ++ not perform any compression: this will be done by deflate(). ++*/ ++ ++ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, ++ const Bytef *dictionary, ++ uInt dictLength)); ++/* ++ Initializes the compression dictionary from the given byte sequence ++ without producing any compressed output. This function must be called ++ immediately after deflateInit, deflateInit2 or deflateReset, before any ++ call of deflate. The compressor and decompressor must use exactly the same ++ dictionary (see inflateSetDictionary). ++ ++ The dictionary should consist of strings (byte sequences) that are likely ++ to be encountered later in the data to be compressed, with the most commonly ++ used strings preferably put towards the end of the dictionary. Using a ++ dictionary is most useful when the data to be compressed is short and can be ++ predicted with good accuracy; the data can then be compressed better than ++ with the default empty dictionary. ++ ++ Depending on the size of the compression data structures selected by ++ deflateInit or deflateInit2, a part of the dictionary may in effect be ++ discarded, for example if the dictionary is larger than the window size in ++ deflate or deflate2. Thus the strings most likely to be useful should be ++ put at the end of the dictionary, not at the front. ++ ++ Upon return of this function, strm->adler is set to the Adler32 value ++ of the dictionary; the decompressor may later use this value to determine ++ which dictionary has been used by the compressor. (The Adler32 value ++ applies to the whole dictionary even if only a subset of the dictionary is ++ actually used by the compressor.) ++ ++ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a ++ parameter is invalid (such as NULL dictionary) or the stream state is ++ inconsistent (for example if deflate has already been called for this stream ++ or if the compression method is bsort). deflateSetDictionary does not ++ perform any compression: this will be done by deflate(). ++*/ ++ ++ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, ++ z_streamp source)); ++/* ++ Sets the destination stream as a complete copy of the source stream. ++ ++ This function can be useful when several compression strategies will be ++ tried, for example when there are several ways of pre-processing the input ++ data with a filter. The streams that will be discarded should then be freed ++ by calling deflateEnd. Note that deflateCopy duplicates the internal ++ compression state which can be quite large, so this strategy is slow and ++ can consume lots of memory. ++ ++ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not ++ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent ++ (such as zalloc being NULL). msg is left unchanged in both source and ++ destination. ++*/ ++ ++ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); ++/* ++ This function is equivalent to deflateEnd followed by deflateInit, ++ but does not free and reallocate all the internal compression state. ++ The stream will keep the same compression level and any other attributes ++ that may have been set by deflateInit2. ++ ++ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source ++ stream state was inconsistent (such as zalloc or state being NULL). ++*/ ++ ++ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, ++ int level, ++ int strategy)); ++/* ++ Dynamically update the compression level and compression strategy. The ++ interpretation of level and strategy is as in deflateInit2. This can be ++ used to switch between compression and straight copy of the input data, or ++ to switch to a different kind of input data requiring a different ++ strategy. If the compression level is changed, the input available so far ++ is compressed with the old level (and may be flushed); the new level will ++ take effect only at the next call of deflate(). ++ ++ Before the call of deflateParams, the stream state must be set as for ++ a call of deflate(), since the currently available input may have to ++ be compressed and flushed. In particular, strm->avail_out must be non-zero. ++ ++ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source ++ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR ++ if strm->avail_out was zero. ++*/ ++ ++/* ++ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, ++ int windowBits)); ++ ++ This is another version of inflateInit with an extra parameter. The ++ fields next_in, avail_in, zalloc, zfree and opaque must be initialized ++ before by the caller. ++ ++ The windowBits parameter is the base two logarithm of the maximum window ++ size (the size of the history buffer). It should be in the range 8..15 for ++ this version of the library. The default value is 15 if inflateInit is used ++ instead. If a compressed stream with a larger window size is given as ++ input, inflate() will return with the error code Z_DATA_ERROR instead of ++ trying to allocate a larger window. ++ ++ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough ++ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative ++ memLevel). msg is set to null if there is no error message. inflateInit2 ++ does not perform any decompression apart from reading the zlib header if ++ present: this will be done by inflate(). (So next_in and avail_in may be ++ modified, but next_out and avail_out are unchanged.) ++*/ ++ ++ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, ++ const Bytef *dictionary, ++ uInt dictLength)); ++/* ++ Initializes the decompression dictionary from the given uncompressed byte ++ sequence. This function must be called immediately after a call of inflate ++ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor ++ can be determined from the Adler32 value returned by this call of ++ inflate. The compressor and decompressor must use exactly the same ++ dictionary (see deflateSetDictionary). ++ ++ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a ++ parameter is invalid (such as NULL dictionary) or the stream state is ++ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the ++ expected one (incorrect Adler32 value). inflateSetDictionary does not ++ perform any decompression: this will be done by subsequent calls of ++ inflate(). ++*/ ++ ++ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); ++/* ++ Skips invalid compressed data until a full flush point (see above the ++ description of deflate with Z_FULL_FLUSH) can be found, or until all ++ available input is skipped. No output is provided. ++ ++ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR ++ if no more input was provided, Z_DATA_ERROR if no flush point has been found, ++ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success ++ case, the application may save the current current value of total_in which ++ indicates where valid compressed data was found. In the error case, the ++ application may repeatedly call inflateSync, providing more input each time, ++ until success or end of the input data. ++*/ ++ ++ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); ++/* ++ This function is equivalent to inflateEnd followed by inflateInit, ++ but does not free and reallocate all the internal decompression state. ++ The stream will keep attributes that may have been set by inflateInit2. ++ ++ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source ++ stream state was inconsistent (such as zalloc or state being NULL). ++*/ ++ ++ ++ /* utility functions */ ++ ++/* ++ The following utility functions are implemented on top of the ++ basic stream-oriented functions. To simplify the interface, some ++ default options are assumed (compression level and memory usage, ++ standard memory allocation functions). The source code of these ++ utility functions can easily be modified if you need special options. ++*/ ++ ++ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, ++ const Bytef *source, uLong sourceLen)); ++/* ++ Compresses the source buffer into the destination buffer. sourceLen is ++ the byte length of the source buffer. Upon entry, destLen is the total ++ size of the destination buffer, which must be at least 0.1% larger than ++ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the ++ compressed buffer. ++ This function can be used to compress a whole file at once if the ++ input file is mmap'ed. ++ compress returns Z_OK if success, Z_MEM_ERROR if there was not ++ enough memory, Z_BUF_ERROR if there was not enough room in the output ++ buffer. ++*/ ++ ++ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, ++ const Bytef *source, uLong sourceLen, ++ int level)); ++/* ++ Compresses the source buffer into the destination buffer. The level ++ parameter has the same meaning as in deflateInit. sourceLen is the byte ++ length of the source buffer. Upon entry, destLen is the total size of the ++ destination buffer, which must be at least 0.1% larger than sourceLen plus ++ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. ++ ++ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough ++ memory, Z_BUF_ERROR if there was not enough room in the output buffer, ++ Z_STREAM_ERROR if the level parameter is invalid. ++*/ ++ ++ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, ++ const Bytef *source, uLong sourceLen)); ++/* ++ Decompresses the source buffer into the destination buffer. sourceLen is ++ the byte length of the source buffer. Upon entry, destLen is the total ++ size of the destination buffer, which must be large enough to hold the ++ entire uncompressed data. (The size of the uncompressed data must have ++ been saved previously by the compressor and transmitted to the decompressor ++ by some mechanism outside the scope of this compression library.) ++ Upon exit, destLen is the actual size of the compressed buffer. ++ This function can be used to decompress a whole file at once if the ++ input file is mmap'ed. ++ ++ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not ++ enough memory, Z_BUF_ERROR if there was not enough room in the output ++ buffer, or Z_DATA_ERROR if the input data was corrupted. ++*/ ++ ++ ++typedef voidp gzFile; ++ ++ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); ++/* ++ Opens a gzip (.gz) file for reading or writing. The mode parameter ++ is as in fopen ("rb" or "wb") but can also include a compression level ++ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for ++ Huffman only compression as in "wb1h". (See the description ++ of deflateInit2 for more information about the strategy parameter.) ++ ++ gzopen can be used to read a file which is not in gzip format; in this ++ case gzread will directly read from the file without decompression. ++ ++ gzopen returns NULL if the file could not be opened or if there was ++ insufficient memory to allocate the (de)compression state; errno ++ can be checked to distinguish the two cases (if errno is zero, the ++ zlib error is Z_MEM_ERROR). */ ++ ++ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); ++/* ++ gzdopen() associates a gzFile with the file descriptor fd. File ++ descriptors are obtained from calls like open, dup, creat, pipe or ++ fileno (in the file has been previously opened with fopen). ++ The mode parameter is as in gzopen. ++ The next call of gzclose on the returned gzFile will also close the ++ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file ++ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). ++ gzdopen returns NULL if there was insufficient memory to allocate ++ the (de)compression state. ++*/ ++ ++ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); ++/* ++ Dynamically update the compression level or strategy. See the description ++ of deflateInit2 for the meaning of these parameters. ++ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not ++ opened for writing. ++*/ ++ ++ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); ++/* ++ Reads the given number of uncompressed bytes from the compressed file. ++ If the input file was not in gzip format, gzread copies the given number ++ of bytes into the buffer. ++ gzread returns the number of uncompressed bytes actually read (0 for ++ end of file, -1 for error). */ ++ ++ZEXTERN int ZEXPORT gzwrite OF((gzFile file, ++ const voidp buf, unsigned len)); ++/* ++ Writes the given number of uncompressed bytes into the compressed file. ++ gzwrite returns the number of uncompressed bytes actually written ++ (0 in case of error). ++*/ ++ ++ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); ++/* ++ Converts, formats, and writes the args to the compressed file under ++ control of the format string, as in fprintf. gzprintf returns the number of ++ uncompressed bytes actually written (0 in case of error). ++*/ ++ ++ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); ++/* ++ Writes the given null-terminated string to the compressed file, excluding ++ the terminating null character. ++ gzputs returns the number of characters written, or -1 in case of error. ++*/ ++ ++ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); ++/* ++ Reads bytes from the compressed file until len-1 characters are read, or ++ a newline character is read and transferred to buf, or an end-of-file ++ condition is encountered. The string is then terminated with a null ++ character. ++ gzgets returns buf, or Z_NULL in case of error. ++*/ ++ ++ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); ++/* ++ Writes c, converted to an unsigned char, into the compressed file. ++ gzputc returns the value that was written, or -1 in case of error. ++*/ ++ ++ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); ++/* ++ Reads one byte from the compressed file. gzgetc returns this byte ++ or -1 in case of end of file or error. ++*/ ++ ++ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); ++/* ++ Flushes all pending output into the compressed file. The parameter ++ flush is as in the deflate() function. The return value is the zlib ++ error number (see function gzerror below). gzflush returns Z_OK if ++ the flush parameter is Z_FINISH and all output could be flushed. ++ gzflush should be called only when strictly necessary because it can ++ degrade compression. ++*/ ++ ++ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, ++ z_off_t offset, int whence)); ++/* ++ Sets the starting position for the next gzread or gzwrite on the ++ given compressed file. The offset represents a number of bytes in the ++ uncompressed data stream. The whence parameter is defined as in lseek(2); ++ the value SEEK_END is not supported. ++ If the file is opened for reading, this function is emulated but can be ++ extremely slow. If the file is opened for writing, only forward seeks are ++ supported; gzseek then compresses a sequence of zeroes up to the new ++ starting position. ++ ++ gzseek returns the resulting offset location as measured in bytes from ++ the beginning of the uncompressed stream, or -1 in case of error, in ++ particular if the file is opened for writing and the new starting position ++ would be before the current position. ++*/ ++ ++ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); ++/* ++ Rewinds the given file. This function is supported only for reading. ++ ++ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) ++*/ ++ ++ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); ++/* ++ Returns the starting position for the next gzread or gzwrite on the ++ given compressed file. This position represents a number of bytes in the ++ uncompressed data stream. ++ ++ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) ++*/ ++ ++ZEXTERN int ZEXPORT gzeof OF((gzFile file)); ++/* ++ Returns 1 when EOF has previously been detected reading the given ++ input stream, otherwise zero. ++*/ ++ ++ZEXTERN int ZEXPORT gzclose OF((gzFile file)); ++/* ++ Flushes all pending output if necessary, closes the compressed file ++ and deallocates all the (de)compression state. The return value is the zlib ++ error number (see function gzerror below). ++*/ ++ ++ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); ++/* ++ Returns the error message for the last error which occurred on the ++ given compressed file. errnum is set to zlib error number. If an ++ error occurred in the file system and not in the compression library, ++ errnum is set to Z_ERRNO and the application may consult errno ++ to get the exact error code. ++*/ ++ ++ /* checksum functions */ ++ ++/* ++ These functions are not related to compression but are exported ++ anyway because they might be useful in applications using the ++ compression library. ++*/ ++ ++ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); ++ ++/* ++ Update a running Adler-32 checksum with the bytes buf[0..len-1] and ++ return the updated checksum. If buf is NULL, this function returns ++ the required initial value for the checksum. ++ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed ++ much faster. Usage example: ++ ++ uLong adler = adler32(0L, Z_NULL, 0); ++ ++ while (read_buffer(buffer, length) != EOF) { ++ adler = adler32(adler, buffer, length); ++ } ++ if (adler != original_adler) error(); ++*/ ++ ++ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); ++/* ++ Update a running crc with the bytes buf[0..len-1] and return the updated ++ crc. If buf is NULL, this function returns the required initial value ++ for the crc. Pre- and post-conditioning (one's complement) is performed ++ within this function so it shouldn't be done by the application. ++ Usage example: ++ ++ uLong crc = crc32(0L, Z_NULL, 0); ++ ++ while (read_buffer(buffer, length) != EOF) { ++ crc = crc32(crc, buffer, length); ++ } ++ if (crc != original_crc) error(); ++*/ ++ ++ ++ /* various hacks, don't look :) */ ++ ++/* deflateInit and inflateInit are macros to allow checking the zlib version ++ * and the compiler's view of z_stream: ++ */ ++ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, ++ const char *version, int stream_size)); ++ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, ++ const char *version, int stream_size)); ++ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, ++ int windowBits, int memLevel, ++ int strategy, const char *version, ++ int stream_size)); ++ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, ++ const char *version, int stream_size)); ++#define deflateInit(strm, level) \ ++ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) ++#define inflateInit(strm) \ ++ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) ++#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ ++ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ ++ (strategy), ZLIB_VERSION, sizeof(z_stream)) ++#define inflateInit2(strm, windowBits) \ ++ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) ++ ++ ++#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) ++ struct internal_state {int dummy;}; /* hack for buggy compilers */ ++#endif ++ ++ZEXTERN const char * ZEXPORT zError OF((int err)); ++ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); ++ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _ZLIB_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/include/zlib/zutil.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,225 @@ ++/* zutil.h -- internal interface and configuration of the compression library ++ * Copyright (C) 1995-2002 Jean-loup Gailly. ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* WARNING: this file should *not* be used by applications. It is ++ part of the implementation of the compression library and is ++ subject to change. Applications should only use zlib.h. ++ */ ++ ++/* @(#) $Id: zutil.h,v 1.4 2002/04/24 07:36:48 mcr Exp $ */ ++ ++#ifndef _Z_UTIL_H ++#define _Z_UTIL_H ++ ++#include "zlib.h" ++ ++#include <linux/string.h> ++#define HAVE_MEMCPY ++ ++#if 0 // #ifdef STDC ++# include <stddef.h> ++# include <string.h> ++# include <stdlib.h> ++#endif ++#ifndef __KERNEL__ ++#ifdef NO_ERRNO_H ++ extern int errno; ++#else ++# include <errno.h> ++#endif ++#endif ++ ++#ifndef local ++# define local static ++#endif ++/* compile with -Dlocal if your debugger can't find static symbols */ ++ ++typedef unsigned char uch; ++typedef uch FAR uchf; ++typedef unsigned short ush; ++typedef ush FAR ushf; ++typedef unsigned long ulg; ++ ++extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ ++/* (size given to avoid silly warnings with Visual C++) */ ++ ++#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] ++ ++#define ERR_RETURN(strm,err) \ ++ return (strm->msg = ERR_MSG(err), (err)) ++/* To be used only when the state is known to be valid */ ++ ++ /* common constants */ ++ ++#ifndef DEF_WBITS ++# define DEF_WBITS MAX_WBITS ++#endif ++/* default windowBits for decompression. MAX_WBITS is for compression only */ ++ ++#if MAX_MEM_LEVEL >= 8 ++# define DEF_MEM_LEVEL 8 ++#else ++# define DEF_MEM_LEVEL MAX_MEM_LEVEL ++#endif ++/* default memLevel */ ++ ++#define STORED_BLOCK 0 ++#define STATIC_TREES 1 ++#define DYN_TREES 2 ++/* The three kinds of block type */ ++ ++#define MIN_MATCH 3 ++#define MAX_MATCH 258 ++/* The minimum and maximum match lengths */ ++ ++#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ ++ ++ /* target dependencies */ ++ ++#ifdef MSDOS ++# define OS_CODE 0x00 ++# if defined(__TURBOC__) || defined(__BORLANDC__) ++# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) ++ /* Allow compilation with ANSI keywords only enabled */ ++ void _Cdecl farfree( void *block ); ++ void *_Cdecl farmalloc( unsigned long nbytes ); ++# else ++# include <alloc.h> ++# endif ++# else /* MSC or DJGPP */ ++# include <malloc.h> ++# endif ++#endif ++ ++#ifdef OS2 ++# define OS_CODE 0x06 ++#endif ++ ++#ifdef WIN32 /* Window 95 & Windows NT */ ++# define OS_CODE 0x0b ++#endif ++ ++#if defined(VAXC) || defined(VMS) ++# define OS_CODE 0x02 ++# define F_OPEN(name, mode) \ ++ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") ++#endif ++ ++#ifdef AMIGA ++# define OS_CODE 0x01 ++#endif ++ ++#if defined(ATARI) || defined(atarist) ++# define OS_CODE 0x05 ++#endif ++ ++#if defined(MACOS) || defined(TARGET_OS_MAC) ++# define OS_CODE 0x07 ++# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os ++# include <unix.h> /* for fdopen */ ++# else ++# ifndef fdopen ++# define fdopen(fd,mode) NULL /* No fdopen() */ ++# endif ++# endif ++#endif ++ ++#ifdef __50SERIES /* Prime/PRIMOS */ ++# define OS_CODE 0x0F ++#endif ++ ++#ifdef TOPS20 ++# define OS_CODE 0x0a ++#endif ++ ++#if defined(_BEOS_) || defined(RISCOS) ++# define fdopen(fd,mode) NULL /* No fdopen() */ ++#endif ++ ++#if (defined(_MSC_VER) && (_MSC_VER > 600)) ++# define fdopen(fd,type) _fdopen(fd,type) ++#endif ++ ++ ++ /* Common defaults */ ++ ++#ifndef OS_CODE ++# define OS_CODE 0x03 /* assume Unix */ ++#endif ++ ++#ifndef F_OPEN ++# define F_OPEN(name, mode) fopen((name), (mode)) ++#endif ++ ++ /* functions */ ++ ++#ifdef HAVE_STRERROR ++ extern char *strerror OF((int)); ++# define zstrerror(errnum) strerror(errnum) ++#else ++# define zstrerror(errnum) "" ++#endif ++ ++#if defined(pyr) ++# define NO_MEMCPY ++#endif ++#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) ++ /* Use our own functions for small and medium model with MSC <= 5.0. ++ * You may have to use the same strategy for Borland C (untested). ++ * The __SC__ check is for Symantec. ++ */ ++# define NO_MEMCPY ++#endif ++#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) ++# define HAVE_MEMCPY ++#endif ++#ifdef HAVE_MEMCPY ++# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ ++# define zmemcpy _fmemcpy ++# define zmemcmp _fmemcmp ++# define zmemzero(dest, len) _fmemset(dest, 0, len) ++# else ++# define zmemcpy memcpy ++# define zmemcmp memcmp ++# define zmemzero(dest, len) memset(dest, 0, len) ++# endif ++#else ++ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); ++ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); ++ extern void zmemzero OF((Bytef* dest, uInt len)); ++#endif ++ ++/* Diagnostic functions */ ++#ifdef DEBUG ++# include <stdio.h> ++ extern int z_verbose; ++ extern void z_error OF((char *m)); ++# define Assert(cond,msg) {if(!(cond)) z_error(msg);} ++# define Trace(x) {if (z_verbose>=0) fprintf x ;} ++# define Tracev(x) {if (z_verbose>0) fprintf x ;} ++# define Tracevv(x) {if (z_verbose>1) fprintf x ;} ++# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} ++# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} ++#else ++# define Assert(cond,msg) ++# define Trace(x) ++# define Tracev(x) ++# define Tracevv(x) ++# define Tracec(c,x) ++# define Tracecv(c,x) ++#endif ++ ++ ++typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, ++ uInt len)); ++voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); ++void zcfree OF((voidpf opaque, voidpf ptr)); ++ ++#define ZALLOC(strm, items, size) \ ++ (*((strm)->zalloc))((strm)->opaque, (items), (size)) ++#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) ++#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} ++ ++#endif /* _Z_UTIL_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/Makefile.objs Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,21 @@ ++obj-y += satot.o ++obj-y += addrtot.o ++obj-y += ultot.o ++obj-y += addrtypeof.o ++obj-y += anyaddr.o ++obj-y += initaddr.o ++obj-y += ultoa.o ++obj-y += addrtoa.o ++obj-y += subnettoa.o ++obj-y += subnetof.o ++obj-y += goodmask.o ++obj-y += datatot.o ++obj-y += rangetoa.o ++obj-y += prng.o ++obj-y += pfkey_v2_parse.o ++obj-y += pfkey_v2_build.o ++obj-y += pfkey_v2_debug.o ++obj-y += pfkey_v2_ext_bits.o ++ ++#version.c: ${LIBFREESWANDIR}/version.in.c ${OPENSWANSRCDIR}/Makefile.ver ++# sed '/"/s/xxx/$(IPSECVERSION)/' ${LIBFREESWANDIR}/version.in.c >$@ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/addrtoa.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,67 @@ ++/* ++ * addresses to ASCII ++ * Copyright (C) 1998, 1999 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: addrtoa.c,v 1.9 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++#define NBYTES 4 /* bytes in an address */ ++#define PERBYTE 4 /* three digits plus a dot or NUL */ ++#define BUFLEN (NBYTES*PERBYTE) ++ ++#if BUFLEN != ADDRTOA_BUF ++#error "ADDRTOA_BUF in openswan.h inconsistent with addrtoa() code" ++#endif ++ ++/* ++ - addrtoa - convert binary address to ASCII dotted decimal ++ */ ++size_t /* space needed for full conversion */ ++addrtoa(addr, format, dst, dstlen) ++struct in_addr addr; ++int format; /* character */ ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ unsigned long a = ntohl(addr.s_addr); ++ int i; ++ size_t n; ++ unsigned long byte; ++ char buf[BUFLEN]; ++ char *p; ++ ++ switch (format) { ++ case 0: ++ break; ++ default: ++ return 0; ++ break; ++ } ++ ++ p = buf; ++ for (i = NBYTES-1; i >= 0; i--) { ++ byte = (a >> (i*8)) & 0xff; ++ p += ultoa(byte, 10, p, PERBYTE); ++ if (i != 0) ++ *(p-1) = '.'; ++ } ++ n = p - buf; ++ ++ if (dstlen > 0) { ++ if (n > dstlen) ++ buf[dstlen - 1] = '\0'; ++ strcpy(dst, buf); ++ } ++ return n; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/addrtot.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,334 @@ ++/* ++ * addresses to text ++ * Copyright (C) 2000 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: addrtot.c,v 1.15 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++#define IP4BYTES 4 /* bytes in an IPv4 address */ ++#define PERBYTE 4 /* three digits plus a dot or NUL */ ++#define IP6BYTES 16 /* bytes in an IPv6 address */ ++ ++/* forwards */ ++static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp); ++static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish); ++static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp); ++static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp); ++ ++/* ++ - addrtot - convert binary address to text (dotted decimal or IPv6 string) ++ */ ++size_t /* space needed for full conversion */ ++addrtot(src, format, dst, dstlen) ++const ip_address *src; ++int format; /* character */ ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ const unsigned char *b; ++ size_t n; ++ char buf[1+ADDRTOT_BUF+1]; /* :address: */ ++ char *p; ++ int t = addrtypeof(src); ++# define TF(t, f) (((t)<<8) | (f)) ++ ++ n = addrbytesptr(src, &b); ++ if (n == 0) { ++ bad: ++ dst[0]='\0'; ++ strncat(dst, "<invalid>", dstlen); ++ return sizeof("<invalid>"); ++ } ++ ++ switch (TF(t, format)) { ++ case TF(AF_INET, 0): ++ n = normal4(b, n, buf, &p); ++ break; ++ case TF(AF_INET6, 0): ++ n = normal6(b, n, buf, &p, 1); ++ break; ++ case TF(AF_INET, 'Q'): ++ n = normal4(b, n, buf, &p); ++ break; ++ case TF(AF_INET6, 'Q'): ++ n = normal6(b, n, buf, &p, 0); ++ break; ++ case TF(AF_INET, 'r'): ++ n = reverse4(b, n, buf, &p); ++ break; ++ case TF(AF_INET6, 'r'): ++ n = reverse6(b, n, buf, &p); ++ break; ++ default: /* including (AF_INET, 'R') */ ++ goto bad; ++ break; ++ } ++ ++ if (dstlen > 0) { ++ if (dstlen < n) ++ p[dstlen - 1] = '\0'; ++ strcpy(dst, p); ++ } ++ return n; ++} ++ ++/* ++ - normal4 - normal IPv4 address-text conversion ++ */ ++static size_t /* size of text, including NUL */ ++normal4(srcp, srclen, buf, dstp) ++const unsigned char *srcp; ++size_t srclen; ++char *buf; /* guaranteed large enough */ ++char **dstp; /* where to put result pointer */ ++{ ++ int i; ++ char *p; ++ ++ if (srclen != IP4BYTES) /* "can't happen" */ ++ return 0; ++ p = buf; ++ for (i = 0; i < IP4BYTES; i++) { ++ p += ultot(srcp[i], 10, p, PERBYTE); ++ if (i != IP4BYTES - 1) ++ *(p-1) = '.'; /* overwrites the NUL */ ++ } ++ *dstp = buf; ++ return p - buf; ++} ++ ++/* ++ - normal6 - normal IPv6 address-text conversion ++ */ ++static size_t /* size of text, including NUL */ ++normal6(srcp, srclen, buf, dstp, squish) ++const unsigned char *srcp; ++size_t srclen; ++char *buf; /* guaranteed large enough, plus 2 */ ++char **dstp; /* where to put result pointer */ ++int squish; /* whether to squish out 0:0 */ ++{ ++ int i; ++ unsigned long piece; ++ char *p; ++ char *q; ++ ++ if (srclen != IP6BYTES) /* "can't happen" */ ++ return 0; ++ p = buf; ++ *p++ = ':'; ++ for (i = 0; i < IP6BYTES/2; i++) { ++ piece = (srcp[2*i] << 8) + srcp[2*i + 1]; ++ p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */ ++ *(p-1) = ':'; /* overwrites the NUL */ ++ } ++ *p = '\0'; ++ q = strstr(buf, ":0:0:"); ++ if (squish && q != NULL) { /* zero squishing is possible */ ++ p = q + 1; ++ while (*p == '0' && *(p+1) == ':') ++ p += 2; ++ q++; ++ *q++ = ':'; /* overwrite first 0 */ ++ while (*p != '\0') ++ *q++ = *p++; ++ *q = '\0'; ++ if (!(*(q-1) == ':' && *(q-2) == ':')) ++ *--q = '\0'; /* strip final : unless :: */ ++ p = buf; ++ if (!(*p == ':' && *(p+1) == ':')) ++ p++; /* skip initial : unless :: */ ++ } else { ++ q = p; ++ *--q = '\0'; /* strip final : */ ++ p = buf + 1; /* skip initial : */ ++ } ++ *dstp = p; ++ return q - p + 1; ++} ++ ++/* ++ - reverse4 - IPv4 reverse-lookup conversion ++ */ ++static size_t /* size of text, including NUL */ ++reverse4(srcp, srclen, buf, dstp) ++const unsigned char *srcp; ++size_t srclen; ++char *buf; /* guaranteed large enough */ ++char **dstp; /* where to put result pointer */ ++{ ++ int i; ++ char *p; ++ ++ if (srclen != IP4BYTES) /* "can't happen" */ ++ return 0; ++ p = buf; ++ for (i = IP4BYTES-1; i >= 0; i--) { ++ p += ultot(srcp[i], 10, p, PERBYTE); ++ *(p-1) = '.'; /* overwrites the NUL */ ++ } ++ strcpy(p, "IN-ADDR.ARPA."); ++ *dstp = buf; ++ return strlen(buf) + 1; ++} ++ ++/* ++ - reverse6 - IPv6 reverse-lookup conversion (RFC 1886) ++ * A trifle inefficient, really shouldn't use ultot... ++ */ ++static size_t /* size of text, including NUL */ ++reverse6(srcp, srclen, buf, dstp) ++const unsigned char *srcp; ++size_t srclen; ++char *buf; /* guaranteed large enough */ ++char **dstp; /* where to put result pointer */ ++{ ++ int i; ++ unsigned long piece; ++ char *p; ++ ++ if (srclen != IP6BYTES) /* "can't happen" */ ++ return 0; ++ p = buf; ++ for (i = IP6BYTES-1; i >= 0; i--) { ++ piece = srcp[i]; ++ p += ultot(piece&0xf, 16, p, 2); ++ *(p-1) = '.'; ++ p += ultot(piece>>4, 16, p, 2); ++ *(p-1) = '.'; ++ } ++ strcpy(p, "IP6.ARPA."); ++ *dstp = buf; ++ return strlen(buf) + 1; ++} ++ ++/* ++ - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874) ++ * this version removed as it was obsoleted in the end. ++ */ ++ ++#ifdef ADDRTOT_MAIN ++ ++#include <stdio.h> ++#include <sys/socket.h> ++#include <netinet/in.h> ++#include <arpa/inet.h> ++ ++void regress(void); ++ ++int ++main(int argc, char *argv[]) ++{ ++ if (argc < 2) { ++ fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n", ++ argv[0]); ++ exit(2); ++ } ++ ++ if (strcmp(argv[1], "-r") == 0) { ++ regress(); ++ fprintf(stderr, "regress() returned?!?\n"); ++ exit(1); ++ } ++ exit(0); ++} ++ ++struct rtab { ++ char *input; ++ char format; ++ char *output; /* NULL means error expected */ ++} rtab[] = { ++ {"1.2.3.0", 0, "1.2.3.0"}, ++ {"1:2::3:4", 0, "1:2::3:4"}, ++ {"1:2::3:4", 'Q', "1:2:0:0:0:0:3:4"}, ++ {"1:2:0:0:3:4:0:0", 0, "1:2::3:4:0:0"}, ++ {"1.2.3.4", 'r' , "4.3.2.1.IN-ADDR.ARPA."}, ++ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */ ++ {"1:2::3:4", 'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA."}, ++ {NULL, 0, NULL} ++}; ++ ++void ++regress() ++{ ++ struct rtab *r; ++ int status = 0; ++ ip_address a; ++ char in[100]; ++ char buf[100]; ++ const char *oops; ++ size_t n; ++ ++ for (r = rtab; r->input != NULL; r++) { ++ strcpy(in, r->input); ++ ++ /* convert it *to* internal format */ ++ oops = ttoaddr(in, strlen(in), 0, &a); ++ ++ /* now convert it back */ ++ ++ n = addrtot(&a, r->format, buf, sizeof(buf)); ++ ++ if (n == 0 && r->output == NULL) ++ {} /* okay, error expected */ ++ ++ else if (n == 0) { ++ printf("`%s' atoasr failed\n", r->input); ++ status = 1; ++ ++ } else if (r->output == NULL) { ++ printf("`%s' atoasr succeeded unexpectedly '%c'\n", ++ r->input, r->format); ++ status = 1; ++ } else { ++ if (strcasecmp(r->output, buf) != 0) { ++ printf("`%s' '%c' gave `%s', expected `%s'\n", ++ r->input, r->format, buf, r->output); ++ status = 1; ++ } ++ } ++ } ++ exit(status); ++} ++ ++#endif /* ADDRTOT_MAIN */ ++ ++/* ++ * $Log: addrtot.c,v $ ++ * Revision 1.15 2004/04/11 17:39:25 mcr ++ * removed internal.h requirements. ++ * ++ * Revision 1.14 2004/03/08 01:59:08 ken ++ * freeswan.h -> openswan.h ++ * ++ * Revision 1.13 2004/01/05 23:21:05 mcr ++ * if the address type is invalid, then return length of <invalid> ++ * string! ++ * ++ * Revision 1.12 2003/12/30 06:42:48 mcr ++ * added $Log: addrtot.c,v $ ++ * added Revision 1.15 2004/04/11 17:39:25 mcr ++ * added removed internal.h requirements. ++ * added ++ * added Revision 1.14 2004/03/08 01:59:08 ken ++ * added freeswan.h -> openswan.h ++ * added ++ * added Revision 1.13 2004/01/05 23:21:05 mcr ++ * added if the address type is invalid, then return length of <invalid> ++ * added string! ++ * added ++ * ++ * ++ */ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/addrtypeof.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,93 @@ ++/* ++ * extract parts of an ip_address ++ * Copyright (C) 2000 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: addrtypeof.c,v 1.9 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++/* ++ - addrtypeof - get the type of an ip_address ++ */ ++int ++addrtypeof(src) ++const ip_address *src; ++{ ++ return src->u.v4.sin_family; ++} ++ ++/* ++ - addrbytesptr - get pointer to the address bytes of an ip_address ++ */ ++size_t /* 0 for error */ ++addrbytesptr(src, dstp) ++const ip_address *src; ++const unsigned char **dstp; /* NULL means just a size query */ ++{ ++ const unsigned char *p; ++ size_t n; ++ ++ switch (src->u.v4.sin_family) { ++ case AF_INET: ++ p = (const unsigned char *)&src->u.v4.sin_addr.s_addr; ++ n = 4; ++ break; ++ case AF_INET6: ++ p = (const unsigned char *)&src->u.v6.sin6_addr; ++ n = 16; ++ break; ++ default: ++ return 0; ++ break; ++ } ++ ++ if (dstp != NULL) ++ *dstp = p; ++ return n; ++} ++ ++/* ++ - addrlenof - get length of the address bytes of an ip_address ++ */ ++size_t /* 0 for error */ ++addrlenof(src) ++const ip_address *src; ++{ ++ return addrbytesptr(src, NULL); ++} ++ ++/* ++ - addrbytesof - get the address bytes of an ip_address ++ */ ++size_t /* 0 for error */ ++addrbytesof(src, dst, dstlen) ++const ip_address *src; ++unsigned char *dst; ++size_t dstlen; ++{ ++ const unsigned char *p; ++ size_t n; ++ size_t ncopy; ++ ++ n = addrbytesptr(src, &p); ++ if (n == 0) ++ return 0; ++ ++ if (dstlen > 0) { ++ ncopy = n; ++ if (ncopy > dstlen) ++ ncopy = dstlen; ++ memcpy(dst, p, ncopy); ++ } ++ return n; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/anyaddr.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,145 @@ ++/* ++ * special addresses ++ * Copyright (C) 2000 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: anyaddr.c,v 1.9 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++/* these are mostly fallbacks for the no-IPv6-support-in-library case */ ++#ifndef IN6ADDR_ANY_INIT ++#define IN6ADDR_ANY_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}} ++#endif ++#ifndef IN6ADDR_LOOPBACK_INIT ++#define IN6ADDR_LOOPBACK_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}} ++#endif ++ ++static struct in6_addr v6any = IN6ADDR_ANY_INIT; ++static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT; ++ ++/* ++ - anyaddr - initialize to the any-address value ++ */ ++err_t /* NULL for success, else string literal */ ++anyaddr(af, dst) ++int af; /* address family */ ++ip_address *dst; ++{ ++ uint32_t v4any = htonl(INADDR_ANY); ++ ++ switch (af) { ++ case AF_INET: ++ return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst); ++ break; ++ case AF_INET6: ++ return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst); ++ break; ++ default: ++ return "unknown address family in anyaddr/unspecaddr"; ++ break; ++ } ++} ++ ++/* ++ - unspecaddr - initialize to the unspecified-address value ++ */ ++err_t /* NULL for success, else string literal */ ++unspecaddr(af, dst) ++int af; /* address family */ ++ip_address *dst; ++{ ++ return anyaddr(af, dst); ++} ++ ++/* ++ - loopbackaddr - initialize to the loopback-address value ++ */ ++err_t /* NULL for success, else string literal */ ++loopbackaddr(af, dst) ++int af; /* address family */ ++ip_address *dst; ++{ ++ uint32_t v4loop = htonl(INADDR_LOOPBACK); ++ ++ switch (af) { ++ case AF_INET: ++ return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst); ++ break; ++ case AF_INET6: ++ return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst); ++ break; ++ default: ++ return "unknown address family in loopbackaddr"; ++ break; ++ } ++} ++ ++/* ++ - isanyaddr - test for the any-address value ++ */ ++int ++isanyaddr(src) ++const ip_address *src; ++{ ++ uint32_t v4any = htonl(INADDR_ANY); ++ int cmp; ++ ++ switch (src->u.v4.sin_family) { ++ case AF_INET: ++ cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any)); ++ break; ++ case AF_INET6: ++ cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any)); ++ break; ++ default: ++ return 0; ++ break; ++ } ++ ++ return (cmp == 0) ? 1 : 0; ++} ++ ++/* ++ - isunspecaddr - test for the unspecified-address value ++ */ ++int ++isunspecaddr(src) ++const ip_address *src; ++{ ++ return isanyaddr(src); ++} ++ ++/* ++ - isloopbackaddr - test for the loopback-address value ++ */ ++int ++isloopbackaddr(src) ++const ip_address *src; ++{ ++ uint32_t v4loop = htonl(INADDR_LOOPBACK); ++ int cmp; ++ ++ switch (src->u.v4.sin_family) { ++ case AF_INET: ++ cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop)); ++ break; ++ case AF_INET6: ++ cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop)); ++ break; ++ default: ++ return 0; ++ break; ++ } ++ ++ return (cmp == 0) ? 1 : 0; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/datatot.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,232 @@ ++/* ++ * convert from binary data (e.g. key) to text form ++ * Copyright (C) 2000 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: datatot.c,v 1.5 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++static void convert(const char *src, size_t nreal, int format, char *out); ++ ++/* ++ - datatot - convert data bytes to text ++ */ ++size_t /* true length (with NUL) for success */ ++datatot(src, srclen, format, dst, dstlen) ++const char *src; ++size_t srclen; ++int format; /* character indicating what format */ ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ size_t inblocksize; /* process this many bytes at a time */ ++ size_t outblocksize; /* producing this many */ ++ size_t breakevery; /* add a _ every this many (0 means don't) */ ++ size_t sincebreak; /* output bytes since last _ */ ++ char breakchar; /* character used to break between groups */ ++ char inblock[10]; /* enough for any format */ ++ char outblock[10]; /* enough for any format */ ++ char fake[1]; /* fake output area for dstlen == 0 */ ++ size_t needed; /* return value */ ++ char *stop; /* where the terminating NUL will go */ ++ size_t ntodo; /* remaining input */ ++ size_t nreal; ++ char *out; ++ char *prefix; ++ ++ breakevery = 0; ++ breakchar = '_'; ++ ++ switch (format) { ++ case 0: ++ case 'h': ++ format = 'x'; ++ breakevery = 8; ++ /* FALLTHROUGH */ ++ case 'x': ++ inblocksize = 1; ++ outblocksize = 2; ++ prefix = "0x"; ++ break; ++ case ':': ++ format = 'x'; ++ breakevery = 2; ++ breakchar = ':'; ++ /* FALLTHROUGH */ ++ case 16: ++ inblocksize = 1; ++ outblocksize = 2; ++ prefix = ""; ++ format = 'x'; ++ break; ++ case 's': ++ inblocksize = 3; ++ outblocksize = 4; ++ prefix = "0s"; ++ break; ++ case 64: /* beware, equals ' ' */ ++ inblocksize = 3; ++ outblocksize = 4; ++ prefix = ""; ++ format = 's'; ++ break; ++ default: ++ return 0; ++ break; ++ } ++ assert(inblocksize < sizeof(inblock)); ++ assert(outblocksize < sizeof(outblock)); ++ assert(breakevery % outblocksize == 0); ++ ++ if (srclen == 0) ++ return 0; ++ ntodo = srclen; ++ ++ if (dstlen == 0) { /* dispose of awkward special case */ ++ dst = fake; ++ dstlen = 1; ++ } ++ stop = dst + dstlen - 1; ++ ++ nreal = strlen(prefix); ++ needed = nreal; /* for starters */ ++ if (dstlen <= nreal) { /* prefix won't fit */ ++ strncpy(dst, prefix, dstlen - 1); ++ dst += dstlen - 1; ++ } else { ++ strcpy(dst, prefix); ++ dst += nreal; ++ } ++ assert(dst <= stop); ++ sincebreak = 0; ++ ++ while (ntodo > 0) { ++ if (ntodo < inblocksize) { /* incomplete input */ ++ memset(inblock, 0, sizeof(inblock)); ++ memcpy(inblock, src, ntodo); ++ src = inblock; ++ nreal = ntodo; ++ ntodo = inblocksize; ++ } else ++ nreal = inblocksize; ++ out = (outblocksize > stop - dst) ? outblock : dst; ++ ++ convert(src, nreal, format, out); ++ needed += outblocksize; ++ sincebreak += outblocksize; ++ if (dst < stop) { ++ if (out != dst) { ++ assert(outblocksize > stop - dst); ++ memcpy(dst, out, stop - dst); ++ dst = stop; ++ } else ++ dst += outblocksize; ++ } ++ ++ src += inblocksize; ++ ntodo -= inblocksize; ++ if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) { ++ if (dst < stop) ++ *dst++ = breakchar; ++ needed++; ++ sincebreak = 0; ++ } ++ } ++ ++ assert(dst <= stop); ++ *dst++ = '\0'; ++ needed++; ++ ++ return needed; ++} ++ ++/* ++ - convert - convert one input block to one output block ++ */ ++static void ++convert(src, nreal, format, out) ++const char *src; ++size_t nreal; /* how much of the input block is real */ ++int format; ++char *out; ++{ ++ static char hex[] = "0123456789abcdef"; ++ static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ "abcdefghijklmnopqrstuvwxyz" ++ "0123456789+/"; ++ unsigned char c; ++ unsigned char c1, c2, c3; ++ ++ assert(nreal > 0); ++ switch (format) { ++ case 'x': ++ assert(nreal == 1); ++ c = (unsigned char)*src; ++ *out++ = hex[c >> 4]; ++ *out++ = hex[c & 0xf]; ++ break; ++ case 's': ++ c1 = (unsigned char)*src++; ++ c2 = (unsigned char)*src++; ++ c3 = (unsigned char)*src++; ++ *out++ = base64[c1 >> 2]; /* top 6 bits of c1 */ ++ c = (c1 & 0x3) << 4; /* bottom 2 of c1... */ ++ c |= c2 >> 4; /* ...top 4 of c2 */ ++ *out++ = base64[c]; ++ if (nreal == 1) ++ *out++ = '='; ++ else { ++ c = (c2 & 0xf) << 2; /* bottom 4 of c2... */ ++ c |= c3 >> 6; /* ...top 2 of c3 */ ++ *out++ = base64[c]; ++ } ++ if (nreal <= 2) ++ *out++ = '='; ++ else ++ *out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */ ++ break; ++ default: ++ assert(nreal == 0); /* unknown format */ ++ break; ++ } ++} ++ ++/* ++ - datatoa - convert data to ASCII ++ * backward-compatibility synonym for datatot ++ */ ++size_t /* true length (with NUL) for success */ ++datatoa(src, srclen, format, dst, dstlen) ++const char *src; ++size_t srclen; ++int format; /* character indicating what format */ ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ return datatot(src, srclen, format, dst, dstlen); ++} ++ ++/* ++ - bytestoa - convert data bytes to ASCII ++ * backward-compatibility synonym for datatot ++ */ ++size_t /* true length (with NUL) for success */ ++bytestoa(src, srclen, format, dst, dstlen) ++const char *src; ++size_t srclen; ++int format; /* character indicating what format */ ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ return datatot(src, srclen, format, dst, dstlen); ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/goodmask.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,100 @@ ++/* ++ * minor utilities for subnet-mask manipulation ++ * Copyright (C) 1998, 1999 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: goodmask.c,v 1.11 2004/04/11 19:43:48 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++#ifndef ABITS ++#define ABITS 32 /* bits in an IPv4 address */ ++#endif ++ ++/* ++ - goodmask - is this a good (^1*0*$) subnet mask? ++ * You are not expected to understand this. See Henry S. Warren Jr, ++ * "Functions realizable with word-parallel logical and two's-complement ++ * addition instructions", CACM 20.6 (June 1977), p.439. ++ */ ++int /* predicate */ ++goodmask(mask) ++struct in_addr mask; ++{ ++ unsigned long x = ntohl(mask.s_addr); ++ /* clear rightmost contiguous string of 1-bits */ ++# define CRCS1B(x) (((x|(x-1))+1)&x) ++# define TOPBIT (1UL << 31) ++ ++ /* either zero, or has one string of 1-bits which is left-justified */ ++ if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT))) ++ return 1; ++ return 0; ++} ++ ++/* ++ - masktobits - how many bits in this mask? ++ * The algorithm is essentially a binary search, but highly optimized ++ * for this particular task. ++ */ ++int /* -1 means !goodmask() */ ++masktobits(mask) ++struct in_addr mask; ++{ ++ unsigned long m = ntohl(mask.s_addr); ++ int masklen; ++ ++ if (!goodmask(mask)) ++ return -1; ++ ++ if (m&0x00000001UL) ++ return 32; ++ masklen = 0; ++ if (m&(0x0000ffffUL<<1)) { /* <<1 for 1-origin numbering */ ++ masklen |= 0x10; ++ m <<= 16; ++ } ++ if (m&(0x00ff0000UL<<1)) { ++ masklen |= 0x08; ++ m <<= 8; ++ } ++ if (m&(0x0f000000UL<<1)) { ++ masklen |= 0x04; ++ m <<= 4; ++ } ++ if (m&(0x30000000UL<<1)) { ++ masklen |= 0x02; ++ m <<= 2; ++ } ++ if (m&(0x40000000UL<<1)) ++ masklen |= 0x01; ++ ++ return masklen; ++} ++ ++/* ++ - bitstomask - return a mask with this many high bits on ++ */ ++struct in_addr ++bitstomask(n) ++int n; ++{ ++ struct in_addr result; ++ ++ if (n > 0 && n <= ABITS) ++ result.s_addr = htonl(~((1UL << (ABITS - n)) - 1)); ++ else if (n == 0) ++ result.s_addr = 0; ++ else ++ result.s_addr = 0; /* best error report we can do */ ++ return result; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/initaddr.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,50 @@ ++/* ++ * initialize address structure ++ * Copyright (C) 2000 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: initaddr.c,v 1.5 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++/* ++ - initaddr - initialize ip_address from bytes ++ */ ++err_t /* NULL for success, else string literal */ ++initaddr(src, srclen, af, dst) ++const unsigned char *src; ++size_t srclen; ++int af; /* address family */ ++ip_address *dst; ++{ ++ switch (af) { ++ case AF_INET: ++ if (srclen != 4) ++ return "IPv4 address must be exactly 4 bytes"; ++ dst->u.v4.sin_family = af; ++ dst->u.v4.sin_port = 0; /* unused */ ++ memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen); ++ break; ++ case AF_INET6: ++ if (srclen != 16) ++ return "IPv6 address must be exactly 16 bytes"; ++ dst->u.v6.sin6_family = af; ++ dst->u.v6.sin6_flowinfo = 0; /* unused */ ++ dst->u.v6.sin6_port = 0; /* unused */ ++ memcpy((char *)&dst->u.v6.sin6_addr, src, srclen); ++ break; ++ default: ++ return "unknown address family in initaddr"; ++ break; ++ } ++ return NULL; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/pfkey_v2_build.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1559 @@ ++/* ++ * RFC2367 PF_KEYv2 Key management API message parser ++ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: pfkey_v2_build.c,v 1.49 2004/04/12 02:59:06 mcr Exp $ ++ */ ++ ++/* ++ * Template from klips/net/ipsec/ipsec/ipsec_parser.c. ++ */ ++ ++char pfkey_v2_build_c_version[] = "$Id: pfkey_v2_build.c,v 1.49 2004/04/12 02:59:06 mcr Exp $"; ++ ++/* ++ * Some ugly stuff to allow consistent debugging code for use in the ++ * kernel and in user space ++*/ ++ ++#ifdef __KERNEL__ ++ ++# include <linux/kernel.h> /* for printk */ ++ ++# include "openswan/ipsec_kversion.h" /* for malloc switch */ ++# ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++# else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++# endif /* MALLOC_SLAB */ ++# include <linux/errno.h> /* error codes */ ++# include <linux/types.h> /* size_t */ ++# include <linux/interrupt.h> /* mark_bh */ ++ ++# include <linux/netdevice.h> /* struct device, and other headers */ ++# include <linux/etherdevice.h> /* eth_type_trans */ ++# include <linux/ip.h> /* struct iphdr */ ++# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++# include <linux/ipv6.h> /* struct ipv6hdr */ ++# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ ++ ++# define MALLOC(size) kmalloc(size, GFP_ATOMIC) ++# define FREE(obj) kfree(obj) ++# include <openswan.h> ++#else /* __KERNEL__ */ ++ ++# include <sys/types.h> ++# include <linux/types.h> ++# include <linux/errno.h> ++# include <malloc.h> ++# include <string.h> /* memset */ ++ ++# include <openswan.h> ++ ++#endif /* __KERNEL__ */ ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#ifdef __KERNEL__ ++#include "openswan/radij.h" /* rd_nodes */ ++#include "openswan/ipsec_encap.h" /* sockaddr_encap */ ++#endif /* __KERNEL__ */ ++ ++ ++#include "openswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ ++#include "openswan/pfkey_debug.h" ++ ++ ++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) ++ ++void ++pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]) ++{ ++ int i; ++ ++ for (i = 0; i != SADB_EXT_MAX + 1; i++) { ++ extensions[i] = NULL; ++ } ++} ++ ++void ++pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]) ++{ ++ int i; ++ ++ if(!extensions) { ++ return; ++ } ++ ++ if(extensions[0]) { ++ memset(extensions[0], 0, sizeof(struct sadb_msg)); ++ FREE(extensions[0]); ++ extensions[0] = NULL; ++ } ++ ++ for (i = 1; i != SADB_EXT_MAX + 1; i++) { ++ if(extensions[i]) { ++ memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); ++ FREE(extensions[i]); ++ extensions[i] = NULL; ++ } ++ } ++} ++ ++void ++pfkey_msg_free(struct sadb_msg **pfkey_msg) ++{ ++ if(*pfkey_msg) { ++ memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); ++ FREE(*pfkey_msg); ++ *pfkey_msg = NULL; ++ } ++} ++ ++/* Default extension builders taken from the KLIPS code */ ++ ++int ++pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext, ++ uint8_t msg_type, ++ uint8_t satype, ++ uint8_t msg_errno, ++ uint32_t seq, ++ uint32_t pid) ++{ ++ int error = 0; ++ struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_hdr_build:\n"); ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_hdr_build: " ++ "on_entry &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", ++ &pfkey_ext, ++ pfkey_ext, ++ *pfkey_ext); ++ /* sanity checks... */ ++ if(pfkey_msg) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_hdr_build: " ++ "why is pfkey_msg already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(!msg_type) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_hdr_build: " ++ "msg type not set, must be non-zero..\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(msg_type > SADB_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_hdr_build: " ++ "msg type too large:%d.\n", ++ msg_type); ++ SENDERR(EINVAL); ++ } ++ ++ if(satype > SADB_SATYPE_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_hdr_build: " ++ "satype %d > max %d\n", ++ satype, SADB_SATYPE_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_msg = (struct sadb_msg*) ++ MALLOC(sizeof(struct sadb_msg)))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_hdr_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_msg, 0, sizeof(struct sadb_msg)); ++ ++ pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; ++ ++ pfkey_msg->sadb_msg_type = msg_type; ++ pfkey_msg->sadb_msg_satype = satype; ++ ++ pfkey_msg->sadb_msg_version = PF_KEY_V2; ++ pfkey_msg->sadb_msg_errno = msg_errno; ++ pfkey_msg->sadb_msg_reserved = 0; ++ pfkey_msg->sadb_msg_seq = seq; ++ pfkey_msg->sadb_msg_pid = pid; ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_hdr_build: " ++ "on_exit &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", ++ &pfkey_ext, ++ pfkey_ext, ++ *pfkey_ext); ++errlab: ++ return error; ++} ++ ++int ++pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext, ++ uint16_t exttype, ++ uint32_t spi, ++ uint8_t replay_window, ++ uint8_t sa_state, ++ uint8_t auth, ++ uint8_t encrypt, ++ uint32_t flags, ++ uint32_t/*IPsecSAref_t*/ ref) ++{ ++ int error = 0; ++ struct sadb_sa *pfkey_sa = (struct sadb_sa *)*pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n", ++ ntohl(spi), /* in network order */ ++ replay_window, ++ sa_state, ++ auth, ++ encrypt, ++ flags); ++ /* sanity checks... */ ++ if(pfkey_sa) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "why is pfkey_sa already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(exttype != SADB_EXT_SA && ++ exttype != SADB_X_EXT_SA2) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "invalid exttype=%d.\n", ++ exttype); ++ SENDERR(EINVAL); ++ } ++ ++ if(replay_window > 64) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "replay window size: %d -- must be 0 <= size <= 64\n", ++ replay_window); ++ SENDERR(EINVAL); ++ } ++ ++ if(auth > SADB_AALG_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "auth=%d > SADB_AALG_MAX=%d.\n", ++ auth, ++ SADB_AALG_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(encrypt > SADB_EALG_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "encrypt=%d > SADB_EALG_MAX=%d.\n", ++ encrypt, ++ SADB_EALG_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(sa_state > SADB_SASTATE_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "sa_state=%d exceeds MAX=%d.\n", ++ sa_state, ++ SADB_SASTATE_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(sa_state == SADB_SASTATE_DEAD) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "sa_state=%d is DEAD=%d is not allowed.\n", ++ sa_state, ++ SADB_SASTATE_DEAD); ++ SENDERR(EINVAL); ++ } ++ ++ if((IPSEC_SAREF_NULL != ref) && (ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", ++ ref, ++ IPSEC_SAREF_NULL, ++ IPSEC_SA_REF_TABLE_NUM_ENTRIES); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_sa = (struct sadb_sa*) ++ MALLOC(sizeof(struct sadb_sa)))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sa_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_sa, 0, sizeof(struct sadb_sa)); ++ ++ pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN; ++ pfkey_sa->sadb_sa_exttype = exttype; ++ pfkey_sa->sadb_sa_spi = spi; ++ pfkey_sa->sadb_sa_replay = replay_window; ++ pfkey_sa->sadb_sa_state = sa_state; ++ pfkey_sa->sadb_sa_auth = auth; ++ pfkey_sa->sadb_sa_encrypt = encrypt; ++ pfkey_sa->sadb_sa_flags = flags; ++ pfkey_sa->sadb_x_sa_ref = ref; ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_sa_build(struct sadb_ext ** pfkey_ext, ++ uint16_t exttype, ++ uint32_t spi, ++ uint8_t replay_window, ++ uint8_t sa_state, ++ uint8_t auth, ++ uint8_t encrypt, ++ uint32_t flags) ++{ ++ return pfkey_sa_ref_build(pfkey_ext, ++ exttype, ++ spi, ++ replay_window, ++ sa_state, ++ auth, ++ encrypt, ++ flags, ++ IPSEC_SAREF_NULL); ++} ++ ++int ++pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, ++ uint16_t exttype, ++ uint32_t allocations, ++ uint64_t bytes, ++ uint64_t addtime, ++ uint64_t usetime, ++ uint32_t packets) ++{ ++ int error = 0; ++ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_lifetime_build:\n"); ++ /* sanity checks... */ ++ if(pfkey_lifetime) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_lifetime_build: " ++ "why is pfkey_lifetime already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(exttype != SADB_EXT_LIFETIME_CURRENT && ++ exttype != SADB_EXT_LIFETIME_HARD && ++ exttype != SADB_EXT_LIFETIME_SOFT) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_lifetime_build: " ++ "invalid exttype=%d.\n", ++ exttype); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_lifetime = (struct sadb_lifetime*) ++ MALLOC(sizeof(struct sadb_lifetime)))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_lifetime_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime)); ++ ++ pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN; ++ pfkey_lifetime->sadb_lifetime_exttype = exttype; ++ pfkey_lifetime->sadb_lifetime_allocations = allocations; ++ pfkey_lifetime->sadb_lifetime_bytes = bytes; ++ pfkey_lifetime->sadb_lifetime_addtime = addtime; ++ pfkey_lifetime->sadb_lifetime_usetime = usetime; ++ pfkey_lifetime->sadb_x_lifetime_packets = packets; ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_address_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint8_t proto, ++ uint8_t prefixlen, ++ struct sockaddr* address) ++{ ++ int error = 0; ++ int saddr_len = 0; ++ char ipaddr_txt[ADDRTOT_BUF + 6/*extra for port number*/]; ++ struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_address_build: " ++ "exttype=%d proto=%d prefixlen=%d\n", ++ exttype, ++ proto, ++ prefixlen); ++ /* sanity checks... */ ++ if(pfkey_address) { ++ ERROR("pfkey_address_build: " ++ "why is pfkey_address already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if (!address) { ++ ERROR("pfkey_address_build: " "address is NULL\n"); ++ SENDERR(EINVAL); ++ } ++ ++ switch(exttype) { ++ case SADB_EXT_ADDRESS_SRC: ++ case SADB_EXT_ADDRESS_DST: ++ case SADB_EXT_ADDRESS_PROXY: ++ case SADB_X_EXT_ADDRESS_DST2: ++ case SADB_X_EXT_ADDRESS_SRC_FLOW: ++ case SADB_X_EXT_ADDRESS_DST_FLOW: ++ case SADB_X_EXT_ADDRESS_SRC_MASK: ++ case SADB_X_EXT_ADDRESS_DST_MASK: ++#ifdef NAT_TRAVERSAL ++ case SADB_X_EXT_NAT_T_OA: ++#endif ++ break; ++ default: ++ ERROR("pfkey_address_build: " ++ "unrecognised ext_type=%d.\n", ++ exttype); ++ SENDERR(EINVAL); ++ } ++ ++ switch(address->sa_family) { ++ case AF_INET: ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_address_build: " ++ "found address family AF_INET.\n"); ++ saddr_len = sizeof(struct sockaddr_in); ++ sprintf(ipaddr_txt, "%d.%d.%d.%d:%d" ++ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 0) & 0xFF ++ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 8) & 0xFF ++ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 16) & 0xFF ++ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 24) & 0xFF ++ , ntohs(((struct sockaddr_in*)address)->sin_port)); ++ break; ++ case AF_INET6: ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_address_build: " ++ "found address family AF_INET6.\n"); ++ saddr_len = sizeof(struct sockaddr_in6); ++ sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x-%x" ++ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[0]) ++ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[1]) ++ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[2]) ++ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[3]) ++ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[4]) ++ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[5]) ++ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[6]) ++ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[7]) ++ , ntohs(((struct sockaddr_in6*)address)->sin6_port)); ++ break; ++ default: ++ ERROR("pfkey_address_build: " ++ "address->sa_family=%d not supported.\n", ++ address->sa_family); ++ SENDERR(EPFNOSUPPORT); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_address_build: " ++ "found address=%s.\n", ++ ipaddr_txt); ++ if(prefixlen != 0) { ++ ERROR("pfkey_address_build: " ++ "address prefixes not supported yet.\n"); ++ SENDERR(EAFNOSUPPORT); /* not supported yet */ ++ } ++ ++ /* allocate some memory for the extension */ ++ pfkey_address = (struct sadb_address*) ++ MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)); ++ *pfkey_ext = (struct sadb_ext*)pfkey_address; ++ ++ if(pfkey_address == NULL ) { ++ ERROR("pfkey_lifetime_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_address, ++ 0, ++ ALIGN_N(sizeof(struct sadb_address) + saddr_len, ++ IPSEC_PFKEYv2_ALIGN)); ++ ++ pfkey_address->sadb_address_len = DIVUP(sizeof(struct sadb_address) + saddr_len, ++ IPSEC_PFKEYv2_ALIGN); ++ ++ pfkey_address->sadb_address_exttype = exttype; ++ pfkey_address->sadb_address_proto = proto; ++ pfkey_address->sadb_address_prefixlen = prefixlen; ++ pfkey_address->sadb_address_reserved = 0; ++ ++ memcpy((char*)pfkey_address + sizeof(struct sadb_address), ++ address, ++ saddr_len); ++ ++#if 0 ++ for(i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) { ++ pfkey_address_s_ska.sin_zero[i] = 0; ++ } ++#endif ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_address_build: " ++ "successful created len: %d.\n", pfkey_address->sadb_address_len); ++ ++ errlab: ++ return error; ++} ++ ++int ++pfkey_key_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint16_t key_bits, ++ char* key) ++{ ++ int error = 0; ++ struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_key_build:\n"); ++ /* sanity checks... */ ++ if(pfkey_key) { ++ ERROR("pfkey_key_build: " ++ "why is pfkey_key already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(!key_bits) { ++ ERROR("pfkey_key_build: " ++ "key_bits is zero, it must be non-zero.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) { ++ ERROR("pfkey_key_build: " ++ "unsupported extension type=%d.\n", ++ exttype); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_key = (struct sadb_key*) ++ MALLOC(sizeof(struct sadb_key) + ++ DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN))) { ++ ERROR("pfkey_key_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_key, ++ 0, ++ sizeof(struct sadb_key) + ++ DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); ++ ++ pfkey_key->sadb_key_len = DIVUP(sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN + key_bits, ++ 64); ++ pfkey_key->sadb_key_exttype = exttype; ++ pfkey_key->sadb_key_bits = key_bits; ++ pfkey_key->sadb_key_reserved = 0; ++ memcpy((char*)pfkey_key + sizeof(struct sadb_key), ++ key, ++ DIVUP(key_bits, 8)); ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_ident_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint16_t ident_type, ++ uint64_t ident_id, ++ uint8_t ident_len, ++ char* ident_string) ++{ ++ int error = 0; ++ struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext; ++ int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_ident_build:\n"); ++ /* sanity checks... */ ++ if(pfkey_ident) { ++ ERROR("pfkey_ident_build: " ++ "why is pfkey_ident already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if( ! ((exttype == SADB_EXT_IDENTITY_SRC) || ++ (exttype == SADB_EXT_IDENTITY_DST))) { ++ ERROR("pfkey_ident_build: " ++ "unsupported extension type=%d.\n", ++ exttype); ++ SENDERR(EINVAL); ++ } ++ ++ if((ident_type == SADB_IDENTTYPE_RESERVED)) { ++ ERROR("pfkey_ident_build: " ++ "ident_type must be non-zero.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(ident_type > SADB_IDENTTYPE_MAX) { ++ ERROR("pfkey_ident_build: " ++ "identtype=%d out of range.\n", ++ ident_type); ++ SENDERR(EINVAL); ++ } ++ ++ if(((ident_type == SADB_IDENTTYPE_PREFIX) || ++ (ident_type == SADB_IDENTTYPE_FQDN)) && ++ !ident_string) { ++ ERROR("pfkey_ident_build: " ++ "string required to allocate size of extension.\n"); ++ SENDERR(EINVAL); ++ } ++ ++#if 0 ++ if((ident_type == SADB_IDENTTYPE_USERFQDN) ) { ++ } ++#endif ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_ident = (struct sadb_ident*) ++ MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN))) { ++ ERROR("pfkey_ident_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN); ++ ++ pfkey_ident->sadb_ident_len = ident_len; ++ pfkey_ident->sadb_ident_exttype = exttype; ++ pfkey_ident->sadb_ident_type = ident_type; ++ pfkey_ident->sadb_ident_reserved = 0; ++ pfkey_ident->sadb_ident_id = ident_id; ++ memcpy((char*)pfkey_ident + sizeof(struct sadb_ident), ++ ident_string, ++ data_len); ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_sens_build(struct sadb_ext** pfkey_ext, ++ uint32_t dpd, ++ uint8_t sens_level, ++ uint8_t sens_len, ++ uint64_t* sens_bitmap, ++ uint8_t integ_level, ++ uint8_t integ_len, ++ uint64_t* integ_bitmap) ++{ ++ int error = 0; ++ struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext; ++ int i; ++ uint64_t* bitmap; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sens_build:\n"); ++ /* sanity checks... */ ++ if(pfkey_sens) { ++ ERROR("pfkey_sens_build: " ++ "why is pfkey_sens already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_sens_build: " ++ "Sorry, I can't build exttype=%d yet.\n", ++ (*pfkey_ext)->sadb_ext_type); ++ SENDERR(EINVAL); /* don't process these yet */ ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_sens = (struct sadb_sens*) ++ MALLOC(sizeof(struct sadb_sens) + ++ (sens_len + integ_len) * sizeof(uint64_t)))) { ++ ERROR("pfkey_sens_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_sens, ++ 0, ++ sizeof(struct sadb_sens) + ++ (sens_len + integ_len) * sizeof(uint64_t)); ++ ++ pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) + ++ (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN; ++ pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY; ++ pfkey_sens->sadb_sens_dpd = dpd; ++ pfkey_sens->sadb_sens_sens_level = sens_level; ++ pfkey_sens->sadb_sens_sens_len = sens_len; ++ pfkey_sens->sadb_sens_integ_level = integ_level; ++ pfkey_sens->sadb_sens_integ_len = integ_len; ++ pfkey_sens->sadb_sens_reserved = 0; ++ ++ bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens)); ++ for(i = 0; i < sens_len; i++) { ++ *bitmap = sens_bitmap[i]; ++ bitmap++; ++ } ++ for(i = 0; i < integ_len; i++) { ++ *bitmap = integ_bitmap[i]; ++ bitmap++; ++ } ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_prop_build(struct sadb_ext** pfkey_ext, ++ uint8_t replay, ++ unsigned int comb_num, ++ struct sadb_comb* comb) ++{ ++ int error = 0; ++ int i; ++ struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext; ++ struct sadb_comb *combp; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_prop_build:\n"); ++ /* sanity checks... */ ++ if(pfkey_prop) { ++ ERROR("pfkey_prop_build: " ++ "why is pfkey_prop already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_prop = (struct sadb_prop*) ++ MALLOC(sizeof(struct sadb_prop) + ++ comb_num * sizeof(struct sadb_comb)))) { ++ ERROR("pfkey_prop_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_prop, ++ 0, ++ sizeof(struct sadb_prop) + ++ comb_num * sizeof(struct sadb_comb)); ++ ++ pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) + ++ comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN; ++ ++ pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; ++ pfkey_prop->sadb_prop_replay = replay; ++ ++ for(i=0; i<3; i++) { ++ pfkey_prop->sadb_prop_reserved[i] = 0; ++ } ++ ++ combp = (struct sadb_comb*)((char*)*pfkey_ext + sizeof(struct sadb_prop)); ++ for(i = 0; i < comb_num; i++) { ++ memcpy (combp, &(comb[i]), sizeof(struct sadb_comb)); ++ combp++; ++ } ++ ++#if 0 ++ uint8_t sadb_comb_auth; ++ uint8_t sadb_comb_encrypt; ++ uint16_t sadb_comb_flags; ++ uint16_t sadb_comb_auth_minbits; ++ uint16_t sadb_comb_auth_maxbits; ++ uint16_t sadb_comb_encrypt_minbits; ++ uint16_t sadb_comb_encrypt_maxbits; ++ uint32_t sadb_comb_reserved; ++ uint32_t sadb_comb_soft_allocations; ++ uint32_t sadb_comb_hard_allocations; ++ uint64_t sadb_comb_soft_bytes; ++ uint64_t sadb_comb_hard_bytes; ++ uint64_t sadb_comb_soft_addtime; ++ uint64_t sadb_comb_hard_addtime; ++ uint64_t sadb_comb_soft_usetime; ++ uint64_t sadb_comb_hard_usetime; ++ uint32_t sadb_comb_soft_packets; ++ uint32_t sadb_comb_hard_packets; ++#endif ++errlab: ++ return error; ++} ++ ++int ++pfkey_supported_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ unsigned int alg_num, ++ struct sadb_alg* alg) ++{ ++ int error = 0; ++ unsigned int i; ++ struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext; ++ struct sadb_alg *pfkey_alg; ++ ++ /* sanity checks... */ ++ if(pfkey_supported) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_supported_build: " ++ "why is pfkey_supported already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_supported_build: " ++ "unsupported extension type=%d.\n", ++ exttype); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_supported = (struct sadb_supported*) ++ MALLOC(sizeof(struct sadb_supported) + ++ alg_num * ++ sizeof(struct sadb_alg)))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_supported_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_supported, ++ 0, ++ sizeof(struct sadb_supported) + ++ alg_num * ++ sizeof(struct sadb_alg)); ++ ++ pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) + ++ alg_num * ++ sizeof(struct sadb_alg)) / ++ IPSEC_PFKEYv2_ALIGN; ++ pfkey_supported->sadb_supported_exttype = exttype; ++ pfkey_supported->sadb_supported_reserved = 0; ++ ++ pfkey_alg = (struct sadb_alg*)((char*)pfkey_supported + sizeof(struct sadb_supported)); ++ for(i = 0; i < alg_num; i++) { ++ memcpy (pfkey_alg, &(alg[i]), sizeof(struct sadb_alg)); ++ pfkey_alg->sadb_alg_reserved = 0; ++ pfkey_alg++; ++ } ++ ++#if 0 ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_supported_build: " ++ "Sorry, I can't build exttype=%d yet.\n", ++ (*pfkey_ext)->sadb_ext_type); ++ SENDERR(EINVAL); /* don't process these yet */ ++ ++ uint8_t sadb_alg_id; ++ uint8_t sadb_alg_ivlen; ++ uint16_t sadb_alg_minbits; ++ uint16_t sadb_alg_maxbits; ++ uint16_t sadb_alg_reserved; ++#endif ++errlab: ++ return error; ++} ++ ++int ++pfkey_spirange_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint32_t min, /* in network order */ ++ uint32_t max) /* in network order */ ++{ ++ int error = 0; ++ struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext; ++ ++ /* sanity checks... */ ++ if(pfkey_spirange) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_spirange_build: " ++ "why is pfkey_spirange already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(ntohl(max) < ntohl(min)) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_spirange_build: " ++ "minspi=%08x must be < maxspi=%08x.\n", ++ ntohl(min), ++ ntohl(max)); ++ SENDERR(EINVAL); ++ } ++ ++ if(ntohl(min) <= 255) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_spirange_build: " ++ "minspi=%08x must be > 255.\n", ++ ntohl(min)); ++ SENDERR(EEXIST); ++ } ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_spirange = (struct sadb_spirange*) ++ MALLOC(sizeof(struct sadb_spirange)))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_spirange_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_spirange, ++ 0, ++ sizeof(struct sadb_spirange)); ++ ++ pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN; ++ ++ pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE; ++ pfkey_spirange->sadb_spirange_min = min; ++ pfkey_spirange->sadb_spirange_max = max; ++ pfkey_spirange->sadb_spirange_reserved = 0; ++ errlab: ++ return error; ++} ++ ++int ++pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext) ++{ ++ int error = 0; ++ struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext; ++ ++ /* sanity checks... */ ++ if(pfkey_x_kmprivate) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_kmprivate_build: " ++ "why is pfkey_x_kmprivate already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_kmprivate_build: " ++ "Sorry, I can't build exttype=%d yet.\n", ++ (*pfkey_ext)->sadb_ext_type); ++ SENDERR(EINVAL); /* don't process these yet */ ++ ++ if(!(*pfkey_ext = (struct sadb_ext*) ++ pfkey_x_kmprivate = (struct sadb_x_kmprivate*) ++ MALLOC(sizeof(struct sadb_x_kmprivate)))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_kmprivate_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_x_kmprivate, ++ 0, ++ sizeof(struct sadb_x_kmprivate)); ++ ++ pfkey_x_kmprivate->sadb_x_kmprivate_len = ++ sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN; ++ ++ pfkey_x_kmprivate->sadb_x_kmprivate_exttype = SADB_X_EXT_KMPRIVATE; ++ pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; ++errlab: ++ return error; ++} ++ ++int ++pfkey_x_satype_build(struct sadb_ext** pfkey_ext, ++ uint8_t satype) ++{ ++ int error = 0; ++ int i; ++ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_satype_build:\n"); ++ /* sanity checks... */ ++ if(pfkey_x_satype) { ++ ERROR("pfkey_x_satype_build: " ++ "why is pfkey_x_satype already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(!satype) { ++ ERROR("pfkey_x_satype_build: " ++ "SA type not set, must be non-zero.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(satype > SADB_SATYPE_MAX) { ++ ERROR("pfkey_x_satype_build: " ++ "satype %d > max %d\n", ++ satype, SADB_SATYPE_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_satype = (struct sadb_x_satype*) ++ MALLOC(sizeof(struct sadb_x_satype)))) { ++ ERROR("pfkey_x_satype_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ memset(pfkey_x_satype, ++ 0, ++ sizeof(struct sadb_x_satype)); ++ ++ pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN; ++ ++ pfkey_x_satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2; ++ pfkey_x_satype->sadb_x_satype_satype = satype; ++ for(i=0; i<3; i++) { ++ pfkey_x_satype->sadb_x_satype_reserved[i] = 0; ++ } ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_x_debug_build(struct sadb_ext** pfkey_ext, ++ uint32_t tunnel, ++ uint32_t netlink, ++ uint32_t xform, ++ uint32_t eroute, ++ uint32_t spi, ++ uint32_t radij, ++ uint32_t esp, ++ uint32_t ah, ++ uint32_t rcv, ++ uint32_t pfkey, ++ uint32_t ipcomp, ++ uint32_t verbose) ++{ ++ int error = 0; ++ int i; ++ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_debug_build:\n"); ++ /* sanity checks... */ ++ if(pfkey_x_debug) { ++ ERROR("pfkey_x_debug_build: " ++ "why is pfkey_x_debug already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_debug_build: " ++ "tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n", ++ tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose); ++ ++ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_debug = (struct sadb_x_debug*) ++ MALLOC(sizeof(struct sadb_x_debug)))) { ++ ERROR("pfkey_x_debug_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++#if 0 ++ memset(pfkey_x_debug, ++ 0, ++ sizeof(struct sadb_x_debug)); ++#endif ++ ++ pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN; ++ pfkey_x_debug->sadb_x_debug_exttype = SADB_X_EXT_DEBUG; ++ ++ pfkey_x_debug->sadb_x_debug_tunnel = tunnel; ++ pfkey_x_debug->sadb_x_debug_netlink = netlink; ++ pfkey_x_debug->sadb_x_debug_xform = xform; ++ pfkey_x_debug->sadb_x_debug_eroute = eroute; ++ pfkey_x_debug->sadb_x_debug_spi = spi; ++ pfkey_x_debug->sadb_x_debug_radij = radij; ++ pfkey_x_debug->sadb_x_debug_esp = esp; ++ pfkey_x_debug->sadb_x_debug_ah = ah; ++ pfkey_x_debug->sadb_x_debug_rcv = rcv; ++ pfkey_x_debug->sadb_x_debug_pfkey = pfkey; ++ pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp; ++ pfkey_x_debug->sadb_x_debug_verbose = verbose; ++ ++ for(i=0; i<4; i++) { ++ pfkey_x_debug->sadb_x_debug_reserved[i] = 0; ++ } ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext, ++ uint8_t type) ++{ ++ int error = 0; ++ int i; ++ struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_nat_t_type_build:\n"); ++ /* sanity checks... */ ++ if(pfkey_x_nat_t_type) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_nat_t_type_build: " ++ "why is pfkey_x_nat_t_type already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_nat_t_type_build: " ++ "type=%d\n", type); ++ ++ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*) ++ MALLOC(sizeof(struct sadb_x_nat_t_type)))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_nat_t_type_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ ++ pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN; ++ pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE; ++ pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type; ++ for(i=0; i<3; i++) { ++ pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0; ++ } ++ ++errlab: ++ return error; ++} ++int ++pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext, ++ uint16_t exttype, ++ uint16_t port) ++{ ++ int error = 0; ++ struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_nat_t_port_build:\n"); ++ /* sanity checks... */ ++ if(pfkey_x_nat_t_port) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_nat_t_port_build: " ++ "why is pfkey_x_nat_t_port already pointing to something?\n"); ++ SENDERR(EINVAL); ++ } ++ ++ switch(exttype) { ++ case SADB_X_EXT_NAT_T_SPORT: ++ case SADB_X_EXT_NAT_T_DPORT: ++ break; ++ default: ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_nat_t_port_build: " ++ "unrecognised ext_type=%d.\n", ++ exttype); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_nat_t_port_build: " ++ "ext=%d, port=%d\n", exttype, port); ++ ++ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*) ++ MALLOC(sizeof(struct sadb_x_nat_t_port)))) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_x_nat_t_port_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ ++ pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN; ++ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype; ++ pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port; ++ pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0; ++ ++errlab: ++ return error; ++} ++ ++int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext, ++ uint8_t protocol) ++{ ++ int error = 0; ++ struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext; ++ DEBUGGING(PF_KEY_DEBUG_BUILD,"pfkey_x_protocol_build: protocol=%u\n", protocol); ++ /* sanity checks... */ ++ if (p != 0) { ++ ERROR("pfkey_x_protocol_build: bogus protocol pointer\n"); ++ SENDERR(EINVAL); ++ } ++ if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) { ++ ERROR("pfkey_build: memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ *pfkey_ext = (struct sadb_ext *)p; ++ p->sadb_protocol_len = sizeof(*p) / sizeof(uint64_t); ++ p->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; ++ p->sadb_protocol_proto = protocol; ++ p->sadb_protocol_flags = 0; ++ p->sadb_protocol_reserved2 = 0; ++ errlab: ++ return error; ++} ++ ++ ++#if I_DONT_THINK_THIS_WILL_BE_USEFUL ++int (*ext_default_builders[SADB_EXT_MAX +1])(struct sadb_msg*, struct sadb_ext*) ++ = ++{ ++ NULL, /* pfkey_msg_build, */ ++ pfkey_sa_build, ++ pfkey_lifetime_build, ++ pfkey_lifetime_build, ++ pfkey_lifetime_build, ++ pfkey_address_build, ++ pfkey_address_build, ++ pfkey_address_build, ++ pfkey_key_build, ++ pfkey_key_build, ++ pfkey_ident_build, ++ pfkey_ident_build, ++ pfkey_sens_build, ++ pfkey_prop_build, ++ pfkey_supported_build, ++ pfkey_supported_build, ++ pfkey_spirange_build, ++ pfkey_x_kmprivate_build, ++ pfkey_x_satype_build, ++ pfkey_sa_build, ++ pfkey_address_build, ++ pfkey_address_build, ++ pfkey_address_build, ++ pfkey_address_build, ++ pfkey_address_build, ++ pfkey_x_ext_debug_build ++}; ++#endif ++ ++int ++pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir) ++{ ++ int error = 0; ++ unsigned ext; ++ unsigned total_size; ++ struct sadb_ext *pfkey_ext; ++ int extensions_seen = 0; ++#ifndef __KERNEL__ ++ struct sadb_ext *extensions_check[SADB_EXT_MAX + 1]; ++#endif ++ ++ if(!extensions[0]) { ++ ERROR("pfkey_msg_build: " ++ "extensions[0] must be specified (struct sadb_msg).\n"); ++ SENDERR(EINVAL); ++ } ++ ++ /* figure out the total size for all the requested extensions */ ++ total_size = IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg)); ++ for(ext = 1; ext <= SADB_EXT_MAX; ext++) { ++ if(extensions[ext]) { ++ total_size += (extensions[ext])->sadb_ext_len; ++ } ++ } ++ ++ /* allocate that much space */ ++ *pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN); ++ if(*pfkey_msg == NULL) { ++ ERROR("pfkey_msg_build: " ++ "memory allocation failed\n"); ++ SENDERR(ENOMEM); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_build: " ++ "pfkey_msg=0p%p allocated %lu bytes, &(extensions[0])=0p%p\n", ++ *pfkey_msg, ++ (unsigned long)(total_size * IPSEC_PFKEYv2_ALIGN), ++ &(extensions[0])); ++ ++ memcpy(*pfkey_msg, ++ extensions[0], ++ sizeof(struct sadb_msg)); ++ (*pfkey_msg)->sadb_msg_len = total_size; ++ (*pfkey_msg)->sadb_msg_reserved = 0; ++ extensions_seen = 1 ; ++ ++ /* ++ * point pfkey_ext to immediately after the space for the header, ++ * i.e. at the first extension location. ++ */ ++ pfkey_ext = (struct sadb_ext*)(((char*)(*pfkey_msg)) + sizeof(struct sadb_msg)); ++ ++ for(ext = 1; ext <= SADB_EXT_MAX; ext++) { ++ /* copy from extension[ext] to buffer */ ++ if(extensions[ext]) { ++ /* Is this type of extension permitted for this type of message? */ ++ if(!(extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type] & ++ 1<<ext)) { ++ ERROR("pfkey_msg_build: " ++ "ext type %d not permitted, exts_perm=%08x, 1<<type=%08x\n", ++ ext, ++ extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type], ++ 1<<ext); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_build: " ++ "copying %lu bytes from extensions[%u] (type=%d)\n", ++ (unsigned long)(extensions[ext]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN), ++ ext, ++ extensions[ext]->sadb_ext_type); ++ ++ memcpy(pfkey_ext, ++ extensions[ext], ++ (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); ++ ((char*)pfkey_ext) += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN; ++ /* Mark that we have seen this extension and remember the header location */ ++ extensions_seen |= ( 1 << ext ); ++ } ++ } ++ ++ /* check required extensions */ ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_build: " ++ "extensions permitted=%08x, seen=%08x, required=%08x.\n", ++ extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type], ++ extensions_seen, ++ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]); ++ ++ if((extensions_seen & ++ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) != ++ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) { ++ DEBUGGING(PF_KEY_DEBUG_BUILD, ++ "pfkey_msg_build: " ++ "required extensions missing:%08x.\n", ++ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type] - ++ (extensions_seen & ++ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) ); ++ SENDERR(EINVAL); ++ } ++ ++#ifndef __KERNEL__ ++/* ++ * this is silly, there is no need to reparse the message that we just built. ++ * ++ */ ++ if((error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir))) { ++ ERROR( ++ "pfkey_msg_build: " ++ "Trouble parsing newly built pfkey message, error=%d.\n", ++ error); ++ SENDERR(-error); ++ } ++#endif ++ ++errlab: ++ ++ return error; ++} ++ ++/* ++ * $Log: pfkey_v2_build.c,v $ ++ * Revision 1.49 2004/04/12 02:59:06 mcr ++ * erroneously moved pfkey_v2_build.c ++ * ++ * Revision 1.48 2004/04/09 18:00:40 mcr ++ * Moved from linux/lib/libfreeswan/pfkey_v2_build.c,v ++ * ++ * Revision 1.47 2004/03/08 01:59:08 ken ++ * freeswan.h -> openswan.h ++ * ++ * Revision 1.46 2003/12/10 01:20:19 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.45 2003/12/04 23:01:12 mcr ++ * removed ipsec_netlink.h ++ * ++ * Revision 1.44 2003/10/31 02:27:12 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.43.4.2 2003/10/29 01:11:32 mcr ++ * added debugging for pfkey library. ++ * ++ * Revision 1.43.4.1 2003/09/21 13:59:44 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.43 2003/05/07 17:29:17 mcr ++ * new function pfkey_debug_func added for us in debugging from ++ * pfkey library. ++ * ++ * Revision 1.42 2003/01/30 02:32:09 rgb ++ * ++ * Rename SAref table macro names for clarity. ++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. ++ * ++ * Revision 1.41 2002/12/13 18:16:02 mcr ++ * restored sa_ref code ++ * ++ * Revision 1.40 2002/12/13 18:06:52 mcr ++ * temporarily removed sadb_x_sa_ref reference for 2.xx ++ * ++ * Revision 1.39 2002/12/13 17:43:28 mcr ++ * commented out access to sadb_x_sa_ref for 2.xx branch ++ * ++ * Revision 1.38 2002/10/09 03:12:05 dhr ++ * ++ * [kenb+dhr] 64-bit fixes ++ * ++ * Revision 1.37 2002/09/20 15:40:39 rgb ++ * Added new function pfkey_sa_ref_build() to accomodate saref parameter. ++ * ++ * Revision 1.36 2002/09/20 05:01:22 rgb ++ * Generalise for platform independance: fix (ia64) using unsigned for sizes. ++ * ++ * Revision 1.35 2002/07/24 18:44:54 rgb ++ * Type fiddling to tame ia64 compiler. ++ * ++ * Revision 1.34 2002/05/23 07:14:11 rgb ++ * Cleaned up %p variants to 0p%p for test suite cleanup. ++ * ++ * Revision 1.33 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.32 2002/04/24 07:36:40 mcr ++ * Moved from ./lib/pfkey_v2_build.c,v ++ * ++ * Revision 1.31 2002/01/29 22:25:35 rgb ++ * Re-add ipsec_kversion.h to keep MALLOC happy. ++ * ++ * Revision 1.30 2002/01/29 01:59:09 mcr ++ * removal of kversions.h - sources that needed it now use ipsec_param.h. ++ * updating of IPv6 structures to match latest in6.h version. ++ * removed dead code from openswan.h that also duplicated kversions.h ++ * code. ++ * ++ * Revision 1.29 2001/12/19 21:06:09 rgb ++ * Added port numbers to pfkey_address_build() debugging. ++ * ++ * Revision 1.28 2001/11/06 19:47:47 rgb ++ * Added packet parameter to lifetime and comb structures. ++ * ++ * Revision 1.27 2001/10/18 04:45:24 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/openswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.26 2001/09/08 21:13:34 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.25 2001/06/14 19:35:16 rgb ++ * Update copyright date. ++ * ++ * Revision 1.24 2001/03/20 03:49:45 rgb ++ * Ditch superfluous debug_pfkey declaration. ++ * Move misplaced openswan.h inclusion for kernel case. ++ * ++ * Revision 1.23 2001/03/16 07:41:50 rgb ++ * Put openswan.h include before pluto includes. ++ * ++ * Revision 1.22 2001/02/27 22:24:56 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.21 2000/11/17 18:10:30 rgb ++ * Fixed bugs mostly relating to spirange, to treat all spi variables as ++ * network byte order since this is the way PF_KEYv2 stored spis. ++ * ++ * Revision 1.20 2000/10/12 00:02:39 rgb ++ * Removed 'format, ##' nonsense from debug macros for RH7.0. ++ * ++ * Revision 1.19 2000/10/10 20:10:20 rgb ++ * Added support for debug_ipcomp and debug_verbose to klipsdebug. ++ * ++ * Revision 1.18 2000/09/12 18:59:54 rgb ++ * Added Gerhard's IPv6 support to pfkey parts of libopenswan. ++ * ++ * Revision 1.17 2000/09/12 03:27:00 rgb ++ * Moved DEBUGGING definition to compile kernel with debug off. ++ * ++ * Revision 1.16 2000/09/08 19:22:12 rgb ++ * Fixed pfkey_prop_build() parameter to be only single indirection. ++ * Fixed struct alg copy. ++ * ++ * Revision 1.15 2000/08/20 21:40:01 rgb ++ * Added an address parameter sanity check to pfkey_address_build(). ++ * ++ * Revision 1.14 2000/08/15 17:29:23 rgb ++ * Fixes from SZI to untested pfkey_prop_build(). ++ * ++ * Revision 1.13 2000/06/02 22:54:14 rgb ++ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support. ++ * ++ * Revision 1.12 2000/05/10 19:24:01 rgb ++ * Fleshed out sensitivity, proposal and supported extensions. ++ * ++ * Revision 1.11 2000/03/16 14:07:23 rgb ++ * Renamed ALIGN macro to avoid fighting with others in kernel. ++ * ++ * Revision 1.10 2000/01/24 21:14:35 rgb ++ * Added disabled pluto pfkey lib debug flag. ++ * ++ * Revision 1.9 2000/01/21 06:27:32 rgb ++ * Added address cases for eroute flows. ++ * Removed unused code. ++ * Dropped unused argument to pfkey_x_satype_build(). ++ * Indented compiler directives for readability. ++ * Added klipsdebug switching capability. ++ * Fixed SADB_EXT_MAX bug not permitting last extension access. ++ * ++ * Revision 1.8 1999/12/29 21:17:41 rgb ++ * Changed pfkey_msg_build() I/F to include a struct sadb_msg** ++ * parameter for cleaner manipulation of extensions[] and to guard ++ * against potential memory leaks. ++ * Changed the I/F to pfkey_msg_free() for the same reason. ++ * ++ * Revision 1.7 1999/12/09 23:12:20 rgb ++ * Removed unused cruft. ++ * Added argument to pfkey_sa_build() to do eroutes. ++ * Fixed exttype check in as yet unused pfkey_lifetime_build(). ++ * ++ * Revision 1.6 1999/12/07 19:54:29 rgb ++ * Removed static pluto debug flag. ++ * Added functions for pfkey message and extensions initialisation ++ * and cleanup. ++ * ++ * Revision 1.5 1999/12/01 22:20:06 rgb ++ * Changed pfkey_sa_build to accept an SPI in network byte order. ++ * Added <string.h> to quiet userspace compiler. ++ * Moved pfkey_lib_debug variable into the library. ++ * Removed SATYPE check from pfkey_msg_hdr_build so FLUSH will work. ++ * Added extension assembly debugging. ++ * Isolated assignment with brackets to be sure of scope. ++ * ++ * Revision 1.4 1999/11/27 11:57:35 rgb ++ * Added ipv6 headers. ++ * Remove over-zealous algorithm sanity checkers from pfkey_sa_build. ++ * Debugging error messages added. ++ * Fixed missing auth and encrypt assignment bug. ++ * Add argument to pfkey_msg_parse() for direction. ++ * Move parse-after-build check inside pfkey_msg_build(). ++ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. ++ * Add CVS log entry to bottom of file. ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/pfkey_v2_debug.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,176 @@ ++/* ++ * @(#) pfkey version 2 debugging messages ++ * ++ * Copyright (C) 2001 Richard Guy Briggs <rgb@openswan.org> ++ * and Michael Richardson <mcr@openswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: pfkey_v2_debug.c,v 1.9 2004/03/08 01:59:08 ken Exp $ ++ * ++ */ ++ ++#ifdef __KERNEL__ ++ ++# include <linux/kernel.h> /* for printk */ ++ ++# include "openswan/ipsec_kversion.h" /* for malloc switch */ ++# ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++# else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++# endif /* MALLOC_SLAB */ ++# include <linux/errno.h> /* error codes */ ++# include <linux/types.h> /* size_t */ ++# include <linux/interrupt.h> /* mark_bh */ ++ ++# include <linux/netdevice.h> /* struct device, and other headers */ ++# include <linux/etherdevice.h> /* eth_type_trans */ ++extern int debug_pfkey; ++ ++#else /* __KERNEL__ */ ++ ++# include <sys/types.h> ++# include <linux/types.h> ++# include <linux/errno.h> ++ ++#endif /* __KERNEL__ */ ++ ++#include "openswan.h" ++#include "pfkeyv2.h" ++#include "pfkey.h" ++ ++/* ++ * This file provides ASCII translations of PF_KEY magic numbers. ++ * ++ */ ++ ++static char *pfkey_sadb_ext_strings[]={ ++ "reserved", /* SADB_EXT_RESERVED 0 */ ++ "security-association", /* SADB_EXT_SA 1 */ ++ "lifetime-current", /* SADB_EXT_LIFETIME_CURRENT 2 */ ++ "lifetime-hard", /* SADB_EXT_LIFETIME_HARD 3 */ ++ "lifetime-soft", /* SADB_EXT_LIFETIME_SOFT 4 */ ++ "source-address", /* SADB_EXT_ADDRESS_SRC 5 */ ++ "destination-address", /* SADB_EXT_ADDRESS_DST 6 */ ++ "proxy-address", /* SADB_EXT_ADDRESS_PROXY 7 */ ++ "authentication-key", /* SADB_EXT_KEY_AUTH 8 */ ++ "cipher-key", /* SADB_EXT_KEY_ENCRYPT 9 */ ++ "source-identity", /* SADB_EXT_IDENTITY_SRC 10 */ ++ "destination-identity", /* SADB_EXT_IDENTITY_DST 11 */ ++ "sensitivity-label", /* SADB_EXT_SENSITIVITY 12 */ ++ "proposal", /* SADB_EXT_PROPOSAL 13 */ ++ "supported-auth", /* SADB_EXT_SUPPORTED_AUTH 14 */ ++ "supported-cipher", /* SADB_EXT_SUPPORTED_ENCRYPT 15 */ ++ "spi-range", /* SADB_EXT_SPIRANGE 16 */ ++ "X-kmpprivate", /* SADB_X_EXT_KMPRIVATE 17 */ ++ "X-satype2", /* SADB_X_EXT_SATYPE2 18 */ ++ "X-security-association", /* SADB_X_EXT_SA2 19 */ ++ "X-destination-address2", /* SADB_X_EXT_ADDRESS_DST2 20 */ ++ "X-source-flow-address", /* SADB_X_EXT_ADDRESS_SRC_FLOW 21 */ ++ "X-dest-flow-address", /* SADB_X_EXT_ADDRESS_DST_FLOW 22 */ ++ "X-source-mask", /* SADB_X_EXT_ADDRESS_SRC_MASK 23 */ ++ "X-dest-mask", /* SADB_X_EXT_ADDRESS_DST_MASK 24 */ ++ "X-set-debug", /* SADB_X_EXT_DEBUG 25 */ ++#ifdef NAT_TRAVERSAL ++ "X-NAT-T-type", /* SADB_X_EXT_NAT_T_TYPE 26 */ ++ "X-NAT-T-sport", /* SADB_X_EXT_NAT_T_SPORT 27 */ ++ "X-NAT-T-dport", /* SADB_X_EXT_NAT_T_DPORT 28 */ ++ "X-NAT-T-OA", /* SADB_X_EXT_NAT_T_OA 29 */ ++#endif ++}; ++ ++const char * ++pfkey_v2_sadb_ext_string(int ext) ++{ ++ if(ext <= SADB_EXT_MAX) { ++ return pfkey_sadb_ext_strings[ext]; ++ } else { ++ return "unknown-ext"; ++ } ++} ++ ++ ++static char *pfkey_sadb_type_strings[]={ ++ "reserved", /* SADB_RESERVED */ ++ "getspi", /* SADB_GETSPI */ ++ "update", /* SADB_UPDATE */ ++ "add", /* SADB_ADD */ ++ "delete", /* SADB_DELETE */ ++ "get", /* SADB_GET */ ++ "acquire", /* SADB_ACQUIRE */ ++ "register", /* SADB_REGISTER */ ++ "expire", /* SADB_EXPIRE */ ++ "flush", /* SADB_FLUSH */ ++ "dump", /* SADB_DUMP */ ++ "x-promisc", /* SADB_X_PROMISC */ ++ "x-pchange", /* SADB_X_PCHANGE */ ++ "x-groupsa", /* SADB_X_GRPSA */ ++ "x-addflow(eroute)", /* SADB_X_ADDFLOW */ ++ "x-delflow(eroute)", /* SADB_X_DELFLOW */ ++ "x-debug", /* SADB_X_DEBUG */ ++}; ++ ++const char * ++pfkey_v2_sadb_type_string(int sadb_type) ++{ ++ if(sadb_type <= SADB_MAX) { ++ return pfkey_sadb_type_strings[sadb_type]; ++ } else { ++ return "unknown-sadb-type"; ++ } ++} ++ ++ ++ ++ ++/* ++ * $Log: pfkey_v2_debug.c,v $ ++ * Revision 1.9 2004/03/08 01:59:08 ken ++ * freeswan.h -> openswan.h ++ * ++ * Revision 1.8 2003/12/10 01:20:19 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.7 2002/09/20 05:01:26 rgb ++ * Fixed limit inclusion error in both type and ext string conversion. ++ * ++ * Revision 1.6 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.5 2002/04/24 07:36:40 mcr ++ * Moved from ./lib/pfkey_v2_debug.c,v ++ * ++ * Revision 1.4 2002/01/29 22:25:36 rgb ++ * Re-add ipsec_kversion.h to keep MALLOC happy. ++ * ++ * Revision 1.3 2002/01/29 01:59:09 mcr ++ * removal of kversions.h - sources that needed it now use ipsec_param.h. ++ * updating of IPv6 structures to match latest in6.h version. ++ * removed dead code from openswan.h that also duplicated kversions.h ++ * code. ++ * ++ * Revision 1.2 2002/01/20 20:34:50 mcr ++ * added pfkey_v2_sadb_type_string to decode sadb_type to string. ++ * ++ * Revision 1.1 2001/11/27 05:30:06 mcr ++ * initial set of debug strings for pfkey debugging. ++ * this will eventually only be included for debug builds. ++ * ++ * Revision 1.1 2001/09/21 04:12:03 mcr ++ * first compilable version. ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/pfkey_v2_ext_bits.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,808 @@ ++/* ++ * RFC2367 PF_KEYv2 Key management API message parser ++ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: pfkey_v2_ext_bits.c,v 1.20 2004/03/08 01:59:08 ken Exp $ ++ */ ++ ++/* ++ * Template from klips/net/ipsec/ipsec/ipsec_parse.c. ++ */ ++ ++char pfkey_v2_ext_bits_c_version[] = "$Id: pfkey_v2_ext_bits.c,v 1.20 2004/03/08 01:59:08 ken Exp $"; ++ ++/* ++ * Some ugly stuff to allow consistent debugging code for use in the ++ * kernel and in user space ++*/ ++ ++#ifdef __KERNEL__ ++ ++# include <linux/kernel.h> /* for printk */ ++ ++# include "openswan/ipsec_kversion.h" /* for malloc switch */ ++# ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++# else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++# endif /* MALLOC_SLAB */ ++# include <linux/errno.h> /* error codes */ ++# include <linux/types.h> /* size_t */ ++# include <linux/interrupt.h> /* mark_bh */ ++ ++# include <linux/netdevice.h> /* struct device, and other headers */ ++# include <linux/etherdevice.h> /* eth_type_trans */ ++# include <linux/ip.h> /* struct iphdr */ ++# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++# include <linux/ipv6.h> ++# endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ ++ ++#else /* __KERNEL__ */ ++ ++# include <sys/types.h> ++# include <linux/types.h> ++# include <linux/errno.h> ++#endif ++ ++#include <openswan.h> ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/] = { ++ ++/* INBOUND EXTENSIONS */ ++{ ++ ++/* PERMITTED IN */ ++{ ++/* SADB_RESERVED */ ++0 ++, ++/* SADB_GETSPI */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_SPIRANGE ++, ++/* SADB_UPDATE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++, ++/* SADB_ADD */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_X_EXT_NAT_T_TYPE ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++| 1<<SADB_X_EXT_NAT_T_OA ++, ++/* SADB_DELETE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_GET */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_ACQUIRE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++, ++/* SADB_REGISTER */ ++1<<SADB_EXT_RESERVED ++, ++/* SADB_EXPIRE */ ++0 ++, ++/* SADB_FLUSH */ ++1<<SADB_EXT_RESERVED ++, ++/* SADB_DUMP */ ++1<<SADB_EXT_RESERVED ++, ++/* SADB_X_PROMISC */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++| 1<<SADB_EXT_SUPPORTED_AUTH ++| 1<<SADB_EXT_SUPPORTED_ENCRYPT ++| 1<<SADB_EXT_SPIRANGE ++| 1<<SADB_X_EXT_KMPRIVATE ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_PCHANGE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++| 1<<SADB_EXT_SUPPORTED_AUTH ++| 1<<SADB_EXT_SUPPORTED_ENCRYPT ++| 1<<SADB_EXT_SPIRANGE ++| 1<<SADB_X_EXT_KMPRIVATE ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_GRPSA */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_ADDFLOW */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW ++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW ++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK ++| 1<<SADB_X_EXT_ADDRESS_DST_MASK ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_X_EXT_PROTOCOL ++, ++/* SADB_X_DELFLOW */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW ++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW ++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK ++| 1<<SADB_X_EXT_ADDRESS_DST_MASK ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_X_EXT_PROTOCOL ++, ++/* SADB_X_DEBUG */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_X_EXT_DEBUG ++, ++/* SADB_X_NAT_T_NEW_MAPPING */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++}, ++ ++/* REQUIRED IN */ ++{ ++/* SADB_RESERVED */ ++0 ++, ++/* SADB_GETSPI */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_SPIRANGE ++, ++/* SADB_UPDATE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++/*| 1<<SADB_EXT_KEY_AUTH*/ ++/*| 1<<SADB_EXT_KEY_ENCRYPT*/ ++, ++/* SADB_ADD */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++/*| 1<<SADB_EXT_KEY_AUTH*/ ++/*| 1<<SADB_EXT_KEY_ENCRYPT*/ ++, ++/* SADB_DELETE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_GET */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_ACQUIRE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_PROPOSAL ++, ++/* SADB_REGISTER */ ++1<<SADB_EXT_RESERVED ++, ++/* SADB_EXPIRE */ ++0 ++, ++/* SADB_FLUSH */ ++1<<SADB_EXT_RESERVED ++, ++/* SADB_DUMP */ ++1<<SADB_EXT_RESERVED ++, ++/* SADB_X_PROMISC */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++| 1<<SADB_EXT_SUPPORTED_AUTH ++| 1<<SADB_EXT_SUPPORTED_ENCRYPT ++| 1<<SADB_EXT_SPIRANGE ++| 1<<SADB_X_EXT_KMPRIVATE ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_PCHANGE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++| 1<<SADB_EXT_SUPPORTED_AUTH ++| 1<<SADB_EXT_SUPPORTED_ENCRYPT ++| 1<<SADB_EXT_SPIRANGE ++| 1<<SADB_X_EXT_KMPRIVATE ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_GRPSA */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_DST ++/*| 1<<SADB_X_EXT_SATYPE2*/ ++/*| 1<<SADB_X_EXT_SA2*/ ++/*| 1<<SADB_X_EXT_ADDRESS_DST2*/ ++, ++/* SADB_X_ADDFLOW */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW ++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW ++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK ++| 1<<SADB_X_EXT_ADDRESS_DST_MASK ++, ++/* SADB_X_DELFLOW */ ++1<<SADB_EXT_RESERVED ++/*| 1<<SADB_EXT_SA*/ ++#if 0 /* SADB_X_CLREROUTE doesn't need all these... */ ++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW ++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW ++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK ++| 1<<SADB_X_EXT_ADDRESS_DST_MASK ++#endif ++, ++/* SADB_X_DEBUG */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_X_EXT_DEBUG ++, ++/* SADB_X_NAT_T_NEW_MAPPING */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++} ++ ++}, ++ ++/* OUTBOUND EXTENSIONS */ ++{ ++ ++/* PERMITTED OUT */ ++{ ++/* SADB_RESERVED */ ++0 ++, ++/* SADB_GETSPI */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_UPDATE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++, ++/* SADB_ADD */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_X_EXT_NAT_T_TYPE ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++| 1<<SADB_X_EXT_NAT_T_OA ++, ++/* SADB_DELETE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_GET */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_X_EXT_NAT_T_TYPE ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++| 1<<SADB_X_EXT_NAT_T_OA ++, ++/* SADB_ACQUIRE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++, ++/* SADB_REGISTER */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SUPPORTED_AUTH ++| 1<<SADB_EXT_SUPPORTED_ENCRYPT ++, ++/* SADB_EXPIRE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_FLUSH */ ++1<<SADB_EXT_RESERVED ++, ++/* SADB_DUMP */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_X_EXT_NAT_T_TYPE ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++| 1<<SADB_X_EXT_NAT_T_OA ++, ++/* SADB_X_PROMISC */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++| 1<<SADB_EXT_SUPPORTED_AUTH ++| 1<<SADB_EXT_SUPPORTED_ENCRYPT ++| 1<<SADB_EXT_SPIRANGE ++| 1<<SADB_X_EXT_KMPRIVATE ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_PCHANGE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++| 1<<SADB_EXT_SUPPORTED_AUTH ++| 1<<SADB_EXT_SUPPORTED_ENCRYPT ++| 1<<SADB_EXT_SPIRANGE ++| 1<<SADB_X_EXT_KMPRIVATE ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_GRPSA */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_ADDFLOW */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW ++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW ++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK ++| 1<<SADB_X_EXT_ADDRESS_DST_MASK ++| 1<<SADB_X_EXT_PROTOCOL ++, ++/* SADB_X_DELFLOW */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW ++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW ++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK ++| 1<<SADB_X_EXT_ADDRESS_DST_MASK ++| 1<<SADB_X_EXT_PROTOCOL ++, ++/* SADB_X_DEBUG */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_X_EXT_DEBUG ++, ++/* SADB_X_NAT_T_NEW_MAPPING */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++}, ++ ++/* REQUIRED OUT */ ++{ ++/* SADB_RESERVED */ ++0 ++, ++/* SADB_GETSPI */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_UPDATE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_ADD */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_DELETE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_GET */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++/* | 1<<SADB_EXT_KEY_AUTH */ ++/* | 1<<SADB_EXT_KEY_ENCRYPT */ ++, ++/* SADB_ACQUIRE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_PROPOSAL ++, ++/* SADB_REGISTER */ ++1<<SADB_EXT_RESERVED ++/* | 1<<SADB_EXT_SUPPORTED_AUTH ++ | 1<<SADB_EXT_SUPPORTED_ENCRYPT */ ++, ++/* SADB_EXPIRE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++/* | 1<<SADB_EXT_LIFETIME_HARD ++ | 1<<SADB_EXT_LIFETIME_SOFT */ ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_FLUSH */ ++1<<SADB_EXT_RESERVED ++, ++/* SADB_DUMP */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++, ++/* SADB_X_PROMISC */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++| 1<<SADB_EXT_SUPPORTED_AUTH ++| 1<<SADB_EXT_SUPPORTED_ENCRYPT ++| 1<<SADB_EXT_SPIRANGE ++| 1<<SADB_X_EXT_KMPRIVATE ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_PCHANGE */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_LIFETIME_CURRENT ++| 1<<SADB_EXT_LIFETIME_HARD ++| 1<<SADB_EXT_LIFETIME_SOFT ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_EXT_ADDRESS_PROXY ++| 1<<SADB_EXT_KEY_AUTH ++| 1<<SADB_EXT_KEY_ENCRYPT ++| 1<<SADB_EXT_IDENTITY_SRC ++| 1<<SADB_EXT_IDENTITY_DST ++| 1<<SADB_EXT_SENSITIVITY ++| 1<<SADB_EXT_PROPOSAL ++| 1<<SADB_EXT_SUPPORTED_AUTH ++| 1<<SADB_EXT_SUPPORTED_ENCRYPT ++| 1<<SADB_EXT_SPIRANGE ++| 1<<SADB_X_EXT_KMPRIVATE ++| 1<<SADB_X_EXT_SATYPE2 ++| 1<<SADB_X_EXT_SA2 ++| 1<<SADB_X_EXT_ADDRESS_DST2 ++, ++/* SADB_X_GRPSA */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_DST ++, ++/* SADB_X_ADDFLOW */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW ++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW ++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK ++| 1<<SADB_X_EXT_ADDRESS_DST_MASK ++, ++/* SADB_X_DELFLOW */ ++1<<SADB_EXT_RESERVED ++/*| 1<<SADB_EXT_SA*/ ++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW ++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW ++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK ++| 1<<SADB_X_EXT_ADDRESS_DST_MASK ++, ++/* SADB_X_DEBUG */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_X_EXT_DEBUG ++, ++/* SADB_X_NAT_T_NEW_MAPPING */ ++1<<SADB_EXT_RESERVED ++| 1<<SADB_EXT_SA ++| 1<<SADB_EXT_ADDRESS_SRC ++| 1<<SADB_EXT_ADDRESS_DST ++| 1<<SADB_X_EXT_NAT_T_SPORT ++| 1<<SADB_X_EXT_NAT_T_DPORT ++} ++} ++}; ++ ++/* ++ * $Log: pfkey_v2_ext_bits.c,v $ ++ * Revision 1.20 2004/03/08 01:59:08 ken ++ * freeswan.h -> openswan.h ++ * ++ * Revision 1.19 2003/12/22 21:38:13 mcr ++ * removed extraenous #endif. ++ * ++ * Revision 1.18 2003/12/22 19:34:41 mcr ++ * added 0.6c NAT-T patch. ++ * ++ * Revision 1.17 2003/12/10 01:20:19 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.16 2003/10/31 02:27:12 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.15.30.1 2003/09/21 13:59:44 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.15 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.14 2002/04/24 07:36:40 mcr ++ * Moved from ./lib/pfkey_v2_ext_bits.c,v ++ * ++ * Revision 1.13 2002/01/29 22:25:36 rgb ++ * Re-add ipsec_kversion.h to keep MALLOC happy. ++ * ++ * Revision 1.12 2002/01/29 01:59:10 mcr ++ * removal of kversions.h - sources that needed it now use ipsec_param.h. ++ * updating of IPv6 structures to match latest in6.h version. ++ * removed dead code from openswan.h that also duplicated kversions.h ++ * code. ++ * ++ * Revision 1.11 2001/10/18 04:45:24 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/openswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.10 2001/09/08 21:13:35 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.9 2001/06/14 19:35:16 rgb ++ * Update copyright date. ++ * ++ * Revision 1.8 2001/03/26 23:07:36 rgb ++ * Remove requirement for auth and enc key from UPDATE. ++ * ++ * Revision 1.7 2000/09/12 22:35:37 rgb ++ * Restructured to remove unused extensions from CLEARFLOW messages. ++ * ++ * Revision 1.6 2000/09/09 06:39:01 rgb ++ * Added comments for clarity. ++ * ++ * Revision 1.5 2000/06/02 22:54:14 rgb ++ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support. ++ * ++ * Revision 1.4 2000/01/21 06:27:56 rgb ++ * Added address cases for eroute flows. ++ * Added comments for each message type. ++ * Added klipsdebug switching capability. ++ * Fixed GRPSA bitfields. ++ * ++ * Revision 1.3 1999/12/01 22:20:27 rgb ++ * Remove requirement for a proxy address in an incoming getspi message. ++ * ++ * Revision 1.2 1999/11/27 11:57:06 rgb ++ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. ++ * Add CVS log entry to bottom of file. ++ * Cleaned out unused bits. ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/pfkey_v2_parse.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1820 @@ ++/* ++ * RFC2367 PF_KEYv2 Key management API message parser ++ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: pfkey_v2_parse.c,v 1.59 2004/04/18 03:03:49 mcr Exp $ ++ */ ++ ++/* ++ * Template from klips/net/ipsec/ipsec/ipsec_parser.c. ++ */ ++ ++char pfkey_v2_parse_c_version[] = "$Id: pfkey_v2_parse.c,v 1.59 2004/04/18 03:03:49 mcr Exp $"; ++ ++/* ++ * Some ugly stuff to allow consistent debugging code for use in the ++ * kernel and in user space ++*/ ++ ++#ifdef __KERNEL__ ++ ++# include <linux/kernel.h> /* for printk */ ++ ++#include "openswan/ipsec_kversion.h" /* for malloc switch */ ++ ++# ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++# else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++# endif /* MALLOC_SLAB */ ++# include <linux/errno.h> /* error codes */ ++# include <linux/types.h> /* size_t */ ++# include <linux/interrupt.h> /* mark_bh */ ++ ++# include <linux/netdevice.h> /* struct device, and other headers */ ++# include <linux/etherdevice.h> /* eth_type_trans */ ++# include <linux/ip.h> /* struct iphdr */ ++# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++# include <linux/ipv6.h> /* struct ipv6hdr */ ++# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ ++extern int debug_pfkey; ++ ++# include <openswan.h> ++ ++#include "openswan/ipsec_encap.h" ++ ++#else /* __KERNEL__ */ ++ ++# include <sys/types.h> ++# include <linux/types.h> ++# include <linux/errno.h> ++ ++# include <openswan.h> ++# include "constants.h" ++# include "programs/pluto/defs.h" /* for PRINTF_LIKE */ ++ ++#endif /* __KERNEL__ */ ++ ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ ++ ++/* ++ * how to handle debugging for pfkey. ++ */ ++#include <openswan/pfkey_debug.h> ++ ++unsigned int pfkey_lib_debug = PF_KEY_DEBUG_PARSE_NONE; ++void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); ++void (*pfkey_error_func)(const char *message, ...) PRINTF_LIKE(1); ++ ++ ++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) ++ ++struct satype_tbl { ++ uint8_t proto; ++ uint8_t satype; ++ char* name; ++} static satype_tbl[] = { ++#ifdef __KERNEL__ ++ { IPPROTO_ESP, SADB_SATYPE_ESP, "ESP" }, ++ { IPPROTO_AH, SADB_SATYPE_AH, "AH" }, ++ { IPPROTO_IPIP, SADB_X_SATYPE_IPIP, "IPIP" }, ++#ifdef CONFIG_IPSEC_IPCOMP ++ { IPPROTO_COMP, SADB_X_SATYPE_COMP, "COMP" }, ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ { IPPROTO_INT, SADB_X_SATYPE_INT, "INT" }, ++#else /* __KERNEL__ */ ++ { SA_ESP, SADB_SATYPE_ESP, "ESP" }, ++ { SA_AH, SADB_SATYPE_AH, "AH" }, ++ { SA_IPIP, SADB_X_SATYPE_IPIP, "IPIP" }, ++ { SA_COMP, SADB_X_SATYPE_COMP, "COMP" }, ++ { SA_INT, SADB_X_SATYPE_INT, "INT" }, ++#endif /* __KERNEL__ */ ++ { 0, 0, "UNKNOWN" } ++}; ++ ++uint8_t ++satype2proto(uint8_t satype) ++{ ++ int i =0; ++ ++ while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) { ++ i++; ++ } ++ return satype_tbl[i].proto; ++} ++ ++uint8_t ++proto2satype(uint8_t proto) ++{ ++ int i = 0; ++ ++ while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) { ++ i++; ++ } ++ return satype_tbl[i].satype; ++} ++ ++char* ++satype2name(uint8_t satype) ++{ ++ int i = 0; ++ ++ while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) { ++ i++; ++ } ++ return satype_tbl[i].name; ++} ++ ++char* ++proto2name(uint8_t proto) ++{ ++ int i = 0; ++ ++ while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) { ++ i++; ++ } ++ return satype_tbl[i].name; ++} ++ ++/* Default extension parsers taken from the KLIPS code */ ++ ++DEBUG_NO_STATIC int ++pfkey_sa_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext; ++#if 0 ++ struct sadb_sa sav2; ++#endif ++ ++ /* sanity checks... */ ++ if(!pfkey_sa) { ++ ERROR("pfkey_sa_parse: " ++ "NULL pointer passed in.\n"); ++ SENDERR(EINVAL); ++ } ++ ++#if 0 ++ /* check if this structure is short, and if so, fix it up. ++ * XXX this is NOT the way to do things. ++ */ ++ if(pfkey_sa->sadb_sa_len == sizeof(struct sadb_sa_v1)/IPSEC_PFKEYv2_ALIGN) { ++ ++ /* yes, so clear out a temporary structure, and copy first */ ++ memset(&sav2, 0, sizeof(sav2)); ++ memcpy(&sav2, pfkey_sa, sizeof(struct sadb_sa_v1)); ++ sav2.sadb_x_sa_ref=-1; ++ sav2.sadb_sa_len = sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN; ++ ++ pfkey_sa = &sav2; ++ } ++#endif ++ ++ ++ if(pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) { ++ ERROR( ++ "pfkey_sa_parse: " ++ "length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n", ++ pfkey_sa->sadb_sa_len, ++ (int)sizeof(struct sadb_sa)); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_sa->sadb_sa_encrypt > SADB_EALG_MAX) { ++ ERROR( ++ "pfkey_sa_parse: " ++ "pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n", ++ pfkey_sa->sadb_sa_encrypt, ++ SADB_EALG_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_sa->sadb_sa_auth > SADB_AALG_MAX) { ++ ERROR( ++ "pfkey_sa_parse: " ++ "pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n", ++ pfkey_sa->sadb_sa_auth, ++ SADB_AALG_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_sa->sadb_sa_state > SADB_SASTATE_MAX) { ++ ERROR( ++ "pfkey_sa_parse: " ++ "state=%d exceeds MAX=%d.\n", ++ pfkey_sa->sadb_sa_state, ++ SADB_SASTATE_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_sa->sadb_sa_state == SADB_SASTATE_DEAD) { ++ ERROR( ++ "pfkey_sa_parse: " ++ "state=%d is DEAD=%d.\n", ++ pfkey_sa->sadb_sa_state, ++ SADB_SASTATE_DEAD); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_sa->sadb_sa_replay > 64) { ++ ERROR( ++ "pfkey_sa_parse: " ++ "replay window size: %d -- must be 0 <= size <= 64\n", ++ pfkey_sa->sadb_sa_replay); ++ SENDERR(EINVAL); ++ } ++ ++ if(! ((pfkey_sa->sadb_sa_exttype == SADB_EXT_SA) || ++ (pfkey_sa->sadb_sa_exttype == SADB_X_EXT_SA2))) ++ { ++ ERROR( ++ "pfkey_sa_parse: " ++ "unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n", ++ pfkey_sa->sadb_sa_exttype, ++ SADB_EXT_SA, ++ SADB_X_EXT_SA2); ++ SENDERR(EINVAL); ++ } ++ ++ if((IPSEC_SAREF_NULL != pfkey_sa->sadb_x_sa_ref) && (pfkey_sa->sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) { ++ ERROR( ++ "pfkey_sa_parse: " ++ "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", ++ pfkey_sa->sadb_x_sa_ref, ++ IPSEC_SAREF_NULL, ++ IPSEC_SA_REF_TABLE_NUM_ENTRIES); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_sa_parse: " ++ "successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d ref=%d.\n", ++ pfkey_sa->sadb_sa_len, ++ pfkey_sa->sadb_sa_exttype, ++ pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype), ++ (long unsigned int)ntohl(pfkey_sa->sadb_sa_spi), ++ pfkey_sa->sadb_sa_replay, ++ pfkey_sa->sadb_sa_state, ++ pfkey_sa->sadb_sa_auth, ++ pfkey_sa->sadb_sa_encrypt, ++ pfkey_sa->sadb_sa_flags, ++ pfkey_sa->sadb_x_sa_ref); ++ ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_lifetime_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, ++ "pfkey_lifetime_parse:enter\n"); ++ /* sanity checks... */ ++ if(!pfkey_lifetime) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_lifetime_parse: " ++ "NULL pointer passed in.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_lifetime->sadb_lifetime_len != ++ sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_lifetime_parse: " ++ "length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n", ++ pfkey_lifetime->sadb_lifetime_len, ++ (int)sizeof(struct sadb_lifetime)); ++ SENDERR(EINVAL); ++ } ++ ++ if((pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_HARD) && ++ (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_SOFT) && ++ (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_CURRENT)) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_lifetime_parse: " ++ "unexpected ext_type=%d.\n", ++ pfkey_lifetime->sadb_lifetime_exttype); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_lifetime_parse: " ++ "life_type=%d(%s) alloc=%u bytes=%u add=%u use=%u pkts=%u.\n", ++ pfkey_lifetime->sadb_lifetime_exttype, ++ pfkey_v2_sadb_ext_string(pfkey_lifetime->sadb_lifetime_exttype), ++ pfkey_lifetime->sadb_lifetime_allocations, ++ (unsigned)pfkey_lifetime->sadb_lifetime_bytes, ++ (unsigned)pfkey_lifetime->sadb_lifetime_addtime, ++ (unsigned)pfkey_lifetime->sadb_lifetime_usetime, ++ pfkey_lifetime->sadb_x_lifetime_packets); ++errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_address_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ int saddr_len = 0; ++ struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; ++ struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); ++ char ipaddr_txt[ADDRTOT_BUF]; ++ ++ /* sanity checks... */ ++ if(!pfkey_address) { ++ ERROR( ++ "pfkey_address_parse: " ++ "NULL pointer passed in.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_address->sadb_address_len < ++ (sizeof(struct sadb_address) + sizeof(struct sockaddr))/ ++ IPSEC_PFKEYv2_ALIGN) { ++ ERROR("pfkey_address_parse: " ++ "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", ++ pfkey_address->sadb_address_len, ++ (int)sizeof(struct sadb_address), ++ (int)sizeof(struct sockaddr)); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_address->sadb_address_reserved) { ++ ERROR("pfkey_address_parse: " ++ "res=%d, must be zero.\n", ++ pfkey_address->sadb_address_reserved); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_address->sadb_address_exttype) { ++ case SADB_EXT_ADDRESS_SRC: ++ case SADB_EXT_ADDRESS_DST: ++ case SADB_EXT_ADDRESS_PROXY: ++ case SADB_X_EXT_ADDRESS_DST2: ++ case SADB_X_EXT_ADDRESS_SRC_FLOW: ++ case SADB_X_EXT_ADDRESS_DST_FLOW: ++ case SADB_X_EXT_ADDRESS_SRC_MASK: ++ case SADB_X_EXT_ADDRESS_DST_MASK: ++#ifdef NAT_TRAVERSAL ++ case SADB_X_EXT_NAT_T_OA: ++#endif ++ break; ++ default: ++ ERROR( ++ "pfkey_address_parse: " ++ "unexpected ext_type=%d.\n", ++ pfkey_address->sadb_address_exttype); ++ SENDERR(EINVAL); ++ } ++ ++ switch(s->sa_family) { ++ case AF_INET: ++ saddr_len = sizeof(struct sockaddr_in); ++ sprintf(ipaddr_txt, "%d.%d.%d.%d" ++ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 0) & 0xFF ++ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 8) & 0xFF ++ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 16) & 0xFF ++ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 24) & 0xFF); ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_address_parse: " ++ "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n", ++ pfkey_address->sadb_address_exttype, ++ pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), ++ s->sa_family, ++ ipaddr_txt, ++ pfkey_address->sadb_address_proto, ++ ntohs(((struct sockaddr_in*)s)->sin_port)); ++ break; ++ case AF_INET6: ++ saddr_len = sizeof(struct sockaddr_in6); ++ sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x" ++ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[0]) ++ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[1]) ++ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[2]) ++ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[3]) ++ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[4]) ++ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[5]) ++ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[6]) ++ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[7])); ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_address_parse: " ++ "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n", ++ pfkey_address->sadb_address_exttype, ++ pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), ++ s->sa_family, ++ ipaddr_txt, ++ pfkey_address->sadb_address_proto, ++ ((struct sockaddr_in6*)s)->sin6_port); ++ break; ++ default: ++ ERROR( ++ "pfkey_address_parse: " ++ "s->sa_family=%d not supported.\n", ++ s->sa_family); ++ SENDERR(EPFNOSUPPORT); ++ } ++ ++ if(pfkey_address->sadb_address_len != ++ DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) { ++ ERROR( ++ "pfkey_address_parse: " ++ "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", ++ pfkey_address->sadb_address_len, ++ (int)sizeof(struct sadb_address), ++ saddr_len); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_address->sadb_address_prefixlen != 0) { ++ ERROR( ++ "pfkey_address_parse: " ++ "address prefixes not supported yet.\n"); ++ SENDERR(EAFNOSUPPORT); /* not supported yet */ ++ } ++ ++ /* XXX check if port!=0 */ ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, ++ "pfkey_address_parse: successful.\n"); ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_key_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext; ++ ++ /* sanity checks... */ ++ ++ if(!pfkey_key) { ++ ERROR( ++ "pfkey_key_parse: " ++ "NULL pointer passed in.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) { ++ ERROR( ++ "pfkey_key_parse: " ++ "size wrong ext_len=%d, key_ext_len=%d.\n", ++ pfkey_key->sadb_key_len, ++ (int)sizeof(struct sadb_key)); ++ SENDERR(EINVAL); ++ } ++ ++ if(!pfkey_key->sadb_key_bits) { ++ ERROR( ++ "pfkey_key_parse: " ++ "key length set to zero, must be non-zero.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_key->sadb_key_len != ++ DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits, ++ PFKEYBITS)) { ++ ERROR( ++ "pfkey_key_parse: " ++ "key length=%d does not agree with extension length=%d.\n", ++ pfkey_key->sadb_key_bits, ++ pfkey_key->sadb_key_len); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_key->sadb_key_reserved) { ++ ERROR( ++ "pfkey_key_parse: " ++ "res=%d, must be zero.\n", ++ pfkey_key->sadb_key_reserved); ++ SENDERR(EINVAL); ++ } ++ ++ if(! ( (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_AUTH) || ++ (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_ENCRYPT))) { ++ ERROR( ++ "pfkey_key_parse: " ++ "expecting extension type AUTH or ENCRYPT, got %d.\n", ++ pfkey_key->sadb_key_exttype); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_key_parse: " ++ "success, found len=%d exttype=%d(%s) bits=%d reserved=%d.\n", ++ pfkey_key->sadb_key_len, ++ pfkey_key->sadb_key_exttype, ++ pfkey_v2_sadb_ext_string(pfkey_key->sadb_key_exttype), ++ pfkey_key->sadb_key_bits, ++ pfkey_key->sadb_key_reserved); ++ ++errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_ident_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext; ++ ++ /* sanity checks... */ ++ if(pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { ++ ERROR( ++ "pfkey_ident_parse: " ++ "size wrong ext_len=%d, key_ext_len=%d.\n", ++ pfkey_ident->sadb_ident_len, ++ (int)sizeof(struct sadb_ident)); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) { ++ ERROR( ++ "pfkey_ident_parse: " ++ "ident_type=%d out of range, must be less than %d.\n", ++ pfkey_ident->sadb_ident_type, ++ SADB_IDENTTYPE_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_ident->sadb_ident_reserved) { ++ ERROR( ++ "pfkey_ident_parse: " ++ "res=%d, must be zero.\n", ++ pfkey_ident->sadb_ident_reserved); ++ SENDERR(EINVAL); ++ } ++ ++ /* string terminator/padding must be zero */ ++ if(pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { ++ if(*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) { ++ ERROR( ++ "pfkey_ident_parse: " ++ "string padding must be zero, last is 0x%02x.\n", ++ *((char*)pfkey_ident + ++ pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)); ++ SENDERR(EINVAL); ++ } ++ } ++ ++ if( ! ((pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) || ++ (pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_DST))) { ++ ERROR( ++ "pfkey_key_parse: " ++ "expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n", ++ pfkey_ident->sadb_ident_exttype); ++ SENDERR(EINVAL); ++ } ++ ++errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_sens_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ struct sadb_sens *pfkey_sens = (struct sadb_sens *)pfkey_ext; ++ ++ /* sanity checks... */ ++ if(pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_sens_parse: " ++ "size wrong ext_len=%d, key_ext_len=%d.\n", ++ pfkey_sens->sadb_sens_len, ++ (int)sizeof(struct sadb_sens)); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_sens_parse: " ++ "Sorry, I can't parse exttype=%d yet.\n", ++ pfkey_ext->sadb_ext_type); ++#if 0 ++ SENDERR(EINVAL); /* don't process these yet */ ++#endif ++ ++errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_prop_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ int i, num_comb; ++ struct sadb_prop *pfkey_prop = (struct sadb_prop *)pfkey_ext; ++ struct sadb_comb *pfkey_comb = (struct sadb_comb *)((char*)pfkey_ext + sizeof(struct sadb_prop)); ++ ++ /* sanity checks... */ ++ if((pfkey_prop->sadb_prop_len < sizeof(struct sadb_prop) / IPSEC_PFKEYv2_ALIGN) || ++ (((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb))) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n", ++ pfkey_prop->sadb_prop_len, ++ (int)sizeof(struct sadb_prop), ++ (int)sizeof(struct sadb_comb)); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_prop->sadb_prop_replay > 64) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "replay window size: %d -- must be 0 <= size <= 64\n", ++ pfkey_prop->sadb_prop_replay); ++ SENDERR(EINVAL); ++ } ++ ++ for(i=0; i<3; i++) { ++ if(pfkey_prop->sadb_prop_reserved[i]) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "res[%d]=%d, must be zero.\n", ++ i, pfkey_prop->sadb_prop_reserved[i]); ++ SENDERR(EINVAL); ++ } ++ } ++ ++ num_comb = ((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb); ++ ++ for(i = 0; i < num_comb; i++) { ++ if(pfkey_comb->sadb_comb_auth > SADB_AALG_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_auth=%d > SADB_AALG_MAX=%d.\n", ++ i, ++ pfkey_comb->sadb_comb_auth, ++ SADB_AALG_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_comb->sadb_comb_auth) { ++ if(!pfkey_comb->sadb_comb_auth_minbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n", ++ i); ++ SENDERR(EINVAL); ++ } ++ if(!pfkey_comb->sadb_comb_auth_maxbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n", ++ i); ++ SENDERR(EINVAL); ++ } ++ if(pfkey_comb->sadb_comb_auth_minbits > pfkey_comb->sadb_comb_auth_maxbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n", ++ i, ++ pfkey_comb->sadb_comb_auth_minbits, ++ pfkey_comb->sadb_comb_auth_maxbits); ++ SENDERR(EINVAL); ++ } ++ } else { ++ if(pfkey_comb->sadb_comb_auth_minbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n", ++ i, ++ pfkey_comb->sadb_comb_auth_minbits); ++ SENDERR(EINVAL); ++ } ++ if(pfkey_comb->sadb_comb_auth_maxbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n", ++ i, ++ pfkey_comb->sadb_comb_auth_maxbits); ++ SENDERR(EINVAL); ++ } ++ } ++ ++ if(pfkey_comb->sadb_comb_encrypt > SADB_EALG_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_comb_parse: " ++ "pfkey_comb[%d]->sadb_comb_encrypt=%d > SADB_EALG_MAX=%d.\n", ++ i, ++ pfkey_comb->sadb_comb_encrypt, ++ SADB_EALG_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_comb->sadb_comb_encrypt) { ++ if(!pfkey_comb->sadb_comb_encrypt_minbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n", ++ i); ++ SENDERR(EINVAL); ++ } ++ if(!pfkey_comb->sadb_comb_encrypt_maxbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n", ++ i); ++ SENDERR(EINVAL); ++ } ++ if(pfkey_comb->sadb_comb_encrypt_minbits > pfkey_comb->sadb_comb_encrypt_maxbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n", ++ i, ++ pfkey_comb->sadb_comb_encrypt_minbits, ++ pfkey_comb->sadb_comb_encrypt_maxbits); ++ SENDERR(EINVAL); ++ } ++ } else { ++ if(pfkey_comb->sadb_comb_encrypt_minbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n", ++ i, ++ pfkey_comb->sadb_comb_encrypt_minbits); ++ SENDERR(EINVAL); ++ } ++ if(pfkey_comb->sadb_comb_encrypt_maxbits) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n", ++ i, ++ pfkey_comb->sadb_comb_encrypt_maxbits); ++ SENDERR(EINVAL); ++ } ++ } ++ ++ /* XXX do sanity check on flags */ ++ ++ if(pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n", ++ i, ++ pfkey_comb->sadb_comb_soft_allocations, ++ pfkey_comb->sadb_comb_hard_allocations); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n", ++ i, ++ (unsigned long long int)pfkey_comb->sadb_comb_soft_bytes, ++ (unsigned long long int)pfkey_comb->sadb_comb_hard_bytes); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n", ++ i, ++ (unsigned long long int)pfkey_comb->sadb_comb_soft_addtime, ++ (unsigned long long int)pfkey_comb->sadb_comb_hard_addtime); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n", ++ i, ++ (unsigned long long int)pfkey_comb->sadb_comb_soft_usetime, ++ (unsigned long long int)pfkey_comb->sadb_comb_hard_usetime); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_comb->sadb_x_comb_hard_packets && pfkey_comb->sadb_x_comb_soft_packets > pfkey_comb->sadb_x_comb_hard_packets) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "pfkey_comb[%d]->sadb_x_comb_soft_packets=%d > hard_packets=%d, fatal.\n", ++ i, ++ pfkey_comb->sadb_x_comb_soft_packets, ++ pfkey_comb->sadb_x_comb_hard_packets); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_comb->sadb_comb_reserved) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_prop_parse: " ++ "comb[%d].res=%d, must be zero.\n", ++ i, ++ pfkey_comb->sadb_comb_reserved); ++ SENDERR(EINVAL); ++ } ++ pfkey_comb++; ++ } ++ ++errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_supported_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ unsigned int i, num_alg; ++ struct sadb_supported *pfkey_supported = (struct sadb_supported *)pfkey_ext; ++ struct sadb_alg *pfkey_alg = (struct sadb_alg*)((char*)pfkey_ext + sizeof(struct sadb_supported)); ++ ++ /* sanity checks... */ ++ if((pfkey_supported->sadb_supported_len < ++ sizeof(struct sadb_supported) / IPSEC_PFKEYv2_ALIGN) || ++ (((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - ++ sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) { ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_supported_parse: " ++ "size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n", ++ pfkey_supported->sadb_supported_len, ++ (int)sizeof(struct sadb_supported), ++ (int)sizeof(struct sadb_alg)); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_supported->sadb_supported_reserved) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_supported_parse: " ++ "res=%d, must be zero.\n", ++ pfkey_supported->sadb_supported_reserved); ++ SENDERR(EINVAL); ++ } ++ ++ num_alg = ((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg); ++ ++ for(i = 0; i < num_alg; i++) { ++ /* process algo description */ ++ if(pfkey_alg->sadb_alg_reserved) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_supported_parse: " ++ "alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n", ++ i, ++ pfkey_alg->sadb_alg_id, ++ pfkey_alg->sadb_alg_ivlen, ++ pfkey_alg->sadb_alg_minbits, ++ pfkey_alg->sadb_alg_maxbits, ++ pfkey_alg->sadb_alg_reserved); ++ SENDERR(EINVAL); ++ } ++ ++ /* XXX can alg_id auth/enc be determined from info given? ++ Yes, but OpenBSD's method does not iteroperate with rfc2367. ++ rgb, 2000-04-06 */ ++ ++ switch(pfkey_supported->sadb_supported_exttype) { ++ case SADB_EXT_SUPPORTED_AUTH: ++ if(pfkey_alg->sadb_alg_id > SADB_AALG_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_supported_parse: " ++ "alg[%d], alg_id=%d > SADB_AALG_MAX=%d, fatal.\n", ++ i, ++ pfkey_alg->sadb_alg_id, ++ SADB_AALG_MAX); ++ SENDERR(EINVAL); ++ } ++ break; ++ case SADB_EXT_SUPPORTED_ENCRYPT: ++ if(pfkey_alg->sadb_alg_id > SADB_EALG_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_supported_parse: " ++ "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n", ++ i, ++ pfkey_alg->sadb_alg_id, ++ SADB_EALG_MAX); ++ SENDERR(EINVAL); ++ } ++ break; ++ default: ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_supported_parse: " ++ "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n", ++ i, ++ pfkey_alg->sadb_alg_id, ++ SADB_EALG_MAX); ++ SENDERR(EINVAL); ++ } ++ pfkey_alg++; ++ } ++ ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_spirange_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)pfkey_ext; ++ ++ /* sanity checks... */ ++ if(pfkey_spirange->sadb_spirange_len != ++ sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_spirange_parse: " ++ "size wrong ext_len=%d, key_ext_len=%d.\n", ++ pfkey_spirange->sadb_spirange_len, ++ (int)sizeof(struct sadb_spirange)); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_spirange->sadb_spirange_reserved) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_spirange_parse: " ++ "reserved=%d must be set to zero.\n", ++ pfkey_spirange->sadb_spirange_reserved); ++ SENDERR(EINVAL); ++ } ++ ++ if(ntohl(pfkey_spirange->sadb_spirange_max) < ntohl(pfkey_spirange->sadb_spirange_min)) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_spirange_parse: " ++ "minspi=%08x must be < maxspi=%08x.\n", ++ ntohl(pfkey_spirange->sadb_spirange_min), ++ ntohl(pfkey_spirange->sadb_spirange_max)); ++ SENDERR(EINVAL); ++ } ++ ++ if(ntohl(pfkey_spirange->sadb_spirange_min) <= 255) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_spirange_parse: " ++ "minspi=%08x must be > 255.\n", ++ ntohl(pfkey_spirange->sadb_spirange_min)); ++ SENDERR(EEXIST); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_spirange_parse: " ++ "ext_len=%u ext_type=%u(%s) min=%u max=%u res=%u.\n", ++ pfkey_spirange->sadb_spirange_len, ++ pfkey_spirange->sadb_spirange_exttype, ++ pfkey_v2_sadb_ext_string(pfkey_spirange->sadb_spirange_exttype), ++ pfkey_spirange->sadb_spirange_min, ++ pfkey_spirange->sadb_spirange_max, ++ pfkey_spirange->sadb_spirange_reserved); ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_kmprivate_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)pfkey_ext; ++ ++ /* sanity checks... */ ++ if(pfkey_x_kmprivate->sadb_x_kmprivate_len < ++ sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_kmprivate_parse: " ++ "size wrong ext_len=%d, key_ext_len=%d.\n", ++ pfkey_x_kmprivate->sadb_x_kmprivate_len, ++ (int)sizeof(struct sadb_x_kmprivate)); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_x_kmprivate->sadb_x_kmprivate_reserved) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_kmprivate_parse: " ++ "reserved=%d must be set to zero.\n", ++ pfkey_x_kmprivate->sadb_x_kmprivate_reserved); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_kmprivate_parse: " ++ "Sorry, I can't parse exttype=%d yet.\n", ++ pfkey_ext->sadb_ext_type); ++ SENDERR(EINVAL); /* don't process these yet */ ++ ++errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_satype_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ int i; ++ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, ++ "pfkey_x_satype_parse: enter\n"); ++ /* sanity checks... */ ++ if(pfkey_x_satype->sadb_x_satype_len != ++ sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_satype_parse: " ++ "size wrong ext_len=%d, key_ext_len=%d.\n", ++ pfkey_x_satype->sadb_x_satype_len, ++ (int)sizeof(struct sadb_x_satype)); ++ SENDERR(EINVAL); ++ } ++ ++ if(!pfkey_x_satype->sadb_x_satype_satype) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_satype_parse: " ++ "satype is zero, must be non-zero.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_x_satype->sadb_x_satype_satype > SADB_SATYPE_MAX) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_satype_parse: " ++ "satype %d > max %d, invalid.\n", ++ pfkey_x_satype->sadb_x_satype_satype, SADB_SATYPE_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_satype_parse: " ++ "proto lookup from satype=%d failed.\n", ++ pfkey_x_satype->sadb_x_satype_satype); ++ SENDERR(EINVAL); ++ } ++ ++ for(i = 0; i < 3; i++) { ++ if(pfkey_x_satype->sadb_x_satype_reserved[i]) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_satype_parse: " ++ "reserved[%d]=%d must be set to zero.\n", ++ i, pfkey_x_satype->sadb_x_satype_reserved[i]); ++ SENDERR(EINVAL); ++ } ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_x_satype_parse: " ++ "len=%u ext=%u(%s) satype=%u(%s) res=%u,%u,%u.\n", ++ pfkey_x_satype->sadb_x_satype_len, ++ pfkey_x_satype->sadb_x_satype_exttype, ++ pfkey_v2_sadb_ext_string(pfkey_x_satype->sadb_x_satype_exttype), ++ pfkey_x_satype->sadb_x_satype_satype, ++ satype2name(pfkey_x_satype->sadb_x_satype_satype), ++ pfkey_x_satype->sadb_x_satype_reserved[0], ++ pfkey_x_satype->sadb_x_satype_reserved[1], ++ pfkey_x_satype->sadb_x_satype_reserved[2]); ++errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_ext_debug_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ int i; ++ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, ++ "pfkey_x_debug_parse: enter\n"); ++ /* sanity checks... */ ++ if(pfkey_x_debug->sadb_x_debug_len != ++ sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_debug_parse: " ++ "size wrong ext_len=%d, key_ext_len=%d.\n", ++ pfkey_x_debug->sadb_x_debug_len, ++ (int)sizeof(struct sadb_x_debug)); ++ SENDERR(EINVAL); ++ } ++ ++ for(i = 0; i < 4; i++) { ++ if(pfkey_x_debug->sadb_x_debug_reserved[i]) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_debug_parse: " ++ "reserved[%d]=%d must be set to zero.\n", ++ i, pfkey_x_debug->sadb_x_debug_reserved[i]); ++ SENDERR(EINVAL); ++ } ++ } ++ ++errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_ext_protocol_parse(struct sadb_ext *pfkey_ext) ++{ ++ int error = 0; ++ struct sadb_protocol *p = (struct sadb_protocol *)pfkey_ext; ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse:\n"); ++ /* sanity checks... */ ++ ++ if (p->sadb_protocol_len != sizeof(*p)/IPSEC_PFKEYv2_ALIGN) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_x_protocol_parse: size wrong ext_len=%d, key_ext_len=%d.\n", ++ p->sadb_protocol_len, (int)sizeof(*p)); ++ SENDERR(EINVAL); ++ } ++ ++ if (p->sadb_protocol_reserved2 != 0) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_protocol_parse: res=%d, must be zero.\n", ++ p->sadb_protocol_reserved2); ++ SENDERR(EINVAL); ++ } ++ ++ errlab: ++ return error; ++} ++ ++#ifdef NAT_TRAVERSAL ++DEBUG_NO_STATIC int ++pfkey_x_ext_nat_t_type_parse(struct sadb_ext *pfkey_ext) ++{ ++ return 0; ++} ++DEBUG_NO_STATIC int ++pfkey_x_ext_nat_t_port_parse(struct sadb_ext *pfkey_ext) ++{ ++ return 0; ++} ++#endif ++ ++#define DEFINEPARSER(NAME) static struct pf_key_ext_parsers_def NAME##_def={NAME, #NAME}; ++ ++DEFINEPARSER(pfkey_sa_parse); ++DEFINEPARSER(pfkey_lifetime_parse); ++DEFINEPARSER(pfkey_address_parse); ++DEFINEPARSER(pfkey_key_parse); ++DEFINEPARSER(pfkey_ident_parse); ++DEFINEPARSER(pfkey_sens_parse); ++DEFINEPARSER(pfkey_prop_parse); ++DEFINEPARSER(pfkey_supported_parse); ++DEFINEPARSER(pfkey_spirange_parse); ++DEFINEPARSER(pfkey_x_kmprivate_parse); ++DEFINEPARSER(pfkey_x_satype_parse); ++DEFINEPARSER(pfkey_x_ext_debug_parse); ++DEFINEPARSER(pfkey_x_ext_protocol_parse); ++#ifdef NAT_TRAVERSAL ++DEFINEPARSER(pfkey_x_ext_nat_t_type_parse); ++DEFINEPARSER(pfkey_x_ext_nat_t_port_parse); ++#endif ++ ++struct pf_key_ext_parsers_def *ext_default_parsers[]= ++{ ++ NULL, /* pfkey_msg_parse, */ ++ &pfkey_sa_parse_def, ++ &pfkey_lifetime_parse_def, ++ &pfkey_lifetime_parse_def, ++ &pfkey_lifetime_parse_def, ++ &pfkey_address_parse_def, ++ &pfkey_address_parse_def, ++ &pfkey_address_parse_def, ++ &pfkey_key_parse_def, ++ &pfkey_key_parse_def, ++ &pfkey_ident_parse_def, ++ &pfkey_ident_parse_def, ++ &pfkey_sens_parse_def, ++ &pfkey_prop_parse_def, ++ &pfkey_supported_parse_def, ++ &pfkey_supported_parse_def, ++ &pfkey_spirange_parse_def, ++ &pfkey_x_kmprivate_parse_def, ++ &pfkey_x_satype_parse_def, ++ &pfkey_sa_parse_def, ++ &pfkey_address_parse_def, ++ &pfkey_address_parse_def, ++ &pfkey_address_parse_def, ++ &pfkey_address_parse_def, ++ &pfkey_address_parse_def, ++ &pfkey_x_ext_debug_parse_def, ++ &pfkey_x_ext_protocol_parse_def ++#ifdef NAT_TRAVERSAL ++ , ++ &pfkey_x_ext_nat_t_type_parse_def, ++ &pfkey_x_ext_nat_t_port_parse_def, ++ &pfkey_x_ext_nat_t_port_parse_def, ++ &pfkey_address_parse_def ++#endif ++}; ++ ++int ++pfkey_msg_parse(struct sadb_msg *pfkey_msg, ++ struct pf_key_ext_parsers_def *ext_parsers[], ++ struct sadb_ext *extensions[], ++ int dir) ++{ ++ int error = 0; ++ int remain; ++ struct sadb_ext *pfkey_ext; ++ int extensions_seen = 0; ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_msg_parse: " ++ "parsing message ver=%d, type=%d(%s), errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", ++ pfkey_msg->sadb_msg_version, ++ pfkey_msg->sadb_msg_type, ++ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), ++ pfkey_msg->sadb_msg_errno, ++ pfkey_msg->sadb_msg_satype, ++ satype2name(pfkey_msg->sadb_msg_satype), ++ pfkey_msg->sadb_msg_len, ++ pfkey_msg->sadb_msg_reserved, ++ pfkey_msg->sadb_msg_seq, ++ pfkey_msg->sadb_msg_pid); ++ ++ if(ext_parsers == NULL) ext_parsers = ext_default_parsers; ++ ++ pfkey_extensions_init(extensions); ++ ++ remain = pfkey_msg->sadb_msg_len; ++ remain -= sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; ++ ++ pfkey_ext = (struct sadb_ext*)((char*)pfkey_msg + ++ sizeof(struct sadb_msg)); ++ ++ extensions[0] = (struct sadb_ext *) pfkey_msg; ++ ++ ++ if(pfkey_msg->sadb_msg_version != PF_KEY_V2) { ++ ERROR("pfkey_msg_parse: " ++ "not PF_KEY_V2 msg, found %d, should be %d.\n", ++ pfkey_msg->sadb_msg_version, ++ PF_KEY_V2); ++ SENDERR(EINVAL); ++ } ++ ++ if(!pfkey_msg->sadb_msg_type) { ++ ERROR("pfkey_msg_parse: " ++ "msg type not set, must be non-zero..\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(pfkey_msg->sadb_msg_type > SADB_MAX) { ++ ERROR("pfkey_msg_parse: " ++ "msg type=%d > max=%d.\n", ++ pfkey_msg->sadb_msg_type, ++ SADB_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_msg->sadb_msg_type) { ++ case SADB_GETSPI: ++ case SADB_UPDATE: ++ case SADB_ADD: ++ case SADB_DELETE: ++ case SADB_GET: ++ case SADB_X_GRPSA: ++ case SADB_X_ADDFLOW: ++ if(!satype2proto(pfkey_msg->sadb_msg_satype)) { ++ ERROR("pfkey_msg_parse: " ++ "satype %d conversion to proto failed for msg_type %d (%s).\n", ++ pfkey_msg->sadb_msg_satype, ++ pfkey_msg->sadb_msg_type, ++ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type)); ++ SENDERR(EINVAL); ++ } else { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "satype %d(%s) conversion to proto gives %d for msg_type %d(%s).\n", ++ pfkey_msg->sadb_msg_satype, ++ satype2name(pfkey_msg->sadb_msg_satype), ++ satype2proto(pfkey_msg->sadb_msg_satype), ++ pfkey_msg->sadb_msg_type, ++ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type)); ++ } ++ case SADB_ACQUIRE: ++ case SADB_REGISTER: ++ case SADB_EXPIRE: ++ if(!pfkey_msg->sadb_msg_satype) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "satype is zero, must be non-zero for msg_type %d(%s).\n", ++ pfkey_msg->sadb_msg_type, ++ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type)); ++ SENDERR(EINVAL); ++ } ++ default: ++ break; ++ } ++ ++ /* errno must not be set in downward messages */ ++ /* this is not entirely true... a response to an ACQUIRE could return an error */ ++ if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type != SADB_ACQUIRE) && pfkey_msg->sadb_msg_errno) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "errno set to %d.\n", ++ pfkey_msg->sadb_msg_errno); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, ++ "pfkey_msg_parse: " ++ "remain=%d, ext_type=%d(%s), ext_len=%d.\n", ++ remain, ++ pfkey_ext->sadb_ext_type, ++ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), ++ pfkey_ext->sadb_ext_len); ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, ++ "pfkey_msg_parse: " ++ "extensions permitted=%08x, required=%08x.\n", ++ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type], ++ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]); ++ ++ extensions_seen = 1; ++ ++ while( (remain * IPSEC_PFKEYv2_ALIGN) >= sizeof(struct sadb_ext) ) { ++ /* Is there enough message left to support another extension header? */ ++ if(remain < pfkey_ext->sadb_ext_len) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "remain %d less than ext len %d.\n", ++ remain, pfkey_ext->sadb_ext_len); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, ++ "pfkey_msg_parse: " ++ "parsing ext type=%d(%s) remain=%d.\n", ++ pfkey_ext->sadb_ext_type, ++ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), ++ remain); ++ ++ /* Is the extension header type valid? */ ++ if((pfkey_ext->sadb_ext_type > SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "ext type %d(%s) invalid, SADB_EXT_MAX=%d.\n", ++ pfkey_ext->sadb_ext_type, ++ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), ++ SADB_EXT_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ /* Have we already seen this type of extension? */ ++ if((extensions_seen & ( 1 << pfkey_ext->sadb_ext_type )) != 0) ++ { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "ext type %d(%s) already seen.\n", ++ pfkey_ext->sadb_ext_type, ++ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); ++ SENDERR(EINVAL); ++ } ++ ++ /* Do I even know about this type of extension? */ ++ if(ext_parsers[pfkey_ext->sadb_ext_type]==NULL) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "ext type %d(%s) unknown, ignoring.\n", ++ pfkey_ext->sadb_ext_type, ++ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); ++ goto next_ext; ++ } ++ ++ /* Is this type of extension permitted for this type of message? */ ++ if(!(extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type] & ++ 1<<pfkey_ext->sadb_ext_type)) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "ext type %d(%s) not permitted, exts_perm_in=%08x, 1<<type=%08x\n", ++ pfkey_ext->sadb_ext_type, ++ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), ++ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type], ++ 1<<pfkey_ext->sadb_ext_type); ++ SENDERR(EINVAL); ++ } ++ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_msg_parse: " ++ "remain=%d ext_type=%d(%s) ext_len=%d parsing ext 0p%p with parser %s.\n", ++ remain, ++ pfkey_ext->sadb_ext_type, ++ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), ++ pfkey_ext->sadb_ext_len, ++ pfkey_ext, ++ ext_parsers[pfkey_ext->sadb_ext_type]->parser_name); ++ ++ /* Parse the extension */ ++ if((error = ++ (*ext_parsers[pfkey_ext->sadb_ext_type]->parser)(pfkey_ext))) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "extension parsing for type %d(%s) failed with error %d.\n", ++ pfkey_ext->sadb_ext_type, ++ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), ++ error); ++ SENDERR(-error); ++ } ++ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, ++ "pfkey_msg_parse: " ++ "Extension %d(%s) parsed.\n", ++ pfkey_ext->sadb_ext_type, ++ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); ++ ++ /* Mark that we have seen this extension and remember the header location */ ++ extensions_seen |= ( 1 << pfkey_ext->sadb_ext_type ); ++ extensions[pfkey_ext->sadb_ext_type] = pfkey_ext; ++ ++ next_ext: ++ /* Calculate how much message remains */ ++ remain -= pfkey_ext->sadb_ext_len; ++ ++ if(!remain) { ++ break; ++ } ++ /* Find the next extension header */ ++ pfkey_ext = (struct sadb_ext*)((char*)pfkey_ext + ++ pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); ++ } ++ ++ if(remain) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "unexpected remainder of %d.\n", ++ remain); ++ /* why is there still something remaining? */ ++ SENDERR(EINVAL); ++ } ++ ++ /* check required extensions */ ++ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, ++ "pfkey_msg_parse: " ++ "extensions permitted=%08x, seen=%08x, required=%08x.\n", ++ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type], ++ extensions_seen, ++ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]); ++ ++ /* don't check further if it is an error return message since it ++ may not have a body */ ++ if(pfkey_msg->sadb_msg_errno) { ++ SENDERR(-error); ++ } ++ ++ if((extensions_seen & ++ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) != ++ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "required extensions missing:%08x.\n", ++ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type] - ++ (extensions_seen & ++ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type])); ++ SENDERR(EINVAL); ++ } ++ ++ if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type == SADB_X_DELFLOW) ++ && ((extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW) ++ != SADB_X_EXT_ADDRESS_DELFLOW) ++ && (((extensions_seen & (1<<SADB_EXT_SA)) != (1<<SADB_EXT_SA)) ++ || ((((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_flags ++ & SADB_X_SAFLAGS_CLEARFLOW) ++ != SADB_X_SAFLAGS_CLEARFLOW))) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "required SADB_X_DELFLOW extensions missing: either %08x must be present or %08x must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n", ++ SADB_X_EXT_ADDRESS_DELFLOW ++ - (extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW), ++ (1<<SADB_EXT_SA) - (extensions_seen & (1<<SADB_EXT_SA))); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_msg->sadb_msg_type) { ++ case SADB_ADD: ++ case SADB_UPDATE: ++ /* check maturity */ ++ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != ++ SADB_SASTATE_MATURE) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "state=%d for add or update should be MATURE=%d.\n", ++ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, ++ SADB_SASTATE_MATURE); ++ SENDERR(EINVAL); ++ } ++ ++ /* check AH and ESP */ ++ switch(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype) { ++ case SADB_SATYPE_AH: ++ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) && ++ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_auth != ++ SADB_AALG_NONE)) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "auth alg is zero, must be non-zero for AH SAs.\n"); ++ SENDERR(EINVAL); ++ } ++ if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt != ++ SADB_EALG_NONE) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "AH handed encalg=%d, must be zero.\n", ++ ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt); ++ SENDERR(EINVAL); ++ } ++ break; ++ case SADB_SATYPE_ESP: ++ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) && ++ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != ++ SADB_EALG_NONE)) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "encrypt alg=%d is zero, must be non-zero for ESP=%d SAs.\n", ++ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); ++ SENDERR(EINVAL); ++ } ++ if((((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt == ++ SADB_EALG_NULL) && ++ (((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth == ++ SADB_AALG_NONE) ) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "ESP handed encNULL+authNONE, illegal combination.\n"); ++ SENDERR(EINVAL); ++ } ++ break; ++ case SADB_X_SATYPE_COMP: ++ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) && ++ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != ++ SADB_EALG_NONE)) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n", ++ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); ++ SENDERR(EINVAL); ++ } ++ if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth != ++ SADB_AALG_NONE) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "COMP handed auth=%d, must be zero.\n", ++ ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth); ++ SENDERR(EINVAL); ++ } ++ break; ++ default: ++ break; ++ } ++ if(ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi) <= 255) { ++ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, ++ "pfkey_msg_parse: " ++ "spi=%08x must be > 255.\n", ++ ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi)); ++ SENDERR(EINVAL); ++ } ++ default: ++ break; ++ } ++errlab: ++ ++ return error; ++} ++ ++/* ++ * $Log: pfkey_v2_parse.c,v $ ++ * Revision 1.59 2004/04/18 03:03:49 mcr ++ * renamed common include files from pluto directory. ++ * ++ * Revision 1.58 2004/03/08 01:59:08 ken ++ * freeswan.h -> openswan.h ++ * ++ * Revision 1.57 2003/12/10 01:20:19 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.56 2003/12/04 23:01:12 mcr ++ * removed ipsec_netlink.h ++ * ++ * Revision 1.55 2003/11/07 01:30:37 ken ++ * Cast sizeof() to int to keep things 64bit clean ++ * ++ * Revision 1.54 2003/10/31 02:27:12 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.53.20.2 2003/10/29 01:11:32 mcr ++ * added debugging for pfkey library. ++ * ++ * Revision 1.53.20.1 2003/09/21 13:59:44 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.53 2003/01/30 02:32:09 rgb ++ * ++ * Rename SAref table macro names for clarity. ++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. ++ * ++ * Revision 1.52 2002/12/30 06:53:07 mcr ++ * deal with short SA structures... #if 0 out for now. Probably ++ * not quite the right way. ++ * ++ * Revision 1.51 2002/12/13 18:16:02 mcr ++ * restored sa_ref code ++ * ++ * Revision 1.50 2002/12/13 18:06:52 mcr ++ * temporarily removed sadb_x_sa_ref reference for 2.xx ++ * ++ * Revision 1.49 2002/10/05 05:02:58 dhr ++ * ++ * C labels go on statements ++ * ++ * Revision 1.48 2002/09/20 15:40:45 rgb ++ * Added sadb_x_sa_ref to struct sadb_sa. ++ * ++ * Revision 1.47 2002/09/20 05:01:31 rgb ++ * Fixed usage of pfkey_lib_debug. ++ * Format for function declaration style consistency. ++ * Added text labels to elucidate numeric values presented. ++ * Re-organised debug output to reduce noise in output. ++ * ++ * Revision 1.46 2002/07/24 18:44:54 rgb ++ * Type fiddling to tame ia64 compiler. ++ * ++ * Revision 1.45 2002/05/23 07:14:11 rgb ++ * Cleaned up %p variants to 0p%p for test suite cleanup. ++ * ++ * Revision 1.44 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.43 2002/04/24 07:36:40 mcr ++ * Moved from ./lib/pfkey_v2_parse.c,v ++ * ++ * Revision 1.42 2002/01/29 22:25:36 rgb ++ * Re-add ipsec_kversion.h to keep MALLOC happy. ++ * ++ * Revision 1.41 2002/01/29 01:59:10 mcr ++ * removal of kversions.h - sources that needed it now use ipsec_param.h. ++ * updating of IPv6 structures to match latest in6.h version. ++ * removed dead code from openswan.h that also duplicated kversions.h ++ * code. ++ * ++ * Revision 1.40 2002/01/20 20:34:50 mcr ++ * added pfkey_v2_sadb_type_string to decode sadb_type to string. ++ * ++ * Revision 1.39 2001/11/27 05:29:22 mcr ++ * pfkey parses are now maintained by a structure ++ * that includes their name for debug purposes. ++ * DEBUGGING() macro changed so that it takes a debug ++ * level so that pf_key() can use this to decode the ++ * structures without innundanting humans. ++ * Also uses pfkey_v2_sadb_ext_string() in messages. ++ * ++ * Revision 1.38 2001/11/06 19:47:47 rgb ++ * Added packet parameter to lifetime and comb structures. ++ * ++ * Revision 1.37 2001/10/18 04:45:24 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/openswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.36 2001/06/14 19:35:16 rgb ++ * Update copyright date. ++ * ++ * Revision 1.35 2001/05/03 19:44:51 rgb ++ * Standardise on SENDERR() macro. ++ * ++ * Revision 1.34 2001/03/16 07:41:51 rgb ++ * Put openswan.h include before pluto includes. ++ * ++ * Revision 1.33 2001/02/27 07:13:51 rgb ++ * Added satype2name() function. ++ * Added text to default satype_tbl entry. ++ * Added satype2name() conversions for most satype debug output. ++ * ++ * Revision 1.32 2001/02/26 20:01:09 rgb ++ * Added internal IP protocol 61 for magic SAs. ++ * Ditch unused sadb_satype2proto[], replaced by satype2proto(). ++ * Re-formatted debug output (split lines, consistent spacing). ++ * Removed acquire, register and expire requirements for a known satype. ++ * Changed message type checking to a switch structure. ++ * Verify expected NULL auth for IPCOMP. ++ * Enforced spi > 0x100 requirement, now that pass uses a magic SA for ++ * appropriate message types. ++ * ++ * Revision 1.31 2000/12/01 07:09:00 rgb ++ * Added ipcomp sanity check to require encalgo is set. ++ * ++ * Revision 1.30 2000/11/17 18:10:30 rgb ++ * Fixed bugs mostly relating to spirange, to treat all spi variables as ++ * network byte order since this is the way PF_KEYv2 stored spis. ++ * ++ * Revision 1.29 2000/10/12 00:02:39 rgb ++ * Removed 'format, ##' nonsense from debug macros for RH7.0. ++ * ++ * Revision 1.28 2000/09/20 16:23:04 rgb ++ * Remove over-paranoid extension check in the presence of sadb_msg_errno. ++ * ++ * Revision 1.27 2000/09/20 04:04:21 rgb ++ * Changed static functions to DEBUG_NO_STATIC to reveal function names in ++ * oopsen. ++ * ++ * Revision 1.26 2000/09/15 11:37:02 rgb ++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk> ++ * IPCOMP zlib deflate code. ++ * ++ * Revision 1.25 2000/09/12 22:35:37 rgb ++ * Restructured to remove unused extensions from CLEARFLOW messages. ++ * ++ * Revision 1.24 2000/09/12 18:59:54 rgb ++ * Added Gerhard's IPv6 support to pfkey parts of libopenswan. ++ * ++ * Revision 1.23 2000/09/12 03:27:00 rgb ++ * Moved DEBUGGING definition to compile kernel with debug off. ++ * ++ * Revision 1.22 2000/09/09 06:39:27 rgb ++ * Restrict pfkey errno check to downward messages only. ++ * ++ * Revision 1.21 2000/09/08 19:22:34 rgb ++ * Enabled pfkey_sens_parse(). ++ * Added check for errno on downward acquire messages only. ++ * ++ * Revision 1.20 2000/09/01 18:48:23 rgb ++ * Fixed reserved check bug and added debug output in ++ * pfkey_supported_parse(). ++ * Fixed debug output label bug in pfkey_ident_parse(). ++ * ++ * Revision 1.19 2000/08/27 01:55:26 rgb ++ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code. ++ * ++ * Revision 1.18 2000/08/24 17:00:36 rgb ++ * Ignore unknown extensions instead of failing. ++ * ++ * Revision 1.17 2000/06/02 22:54:14 rgb ++ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support. ++ * ++ * Revision 1.16 2000/05/10 19:25:11 rgb ++ * Fleshed out proposal and supported extensions. ++ * ++ * Revision 1.15 2000/01/24 21:15:31 rgb ++ * Added disabled pluto pfkey lib debug flag. ++ * Added algo debugging reporting. ++ * ++ * Revision 1.14 2000/01/22 23:24:29 rgb ++ * Added new functions proto2satype() and satype2proto() and lookup ++ * table satype_tbl. Also added proto2name() since it was easy. ++ * ++ * Revision 1.13 2000/01/21 09:43:59 rgb ++ * Cast ntohl(spi) as (unsigned long int) to shut up compiler. ++ * ++ * Revision 1.12 2000/01/21 06:28:19 rgb ++ * Added address cases for eroute flows. ++ * Indented compiler directives for readability. ++ * Added klipsdebug switching capability. ++ * ++ * Revision 1.11 1999/12/29 21:14:59 rgb ++ * Fixed debug text cut and paste typo. ++ * ++ * Revision 1.10 1999/12/10 17:45:24 rgb ++ * Added address debugging. ++ * ++ * Revision 1.9 1999/12/09 23:11:42 rgb ++ * Ditched <string.h> include since we no longer use memset(). ++ * Use new pfkey_extensions_init() instead of memset(). ++ * Added check for SATYPE in pfkey_msg_build(). ++ * Tidy up comments and debugging comments. ++ * ++ * Revision 1.8 1999/12/07 19:55:26 rgb ++ * Removed unused first argument from extension parsers. ++ * Removed static pluto debug flag. ++ * Moved message type and state checking to pfkey_msg_parse(). ++ * Changed print[fk] type from lx to x to quiet compiler. ++ * Removed redundant remain check. ++ * Changed __u* types to uint* to avoid use of asm/types.h and ++ * sys/types.h in userspace code. ++ * ++ * Revision 1.7 1999/12/01 22:20:51 rgb ++ * Moved pfkey_lib_debug variable into the library. ++ * Added pfkey version check into header parsing. ++ * Added check for SATYPE only for those extensions that require a ++ * non-zero value. ++ * ++ * Revision 1.6 1999/11/27 11:58:05 rgb ++ * Added ipv6 headers. ++ * Moved sadb_satype2proto protocol lookup table from ++ * klips/net/ipsec/pfkey_v2_parser.c. ++ * Enable lifetime_current checking. ++ * Debugging error messages added. ++ * Add argument to pfkey_msg_parse() for direction. ++ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. ++ * Add CVS log entry to bottom of file. ++ * Moved auth and enc alg check to pfkey_msg_parse(). ++ * Enable accidentally disabled spirange parsing. ++ * Moved protocol/algorithm checks from klips/net/ipsec/pfkey_v2_parser.c ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/prng.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,201 @@ ++/* ++ * crypto-class pseudorandom number generator ++ * currently uses same algorithm as RC4(TM), from Schneier 2nd ed p397 ++ * Copyright (C) 2002 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: prng.c,v 1.6 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++/* ++ - prng_init - initialize PRNG from a key ++ */ ++void ++prng_init(prng, key, keylen) ++struct prng *prng; ++const unsigned char *key; ++size_t keylen; ++{ ++ unsigned char k[256]; ++ int i, j; ++ unsigned const char *p; ++ unsigned const char *keyend = key + keylen; ++ unsigned char t; ++ ++ for (i = 0; i <= 255; i++) ++ prng->sbox[i] = i; ++ p = key; ++ for (i = 0; i <= 255; i++) { ++ k[i] = *p++; ++ if (p >= keyend) ++ p = key; ++ } ++ j = 0; ++ for (i = 0; i <= 255; i++) { ++ j = (j + prng->sbox[i] + k[i]) & 0xff; ++ t = prng->sbox[i]; ++ prng->sbox[i] = prng->sbox[j]; ++ prng->sbox[j] = t; ++ k[i] = 0; /* clear out key memory */ ++ } ++ prng->i = 0; ++ prng->j = 0; ++ prng->count = 0; ++} ++ ++/* ++ - prng_bytes - get some pseudorandom bytes from PRNG ++ */ ++void ++prng_bytes(prng, dst, dstlen) ++struct prng *prng; ++unsigned char *dst; ++size_t dstlen; ++{ ++ int i, j, t; ++ unsigned char *p = dst; ++ size_t remain = dstlen; ++# define MAX 4000000000ul ++ ++ while (remain > 0) { ++ i = (prng->i + 1) & 0xff; ++ prng->i = i; ++ j = (prng->j + prng->sbox[i]) & 0xff; ++ prng->j = j; ++ t = prng->sbox[i]; ++ prng->sbox[i] = prng->sbox[j]; ++ prng->sbox[j] = t; ++ t = (t + prng->sbox[i]) & 0xff; ++ *p++ = prng->sbox[t]; ++ remain--; ++ } ++ if (prng->count < MAX - dstlen) ++ prng->count += dstlen; ++ else ++ prng->count = MAX; ++} ++ ++/* ++ - prnt_count - how many bytes have been extracted from PRNG so far? ++ */ ++unsigned long ++prng_count(prng) ++struct prng *prng; ++{ ++ return prng->count; ++} ++ ++/* ++ - prng_final - clear out PRNG to ensure nothing left in memory ++ */ ++void ++prng_final(prng) ++struct prng *prng; ++{ ++ int i; ++ ++ for (i = 0; i <= 255; i++) ++ prng->sbox[i] = 0; ++ prng->i = 0; ++ prng->j = 0; ++ prng->count = 0; /* just for good measure */ ++} ++ ++ ++ ++#ifdef PRNG_MAIN ++ ++#include <stdio.h> ++ ++void regress(); ++ ++int ++main(argc, argv) ++int argc; ++char *argv[]; ++{ ++ struct prng pr; ++ unsigned char buf[100]; ++ unsigned char *p; ++ size_t n; ++ ++ if (argc < 2) { ++ fprintf(stderr, "Usage: %s {key|-r}\n", argv[0]); ++ exit(2); ++ } ++ ++ if (strcmp(argv[1], "-r") == 0) { ++ regress(); ++ fprintf(stderr, "regress() returned?!?\n"); ++ exit(1); ++ } ++ ++ prng_init(&pr, argv[1], strlen(argv[1])); ++ prng_bytes(&pr, buf, 32); ++ printf("0x"); ++ for (p = buf, n = 32; n > 0; p++, n--) ++ printf("%02x", *p); ++ printf("\n%lu bytes\n", prng_count(&pr)); ++ prng_final(&pr); ++ exit(0); ++} ++ ++void ++regress() ++{ ++ struct prng pr; ++ unsigned char buf[100]; ++ unsigned char *p; ++ size_t n; ++ /* somewhat non-random sample key */ ++ unsigned char key[] = "here we go gathering nuts in May"; ++ /* first thirty bytes of output from that key */ ++ unsigned char good[] = "\x3f\x02\x8e\x4a\x2a\xea\x23\x18\x92\x7c" ++ "\x09\x52\x83\x61\xaa\x26\xce\xbb\x9d\x71" ++ "\x71\xe5\x10\x22\xaf\x60\x54\x8d\x5b\x28"; ++ int nzero, none; ++ int show = 0; ++ ++ prng_init(&pr, key, strlen(key)); ++ prng_bytes(&pr, buf, sizeof(buf)); ++ for (p = buf, n = sizeof(buf); n > 0; p++, n--) { ++ if (*p == 0) ++ nzero++; ++ if (*p == 255) ++ none++; ++ } ++ if (nzero > 3 || none > 3) { ++ fprintf(stderr, "suspiciously non-random output!\n"); ++ show = 1; ++ } ++ if (memcmp(buf, good, strlen(good)) != 0) { ++ fprintf(stderr, "incorrect output!\n"); ++ show = 1; ++ } ++ if (show) { ++ fprintf(stderr, "0x"); ++ for (p = buf, n = sizeof(buf); n > 0; p++, n--) ++ fprintf(stderr, "%02x", *p); ++ fprintf(stderr, "\n"); ++ exit(1); ++ } ++ if (prng_count(&pr) != sizeof(buf)) { ++ fprintf(stderr, "got %u bytes, but count is %lu\n", ++ sizeof(buf), prng_count(&pr)); ++ exit(1); ++ } ++ prng_final(&pr); ++ exit(0); ++} ++ ++#endif /* PRNG_MAIN */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/rangetoa.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,60 @@ ++/* ++ * convert binary form of address range to ASCII ++ * Copyright (C) 1998, 1999 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: rangetoa.c,v 1.8 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++/* ++ - rangetoa - convert address range to ASCII ++ */ ++size_t /* space needed for full conversion */ ++rangetoa(addrs, format, dst, dstlen) ++struct in_addr addrs[2]; ++int format; /* character */ ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ size_t len; ++ size_t rest; ++ int n; ++ char *p; ++ ++ switch (format) { ++ case 0: ++ break; ++ default: ++ return 0; ++ break; ++ } ++ ++ len = addrtoa(addrs[0], 0, dst, dstlen); ++ if (len < dstlen) ++ for (p = dst + len - 1, n = 3; len < dstlen && n > 0; ++ p++, len++, n--) ++ *p = '.'; ++ else ++ p = NULL; ++ if (len < dstlen) ++ rest = dstlen - len; ++ else { ++ if (dstlen > 0) ++ *(dst + dstlen - 1) = '\0'; ++ rest = 0; ++ } ++ ++ len += addrtoa(addrs[1], 0, p, rest); ++ ++ return len; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/satot.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,133 @@ ++/* ++ * convert from binary form of SA ID to text ++ * Copyright (C) 2000, 2001 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: satot.c,v 1.12 2004/04/11 17:10:21 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++static struct typename { ++ char type; ++ char *name; ++} typenames[] = { ++ { SA_AH, "ah" }, ++ { SA_ESP, "esp" }, ++ { SA_IPIP, "tun" }, ++ { SA_COMP, "comp" }, ++ { SA_INT, "int" }, ++ { 0, NULL } ++}; ++ ++/* ++ - satot - convert SA to text "ah507@1.2.3.4" ++ */ ++size_t /* space needed for full conversion */ ++satot(sa, format, dst, dstlen) ++const ip_said *sa; ++int format; /* character */ ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ size_t len = 0; /* 0 means "not recognized yet" */ ++ int base; ++ int showversion; /* use delimiter to show IP version? */ ++ struct typename *tn; ++ char *p; ++ char *pre; ++ char buf[10+1+ULTOT_BUF+ADDRTOT_BUF]; ++ char unk[10]; ++ ++ switch (format) { ++ case 0: ++ base = 16; ++ showversion = 1; ++ break; ++ case 'f': ++ base = 17; ++ showversion = 1; ++ break; ++ case 'x': ++ base = 'x'; ++ showversion = 0; ++ break; ++ case 'd': ++ base = 10; ++ showversion = 0; ++ break; ++ default: ++ return 0; ++ break; ++ } ++ ++ memset(buf, 0, sizeof(buf)); ++ ++ pre = NULL; ++ for (tn = typenames; tn->name != NULL; tn++) ++ if (sa->proto == tn->type) { ++ pre = tn->name; ++ break; /* NOTE BREAK OUT */ ++ } ++ if (pre == NULL) { /* unknown protocol */ ++ strcpy(unk, "unk"); ++ (void) ultot((unsigned char)sa->proto, 10, unk+strlen(unk), ++ sizeof(unk)-strlen(unk)); ++ pre = unk; ++ } ++ ++ if (strcmp(pre, PASSTHROUGHTYPE) == 0 && ++ sa->spi == PASSTHROUGHSPI && ++ isunspecaddr(&sa->dst)) { ++ strcpy(buf, (addrtypeof(&sa->dst) == AF_INET) ? ++ PASSTHROUGH4NAME : ++ PASSTHROUGH6NAME); ++ len = strlen(buf); ++ } ++ ++ if (sa->proto == SA_INT) { ++ switch (ntohl(sa->spi)) { ++ case SPI_PASS: p = "%pass"; break; ++ case SPI_DROP: p = "%drop"; break; ++ case SPI_REJECT: p = "%reject"; break; ++ case SPI_HOLD: p = "%hold"; break; ++ case SPI_TRAP: p = "%trap"; break; ++ case SPI_TRAPSUBNET: p = "%trapsubnet"; break; ++ default: p = NULL; break; ++ } ++ if (p != NULL) { ++ strcpy(buf, p); ++ len = strlen(buf); ++ } ++ } ++ ++ if (len == 0) { /* general case needed */ ++ strcpy(buf, pre); ++ len = strlen(buf); ++ if (showversion) { ++ *(buf+len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' : ++ ':'; ++ len++; ++ *(buf+len) = '\0'; ++ } ++ len += ultot(ntohl(sa->spi), base, buf+len, sizeof(buf)-len); ++ *(buf+len-1) = '@'; ++ len += addrtot(&sa->dst, 0, buf+len, sizeof(buf)-len); ++ *(buf+len) = '\0'; ++ } ++ ++ if (dst != NULL) { ++ if (len > dstlen) ++ *(buf+dstlen-1) = '\0'; ++ strcpy(dst, buf); ++ } ++ return len; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/subnetof.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,59 @@ ++/* ++ * minor network-address manipulation utilities ++ * Copyright (C) 1998, 1999 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: subnetof.c,v 1.7 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++/* ++ - subnetof - given address and mask, return subnet part ++ */ ++struct in_addr ++subnetof(addr, mask) ++struct in_addr addr; ++struct in_addr mask; ++{ ++ struct in_addr result; ++ ++ result.s_addr = addr.s_addr & mask.s_addr; ++ return result; ++} ++ ++/* ++ - hostof - given address and mask, return host part ++ */ ++struct in_addr ++hostof(addr, mask) ++struct in_addr addr; ++struct in_addr mask; ++{ ++ struct in_addr result; ++ ++ result.s_addr = addr.s_addr & ~mask.s_addr; ++ return result; ++} ++ ++/* ++ - broadcastof - given (network) address and mask, return broadcast address ++ */ ++struct in_addr ++broadcastof(addr, mask) ++struct in_addr addr; ++struct in_addr mask; ++{ ++ struct in_addr result; ++ ++ result.s_addr = addr.s_addr | ~mask.s_addr; ++ return result; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/subnettoa.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,61 @@ ++/* ++ * convert binary form of subnet description to ASCII ++ * Copyright (C) 1998, 1999 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: subnettoa.c,v 1.10 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++/* ++ - subnettoa - convert address and mask to ASCII "addr/mask" ++ * Output expresses the mask as a bit count if possible, else dotted decimal. ++ */ ++size_t /* space needed for full conversion */ ++subnettoa(addr, mask, format, dst, dstlen) ++struct in_addr addr; ++struct in_addr mask; ++int format; /* character */ ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ size_t len; ++ size_t rest; ++ int n; ++ char *p; ++ ++ switch (format) { ++ case 0: ++ break; ++ default: ++ return 0; ++ break; ++ } ++ ++ len = addrtoa(addr, 0, dst, dstlen); ++ if (len < dstlen) { ++ dst[len - 1] = '/'; ++ p = dst + len; ++ rest = dstlen - len; ++ } else { ++ p = NULL; ++ rest = 0; ++ } ++ ++ n = masktobits(mask); ++ if (n >= 0) ++ len += ultoa((unsigned long)n, 10, p, rest); ++ else ++ len += addrtoa(mask, 0, p, rest); ++ ++ return len; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/ultoa.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,66 @@ ++/* ++ * convert unsigned long to ASCII ++ * Copyright (C) 1998, 1999 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: ultoa.c,v 1.9 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++/* ++ - ultoa - convert unsigned long to decimal ASCII ++ */ ++size_t /* length required for full conversion */ ++ultoa(n, base, dst, dstlen) ++unsigned long n; ++int base; ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ char buf[3*sizeof(unsigned long) + 1]; ++ char *bufend = buf + sizeof(buf); ++ size_t len; ++ char *p; ++ static char hex[] = "0123456789abcdef"; ++ ++ p = bufend; ++ *--p = '\0'; ++ if (base == 10) { ++ do { ++ *--p = n%10 + '0'; ++ n /= 10; ++ } while (n != 0); ++ } else if (base == 16) { ++ do { ++ *--p = hex[n&0xf]; ++ n >>= 4; ++ } while (n != 0); ++ *--p = 'x'; ++ *--p = '0'; ++ } else if (base == 8) { ++ do { ++ *--p = (n&07) + '0'; ++ n >>= 3; ++ } while (n != 0); ++ *--p = '0'; ++ } else ++ *--p = '?'; ++ ++ len = bufend - p; ++ ++ if (dstlen > 0) { ++ if (len > dstlen) ++ *(p + dstlen - 1) = '\0'; ++ strcpy(dst, p); ++ } ++ return len; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/libfreeswan/ultot.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,82 @@ ++/* ++ * convert unsigned long to text ++ * Copyright (C) 2000 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: ultot.c,v 1.4 2004/04/11 17:39:25 mcr Exp $ ++ */ ++#include "openswan.h" ++ ++/* ++ - ultot - convert unsigned long to text ++ */ ++size_t /* length required for full conversion */ ++ultot(n, base, dst, dstlen) ++unsigned long n; ++int base; ++char *dst; /* need not be valid if dstlen is 0 */ ++size_t dstlen; ++{ ++ char buf[3*sizeof(unsigned long) + 1]; ++ char *bufend = buf + sizeof(buf); ++ size_t len; ++ char *p; ++ static char hex[] = "0123456789abcdef"; ++# define HEX32 (32/4) ++ ++ p = bufend; ++ *--p = '\0'; ++ switch (base) { ++ case 10: ++ case 'd': ++ do { ++ *--p = n%10 + '0'; ++ n /= 10; ++ } while (n != 0); ++ break; ++ case 16: ++ case 17: ++ case 'x': ++ do { ++ *--p = hex[n&0xf]; ++ n >>= 4; ++ } while (n != 0); ++ if (base == 17) ++ while (bufend - p < HEX32 + 1) ++ *--p = '0'; ++ if (base == 'x') { ++ *--p = 'x'; ++ *--p = '0'; ++ } ++ break; ++ case 8: ++ case 'o': ++ do { ++ *--p = (n&07) + '0'; ++ n >>= 3; ++ } while (n != 0); ++ if (base == 'o') ++ *--p = '0'; ++ break; ++ default: ++ return 0; ++ break; ++ } ++ ++ len = bufend - p; ++ if (dstlen > 0) { ++ if (len > dstlen) ++ *(p + dstlen - 1) = '\0'; ++ strcpy(dst, p); ++ } ++ return len; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/Makefile Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,118 @@ ++# (kernel) Makefile for IPCOMP zlib deflate code ++# Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++# Copyright (C) 2000 Svenning Soerensen ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License as published by the ++# Free Software Foundation; either version 2 of the License, or (at your ++# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++# ++# This program is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++# for more details. ++# ++# RCSID $Id: Makefile,v 1.9 2002/04/24 07:55:32 mcr Exp $ ++# ++ ++ ++ ++include ../Makefile.inc ++ ++ ++ ++ifndef TOPDIR ++TOPDIR := /usr/src/linux ++endif ++ ++ ++L_TARGET := zlib.a ++ ++obj-y := ++ ++include Makefile.objs ++ ++EXTRA_CFLAGS += $(KLIPSCOMPILE) ++ ++EXTRA_CFLAGS += -Wall ++#EXTRA_CFLAGS += -Wconversion ++#EXTRA_CFLAGS += -Wmissing-prototypes ++EXTRA_CFLAGS += -Wpointer-arith ++#EXTRA_CFLAGS += -Wcast-qual ++#EXTRA_CFLAGS += -Wmissing-declarations ++EXTRA_CFLAGS += -Wstrict-prototypes ++#EXTRA_CFLAGS += -pedantic ++#EXTRA_CFLAGS += -W ++#EXTRA_CFLAGS += -Wwrite-strings ++EXTRA_CFLAGS += -Wbad-function-cast ++EXTRA_CFLAGS += -DIPCOMP_PREFIX ++ ++.S.o: ++ $(CC) -D__ASSEMBLY__ -DNO_UNDERLINE -traditional -c $< -o $*.o ++ ++asm-obj-$(CONFIG_M586) += match586.o ++asm-obj-$(CONFIG_M586TSC) += match586.o ++asm-obj-$(CONFIG_M586MMX) += match586.o ++asm-obj-$(CONFIG_M686) += match686.o ++asm-obj-$(CONFIG_MPENTIUMIII) += match686.o ++asm-obj-$(CONFIG_MPENTIUM4) += match686.o ++asm-obj-$(CONFIG_MK6) += match586.o ++asm-obj-$(CONFIG_MK7) += match686.o ++asm-obj-$(CONFIG_MCRUSOE) += match586.o ++asm-obj-$(CONFIG_MWINCHIPC6) += match586.o ++asm-obj-$(CONFIG_MWINCHIP2) += match686.o ++asm-obj-$(CONFIG_MWINCHIP3D) += match686.o ++ ++obj-y += $(asm-obj-y) ++ifneq ($(strip $(asm-obj-y)),) ++ EXTRA_CFLAGS += -DASMV ++endif ++ ++active-objs := $(sort $(obj-y) $(obj-m)) ++L_OBJS := $(obj-y) ++M_OBJS := $(obj-m) ++MIX_OBJS := $(filter $(export-objs), $(active-objs)) ++ ++include $(TOPDIR)/Rules.make ++ ++$(obj-y) : $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h ++ ++ ++clean: ++ -rm -f *.o *.a ++ ++checkprograms: ++programs: $(L_TARGET) ++ ++# ++# $Log: Makefile,v $ ++# Revision 1.9 2002/04/24 07:55:32 mcr ++# #include patches and Makefiles for post-reorg compilation. ++# ++# Revision 1.8 2002/04/24 07:36:44 mcr ++# Moved from ./zlib/Makefile,v ++# ++# Revision 1.7 2002/03/27 23:34:35 mcr ++# added programs: target ++# ++# Revision 1.6 2001/12/05 20:19:08 henry ++# use new compile-control variable ++# ++# Revision 1.5 2001/11/27 16:38:08 mcr ++# added new "checkprograms" target to deal with programs that ++# are required for "make check", but that may not be ready to ++# build for every user due to external dependancies. ++# ++# Revision 1.4 2001/10/24 14:46:24 henry ++# Makefile.inc ++# ++# Revision 1.3 2001/04/21 23:05:24 rgb ++# Update asm directives for 2.4 style makefiles. ++# ++# Revision 1.2 2001/01/29 22:22:00 rgb ++# Convert to 2.4 new style with back compat. ++# ++# Revision 1.1.1.1 2000/09/29 18:51:33 rgb ++# zlib_beginnings ++# ++# +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/Makefile.objs Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,27 @@ ++obj-$(CONFIG_IPSEC_IPCOMP) += adler32.o ++obj-$(CONFIG_IPSEC_IPCOMP) += deflate.o ++obj-$(CONFIG_IPSEC_IPCOMP) += infblock.o ++obj-$(CONFIG_IPSEC_IPCOMP) += infcodes.o ++obj-$(CONFIG_IPSEC_IPCOMP) += inffast.o ++obj-$(CONFIG_IPSEC_IPCOMP) += inflate.o ++obj-$(CONFIG_IPSEC_IPCOMP) += inftrees.o ++obj-$(CONFIG_IPSEC_IPCOMP) += infutil.o ++obj-$(CONFIG_IPSEC_IPCOMP) += trees.o ++obj-$(CONFIG_IPSEC_IPCOMP) += zutil.o ++ ++asm-obj-$(CONFIG_M586) += ${LIBZLIBSRCDIR}/match586.o ++asm-obj-$(CONFIG_M586TSC) += ${LIBZLIBSRCDIR}/match586.o ++asm-obj-$(CONFIG_M586MMX) += ${LIBZLIBSRCDIR}/match586.o ++asm-obj-$(CONFIG_M686) += ${LIBZLIBSRCDIR}/match686.o ++asm-obj-$(CONFIG_MPENTIUMIII) += ${LIBZLIBSRCDIR}/match686.o ++asm-obj-$(CONFIG_MPENTIUM4) += ${LIBZLIBSRCDIR}/match686.o ++asm-obj-$(CONFIG_MK6) += ${LIBZLIBSRCDIR}/match586.o ++asm-obj-$(CONFIG_MK7) += ${LIBZLIBSRCDIR}/match686.o ++asm-obj-$(CONFIG_MCRUSOE) += ${LIBZLIBSRCDIR}/match586.o ++asm-obj-$(CONFIG_MWINCHIPC6) += ${LIBZLIBSRCDIR}/match586.o ++asm-obj-$(CONFIG_MWINCHIP2) += ${LIBZLIBSRCDIR}/match686.o ++asm-obj-$(CONFIG_MWINCHIP3D) += ${LIBZLIBSRCDIR}/match686.o ++ ++EXTRA_CFLAGS += -DIPCOMP_PREFIX ++ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/README Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,147 @@ ++zlib 1.1.4 is a general purpose data compression library. All the code ++is thread safe. The data format used by the zlib library ++is described by RFCs (Request for Comments) 1950 to 1952 in the files ++http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate ++format) and rfc1952.txt (gzip format). These documents are also available in ++other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html ++ ++All functions of the compression library are documented in the file zlib.h ++(volunteer to write man pages welcome, contact jloup@gzip.org). A usage ++example of the library is given in the file example.c which also tests that ++the library is working correctly. Another example is given in the file ++minigzip.c. The compression library itself is composed of all source files ++except example.c and minigzip.c. ++ ++To compile all files and run the test program, follow the instructions ++given at the top of Makefile. In short "make test; make install" ++should work for most machines. For Unix: "./configure; make test; make install" ++For MSDOS, use one of the special makefiles such as Makefile.msc. ++For VMS, use Make_vms.com or descrip.mms. ++ ++Questions about zlib should be sent to <zlib@gzip.org>, or to ++Gilles Vollant <info@winimage.com> for the Windows DLL version. ++The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/ ++Before reporting a problem, please check this site to verify that ++you have the latest version of zlib; otherwise get the latest version and ++check whether the problem still exists or not. ++ ++PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html ++before asking for help. ++ ++Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997 ++issue of Dr. Dobb's Journal; a copy of the article is available in ++http://dogma.net/markn/articles/zlibtool/zlibtool.htm ++ ++The changes made in version 1.1.4 are documented in the file ChangeLog. ++The only changes made since 1.1.3 are bug corrections: ++ ++- ZFREE was repeated on same allocation on some error conditions. ++ This creates a security problem described in ++ http://www.zlib.org/advisory-2002-03-11.txt ++- Returned incorrect error (Z_MEM_ERROR) on some invalid data ++- Avoid accesses before window for invalid distances with inflate window ++ less than 32K. ++- force windowBits > 8 to avoid a bug in the encoder for a window size ++ of 256 bytes. (A complete fix will be available in 1.1.5). ++ ++The beta version 1.1.5beta includes many more changes. A new official ++version 1.1.5 will be released as soon as extensive testing has been ++completed on it. ++ ++ ++Unsupported third party contributions are provided in directory "contrib". ++ ++A Java implementation of zlib is available in the Java Development Kit ++http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html ++See the zlib home page http://www.zlib.org for details. ++ ++A Perl interface to zlib written by Paul Marquess <pmarquess@bfsec.bt.co.uk> ++is in the CPAN (Comprehensive Perl Archive Network) sites ++http://www.cpan.org/modules/by-module/Compress/ ++ ++A Python interface to zlib written by A.M. Kuchling <amk@magnet.com> ++is available in Python 1.5 and later versions, see ++http://www.python.org/doc/lib/module-zlib.html ++ ++A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> ++is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html ++ ++An experimental package to read and write files in .zip format, ++written on top of zlib by Gilles Vollant <info@winimage.com>, is ++available at http://www.winimage.com/zLibDll/unzip.html ++and also in the contrib/minizip directory of zlib. ++ ++ ++Notes for some targets: ++ ++- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc ++ and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL ++ The zlib DLL support was initially done by Alessandro Iacopetti and is ++ now maintained by Gilles Vollant <info@winimage.com>. Check the zlib DLL ++ home page at http://www.winimage.com/zLibDll ++ ++ From Visual Basic, you can call the DLL functions which do not take ++ a structure as argument: compress, uncompress and all gz* functions. ++ See contrib/visual-basic.txt for more information, or get ++ http://www.tcfb.com/dowseware/cmp-z-it.zip ++ ++- For 64-bit Irix, deflate.c must be compiled without any optimization. ++ With -O, one libpng test fails. The test works in 32 bit mode (with ++ the -n32 compiler flag). The compiler bug has been reported to SGI. ++ ++- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 ++ it works when compiled with cc. ++ ++- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 ++ is necessary to get gzprintf working correctly. This is done by configure. ++ ++- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works ++ with other compilers. Use "make test" to check your compiler. ++ ++- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. ++ ++- For Turbo C the small model is supported only with reduced performance to ++ avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 ++ ++- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html ++ Per Harald Myrvang <perm@stud.cs.uit.no> ++ ++ ++Acknowledgments: ++ ++ The deflate format used by zlib was defined by Phil Katz. The deflate ++ and zlib specifications were written by L. Peter Deutsch. Thanks to all the ++ people who reported problems and suggested various improvements in zlib; ++ they are too numerous to cite here. ++ ++Copyright notice: ++ ++ (C) 1995-2002 Jean-loup Gailly and Mark Adler ++ ++ This software is provided 'as-is', without any express or implied ++ warranty. In no event will the authors be held liable for any damages ++ arising from the use of this software. ++ ++ Permission is granted to anyone to use this software for any purpose, ++ including commercial applications, and to alter it and redistribute it ++ freely, subject to the following restrictions: ++ ++ 1. The origin of this software must not be misrepresented; you must not ++ claim that you wrote the original software. If you use this software ++ in a product, an acknowledgment in the product documentation would be ++ appreciated but is not required. ++ 2. Altered source versions must be plainly marked as such, and must not be ++ misrepresented as being the original software. ++ 3. This notice may not be removed or altered from any source distribution. ++ ++ Jean-loup Gailly Mark Adler ++ jloup@gzip.org madler@alumni.caltech.edu ++ ++If you use the zlib library in a product, we would appreciate *not* ++receiving lengthy legal documents to sign. The sources are provided ++for free but without warranty of any kind. The library has been ++entirely written by Jean-loup Gailly and Mark Adler; it does not ++include third-party code. ++ ++If you redistribute modified sources, we would appreciate that you include ++in the file ChangeLog history information documenting your changes. +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/README.freeswan Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,13 @@ ++The only changes made to these files for use in FreeS/WAN are: ++ ++ - In zconf.h, macros are defined to prefix global symbols with "ipcomp_" ++ (or "_ipcomp"), when compiled with -DIPCOMP_PREFIX. ++ - The copyright strings are defined local (static) ++ ++ The above changes are made to avoid name collisions with ppp_deflate ++ and ext2compr. ++ ++ - Files not needed for FreeS/WAN have been removed ++ ++ See the "README" file for information about where to obtain the complete ++ zlib package. +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/adler32.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,49 @@ ++/* adler32.c -- compute the Adler-32 checksum of a data stream ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* @(#) $Id: adler32.c,v 1.4 2002/04/24 07:55:32 mcr Exp $ */ ++ ++#include <zlib/zlib.h> ++#include "zconf.h" ++ ++#define BASE 65521L /* largest prime smaller than 65536 */ ++#define NMAX 5552 ++/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ ++ ++#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} ++#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); ++#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); ++#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); ++#define DO16(buf) DO8(buf,0); DO8(buf,8); ++ ++/* ========================================================================= */ ++uLong ZEXPORT adler32(adler, buf, len) ++ uLong adler; ++ const Bytef *buf; ++ uInt len; ++{ ++ unsigned long s1 = adler & 0xffff; ++ unsigned long s2 = (adler >> 16) & 0xffff; ++ int k; ++ ++ if (buf == Z_NULL) return 1L; ++ ++ while (len > 0) { ++ k = len < NMAX ? len : NMAX; ++ len -= k; ++ while (k >= 16) { ++ DO16(buf); ++ buf += 16; ++ k -= 16; ++ } ++ if (k != 0) do { ++ s1 += *buf++; ++ s2 += s1; ++ } while (--k); ++ s1 %= BASE; ++ s2 %= BASE; ++ } ++ return (s2 << 16) | s1; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/deflate.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1351 @@ ++/* deflate.c -- compress data using the deflation algorithm ++ * Copyright (C) 1995-2002 Jean-loup Gailly. ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* ++ * ALGORITHM ++ * ++ * The "deflation" process depends on being able to identify portions ++ * of the input text which are identical to earlier input (within a ++ * sliding window trailing behind the input currently being processed). ++ * ++ * The most straightforward technique turns out to be the fastest for ++ * most input files: try all possible matches and select the longest. ++ * The key feature of this algorithm is that insertions into the string ++ * dictionary are very simple and thus fast, and deletions are avoided ++ * completely. Insertions are performed at each input character, whereas ++ * string matches are performed only when the previous match ends. So it ++ * is preferable to spend more time in matches to allow very fast string ++ * insertions and avoid deletions. The matching algorithm for small ++ * strings is inspired from that of Rabin & Karp. A brute force approach ++ * is used to find longer strings when a small match has been found. ++ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze ++ * (by Leonid Broukhis). ++ * A previous version of this file used a more sophisticated algorithm ++ * (by Fiala and Greene) which is guaranteed to run in linear amortized ++ * time, but has a larger average cost, uses more memory and is patented. ++ * However the F&G algorithm may be faster for some highly redundant ++ * files if the parameter max_chain_length (described below) is too large. ++ * ++ * ACKNOWLEDGEMENTS ++ * ++ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and ++ * I found it in 'freeze' written by Leonid Broukhis. ++ * Thanks to many people for bug reports and testing. ++ * ++ * REFERENCES ++ * ++ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". ++ * Available in ftp://ds.internic.net/rfc/rfc1951.txt ++ * ++ * A description of the Rabin and Karp algorithm is given in the book ++ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. ++ * ++ * Fiala,E.R., and Greene,D.H. ++ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 ++ * ++ */ ++ ++/* @(#) $Id: deflate.c,v 1.3 2002/04/24 07:36:44 mcr Exp $ */ ++ ++#include "deflate.h" ++ ++local const char deflate_copyright[] = ++ " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; ++/* ++ If you use the zlib library in a product, an acknowledgment is welcome ++ in the documentation of your product. If for some reason you cannot ++ include such an acknowledgment, I would appreciate that you keep this ++ copyright string in the executable of your product. ++ */ ++ ++/* =========================================================================== ++ * Function prototypes. ++ */ ++typedef enum { ++ need_more, /* block not completed, need more input or more output */ ++ block_done, /* block flush performed */ ++ finish_started, /* finish started, need only more output at next deflate */ ++ finish_done /* finish done, accept no more input or output */ ++} block_state; ++ ++typedef block_state (*compress_func) OF((deflate_state *s, int flush)); ++/* Compression function. Returns the block state after the call. */ ++ ++local void fill_window OF((deflate_state *s)); ++local block_state deflate_stored OF((deflate_state *s, int flush)); ++local block_state deflate_fast OF((deflate_state *s, int flush)); ++local block_state deflate_slow OF((deflate_state *s, int flush)); ++local void lm_init OF((deflate_state *s)); ++local void putShortMSB OF((deflate_state *s, uInt b)); ++local void flush_pending OF((z_streamp strm)); ++local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); ++#ifdef ASMV ++ void match_init OF((void)); /* asm code initialization */ ++ uInt longest_match OF((deflate_state *s, IPos cur_match)); ++#else ++local uInt longest_match OF((deflate_state *s, IPos cur_match)); ++#endif ++ ++#ifdef DEBUG ++local void check_match OF((deflate_state *s, IPos start, IPos match, ++ int length)); ++#endif ++ ++/* =========================================================================== ++ * Local data ++ */ ++ ++#define NIL 0 ++/* Tail of hash chains */ ++ ++#ifndef TOO_FAR ++# define TOO_FAR 4096 ++#endif ++/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ ++ ++#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) ++/* Minimum amount of lookahead, except at the end of the input file. ++ * See deflate.c for comments about the MIN_MATCH+1. ++ */ ++ ++/* Values for max_lazy_match, good_match and max_chain_length, depending on ++ * the desired pack level (0..9). The values given below have been tuned to ++ * exclude worst case performance for pathological files. Better values may be ++ * found for specific files. ++ */ ++typedef struct config_s { ++ ush good_length; /* reduce lazy search above this match length */ ++ ush max_lazy; /* do not perform lazy search above this match length */ ++ ush nice_length; /* quit search above this match length */ ++ ush max_chain; ++ compress_func func; ++} config; ++ ++local const config configuration_table[10] = { ++/* good lazy nice chain */ ++/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ ++/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ ++/* 2 */ {4, 5, 16, 8, deflate_fast}, ++/* 3 */ {4, 6, 32, 32, deflate_fast}, ++ ++/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ ++/* 5 */ {8, 16, 32, 32, deflate_slow}, ++/* 6 */ {8, 16, 128, 128, deflate_slow}, ++/* 7 */ {8, 32, 128, 256, deflate_slow}, ++/* 8 */ {32, 128, 258, 1024, deflate_slow}, ++/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ ++ ++/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 ++ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different ++ * meaning. ++ */ ++ ++#define EQUAL 0 ++/* result of memcmp for equal strings */ ++ ++struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ ++ ++/* =========================================================================== ++ * Update a hash value with the given input byte ++ * IN assertion: all calls to to UPDATE_HASH are made with consecutive ++ * input characters, so that a running hash key can be computed from the ++ * previous key instead of complete recalculation each time. ++ */ ++#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) ++ ++ ++/* =========================================================================== ++ * Insert string str in the dictionary and set match_head to the previous head ++ * of the hash chain (the most recent string with same hash key). Return ++ * the previous length of the hash chain. ++ * If this file is compiled with -DFASTEST, the compression level is forced ++ * to 1, and no hash chains are maintained. ++ * IN assertion: all calls to to INSERT_STRING are made with consecutive ++ * input characters and the first MIN_MATCH bytes of str are valid ++ * (except for the last MIN_MATCH-1 bytes of the input file). ++ */ ++#ifdef FASTEST ++#define INSERT_STRING(s, str, match_head) \ ++ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ ++ match_head = s->head[s->ins_h], \ ++ s->head[s->ins_h] = (Pos)(str)) ++#else ++#define INSERT_STRING(s, str, match_head) \ ++ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ ++ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ ++ s->head[s->ins_h] = (Pos)(str)) ++#endif ++ ++/* =========================================================================== ++ * Initialize the hash table (avoiding 64K overflow for 16 bit systems). ++ * prev[] will be initialized on the fly. ++ */ ++#define CLEAR_HASH(s) \ ++ s->head[s->hash_size-1] = NIL; \ ++ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); ++ ++/* ========================================================================= */ ++int ZEXPORT deflateInit_(strm, level, version, stream_size) ++ z_streamp strm; ++ int level; ++ const char *version; ++ int stream_size; ++{ ++ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, ++ Z_DEFAULT_STRATEGY, version, stream_size); ++ /* To do: ignore strm->next_in if we use it as window */ ++} ++ ++/* ========================================================================= */ ++int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, ++ version, stream_size) ++ z_streamp strm; ++ int level; ++ int method; ++ int windowBits; ++ int memLevel; ++ int strategy; ++ const char *version; ++ int stream_size; ++{ ++ deflate_state *s; ++ int noheader = 0; ++ static const char* my_version = ZLIB_VERSION; ++ ++ ushf *overlay; ++ /* We overlay pending_buf and d_buf+l_buf. This works since the average ++ * output size for (length,distance) codes is <= 24 bits. ++ */ ++ ++ if (version == Z_NULL || version[0] != my_version[0] || ++ stream_size != sizeof(z_stream)) { ++ return Z_VERSION_ERROR; ++ } ++ if (strm == Z_NULL) return Z_STREAM_ERROR; ++ ++ strm->msg = Z_NULL; ++ if (strm->zalloc == Z_NULL) { ++ return Z_STREAM_ERROR; ++/* strm->zalloc = zcalloc; ++ strm->opaque = (voidpf)0;*/ ++ } ++ if (strm->zfree == Z_NULL) return Z_STREAM_ERROR; /* strm->zfree = zcfree; */ ++ ++ if (level == Z_DEFAULT_COMPRESSION) level = 6; ++#ifdef FASTEST ++ level = 1; ++#endif ++ ++ if (windowBits < 0) { /* undocumented feature: suppress zlib header */ ++ noheader = 1; ++ windowBits = -windowBits; ++ } ++ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || ++ windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || ++ strategy < 0 || strategy > Z_HUFFMAN_ONLY) { ++ return Z_STREAM_ERROR; ++ } ++ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); ++ if (s == Z_NULL) return Z_MEM_ERROR; ++ strm->state = (struct internal_state FAR *)s; ++ s->strm = strm; ++ ++ s->noheader = noheader; ++ s->w_bits = windowBits; ++ s->w_size = 1 << s->w_bits; ++ s->w_mask = s->w_size - 1; ++ ++ s->hash_bits = memLevel + 7; ++ s->hash_size = 1 << s->hash_bits; ++ s->hash_mask = s->hash_size - 1; ++ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); ++ ++ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); ++ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); ++ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); ++ ++ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ ++ ++ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); ++ s->pending_buf = (uchf *) overlay; ++ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); ++ ++ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || ++ s->pending_buf == Z_NULL) { ++ strm->msg = ERR_MSG(Z_MEM_ERROR); ++ deflateEnd (strm); ++ return Z_MEM_ERROR; ++ } ++ s->d_buf = overlay + s->lit_bufsize/sizeof(ush); ++ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; ++ ++ s->level = level; ++ s->strategy = strategy; ++ s->method = (Byte)method; ++ ++ return deflateReset(strm); ++} ++ ++/* ========================================================================= */ ++int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) ++ z_streamp strm; ++ const Bytef *dictionary; ++ uInt dictLength; ++{ ++ deflate_state *s; ++ uInt length = dictLength; ++ uInt n; ++ IPos hash_head = 0; ++ ++ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || ++ strm->state->status != INIT_STATE) return Z_STREAM_ERROR; ++ ++ s = strm->state; ++ strm->adler = adler32(strm->adler, dictionary, dictLength); ++ ++ if (length < MIN_MATCH) return Z_OK; ++ if (length > MAX_DIST(s)) { ++ length = MAX_DIST(s); ++#ifndef USE_DICT_HEAD ++ dictionary += dictLength - length; /* use the tail of the dictionary */ ++#endif ++ } ++ zmemcpy(s->window, dictionary, length); ++ s->strstart = length; ++ s->block_start = (long)length; ++ ++ /* Insert all strings in the hash table (except for the last two bytes). ++ * s->lookahead stays null, so s->ins_h will be recomputed at the next ++ * call of fill_window. ++ */ ++ s->ins_h = s->window[0]; ++ UPDATE_HASH(s, s->ins_h, s->window[1]); ++ for (n = 0; n <= length - MIN_MATCH; n++) { ++ INSERT_STRING(s, n, hash_head); ++ } ++ if (hash_head) hash_head = 0; /* to make compiler happy */ ++ return Z_OK; ++} ++ ++/* ========================================================================= */ ++int ZEXPORT deflateReset (strm) ++ z_streamp strm; ++{ ++ deflate_state *s; ++ ++ if (strm == Z_NULL || strm->state == Z_NULL || ++ strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; ++ ++ strm->total_in = strm->total_out = 0; ++ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ ++ strm->data_type = Z_UNKNOWN; ++ ++ s = (deflate_state *)strm->state; ++ s->pending = 0; ++ s->pending_out = s->pending_buf; ++ ++ if (s->noheader < 0) { ++ s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ ++ } ++ s->status = s->noheader ? BUSY_STATE : INIT_STATE; ++ strm->adler = 1; ++ s->last_flush = Z_NO_FLUSH; ++ ++ _tr_init(s); ++ lm_init(s); ++ ++ return Z_OK; ++} ++ ++/* ========================================================================= */ ++int ZEXPORT deflateParams(strm, level, strategy) ++ z_streamp strm; ++ int level; ++ int strategy; ++{ ++ deflate_state *s; ++ compress_func func; ++ int err = Z_OK; ++ ++ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; ++ s = strm->state; ++ ++ if (level == Z_DEFAULT_COMPRESSION) { ++ level = 6; ++ } ++ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { ++ return Z_STREAM_ERROR; ++ } ++ func = configuration_table[s->level].func; ++ ++ if (func != configuration_table[level].func && strm->total_in != 0) { ++ /* Flush the last buffer: */ ++ err = deflate(strm, Z_PARTIAL_FLUSH); ++ } ++ if (s->level != level) { ++ s->level = level; ++ s->max_lazy_match = configuration_table[level].max_lazy; ++ s->good_match = configuration_table[level].good_length; ++ s->nice_match = configuration_table[level].nice_length; ++ s->max_chain_length = configuration_table[level].max_chain; ++ } ++ s->strategy = strategy; ++ return err; ++} ++ ++/* ========================================================================= ++ * Put a short in the pending buffer. The 16-bit value is put in MSB order. ++ * IN assertion: the stream state is correct and there is enough room in ++ * pending_buf. ++ */ ++local void putShortMSB (s, b) ++ deflate_state *s; ++ uInt b; ++{ ++ put_byte(s, (Byte)(b >> 8)); ++ put_byte(s, (Byte)(b & 0xff)); ++} ++ ++/* ========================================================================= ++ * Flush as much pending output as possible. All deflate() output goes ++ * through this function so some applications may wish to modify it ++ * to avoid allocating a large strm->next_out buffer and copying into it. ++ * (See also read_buf()). ++ */ ++local void flush_pending(strm) ++ z_streamp strm; ++{ ++ unsigned len = strm->state->pending; ++ ++ if (len > strm->avail_out) len = strm->avail_out; ++ if (len == 0) return; ++ ++ zmemcpy(strm->next_out, strm->state->pending_out, len); ++ strm->next_out += len; ++ strm->state->pending_out += len; ++ strm->total_out += len; ++ strm->avail_out -= len; ++ strm->state->pending -= len; ++ if (strm->state->pending == 0) { ++ strm->state->pending_out = strm->state->pending_buf; ++ } ++} ++ ++/* ========================================================================= */ ++int ZEXPORT deflate (strm, flush) ++ z_streamp strm; ++ int flush; ++{ ++ int old_flush; /* value of flush param for previous deflate call */ ++ deflate_state *s; ++ ++ if (strm == Z_NULL || strm->state == Z_NULL || ++ flush > Z_FINISH || flush < 0) { ++ return Z_STREAM_ERROR; ++ } ++ s = strm->state; ++ ++ if (strm->next_out == Z_NULL || ++ (strm->next_in == Z_NULL && strm->avail_in != 0) || ++ (s->status == FINISH_STATE && flush != Z_FINISH)) { ++ ERR_RETURN(strm, Z_STREAM_ERROR); ++ } ++ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); ++ ++ s->strm = strm; /* just in case */ ++ old_flush = s->last_flush; ++ s->last_flush = flush; ++ ++ /* Write the zlib header */ ++ if (s->status == INIT_STATE) { ++ ++ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; ++ uInt level_flags = (s->level-1) >> 1; ++ ++ if (level_flags > 3) level_flags = 3; ++ header |= (level_flags << 6); ++ if (s->strstart != 0) header |= PRESET_DICT; ++ header += 31 - (header % 31); ++ ++ s->status = BUSY_STATE; ++ putShortMSB(s, header); ++ ++ /* Save the adler32 of the preset dictionary: */ ++ if (s->strstart != 0) { ++ putShortMSB(s, (uInt)(strm->adler >> 16)); ++ putShortMSB(s, (uInt)(strm->adler & 0xffff)); ++ } ++ strm->adler = 1L; ++ } ++ ++ /* Flush as much pending output as possible */ ++ if (s->pending != 0) { ++ flush_pending(strm); ++ if (strm->avail_out == 0) { ++ /* Since avail_out is 0, deflate will be called again with ++ * more output space, but possibly with both pending and ++ * avail_in equal to zero. There won't be anything to do, ++ * but this is not an error situation so make sure we ++ * return OK instead of BUF_ERROR at next call of deflate: ++ */ ++ s->last_flush = -1; ++ return Z_OK; ++ } ++ ++ /* Make sure there is something to do and avoid duplicate consecutive ++ * flushes. For repeated and useless calls with Z_FINISH, we keep ++ * returning Z_STREAM_END instead of Z_BUFF_ERROR. ++ */ ++ } else if (strm->avail_in == 0 && flush <= old_flush && ++ flush != Z_FINISH) { ++ ERR_RETURN(strm, Z_BUF_ERROR); ++ } ++ ++ /* User must not provide more input after the first FINISH: */ ++ if (s->status == FINISH_STATE && strm->avail_in != 0) { ++ ERR_RETURN(strm, Z_BUF_ERROR); ++ } ++ ++ /* Start a new block or continue the current one. ++ */ ++ if (strm->avail_in != 0 || s->lookahead != 0 || ++ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { ++ block_state bstate; ++ ++ bstate = (*(configuration_table[s->level].func))(s, flush); ++ ++ if (bstate == finish_started || bstate == finish_done) { ++ s->status = FINISH_STATE; ++ } ++ if (bstate == need_more || bstate == finish_started) { ++ if (strm->avail_out == 0) { ++ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ ++ } ++ return Z_OK; ++ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call ++ * of deflate should use the same flush parameter to make sure ++ * that the flush is complete. So we don't have to output an ++ * empty block here, this will be done at next call. This also ++ * ensures that for a very small output buffer, we emit at most ++ * one empty block. ++ */ ++ } ++ if (bstate == block_done) { ++ if (flush == Z_PARTIAL_FLUSH) { ++ _tr_align(s); ++ } else { /* FULL_FLUSH or SYNC_FLUSH */ ++ _tr_stored_block(s, (char*)0, 0L, 0); ++ /* For a full flush, this empty block will be recognized ++ * as a special marker by inflate_sync(). ++ */ ++ if (flush == Z_FULL_FLUSH) { ++ CLEAR_HASH(s); /* forget history */ ++ } ++ } ++ flush_pending(strm); ++ if (strm->avail_out == 0) { ++ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ ++ return Z_OK; ++ } ++ } ++ } ++ Assert(strm->avail_out > 0, "bug2"); ++ ++ if (flush != Z_FINISH) return Z_OK; ++ if (s->noheader) return Z_STREAM_END; ++ ++ /* Write the zlib trailer (adler32) */ ++ putShortMSB(s, (uInt)(strm->adler >> 16)); ++ putShortMSB(s, (uInt)(strm->adler & 0xffff)); ++ flush_pending(strm); ++ /* If avail_out is zero, the application will call deflate again ++ * to flush the rest. ++ */ ++ s->noheader = -1; /* write the trailer only once! */ ++ return s->pending != 0 ? Z_OK : Z_STREAM_END; ++} ++ ++/* ========================================================================= */ ++int ZEXPORT deflateEnd (strm) ++ z_streamp strm; ++{ ++ int status; ++ ++ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; ++ ++ status = strm->state->status; ++ if (status != INIT_STATE && status != BUSY_STATE && ++ status != FINISH_STATE) { ++ return Z_STREAM_ERROR; ++ } ++ ++ /* Deallocate in reverse order of allocations: */ ++ TRY_FREE(strm, strm->state->pending_buf); ++ TRY_FREE(strm, strm->state->head); ++ TRY_FREE(strm, strm->state->prev); ++ TRY_FREE(strm, strm->state->window); ++ ++ ZFREE(strm, strm->state); ++ strm->state = Z_NULL; ++ ++ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; ++} ++ ++/* ========================================================================= ++ * Copy the source state to the destination state. ++ * To simplify the source, this is not supported for 16-bit MSDOS (which ++ * doesn't have enough memory anyway to duplicate compression states). ++ */ ++int ZEXPORT deflateCopy (dest, source) ++ z_streamp dest; ++ z_streamp source; ++{ ++#ifdef MAXSEG_64K ++ return Z_STREAM_ERROR; ++#else ++ deflate_state *ds; ++ deflate_state *ss; ++ ushf *overlay; ++ ++ ++ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { ++ return Z_STREAM_ERROR; ++ } ++ ++ ss = source->state; ++ ++ *dest = *source; ++ ++ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); ++ if (ds == Z_NULL) return Z_MEM_ERROR; ++ dest->state = (struct internal_state FAR *) ds; ++ *ds = *ss; ++ ds->strm = dest; ++ ++ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ++ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ++ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); ++ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); ++ ds->pending_buf = (uchf *) overlay; ++ ++ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ++ ds->pending_buf == Z_NULL) { ++ deflateEnd (dest); ++ return Z_MEM_ERROR; ++ } ++ /* following zmemcpy do not work for 16-bit MSDOS */ ++ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); ++ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); ++ zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); ++ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ++ ++ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); ++ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); ++ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; ++ ++ ds->l_desc.dyn_tree = ds->dyn_ltree; ++ ds->d_desc.dyn_tree = ds->dyn_dtree; ++ ds->bl_desc.dyn_tree = ds->bl_tree; ++ ++ return Z_OK; ++#endif ++} ++ ++/* =========================================================================== ++ * Read a new buffer from the current input stream, update the adler32 ++ * and total number of bytes read. All deflate() input goes through ++ * this function so some applications may wish to modify it to avoid ++ * allocating a large strm->next_in buffer and copying from it. ++ * (See also flush_pending()). ++ */ ++local int read_buf(strm, buf, size) ++ z_streamp strm; ++ Bytef *buf; ++ unsigned size; ++{ ++ unsigned len = strm->avail_in; ++ ++ if (len > size) len = size; ++ if (len == 0) return 0; ++ ++ strm->avail_in -= len; ++ ++ if (!strm->state->noheader) { ++ strm->adler = adler32(strm->adler, strm->next_in, len); ++ } ++ zmemcpy(buf, strm->next_in, len); ++ strm->next_in += len; ++ strm->total_in += len; ++ ++ return (int)len; ++} ++ ++/* =========================================================================== ++ * Initialize the "longest match" routines for a new zlib stream ++ */ ++local void lm_init (s) ++ deflate_state *s; ++{ ++ s->window_size = (ulg)2L*s->w_size; ++ ++ CLEAR_HASH(s); ++ ++ /* Set the default configuration parameters: ++ */ ++ s->max_lazy_match = configuration_table[s->level].max_lazy; ++ s->good_match = configuration_table[s->level].good_length; ++ s->nice_match = configuration_table[s->level].nice_length; ++ s->max_chain_length = configuration_table[s->level].max_chain; ++ ++ s->strstart = 0; ++ s->block_start = 0L; ++ s->lookahead = 0; ++ s->match_length = s->prev_length = MIN_MATCH-1; ++ s->match_available = 0; ++ s->ins_h = 0; ++#ifdef ASMV ++ match_init(); /* initialize the asm code */ ++#endif ++} ++ ++/* =========================================================================== ++ * Set match_start to the longest match starting at the given string and ++ * return its length. Matches shorter or equal to prev_length are discarded, ++ * in which case the result is equal to prev_length and match_start is ++ * garbage. ++ * IN assertions: cur_match is the head of the hash chain for the current ++ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 ++ * OUT assertion: the match length is not greater than s->lookahead. ++ */ ++#ifndef ASMV ++/* For 80x86 and 680x0, an optimized version will be provided in match.asm or ++ * match.S. The code will be functionally equivalent. ++ */ ++#ifndef FASTEST ++local uInt longest_match(s, cur_match) ++ deflate_state *s; ++ IPos cur_match; /* current match */ ++{ ++ unsigned chain_length = s->max_chain_length;/* max hash chain length */ ++ register Bytef *scan = s->window + s->strstart; /* current string */ ++ register Bytef *match; /* matched string */ ++ register int len; /* length of current match */ ++ int best_len = s->prev_length; /* best match length so far */ ++ int nice_match = s->nice_match; /* stop if match long enough */ ++ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? ++ s->strstart - (IPos)MAX_DIST(s) : NIL; ++ /* Stop when cur_match becomes <= limit. To simplify the code, ++ * we prevent matches with the string of window index 0. ++ */ ++ Posf *prev = s->prev; ++ uInt wmask = s->w_mask; ++ ++#ifdef UNALIGNED_OK ++ /* Compare two bytes at a time. Note: this is not always beneficial. ++ * Try with and without -DUNALIGNED_OK to check. ++ */ ++ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; ++ register ush scan_start = *(ushf*)scan; ++ register ush scan_end = *(ushf*)(scan+best_len-1); ++#else ++ register Bytef *strend = s->window + s->strstart + MAX_MATCH; ++ register Byte scan_end1 = scan[best_len-1]; ++ register Byte scan_end = scan[best_len]; ++#endif ++ ++ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. ++ * It is easy to get rid of this optimization if necessary. ++ */ ++ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); ++ ++ /* Do not waste too much time if we already have a good match: */ ++ if (s->prev_length >= s->good_match) { ++ chain_length >>= 2; ++ } ++ /* Do not look for matches beyond the end of the input. This is necessary ++ * to make deflate deterministic. ++ */ ++ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; ++ ++ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); ++ ++ do { ++ Assert(cur_match < s->strstart, "no future"); ++ match = s->window + cur_match; ++ ++ /* Skip to next match if the match length cannot increase ++ * or if the match length is less than 2: ++ */ ++#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) ++ /* This code assumes sizeof(unsigned short) == 2. Do not use ++ * UNALIGNED_OK if your compiler uses a different size. ++ */ ++ if (*(ushf*)(match+best_len-1) != scan_end || ++ *(ushf*)match != scan_start) continue; ++ ++ /* It is not necessary to compare scan[2] and match[2] since they are ++ * always equal when the other bytes match, given that the hash keys ++ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at ++ * strstart+3, +5, ... up to strstart+257. We check for insufficient ++ * lookahead only every 4th comparison; the 128th check will be made ++ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is ++ * necessary to put more guard bytes at the end of the window, or ++ * to check more often for insufficient lookahead. ++ */ ++ Assert(scan[2] == match[2], "scan[2]?"); ++ scan++, match++; ++ do { ++ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && ++ *(ushf*)(scan+=2) == *(ushf*)(match+=2) && ++ *(ushf*)(scan+=2) == *(ushf*)(match+=2) && ++ *(ushf*)(scan+=2) == *(ushf*)(match+=2) && ++ scan < strend); ++ /* The funny "do {}" generates better code on most compilers */ ++ ++ /* Here, scan <= window+strstart+257 */ ++ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); ++ if (*scan == *match) scan++; ++ ++ len = (MAX_MATCH - 1) - (int)(strend-scan); ++ scan = strend - (MAX_MATCH-1); ++ ++#else /* UNALIGNED_OK */ ++ ++ if (match[best_len] != scan_end || ++ match[best_len-1] != scan_end1 || ++ *match != *scan || ++ *++match != scan[1]) continue; ++ ++ /* The check at best_len-1 can be removed because it will be made ++ * again later. (This heuristic is not always a win.) ++ * It is not necessary to compare scan[2] and match[2] since they ++ * are always equal when the other bytes match, given that ++ * the hash keys are equal and that HASH_BITS >= 8. ++ */ ++ scan += 2, match++; ++ Assert(*scan == *match, "match[2]?"); ++ ++ /* We check for insufficient lookahead only every 8th comparison; ++ * the 256th check will be made at strstart+258. ++ */ ++ do { ++ } while (*++scan == *++match && *++scan == *++match && ++ *++scan == *++match && *++scan == *++match && ++ *++scan == *++match && *++scan == *++match && ++ *++scan == *++match && *++scan == *++match && ++ scan < strend); ++ ++ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); ++ ++ len = MAX_MATCH - (int)(strend - scan); ++ scan = strend - MAX_MATCH; ++ ++#endif /* UNALIGNED_OK */ ++ ++ if (len > best_len) { ++ s->match_start = cur_match; ++ best_len = len; ++ if (len >= nice_match) break; ++#ifdef UNALIGNED_OK ++ scan_end = *(ushf*)(scan+best_len-1); ++#else ++ scan_end1 = scan[best_len-1]; ++ scan_end = scan[best_len]; ++#endif ++ } ++ } while ((cur_match = prev[cur_match & wmask]) > limit ++ && --chain_length != 0); ++ ++ if ((uInt)best_len <= s->lookahead) return (uInt)best_len; ++ return s->lookahead; ++} ++ ++#else /* FASTEST */ ++/* --------------------------------------------------------------------------- ++ * Optimized version for level == 1 only ++ */ ++local uInt longest_match(s, cur_match) ++ deflate_state *s; ++ IPos cur_match; /* current match */ ++{ ++ register Bytef *scan = s->window + s->strstart; /* current string */ ++ register Bytef *match; /* matched string */ ++ register int len; /* length of current match */ ++ register Bytef *strend = s->window + s->strstart + MAX_MATCH; ++ ++ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. ++ * It is easy to get rid of this optimization if necessary. ++ */ ++ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); ++ ++ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); ++ ++ Assert(cur_match < s->strstart, "no future"); ++ ++ match = s->window + cur_match; ++ ++ /* Return failure if the match length is less than 2: ++ */ ++ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; ++ ++ /* The check at best_len-1 can be removed because it will be made ++ * again later. (This heuristic is not always a win.) ++ * It is not necessary to compare scan[2] and match[2] since they ++ * are always equal when the other bytes match, given that ++ * the hash keys are equal and that HASH_BITS >= 8. ++ */ ++ scan += 2, match += 2; ++ Assert(*scan == *match, "match[2]?"); ++ ++ /* We check for insufficient lookahead only every 8th comparison; ++ * the 256th check will be made at strstart+258. ++ */ ++ do { ++ } while (*++scan == *++match && *++scan == *++match && ++ *++scan == *++match && *++scan == *++match && ++ *++scan == *++match && *++scan == *++match && ++ *++scan == *++match && *++scan == *++match && ++ scan < strend); ++ ++ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); ++ ++ len = MAX_MATCH - (int)(strend - scan); ++ ++ if (len < MIN_MATCH) return MIN_MATCH - 1; ++ ++ s->match_start = cur_match; ++ return len <= s->lookahead ? len : s->lookahead; ++} ++#endif /* FASTEST */ ++#endif /* ASMV */ ++ ++#ifdef DEBUG ++/* =========================================================================== ++ * Check that the match at match_start is indeed a match. ++ */ ++local void check_match(s, start, match, length) ++ deflate_state *s; ++ IPos start, match; ++ int length; ++{ ++ /* check that the match is indeed a match */ ++ if (zmemcmp(s->window + match, ++ s->window + start, length) != EQUAL) { ++ fprintf(stderr, " start %u, match %u, length %d\n", ++ start, match, length); ++ do { ++ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); ++ } while (--length != 0); ++ z_error("invalid match"); ++ } ++ if (z_verbose > 1) { ++ fprintf(stderr,"\\[%d,%d]", start-match, length); ++ do { putc(s->window[start++], stderr); } while (--length != 0); ++ } ++} ++#else ++# define check_match(s, start, match, length) ++#endif ++ ++/* =========================================================================== ++ * Fill the window when the lookahead becomes insufficient. ++ * Updates strstart and lookahead. ++ * ++ * IN assertion: lookahead < MIN_LOOKAHEAD ++ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD ++ * At least one byte has been read, or avail_in == 0; reads are ++ * performed for at least two bytes (required for the zip translate_eol ++ * option -- not supported here). ++ */ ++local void fill_window(s) ++ deflate_state *s; ++{ ++ register unsigned n, m; ++ register Posf *p; ++ unsigned more; /* Amount of free space at the end of the window. */ ++ uInt wsize = s->w_size; ++ ++ do { ++ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); ++ ++ /* Deal with !@#$% 64K limit: */ ++ if (more == 0 && s->strstart == 0 && s->lookahead == 0) { ++ more = wsize; ++ ++ } else if (more == (unsigned)(-1)) { ++ /* Very unlikely, but possible on 16 bit machine if strstart == 0 ++ * and lookahead == 1 (input done one byte at time) ++ */ ++ more--; ++ ++ /* If the window is almost full and there is insufficient lookahead, ++ * move the upper half to the lower one to make room in the upper half. ++ */ ++ } else if (s->strstart >= wsize+MAX_DIST(s)) { ++ ++ zmemcpy(s->window, s->window+wsize, (unsigned)wsize); ++ s->match_start -= wsize; ++ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ ++ s->block_start -= (long) wsize; ++ ++ /* Slide the hash table (could be avoided with 32 bit values ++ at the expense of memory usage). We slide even when level == 0 ++ to keep the hash table consistent if we switch back to level > 0 ++ later. (Using level 0 permanently is not an optimal usage of ++ zlib, so we don't care about this pathological case.) ++ */ ++ n = s->hash_size; ++ p = &s->head[n]; ++ do { ++ m = *--p; ++ *p = (Pos)(m >= wsize ? m-wsize : NIL); ++ } while (--n); ++ ++ n = wsize; ++#ifndef FASTEST ++ p = &s->prev[n]; ++ do { ++ m = *--p; ++ *p = (Pos)(m >= wsize ? m-wsize : NIL); ++ /* If n is not on any hash chain, prev[n] is garbage but ++ * its value will never be used. ++ */ ++ } while (--n); ++#endif ++ more += wsize; ++ } ++ if (s->strm->avail_in == 0) return; ++ ++ /* If there was no sliding: ++ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && ++ * more == window_size - lookahead - strstart ++ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) ++ * => more >= window_size - 2*WSIZE + 2 ++ * In the BIG_MEM or MMAP case (not yet supported), ++ * window_size == input_size + MIN_LOOKAHEAD && ++ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. ++ * Otherwise, window_size == 2*WSIZE so more >= 2. ++ * If there was sliding, more >= WSIZE. So in all cases, more >= 2. ++ */ ++ Assert(more >= 2, "more < 2"); ++ ++ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); ++ s->lookahead += n; ++ ++ /* Initialize the hash value now that we have some input: */ ++ if (s->lookahead >= MIN_MATCH) { ++ s->ins_h = s->window[s->strstart]; ++ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); ++#if MIN_MATCH != 3 ++ Call UPDATE_HASH() MIN_MATCH-3 more times ++#endif ++ } ++ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, ++ * but this is not important since only literal bytes will be emitted. ++ */ ++ ++ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); ++} ++ ++/* =========================================================================== ++ * Flush the current block, with given end-of-file flag. ++ * IN assertion: strstart is set to the end of the current match. ++ */ ++#define FLUSH_BLOCK_ONLY(s, eof) { \ ++ _tr_flush_block(s, (s->block_start >= 0L ? \ ++ (charf *)&s->window[(unsigned)s->block_start] : \ ++ (charf *)Z_NULL), \ ++ (ulg)((long)s->strstart - s->block_start), \ ++ (eof)); \ ++ s->block_start = s->strstart; \ ++ flush_pending(s->strm); \ ++ Tracev((stderr,"[FLUSH]")); \ ++} ++ ++/* Same but force premature exit if necessary. */ ++#define FLUSH_BLOCK(s, eof) { \ ++ FLUSH_BLOCK_ONLY(s, eof); \ ++ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ ++} ++ ++/* =========================================================================== ++ * Copy without compression as much as possible from the input stream, return ++ * the current block state. ++ * This function does not insert new strings in the dictionary since ++ * uncompressible data is probably not useful. This function is used ++ * only for the level=0 compression option. ++ * NOTE: this function should be optimized to avoid extra copying from ++ * window to pending_buf. ++ */ ++local block_state deflate_stored(s, flush) ++ deflate_state *s; ++ int flush; ++{ ++ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited ++ * to pending_buf_size, and each stored block has a 5 byte header: ++ */ ++ ulg max_block_size = 0xffff; ++ ulg max_start; ++ ++ if (max_block_size > s->pending_buf_size - 5) { ++ max_block_size = s->pending_buf_size - 5; ++ } ++ ++ /* Copy as much as possible from input to output: */ ++ for (;;) { ++ /* Fill the window as much as possible: */ ++ if (s->lookahead <= 1) { ++ ++ Assert(s->strstart < s->w_size+MAX_DIST(s) || ++ s->block_start >= (long)s->w_size, "slide too late"); ++ ++ fill_window(s); ++ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; ++ ++ if (s->lookahead == 0) break; /* flush the current block */ ++ } ++ Assert(s->block_start >= 0L, "block gone"); ++ ++ s->strstart += s->lookahead; ++ s->lookahead = 0; ++ ++ /* Emit a stored block if pending_buf will be full: */ ++ max_start = s->block_start + max_block_size; ++ if (s->strstart == 0 || (ulg)s->strstart >= max_start) { ++ /* strstart == 0 is possible when wraparound on 16-bit machine */ ++ s->lookahead = (uInt)(s->strstart - max_start); ++ s->strstart = (uInt)max_start; ++ FLUSH_BLOCK(s, 0); ++ } ++ /* Flush if we may have to slide, otherwise block_start may become ++ * negative and the data will be gone: ++ */ ++ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { ++ FLUSH_BLOCK(s, 0); ++ } ++ } ++ FLUSH_BLOCK(s, flush == Z_FINISH); ++ return flush == Z_FINISH ? finish_done : block_done; ++} ++ ++/* =========================================================================== ++ * Compress as much as possible from the input stream, return the current ++ * block state. ++ * This function does not perform lazy evaluation of matches and inserts ++ * new strings in the dictionary only for unmatched strings or for short ++ * matches. It is used only for the fast compression options. ++ */ ++local block_state deflate_fast(s, flush) ++ deflate_state *s; ++ int flush; ++{ ++ IPos hash_head = NIL; /* head of the hash chain */ ++ int bflush; /* set if current block must be flushed */ ++ ++ for (;;) { ++ /* Make sure that we always have enough lookahead, except ++ * at the end of the input file. We need MAX_MATCH bytes ++ * for the next match, plus MIN_MATCH bytes to insert the ++ * string following the next match. ++ */ ++ if (s->lookahead < MIN_LOOKAHEAD) { ++ fill_window(s); ++ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { ++ return need_more; ++ } ++ if (s->lookahead == 0) break; /* flush the current block */ ++ } ++ ++ /* Insert the string window[strstart .. strstart+2] in the ++ * dictionary, and set hash_head to the head of the hash chain: ++ */ ++ if (s->lookahead >= MIN_MATCH) { ++ INSERT_STRING(s, s->strstart, hash_head); ++ } ++ ++ /* Find the longest match, discarding those <= prev_length. ++ * At this point we have always match_length < MIN_MATCH ++ */ ++ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { ++ /* To simplify the code, we prevent matches with the string ++ * of window index 0 (in particular we have to avoid a match ++ * of the string with itself at the start of the input file). ++ */ ++ if (s->strategy != Z_HUFFMAN_ONLY) { ++ s->match_length = longest_match (s, hash_head); ++ } ++ /* longest_match() sets match_start */ ++ } ++ if (s->match_length >= MIN_MATCH) { ++ check_match(s, s->strstart, s->match_start, s->match_length); ++ ++ _tr_tally_dist(s, s->strstart - s->match_start, ++ s->match_length - MIN_MATCH, bflush); ++ ++ s->lookahead -= s->match_length; ++ ++ /* Insert new strings in the hash table only if the match length ++ * is not too large. This saves time but degrades compression. ++ */ ++#ifndef FASTEST ++ if (s->match_length <= s->max_insert_length && ++ s->lookahead >= MIN_MATCH) { ++ s->match_length--; /* string at strstart already in hash table */ ++ do { ++ s->strstart++; ++ INSERT_STRING(s, s->strstart, hash_head); ++ /* strstart never exceeds WSIZE-MAX_MATCH, so there are ++ * always MIN_MATCH bytes ahead. ++ */ ++ } while (--s->match_length != 0); ++ s->strstart++; ++ } else ++#endif ++ { ++ s->strstart += s->match_length; ++ s->match_length = 0; ++ s->ins_h = s->window[s->strstart]; ++ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); ++#if MIN_MATCH != 3 ++ Call UPDATE_HASH() MIN_MATCH-3 more times ++#endif ++ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not ++ * matter since it will be recomputed at next deflate call. ++ */ ++ } ++ } else { ++ /* No match, output a literal byte */ ++ Tracevv((stderr,"%c", s->window[s->strstart])); ++ _tr_tally_lit (s, s->window[s->strstart], bflush); ++ s->lookahead--; ++ s->strstart++; ++ } ++ if (bflush) FLUSH_BLOCK(s, 0); ++ } ++ FLUSH_BLOCK(s, flush == Z_FINISH); ++ return flush == Z_FINISH ? finish_done : block_done; ++} ++ ++/* =========================================================================== ++ * Same as above, but achieves better compression. We use a lazy ++ * evaluation for matches: a match is finally adopted only if there is ++ * no better match at the next window position. ++ */ ++local block_state deflate_slow(s, flush) ++ deflate_state *s; ++ int flush; ++{ ++ IPos hash_head = NIL; /* head of hash chain */ ++ int bflush; /* set if current block must be flushed */ ++ ++ /* Process the input block. */ ++ for (;;) { ++ /* Make sure that we always have enough lookahead, except ++ * at the end of the input file. We need MAX_MATCH bytes ++ * for the next match, plus MIN_MATCH bytes to insert the ++ * string following the next match. ++ */ ++ if (s->lookahead < MIN_LOOKAHEAD) { ++ fill_window(s); ++ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { ++ return need_more; ++ } ++ if (s->lookahead == 0) break; /* flush the current block */ ++ } ++ ++ /* Insert the string window[strstart .. strstart+2] in the ++ * dictionary, and set hash_head to the head of the hash chain: ++ */ ++ if (s->lookahead >= MIN_MATCH) { ++ INSERT_STRING(s, s->strstart, hash_head); ++ } ++ ++ /* Find the longest match, discarding those <= prev_length. ++ */ ++ s->prev_length = s->match_length, s->prev_match = s->match_start; ++ s->match_length = MIN_MATCH-1; ++ ++ if (hash_head != NIL && s->prev_length < s->max_lazy_match && ++ s->strstart - hash_head <= MAX_DIST(s)) { ++ /* To simplify the code, we prevent matches with the string ++ * of window index 0 (in particular we have to avoid a match ++ * of the string with itself at the start of the input file). ++ */ ++ if (s->strategy != Z_HUFFMAN_ONLY) { ++ s->match_length = longest_match (s, hash_head); ++ } ++ /* longest_match() sets match_start */ ++ ++ if (s->match_length <= 5 && (s->strategy == Z_FILTERED || ++ (s->match_length == MIN_MATCH && ++ s->strstart - s->match_start > TOO_FAR))) { ++ ++ /* If prev_match is also MIN_MATCH, match_start is garbage ++ * but we will ignore the current match anyway. ++ */ ++ s->match_length = MIN_MATCH-1; ++ } ++ } ++ /* If there was a match at the previous step and the current ++ * match is not better, output the previous match: ++ */ ++ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { ++ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; ++ /* Do not insert strings in hash table beyond this. */ ++ ++ check_match(s, s->strstart-1, s->prev_match, s->prev_length); ++ ++ _tr_tally_dist(s, s->strstart -1 - s->prev_match, ++ s->prev_length - MIN_MATCH, bflush); ++ ++ /* Insert in hash table all strings up to the end of the match. ++ * strstart-1 and strstart are already inserted. If there is not ++ * enough lookahead, the last two strings are not inserted in ++ * the hash table. ++ */ ++ s->lookahead -= s->prev_length-1; ++ s->prev_length -= 2; ++ do { ++ if (++s->strstart <= max_insert) { ++ INSERT_STRING(s, s->strstart, hash_head); ++ } ++ } while (--s->prev_length != 0); ++ s->match_available = 0; ++ s->match_length = MIN_MATCH-1; ++ s->strstart++; ++ ++ if (bflush) FLUSH_BLOCK(s, 0); ++ ++ } else if (s->match_available) { ++ /* If there was no match at the previous position, output a ++ * single literal. If there was a match but the current match ++ * is longer, truncate the previous match to a single literal. ++ */ ++ Tracevv((stderr,"%c", s->window[s->strstart-1])); ++ _tr_tally_lit(s, s->window[s->strstart-1], bflush); ++ if (bflush) { ++ FLUSH_BLOCK_ONLY(s, 0); ++ } ++ s->strstart++; ++ s->lookahead--; ++ if (s->strm->avail_out == 0) return need_more; ++ } else { ++ /* There is no previous match to compare with, wait for ++ * the next step to decide. ++ */ ++ s->match_available = 1; ++ s->strstart++; ++ s->lookahead--; ++ } ++ } ++ Assert (flush != Z_NO_FLUSH, "no flush?"); ++ if (s->match_available) { ++ Tracevv((stderr,"%c", s->window[s->strstart-1])); ++ _tr_tally_lit(s, s->window[s->strstart-1], bflush); ++ s->match_available = 0; ++ } ++ FLUSH_BLOCK(s, flush == Z_FINISH); ++ return flush == Z_FINISH ? finish_done : block_done; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/deflate.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,318 @@ ++/* deflate.h -- internal compression state ++ * Copyright (C) 1995-2002 Jean-loup Gailly ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* WARNING: this file should *not* be used by applications. It is ++ part of the implementation of the compression library and is ++ subject to change. Applications should only use zlib.h. ++ */ ++ ++/* @(#) $Id: deflate.h,v 1.4 2002/04/24 07:55:32 mcr Exp $ */ ++ ++#ifndef _DEFLATE_H ++#define _DEFLATE_H ++ ++#include "zlib/zutil.h" ++ ++/* =========================================================================== ++ * Internal compression state. ++ */ ++ ++#define LENGTH_CODES 29 ++/* number of length codes, not counting the special END_BLOCK code */ ++ ++#define LITERALS 256 ++/* number of literal bytes 0..255 */ ++ ++#define L_CODES (LITERALS+1+LENGTH_CODES) ++/* number of Literal or Length codes, including the END_BLOCK code */ ++ ++#define D_CODES 30 ++/* number of distance codes */ ++ ++#define BL_CODES 19 ++/* number of codes used to transfer the bit lengths */ ++ ++#define HEAP_SIZE (2*L_CODES+1) ++/* maximum heap size */ ++ ++#define MAX_BITS 15 ++/* All codes must not exceed MAX_BITS bits */ ++ ++#define INIT_STATE 42 ++#define BUSY_STATE 113 ++#define FINISH_STATE 666 ++/* Stream status */ ++ ++ ++/* Data structure describing a single value and its code string. */ ++typedef struct ct_data_s { ++ union { ++ ush freq; /* frequency count */ ++ ush code; /* bit string */ ++ } fc; ++ union { ++ ush dad; /* father node in Huffman tree */ ++ ush len; /* length of bit string */ ++ } dl; ++} FAR ct_data; ++ ++#define Freq fc.freq ++#define Code fc.code ++#define Dad dl.dad ++#define Len dl.len ++ ++typedef struct static_tree_desc_s static_tree_desc; ++ ++typedef struct tree_desc_s { ++ ct_data *dyn_tree; /* the dynamic tree */ ++ int max_code; /* largest code with non zero frequency */ ++ static_tree_desc *stat_desc; /* the corresponding static tree */ ++} FAR tree_desc; ++ ++typedef ush Pos; ++typedef Pos FAR Posf; ++typedef unsigned IPos; ++ ++/* A Pos is an index in the character window. We use short instead of int to ++ * save space in the various tables. IPos is used only for parameter passing. ++ */ ++ ++typedef struct internal_state { ++ z_streamp strm; /* pointer back to this zlib stream */ ++ int status; /* as the name implies */ ++ Bytef *pending_buf; /* output still pending */ ++ ulg pending_buf_size; /* size of pending_buf */ ++ Bytef *pending_out; /* next pending byte to output to the stream */ ++ int pending; /* nb of bytes in the pending buffer */ ++ int noheader; /* suppress zlib header and adler32 */ ++ Byte data_type; /* UNKNOWN, BINARY or ASCII */ ++ Byte method; /* STORED (for zip only) or DEFLATED */ ++ int last_flush; /* value of flush param for previous deflate call */ ++ ++ /* used by deflate.c: */ ++ ++ uInt w_size; /* LZ77 window size (32K by default) */ ++ uInt w_bits; /* log2(w_size) (8..16) */ ++ uInt w_mask; /* w_size - 1 */ ++ ++ Bytef *window; ++ /* Sliding window. Input bytes are read into the second half of the window, ++ * and move to the first half later to keep a dictionary of at least wSize ++ * bytes. With this organization, matches are limited to a distance of ++ * wSize-MAX_MATCH bytes, but this ensures that IO is always ++ * performed with a length multiple of the block size. Also, it limits ++ * the window size to 64K, which is quite useful on MSDOS. ++ * To do: use the user input buffer as sliding window. ++ */ ++ ++ ulg window_size; ++ /* Actual size of window: 2*wSize, except when the user input buffer ++ * is directly used as sliding window. ++ */ ++ ++ Posf *prev; ++ /* Link to older string with same hash index. To limit the size of this ++ * array to 64K, this link is maintained only for the last 32K strings. ++ * An index in this array is thus a window index modulo 32K. ++ */ ++ ++ Posf *head; /* Heads of the hash chains or NIL. */ ++ ++ uInt ins_h; /* hash index of string to be inserted */ ++ uInt hash_size; /* number of elements in hash table */ ++ uInt hash_bits; /* log2(hash_size) */ ++ uInt hash_mask; /* hash_size-1 */ ++ ++ uInt hash_shift; ++ /* Number of bits by which ins_h must be shifted at each input ++ * step. It must be such that after MIN_MATCH steps, the oldest ++ * byte no longer takes part in the hash key, that is: ++ * hash_shift * MIN_MATCH >= hash_bits ++ */ ++ ++ long block_start; ++ /* Window position at the beginning of the current output block. Gets ++ * negative when the window is moved backwards. ++ */ ++ ++ uInt match_length; /* length of best match */ ++ IPos prev_match; /* previous match */ ++ int match_available; /* set if previous match exists */ ++ uInt strstart; /* start of string to insert */ ++ uInt match_start; /* start of matching string */ ++ uInt lookahead; /* number of valid bytes ahead in window */ ++ ++ uInt prev_length; ++ /* Length of the best match at previous step. Matches not greater than this ++ * are discarded. This is used in the lazy match evaluation. ++ */ ++ ++ uInt max_chain_length; ++ /* To speed up deflation, hash chains are never searched beyond this ++ * length. A higher limit improves compression ratio but degrades the ++ * speed. ++ */ ++ ++ uInt max_lazy_match; ++ /* Attempt to find a better match only when the current match is strictly ++ * smaller than this value. This mechanism is used only for compression ++ * levels >= 4. ++ */ ++# define max_insert_length max_lazy_match ++ /* Insert new strings in the hash table only if the match length is not ++ * greater than this length. This saves time but degrades compression. ++ * max_insert_length is used only for compression levels <= 3. ++ */ ++ ++ int level; /* compression level (1..9) */ ++ int strategy; /* favor or force Huffman coding*/ ++ ++ uInt good_match; ++ /* Use a faster search when the previous match is longer than this */ ++ ++ int nice_match; /* Stop searching when current match exceeds this */ ++ ++ /* used by trees.c: */ ++ /* Didn't use ct_data typedef below to supress compiler warning */ ++ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ ++ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ ++ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ ++ ++ struct tree_desc_s l_desc; /* desc. for literal tree */ ++ struct tree_desc_s d_desc; /* desc. for distance tree */ ++ struct tree_desc_s bl_desc; /* desc. for bit length tree */ ++ ++ ush bl_count[MAX_BITS+1]; ++ /* number of codes at each bit length for an optimal tree */ ++ ++ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ ++ int heap_len; /* number of elements in the heap */ ++ int heap_max; /* element of largest frequency */ ++ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. ++ * The same heap array is used to build all trees. ++ */ ++ ++ uch depth[2*L_CODES+1]; ++ /* Depth of each subtree used as tie breaker for trees of equal frequency ++ */ ++ ++ uchf *l_buf; /* buffer for literals or lengths */ ++ ++ uInt lit_bufsize; ++ /* Size of match buffer for literals/lengths. There are 4 reasons for ++ * limiting lit_bufsize to 64K: ++ * - frequencies can be kept in 16 bit counters ++ * - if compression is not successful for the first block, all input ++ * data is still in the window so we can still emit a stored block even ++ * when input comes from standard input. (This can also be done for ++ * all blocks if lit_bufsize is not greater than 32K.) ++ * - if compression is not successful for a file smaller than 64K, we can ++ * even emit a stored file instead of a stored block (saving 5 bytes). ++ * This is applicable only for zip (not gzip or zlib). ++ * - creating new Huffman trees less frequently may not provide fast ++ * adaptation to changes in the input data statistics. (Take for ++ * example a binary file with poorly compressible code followed by ++ * a highly compressible string table.) Smaller buffer sizes give ++ * fast adaptation but have of course the overhead of transmitting ++ * trees more frequently. ++ * - I can't count above 4 ++ */ ++ ++ uInt last_lit; /* running index in l_buf */ ++ ++ ushf *d_buf; ++ /* Buffer for distances. To simplify the code, d_buf and l_buf have ++ * the same number of elements. To use different lengths, an extra flag ++ * array would be necessary. ++ */ ++ ++ ulg opt_len; /* bit length of current block with optimal trees */ ++ ulg static_len; /* bit length of current block with static trees */ ++ uInt matches; /* number of string matches in current block */ ++ int last_eob_len; /* bit length of EOB code for last block */ ++ ++#ifdef DEBUG ++ ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ++ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ ++#endif ++ ++ ush bi_buf; ++ /* Output buffer. bits are inserted starting at the bottom (least ++ * significant bits). ++ */ ++ int bi_valid; ++ /* Number of valid bits in bi_buf. All bits above the last valid bit ++ * are always zero. ++ */ ++ ++} FAR deflate_state; ++ ++/* Output a byte on the stream. ++ * IN assertion: there is enough room in pending_buf. ++ */ ++#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} ++ ++ ++#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) ++/* Minimum amount of lookahead, except at the end of the input file. ++ * See deflate.c for comments about the MIN_MATCH+1. ++ */ ++ ++#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) ++/* In order to simplify the code, particularly on 16 bit machines, match ++ * distances are limited to MAX_DIST instead of WSIZE. ++ */ ++ ++ /* in trees.c */ ++void _tr_init OF((deflate_state *s)); ++int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); ++void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, ++ int eof)); ++void _tr_align OF((deflate_state *s)); ++void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, ++ int eof)); ++ ++#define d_code(dist) \ ++ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) ++/* Mapping from a distance to a distance code. dist is the distance - 1 and ++ * must not have side effects. _dist_code[256] and _dist_code[257] are never ++ * used. ++ */ ++ ++#ifndef DEBUG ++/* Inline versions of _tr_tally for speed: */ ++ ++#if defined(GEN_TREES_H) || !defined(STDC) ++ extern uch _length_code[]; ++ extern uch _dist_code[]; ++#else ++ extern const uch _length_code[]; ++ extern const uch _dist_code[]; ++#endif ++ ++# define _tr_tally_lit(s, c, flush) \ ++ { uch cc = (c); \ ++ s->d_buf[s->last_lit] = 0; \ ++ s->l_buf[s->last_lit++] = cc; \ ++ s->dyn_ltree[cc].Freq++; \ ++ flush = (s->last_lit == s->lit_bufsize-1); \ ++ } ++# define _tr_tally_dist(s, distance, length, flush) \ ++ { uch len = (length); \ ++ ush dist = (distance); \ ++ s->d_buf[s->last_lit] = dist; \ ++ s->l_buf[s->last_lit++] = len; \ ++ dist--; \ ++ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ ++ s->dyn_dtree[d_code(dist)].Freq++; \ ++ flush = (s->last_lit == s->lit_bufsize-1); \ ++ } ++#else ++# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) ++# define _tr_tally_dist(s, distance, length, flush) \ ++ flush = _tr_tally(s, distance, length) ++#endif ++ ++#endif /* _DEFLATE_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/infblock.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,403 @@ ++/* infblock.c -- interpret and process block types to last block ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++#include <zlib/zutil.h> ++#include "infblock.h" ++#include "inftrees.h" ++#include "infcodes.h" ++#include "infutil.h" ++ ++struct inflate_codes_state {int dummy;}; /* for buggy compilers */ ++ ++/* simplify the use of the inflate_huft type with some defines */ ++#define exop word.what.Exop ++#define bits word.what.Bits ++ ++/* Table for deflate from PKZIP's appnote.txt. */ ++local const uInt border[] = { /* Order of the bit length code lengths */ ++ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; ++ ++/* ++ Notes beyond the 1.93a appnote.txt: ++ ++ 1. Distance pointers never point before the beginning of the output ++ stream. ++ 2. Distance pointers can point back across blocks, up to 32k away. ++ 3. There is an implied maximum of 7 bits for the bit length table and ++ 15 bits for the actual data. ++ 4. If only one code exists, then it is encoded using one bit. (Zero ++ would be more efficient, but perhaps a little confusing.) If two ++ codes exist, they are coded using one bit each (0 and 1). ++ 5. There is no way of sending zero distance codes--a dummy must be ++ sent if there are none. (History: a pre 2.0 version of PKZIP would ++ store blocks with no distance codes, but this was discovered to be ++ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow ++ zero distance codes, which is sent as one code of zero bits in ++ length. ++ 6. There are up to 286 literal/length codes. Code 256 represents the ++ end-of-block. Note however that the static length tree defines ++ 288 codes just to fill out the Huffman codes. Codes 286 and 287 ++ cannot be used though, since there is no length base or extra bits ++ defined for them. Similarily, there are up to 30 distance codes. ++ However, static trees define 32 codes (all 5 bits) to fill out the ++ Huffman codes, but the last two had better not show up in the data. ++ 7. Unzip can check dynamic Huffman blocks for complete code sets. ++ The exception is that a single code would not be complete (see #4). ++ 8. The five bits following the block type is really the number of ++ literal codes sent minus 257. ++ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits ++ (1+6+6). Therefore, to output three times the length, you output ++ three codes (1+1+1), whereas to output four times the same length, ++ you only need two codes (1+3). Hmm. ++ 10. In the tree reconstruction algorithm, Code = Code + Increment ++ only if BitLength(i) is not zero. (Pretty obvious.) ++ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) ++ 12. Note: length code 284 can represent 227-258, but length code 285 ++ really is 258. The last length deserves its own, short code ++ since it gets used a lot in very redundant files. The length ++ 258 is special since 258 - 3 (the min match length) is 255. ++ 13. The literal/length and distance code bit lengths are read as a ++ single stream of lengths. It is possible (and advantageous) for ++ a repeat code (16, 17, or 18) to go across the boundary between ++ the two sets of lengths. ++ */ ++ ++ ++void inflate_blocks_reset(s, z, c) ++inflate_blocks_statef *s; ++z_streamp z; ++uLongf *c; ++{ ++ if (c != Z_NULL) ++ *c = s->check; ++ if (s->mode == BTREE || s->mode == DTREE) ++ ZFREE(z, s->sub.trees.blens); ++ if (s->mode == CODES) ++ inflate_codes_free(s->sub.decode.codes, z); ++ s->mode = TYPE; ++ s->bitk = 0; ++ s->bitb = 0; ++ s->read = s->write = s->window; ++ if (s->checkfn != Z_NULL) ++ z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); ++ Tracev((stderr, "inflate: blocks reset\n")); ++} ++ ++ ++inflate_blocks_statef *inflate_blocks_new(z, c, w) ++z_streamp z; ++check_func c; ++uInt w; ++{ ++ inflate_blocks_statef *s; ++ ++ if ((s = (inflate_blocks_statef *)ZALLOC ++ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) ++ return s; ++ if ((s->hufts = ++ (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) ++ { ++ ZFREE(z, s); ++ return Z_NULL; ++ } ++ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) ++ { ++ ZFREE(z, s->hufts); ++ ZFREE(z, s); ++ return Z_NULL; ++ } ++ s->end = s->window + w; ++ s->checkfn = c; ++ s->mode = TYPE; ++ Tracev((stderr, "inflate: blocks allocated\n")); ++ inflate_blocks_reset(s, z, Z_NULL); ++ return s; ++} ++ ++ ++int inflate_blocks(s, z, r) ++inflate_blocks_statef *s; ++z_streamp z; ++int r; ++{ ++ uInt t; /* temporary storage */ ++ uLong b; /* bit buffer */ ++ uInt k; /* bits in bit buffer */ ++ Bytef *p; /* input data pointer */ ++ uInt n; /* bytes available there */ ++ Bytef *q; /* output window write pointer */ ++ uInt m; /* bytes to end of window or read pointer */ ++ ++ /* copy input/output information to locals (UPDATE macro restores) */ ++ LOAD ++ ++ /* process input based on current state */ ++ while (1) switch (s->mode) ++ { ++ case TYPE: ++ NEEDBITS(3) ++ t = (uInt)b & 7; ++ s->last = t & 1; ++ switch (t >> 1) ++ { ++ case 0: /* stored */ ++ Tracev((stderr, "inflate: stored block%s\n", ++ s->last ? " (last)" : "")); ++ DUMPBITS(3) ++ t = k & 7; /* go to byte boundary */ ++ DUMPBITS(t) ++ s->mode = LENS; /* get length of stored block */ ++ break; ++ case 1: /* fixed */ ++ Tracev((stderr, "inflate: fixed codes block%s\n", ++ s->last ? " (last)" : "")); ++ { ++ uInt bl, bd; ++ inflate_huft *tl, *td; ++ ++ inflate_trees_fixed(&bl, &bd, &tl, &td, z); ++ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); ++ if (s->sub.decode.codes == Z_NULL) ++ { ++ r = Z_MEM_ERROR; ++ LEAVE ++ } ++ } ++ DUMPBITS(3) ++ s->mode = CODES; ++ break; ++ case 2: /* dynamic */ ++ Tracev((stderr, "inflate: dynamic codes block%s\n", ++ s->last ? " (last)" : "")); ++ DUMPBITS(3) ++ s->mode = TABLE; ++ break; ++ case 3: /* illegal */ ++ DUMPBITS(3) ++ s->mode = BAD; ++ z->msg = (char*)"invalid block type"; ++ r = Z_DATA_ERROR; ++ LEAVE ++ } ++ break; ++ case LENS: ++ NEEDBITS(32) ++ if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) ++ { ++ s->mode = BAD; ++ z->msg = (char*)"invalid stored block lengths"; ++ r = Z_DATA_ERROR; ++ LEAVE ++ } ++ s->sub.left = (uInt)b & 0xffff; ++ b = k = 0; /* dump bits */ ++ Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); ++ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); ++ break; ++ case STORED: ++ if (n == 0) ++ LEAVE ++ NEEDOUT ++ t = s->sub.left; ++ if (t > n) t = n; ++ if (t > m) t = m; ++ zmemcpy(q, p, t); ++ p += t; n -= t; ++ q += t; m -= t; ++ if ((s->sub.left -= t) != 0) ++ break; ++ Tracev((stderr, "inflate: stored end, %lu total out\n", ++ z->total_out + (q >= s->read ? q - s->read : ++ (s->end - s->read) + (q - s->window)))); ++ s->mode = s->last ? DRY : TYPE; ++ break; ++ case TABLE: ++ NEEDBITS(14) ++ s->sub.trees.table = t = (uInt)b & 0x3fff; ++#ifndef PKZIP_BUG_WORKAROUND ++ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) ++ { ++ s->mode = BAD; ++ z->msg = (char*)"too many length or distance symbols"; ++ r = Z_DATA_ERROR; ++ LEAVE ++ } ++#endif ++ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); ++ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) ++ { ++ r = Z_MEM_ERROR; ++ LEAVE ++ } ++ DUMPBITS(14) ++ s->sub.trees.index = 0; ++ Tracev((stderr, "inflate: table sizes ok\n")); ++ s->mode = BTREE; ++ case BTREE: ++ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) ++ { ++ NEEDBITS(3) ++ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; ++ DUMPBITS(3) ++ } ++ while (s->sub.trees.index < 19) ++ s->sub.trees.blens[border[s->sub.trees.index++]] = 0; ++ s->sub.trees.bb = 7; ++ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, ++ &s->sub.trees.tb, s->hufts, z); ++ if (t != Z_OK) ++ { ++ r = t; ++ if (r == Z_DATA_ERROR) ++ { ++ ZFREE(z, s->sub.trees.blens); ++ s->mode = BAD; ++ } ++ LEAVE ++ } ++ s->sub.trees.index = 0; ++ Tracev((stderr, "inflate: bits tree ok\n")); ++ s->mode = DTREE; ++ case DTREE: ++ while (t = s->sub.trees.table, ++ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) ++ { ++ inflate_huft *h; ++ uInt i, j, c; ++ ++ t = s->sub.trees.bb; ++ NEEDBITS(t) ++ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); ++ t = h->bits; ++ c = h->base; ++ if (c < 16) ++ { ++ DUMPBITS(t) ++ s->sub.trees.blens[s->sub.trees.index++] = c; ++ } ++ else /* c == 16..18 */ ++ { ++ i = c == 18 ? 7 : c - 14; ++ j = c == 18 ? 11 : 3; ++ NEEDBITS(t + i) ++ DUMPBITS(t) ++ j += (uInt)b & inflate_mask[i]; ++ DUMPBITS(i) ++ i = s->sub.trees.index; ++ t = s->sub.trees.table; ++ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || ++ (c == 16 && i < 1)) ++ { ++ ZFREE(z, s->sub.trees.blens); ++ s->mode = BAD; ++ z->msg = (char*)"invalid bit length repeat"; ++ r = Z_DATA_ERROR; ++ LEAVE ++ } ++ c = c == 16 ? s->sub.trees.blens[i - 1] : 0; ++ do { ++ s->sub.trees.blens[i++] = c; ++ } while (--j); ++ s->sub.trees.index = i; ++ } ++ } ++ s->sub.trees.tb = Z_NULL; ++ { ++ uInt bl, bd; ++ inflate_huft *tl, *td; ++ inflate_codes_statef *c; ++ ++ bl = 9; /* must be <= 9 for lookahead assumptions */ ++ bd = 6; /* must be <= 9 for lookahead assumptions */ ++ t = s->sub.trees.table; ++ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), ++ s->sub.trees.blens, &bl, &bd, &tl, &td, ++ s->hufts, z); ++ if (t != Z_OK) ++ { ++ if (t == (uInt)Z_DATA_ERROR) ++ { ++ ZFREE(z, s->sub.trees.blens); ++ s->mode = BAD; ++ } ++ r = t; ++ LEAVE ++ } ++ Tracev((stderr, "inflate: trees ok\n")); ++ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) ++ { ++ r = Z_MEM_ERROR; ++ LEAVE ++ } ++ s->sub.decode.codes = c; ++ } ++ ZFREE(z, s->sub.trees.blens); ++ s->mode = CODES; ++ case CODES: ++ UPDATE ++ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) ++ return inflate_flush(s, z, r); ++ r = Z_OK; ++ inflate_codes_free(s->sub.decode.codes, z); ++ LOAD ++ Tracev((stderr, "inflate: codes end, %lu total out\n", ++ z->total_out + (q >= s->read ? q - s->read : ++ (s->end - s->read) + (q - s->window)))); ++ if (!s->last) ++ { ++ s->mode = TYPE; ++ break; ++ } ++ s->mode = DRY; ++ case DRY: ++ FLUSH ++ if (s->read != s->write) ++ LEAVE ++ s->mode = DONE; ++ case DONE: ++ r = Z_STREAM_END; ++ LEAVE ++ case BAD: ++ r = Z_DATA_ERROR; ++ LEAVE ++ default: ++ r = Z_STREAM_ERROR; ++ LEAVE ++ } ++} ++ ++ ++int inflate_blocks_free(s, z) ++inflate_blocks_statef *s; ++z_streamp z; ++{ ++ inflate_blocks_reset(s, z, Z_NULL); ++ ZFREE(z, s->window); ++ ZFREE(z, s->hufts); ++ ZFREE(z, s); ++ Tracev((stderr, "inflate: blocks freed\n")); ++ return Z_OK; ++} ++ ++ ++void inflate_set_dictionary(s, d, n) ++inflate_blocks_statef *s; ++const Bytef *d; ++uInt n; ++{ ++ zmemcpy(s->window, d, n); ++ s->read = s->write = s->window + n; ++} ++ ++ ++/* Returns true if inflate is currently at the end of a block generated ++ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. ++ * IN assertion: s != Z_NULL ++ */ ++int inflate_blocks_sync_point(s) ++inflate_blocks_statef *s; ++{ ++ return s->mode == LENS; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/infblock.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,39 @@ ++/* infblock.h -- header to use infblock.c ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* WARNING: this file should *not* be used by applications. It is ++ part of the implementation of the compression library and is ++ subject to change. Applications should only use zlib.h. ++ */ ++ ++struct inflate_blocks_state; ++typedef struct inflate_blocks_state FAR inflate_blocks_statef; ++ ++extern inflate_blocks_statef * inflate_blocks_new OF(( ++ z_streamp z, ++ check_func c, /* check function */ ++ uInt w)); /* window size */ ++ ++extern int inflate_blocks OF(( ++ inflate_blocks_statef *, ++ z_streamp , ++ int)); /* initial return code */ ++ ++extern void inflate_blocks_reset OF(( ++ inflate_blocks_statef *, ++ z_streamp , ++ uLongf *)); /* check value on output */ ++ ++extern int inflate_blocks_free OF(( ++ inflate_blocks_statef *, ++ z_streamp)); ++ ++extern void inflate_set_dictionary OF(( ++ inflate_blocks_statef *s, ++ const Bytef *d, /* dictionary */ ++ uInt n)); /* dictionary length */ ++ ++extern int inflate_blocks_sync_point OF(( ++ inflate_blocks_statef *s)); +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/infcodes.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,251 @@ ++/* infcodes.c -- process literals and length/distance pairs ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++#include <zlib/zutil.h> ++#include "inftrees.h" ++#include "infblock.h" ++#include "infcodes.h" ++#include "infutil.h" ++#include "inffast.h" ++ ++/* simplify the use of the inflate_huft type with some defines */ ++#define exop word.what.Exop ++#define bits word.what.Bits ++ ++typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ ++ START, /* x: set up for LEN */ ++ LEN, /* i: get length/literal/eob next */ ++ LENEXT, /* i: getting length extra (have base) */ ++ DIST, /* i: get distance next */ ++ DISTEXT, /* i: getting distance extra */ ++ COPY, /* o: copying bytes in window, waiting for space */ ++ LIT, /* o: got literal, waiting for output space */ ++ WASH, /* o: got eob, possibly still output waiting */ ++ END, /* x: got eob and all data flushed */ ++ BADCODE} /* x: got error */ ++inflate_codes_mode; ++ ++/* inflate codes private state */ ++struct inflate_codes_state { ++ ++ /* mode */ ++ inflate_codes_mode mode; /* current inflate_codes mode */ ++ ++ /* mode dependent information */ ++ uInt len; ++ union { ++ struct { ++ inflate_huft *tree; /* pointer into tree */ ++ uInt need; /* bits needed */ ++ } code; /* if LEN or DIST, where in tree */ ++ uInt lit; /* if LIT, literal */ ++ struct { ++ uInt get; /* bits to get for extra */ ++ uInt dist; /* distance back to copy from */ ++ } copy; /* if EXT or COPY, where and how much */ ++ } sub; /* submode */ ++ ++ /* mode independent information */ ++ Byte lbits; /* ltree bits decoded per branch */ ++ Byte dbits; /* dtree bits decoder per branch */ ++ inflate_huft *ltree; /* literal/length/eob tree */ ++ inflate_huft *dtree; /* distance tree */ ++ ++}; ++ ++ ++inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) ++uInt bl, bd; ++inflate_huft *tl; ++inflate_huft *td; /* need separate declaration for Borland C++ */ ++z_streamp z; ++{ ++ inflate_codes_statef *c; ++ ++ if ((c = (inflate_codes_statef *) ++ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) ++ { ++ c->mode = START; ++ c->lbits = (Byte)bl; ++ c->dbits = (Byte)bd; ++ c->ltree = tl; ++ c->dtree = td; ++ Tracev((stderr, "inflate: codes new\n")); ++ } ++ return c; ++} ++ ++ ++int inflate_codes(s, z, r) ++inflate_blocks_statef *s; ++z_streamp z; ++int r; ++{ ++ uInt j; /* temporary storage */ ++ inflate_huft *t; /* temporary pointer */ ++ uInt e; /* extra bits or operation */ ++ uLong b; /* bit buffer */ ++ uInt k; /* bits in bit buffer */ ++ Bytef *p; /* input data pointer */ ++ uInt n; /* bytes available there */ ++ Bytef *q; /* output window write pointer */ ++ uInt m; /* bytes to end of window or read pointer */ ++ Bytef *f; /* pointer to copy strings from */ ++ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ ++ ++ /* copy input/output information to locals (UPDATE macro restores) */ ++ LOAD ++ ++ /* process input and output based on current state */ ++ while (1) switch (c->mode) ++ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ ++ case START: /* x: set up for LEN */ ++#ifndef SLOW ++ if (m >= 258 && n >= 10) ++ { ++ UPDATE ++ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); ++ LOAD ++ if (r != Z_OK) ++ { ++ c->mode = r == Z_STREAM_END ? WASH : BADCODE; ++ break; ++ } ++ } ++#endif /* !SLOW */ ++ c->sub.code.need = c->lbits; ++ c->sub.code.tree = c->ltree; ++ c->mode = LEN; ++ case LEN: /* i: get length/literal/eob next */ ++ j = c->sub.code.need; ++ NEEDBITS(j) ++ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); ++ DUMPBITS(t->bits) ++ e = (uInt)(t->exop); ++ if (e == 0) /* literal */ ++ { ++ c->sub.lit = t->base; ++ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? ++ "inflate: literal '%c'\n" : ++ "inflate: literal 0x%02x\n", t->base)); ++ c->mode = LIT; ++ break; ++ } ++ if (e & 16) /* length */ ++ { ++ c->sub.copy.get = e & 15; ++ c->len = t->base; ++ c->mode = LENEXT; ++ break; ++ } ++ if ((e & 64) == 0) /* next table */ ++ { ++ c->sub.code.need = e; ++ c->sub.code.tree = t + t->base; ++ break; ++ } ++ if (e & 32) /* end of block */ ++ { ++ Tracevv((stderr, "inflate: end of block\n")); ++ c->mode = WASH; ++ break; ++ } ++ c->mode = BADCODE; /* invalid code */ ++ z->msg = (char*)"invalid literal/length code"; ++ r = Z_DATA_ERROR; ++ LEAVE ++ case LENEXT: /* i: getting length extra (have base) */ ++ j = c->sub.copy.get; ++ NEEDBITS(j) ++ c->len += (uInt)b & inflate_mask[j]; ++ DUMPBITS(j) ++ c->sub.code.need = c->dbits; ++ c->sub.code.tree = c->dtree; ++ Tracevv((stderr, "inflate: length %u\n", c->len)); ++ c->mode = DIST; ++ case DIST: /* i: get distance next */ ++ j = c->sub.code.need; ++ NEEDBITS(j) ++ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); ++ DUMPBITS(t->bits) ++ e = (uInt)(t->exop); ++ if (e & 16) /* distance */ ++ { ++ c->sub.copy.get = e & 15; ++ c->sub.copy.dist = t->base; ++ c->mode = DISTEXT; ++ break; ++ } ++ if ((e & 64) == 0) /* next table */ ++ { ++ c->sub.code.need = e; ++ c->sub.code.tree = t + t->base; ++ break; ++ } ++ c->mode = BADCODE; /* invalid code */ ++ z->msg = (char*)"invalid distance code"; ++ r = Z_DATA_ERROR; ++ LEAVE ++ case DISTEXT: /* i: getting distance extra */ ++ j = c->sub.copy.get; ++ NEEDBITS(j) ++ c->sub.copy.dist += (uInt)b & inflate_mask[j]; ++ DUMPBITS(j) ++ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); ++ c->mode = COPY; ++ case COPY: /* o: copying bytes in window, waiting for space */ ++ f = q - c->sub.copy.dist; ++ while (f < s->window) /* modulo window size-"while" instead */ ++ f += s->end - s->window; /* of "if" handles invalid distances */ ++ while (c->len) ++ { ++ NEEDOUT ++ OUTBYTE(*f++) ++ if (f == s->end) ++ f = s->window; ++ c->len--; ++ } ++ c->mode = START; ++ break; ++ case LIT: /* o: got literal, waiting for output space */ ++ NEEDOUT ++ OUTBYTE(c->sub.lit) ++ c->mode = START; ++ break; ++ case WASH: /* o: got eob, possibly more output */ ++ if (k > 7) /* return unused byte, if any */ ++ { ++ Assert(k < 16, "inflate_codes grabbed too many bytes") ++ k -= 8; ++ n++; ++ p--; /* can always return one */ ++ } ++ FLUSH ++ if (s->read != s->write) ++ LEAVE ++ c->mode = END; ++ case END: ++ r = Z_STREAM_END; ++ LEAVE ++ case BADCODE: /* x: got error */ ++ r = Z_DATA_ERROR; ++ LEAVE ++ default: ++ r = Z_STREAM_ERROR; ++ LEAVE ++ } ++#ifdef NEED_DUMMY_RETURN ++ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ ++#endif ++} ++ ++ ++void inflate_codes_free(c, z) ++inflate_codes_statef *c; ++z_streamp z; ++{ ++ ZFREE(z, c); ++ Tracev((stderr, "inflate: codes free\n")); ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/infcodes.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,31 @@ ++/* infcodes.h -- header to use infcodes.c ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* WARNING: this file should *not* be used by applications. It is ++ part of the implementation of the compression library and is ++ subject to change. Applications should only use zlib.h. ++ */ ++ ++#ifndef _INFCODES_H ++#define _INFCODES_H ++ ++struct inflate_codes_state; ++typedef struct inflate_codes_state FAR inflate_codes_statef; ++ ++extern inflate_codes_statef *inflate_codes_new OF(( ++ uInt, uInt, ++ inflate_huft *, inflate_huft *, ++ z_streamp )); ++ ++extern int inflate_codes OF(( ++ inflate_blocks_statef *, ++ z_streamp , ++ int)); ++ ++extern void inflate_codes_free OF(( ++ inflate_codes_statef *, ++ z_streamp )); ++ ++#endif /* _INFCODES_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/inffast.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,183 @@ ++/* inffast.c -- process literals and length/distance pairs fast ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++#include <zlib/zutil.h> ++#include "inftrees.h" ++#include "infblock.h" ++#include "infcodes.h" ++#include "infutil.h" ++#include "inffast.h" ++ ++struct inflate_codes_state {int dummy;}; /* for buggy compilers */ ++ ++/* simplify the use of the inflate_huft type with some defines */ ++#define exop word.what.Exop ++#define bits word.what.Bits ++ ++/* macros for bit input with no checking and for returning unused bytes */ ++#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}} ++#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;} ++ ++/* Called with number of bytes left to write in window at least 258 ++ (the maximum string length) and number of input bytes available ++ at least ten. The ten bytes are six bytes for the longest length/ ++ distance pair plus four bytes for overloading the bit buffer. */ ++ ++int inflate_fast(bl, bd, tl, td, s, z) ++uInt bl, bd; ++inflate_huft *tl; ++inflate_huft *td; /* need separate declaration for Borland C++ */ ++inflate_blocks_statef *s; ++z_streamp z; ++{ ++ inflate_huft *t; /* temporary pointer */ ++ uInt e; /* extra bits or operation */ ++ uLong b; /* bit buffer */ ++ uInt k; /* bits in bit buffer */ ++ Bytef *p; /* input data pointer */ ++ uInt n; /* bytes available there */ ++ Bytef *q; /* output window write pointer */ ++ uInt m; /* bytes to end of window or read pointer */ ++ uInt ml; /* mask for literal/length tree */ ++ uInt md; /* mask for distance tree */ ++ uInt c; /* bytes to copy */ ++ uInt d; /* distance back to copy from */ ++ Bytef *r; /* copy source pointer */ ++ ++ /* load input, output, bit values */ ++ LOAD ++ ++ /* initialize masks */ ++ ml = inflate_mask[bl]; ++ md = inflate_mask[bd]; ++ ++ /* do until not enough input or output space for fast loop */ ++ do { /* assume called with m >= 258 && n >= 10 */ ++ /* get literal/length code */ ++ GRABBITS(20) /* max bits for literal/length code */ ++ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) ++ { ++ DUMPBITS(t->bits) ++ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? ++ "inflate: * literal '%c'\n" : ++ "inflate: * literal 0x%02x\n", t->base)); ++ *q++ = (Byte)t->base; ++ m--; ++ continue; ++ } ++ do { ++ DUMPBITS(t->bits) ++ if (e & 16) ++ { ++ /* get extra bits for length */ ++ e &= 15; ++ c = t->base + ((uInt)b & inflate_mask[e]); ++ DUMPBITS(e) ++ Tracevv((stderr, "inflate: * length %u\n", c)); ++ ++ /* decode distance base of block to copy */ ++ GRABBITS(15); /* max bits for distance code */ ++ e = (t = td + ((uInt)b & md))->exop; ++ do { ++ DUMPBITS(t->bits) ++ if (e & 16) ++ { ++ /* get extra bits to add to distance base */ ++ e &= 15; ++ GRABBITS(e) /* get extra bits (up to 13) */ ++ d = t->base + ((uInt)b & inflate_mask[e]); ++ DUMPBITS(e) ++ Tracevv((stderr, "inflate: * distance %u\n", d)); ++ ++ /* do the copy */ ++ m -= c; ++ r = q - d; ++ if (r < s->window) /* wrap if needed */ ++ { ++ do { ++ r += s->end - s->window; /* force pointer in window */ ++ } while (r < s->window); /* covers invalid distances */ ++ e = s->end - r; ++ if (c > e) ++ { ++ c -= e; /* wrapped copy */ ++ do { ++ *q++ = *r++; ++ } while (--e); ++ r = s->window; ++ do { ++ *q++ = *r++; ++ } while (--c); ++ } ++ else /* normal copy */ ++ { ++ *q++ = *r++; c--; ++ *q++ = *r++; c--; ++ do { ++ *q++ = *r++; ++ } while (--c); ++ } ++ } ++ else /* normal copy */ ++ { ++ *q++ = *r++; c--; ++ *q++ = *r++; c--; ++ do { ++ *q++ = *r++; ++ } while (--c); ++ } ++ break; ++ } ++ else if ((e & 64) == 0) ++ { ++ t += t->base; ++ e = (t += ((uInt)b & inflate_mask[e]))->exop; ++ } ++ else ++ { ++ z->msg = (char*)"invalid distance code"; ++ UNGRAB ++ UPDATE ++ return Z_DATA_ERROR; ++ } ++ } while (1); ++ break; ++ } ++ if ((e & 64) == 0) ++ { ++ t += t->base; ++ if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) ++ { ++ DUMPBITS(t->bits) ++ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? ++ "inflate: * literal '%c'\n" : ++ "inflate: * literal 0x%02x\n", t->base)); ++ *q++ = (Byte)t->base; ++ m--; ++ break; ++ } ++ } ++ else if (e & 32) ++ { ++ Tracevv((stderr, "inflate: * end of block\n")); ++ UNGRAB ++ UPDATE ++ return Z_STREAM_END; ++ } ++ else ++ { ++ z->msg = (char*)"invalid literal/length code"; ++ UNGRAB ++ UPDATE ++ return Z_DATA_ERROR; ++ } ++ } while (1); ++ } while (m >= 258 && n >= 10); ++ ++ /* not enough input or output--restore pointers and return */ ++ UNGRAB ++ UPDATE ++ return Z_OK; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/inffast.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,22 @@ ++/* inffast.h -- header to use inffast.c ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* WARNING: this file should *not* be used by applications. It is ++ part of the implementation of the compression library and is ++ subject to change. Applications should only use zlib.h. ++ */ ++ ++#ifndef _INFFAST_H ++#define _INFFAST_H ++ ++extern int inflate_fast OF(( ++ uInt, ++ uInt, ++ inflate_huft *, ++ inflate_huft *, ++ inflate_blocks_statef *, ++ z_streamp )); ++ ++#endif /* _INFFAST_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/inffixed.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,151 @@ ++/* inffixed.h -- table for decoding fixed codes ++ * Generated automatically by the maketree.c program ++ */ ++ ++/* WARNING: this file should *not* be used by applications. It is ++ part of the implementation of the compression library and is ++ subject to change. Applications should only use zlib.h. ++ */ ++ ++local uInt fixed_bl = 9; ++local uInt fixed_bd = 5; ++local inflate_huft fixed_tl[] = { ++ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, ++ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, ++ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, ++ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, ++ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, ++ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, ++ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, ++ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, ++ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, ++ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, ++ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, ++ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, ++ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, ++ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, ++ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, ++ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, ++ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, ++ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, ++ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, ++ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, ++ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, ++ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, ++ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, ++ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, ++ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, ++ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, ++ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, ++ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, ++ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, ++ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, ++ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, ++ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, ++ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, ++ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, ++ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, ++ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, ++ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, ++ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, ++ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, ++ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, ++ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, ++ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, ++ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, ++ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, ++ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, ++ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, ++ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, ++ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, ++ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, ++ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, ++ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, ++ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, ++ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, ++ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, ++ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, ++ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, ++ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, ++ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, ++ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, ++ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, ++ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, ++ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, ++ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, ++ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, ++ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, ++ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, ++ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, ++ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, ++ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, ++ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, ++ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, ++ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, ++ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, ++ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, ++ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, ++ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, ++ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, ++ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, ++ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, ++ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, ++ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, ++ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, ++ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, ++ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, ++ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, ++ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, ++ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, ++ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, ++ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, ++ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, ++ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, ++ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, ++ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, ++ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, ++ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, ++ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, ++ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, ++ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, ++ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, ++ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, ++ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, ++ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, ++ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, ++ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, ++ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, ++ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, ++ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, ++ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, ++ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, ++ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, ++ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, ++ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, ++ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, ++ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, ++ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, ++ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, ++ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, ++ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, ++ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, ++ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, ++ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, ++ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, ++ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, ++ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, ++ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, ++ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, ++ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, ++ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} ++ }; ++local inflate_huft fixed_td[] = { ++ {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, ++ {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, ++ {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, ++ {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, ++ {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, ++ {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, ++ {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, ++ {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} ++ }; +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/inflate.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,368 @@ ++/* inflate.c -- zlib interface to inflate modules ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++#include <zlib/zutil.h> ++#include "infblock.h" ++ ++struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ ++ ++typedef enum { ++ METHOD, /* waiting for method byte */ ++ FLAG, /* waiting for flag byte */ ++ DICT4, /* four dictionary check bytes to go */ ++ DICT3, /* three dictionary check bytes to go */ ++ DICT2, /* two dictionary check bytes to go */ ++ DICT1, /* one dictionary check byte to go */ ++ DICT0, /* waiting for inflateSetDictionary */ ++ BLOCKS, /* decompressing blocks */ ++ CHECK4, /* four check bytes to go */ ++ CHECK3, /* three check bytes to go */ ++ CHECK2, /* two check bytes to go */ ++ CHECK1, /* one check byte to go */ ++ DONE, /* finished check, done */ ++ BAD} /* got an error--stay here */ ++inflate_mode; ++ ++/* inflate private state */ ++struct internal_state { ++ ++ /* mode */ ++ inflate_mode mode; /* current inflate mode */ ++ ++ /* mode dependent information */ ++ union { ++ uInt method; /* if FLAGS, method byte */ ++ struct { ++ uLong was; /* computed check value */ ++ uLong need; /* stream check value */ ++ } check; /* if CHECK, check values to compare */ ++ uInt marker; /* if BAD, inflateSync's marker bytes count */ ++ } sub; /* submode */ ++ ++ /* mode independent information */ ++ int nowrap; /* flag for no wrapper */ ++ uInt wbits; /* log2(window size) (8..15, defaults to 15) */ ++ inflate_blocks_statef ++ *blocks; /* current inflate_blocks state */ ++ ++}; ++ ++ ++int ZEXPORT inflateReset(z) ++z_streamp z; ++{ ++ if (z == Z_NULL || z->state == Z_NULL) ++ return Z_STREAM_ERROR; ++ z->total_in = z->total_out = 0; ++ z->msg = Z_NULL; ++ z->state->mode = z->state->nowrap ? BLOCKS : METHOD; ++ inflate_blocks_reset(z->state->blocks, z, Z_NULL); ++ Tracev((stderr, "inflate: reset\n")); ++ return Z_OK; ++} ++ ++ ++int ZEXPORT inflateEnd(z) ++z_streamp z; ++{ ++ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) ++ return Z_STREAM_ERROR; ++ if (z->state->blocks != Z_NULL) ++ inflate_blocks_free(z->state->blocks, z); ++ ZFREE(z, z->state); ++ z->state = Z_NULL; ++ Tracev((stderr, "inflate: end\n")); ++ return Z_OK; ++} ++ ++ ++int ZEXPORT inflateInit2_(z, w, version, stream_size) ++z_streamp z; ++int w; ++const char *version; ++int stream_size; ++{ ++ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || ++ stream_size != sizeof(z_stream)) ++ return Z_VERSION_ERROR; ++ ++ /* initialize state */ ++ if (z == Z_NULL) ++ return Z_STREAM_ERROR; ++ z->msg = Z_NULL; ++ if (z->zalloc == Z_NULL) ++ { ++ return Z_STREAM_ERROR; ++/* z->zalloc = zcalloc; ++ z->opaque = (voidpf)0; ++*/ ++ } ++ if (z->zfree == Z_NULL) return Z_STREAM_ERROR; /* z->zfree = zcfree; */ ++ if ((z->state = (struct internal_state FAR *) ++ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) ++ return Z_MEM_ERROR; ++ z->state->blocks = Z_NULL; ++ ++ /* handle undocumented nowrap option (no zlib header or check) */ ++ z->state->nowrap = 0; ++ if (w < 0) ++ { ++ w = - w; ++ z->state->nowrap = 1; ++ } ++ ++ /* set window size */ ++ if (w < 8 || w > 15) ++ { ++ inflateEnd(z); ++ return Z_STREAM_ERROR; ++ } ++ z->state->wbits = (uInt)w; ++ ++ /* create inflate_blocks state */ ++ if ((z->state->blocks = ++ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) ++ == Z_NULL) ++ { ++ inflateEnd(z); ++ return Z_MEM_ERROR; ++ } ++ Tracev((stderr, "inflate: allocated\n")); ++ ++ /* reset state */ ++ inflateReset(z); ++ return Z_OK; ++} ++ ++ ++int ZEXPORT inflateInit_(z, version, stream_size) ++z_streamp z; ++const char *version; ++int stream_size; ++{ ++ return inflateInit2_(z, DEF_WBITS, version, stream_size); ++} ++ ++ ++#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} ++#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) ++ ++int ZEXPORT inflate(z, f) ++z_streamp z; ++int f; ++{ ++ int r; ++ uInt b; ++ ++ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) ++ return Z_STREAM_ERROR; ++ f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; ++ r = Z_BUF_ERROR; ++ while (1) switch (z->state->mode) ++ { ++ case METHOD: ++ NEEDBYTE ++ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) ++ { ++ z->state->mode = BAD; ++ z->msg = (char*)"unknown compression method"; ++ z->state->sub.marker = 5; /* can't try inflateSync */ ++ break; ++ } ++ if ((z->state->sub.method >> 4) + 8 > z->state->wbits) ++ { ++ z->state->mode = BAD; ++ z->msg = (char*)"invalid window size"; ++ z->state->sub.marker = 5; /* can't try inflateSync */ ++ break; ++ } ++ z->state->mode = FLAG; ++ case FLAG: ++ NEEDBYTE ++ b = NEXTBYTE; ++ if (((z->state->sub.method << 8) + b) % 31) ++ { ++ z->state->mode = BAD; ++ z->msg = (char*)"incorrect header check"; ++ z->state->sub.marker = 5; /* can't try inflateSync */ ++ break; ++ } ++ Tracev((stderr, "inflate: zlib header ok\n")); ++ if (!(b & PRESET_DICT)) ++ { ++ z->state->mode = BLOCKS; ++ break; ++ } ++ z->state->mode = DICT4; ++ case DICT4: ++ NEEDBYTE ++ z->state->sub.check.need = (uLong)NEXTBYTE << 24; ++ z->state->mode = DICT3; ++ case DICT3: ++ NEEDBYTE ++ z->state->sub.check.need += (uLong)NEXTBYTE << 16; ++ z->state->mode = DICT2; ++ case DICT2: ++ NEEDBYTE ++ z->state->sub.check.need += (uLong)NEXTBYTE << 8; ++ z->state->mode = DICT1; ++ case DICT1: ++ NEEDBYTE ++ z->state->sub.check.need += (uLong)NEXTBYTE; ++ z->adler = z->state->sub.check.need; ++ z->state->mode = DICT0; ++ return Z_NEED_DICT; ++ case DICT0: ++ z->state->mode = BAD; ++ z->msg = (char*)"need dictionary"; ++ z->state->sub.marker = 0; /* can try inflateSync */ ++ return Z_STREAM_ERROR; ++ case BLOCKS: ++ r = inflate_blocks(z->state->blocks, z, r); ++ if (r == Z_DATA_ERROR) ++ { ++ z->state->mode = BAD; ++ z->state->sub.marker = 0; /* can try inflateSync */ ++ break; ++ } ++ if (r == Z_OK) ++ r = f; ++ if (r != Z_STREAM_END) ++ return r; ++ r = f; ++ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); ++ if (z->state->nowrap) ++ { ++ z->state->mode = DONE; ++ break; ++ } ++ z->state->mode = CHECK4; ++ case CHECK4: ++ NEEDBYTE ++ z->state->sub.check.need = (uLong)NEXTBYTE << 24; ++ z->state->mode = CHECK3; ++ case CHECK3: ++ NEEDBYTE ++ z->state->sub.check.need += (uLong)NEXTBYTE << 16; ++ z->state->mode = CHECK2; ++ case CHECK2: ++ NEEDBYTE ++ z->state->sub.check.need += (uLong)NEXTBYTE << 8; ++ z->state->mode = CHECK1; ++ case CHECK1: ++ NEEDBYTE ++ z->state->sub.check.need += (uLong)NEXTBYTE; ++ ++ if (z->state->sub.check.was != z->state->sub.check.need) ++ { ++ z->state->mode = BAD; ++ z->msg = (char*)"incorrect data check"; ++ z->state->sub.marker = 5; /* can't try inflateSync */ ++ break; ++ } ++ Tracev((stderr, "inflate: zlib check ok\n")); ++ z->state->mode = DONE; ++ case DONE: ++ return Z_STREAM_END; ++ case BAD: ++ return Z_DATA_ERROR; ++ default: ++ return Z_STREAM_ERROR; ++ } ++#ifdef NEED_DUMMY_RETURN ++ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ ++#endif ++} ++ ++ ++int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) ++z_streamp z; ++const Bytef *dictionary; ++uInt dictLength; ++{ ++ uInt length = dictLength; ++ ++ if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) ++ return Z_STREAM_ERROR; ++ ++ if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; ++ z->adler = 1L; ++ ++ if (length >= ((uInt)1<<z->state->wbits)) ++ { ++ length = (1<<z->state->wbits)-1; ++ dictionary += dictLength - length; ++ } ++ inflate_set_dictionary(z->state->blocks, dictionary, length); ++ z->state->mode = BLOCKS; ++ return Z_OK; ++} ++ ++ ++int ZEXPORT inflateSync(z) ++z_streamp z; ++{ ++ uInt n; /* number of bytes to look at */ ++ Bytef *p; /* pointer to bytes */ ++ uInt m; /* number of marker bytes found in a row */ ++ uLong r, w; /* temporaries to save total_in and total_out */ ++ ++ /* set up */ ++ if (z == Z_NULL || z->state == Z_NULL) ++ return Z_STREAM_ERROR; ++ if (z->state->mode != BAD) ++ { ++ z->state->mode = BAD; ++ z->state->sub.marker = 0; ++ } ++ if ((n = z->avail_in) == 0) ++ return Z_BUF_ERROR; ++ p = z->next_in; ++ m = z->state->sub.marker; ++ ++ /* search */ ++ while (n && m < 4) ++ { ++ static const Byte mark[4] = {0, 0, 0xff, 0xff}; ++ if (*p == mark[m]) ++ m++; ++ else if (*p) ++ m = 0; ++ else ++ m = 4 - m; ++ p++, n--; ++ } ++ ++ /* restore */ ++ z->total_in += p - z->next_in; ++ z->next_in = p; ++ z->avail_in = n; ++ z->state->sub.marker = m; ++ ++ /* return no joy or set up to restart on a new block */ ++ if (m != 4) ++ return Z_DATA_ERROR; ++ r = z->total_in; w = z->total_out; ++ inflateReset(z); ++ z->total_in = r; z->total_out = w; ++ z->state->mode = BLOCKS; ++ return Z_OK; ++} ++ ++ ++/* Returns true if inflate is currently at the end of a block generated ++ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP ++ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH ++ * but removes the length bytes of the resulting empty stored block. When ++ * decompressing, PPP checks that at the end of input packet, inflate is ++ * waiting for these length bytes. ++ */ ++int ZEXPORT inflateSyncPoint(z) ++z_streamp z; ++{ ++ if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) ++ return Z_STREAM_ERROR; ++ return inflate_blocks_sync_point(z->state->blocks); ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/inftrees.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,454 @@ ++/* inftrees.c -- generate Huffman trees for efficient decoding ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++#include <zlib/zutil.h> ++#include "inftrees.h" ++ ++#if !defined(BUILDFIXED) && !defined(STDC) ++# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ ++#endif ++ ++local const char inflate_copyright[] = ++ " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; ++/* ++ If you use the zlib library in a product, an acknowledgment is welcome ++ in the documentation of your product. If for some reason you cannot ++ include such an acknowledgment, I would appreciate that you keep this ++ copyright string in the executable of your product. ++ */ ++struct internal_state {int dummy;}; /* for buggy compilers */ ++ ++/* simplify the use of the inflate_huft type with some defines */ ++#define exop word.what.Exop ++#define bits word.what.Bits ++ ++ ++local int huft_build OF(( ++ uIntf *, /* code lengths in bits */ ++ uInt, /* number of codes */ ++ uInt, /* number of "simple" codes */ ++ const uIntf *, /* list of base values for non-simple codes */ ++ const uIntf *, /* list of extra bits for non-simple codes */ ++ inflate_huft * FAR*,/* result: starting table */ ++ uIntf *, /* maximum lookup bits (returns actual) */ ++ inflate_huft *, /* space for trees */ ++ uInt *, /* hufts used in space */ ++ uIntf * )); /* space for values */ ++ ++/* Tables for deflate from PKZIP's appnote.txt. */ ++local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ ++ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, ++ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; ++ /* see note #13 above about 258 */ ++local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, ++ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ ++local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ ++ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, ++ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, ++ 8193, 12289, 16385, 24577}; ++local const uInt cpdext[30] = { /* Extra bits for distance codes */ ++ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, ++ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, ++ 12, 12, 13, 13}; ++ ++/* ++ Huffman code decoding is performed using a multi-level table lookup. ++ The fastest way to decode is to simply build a lookup table whose ++ size is determined by the longest code. However, the time it takes ++ to build this table can also be a factor if the data being decoded ++ is not very long. The most common codes are necessarily the ++ shortest codes, so those codes dominate the decoding time, and hence ++ the speed. The idea is you can have a shorter table that decodes the ++ shorter, more probable codes, and then point to subsidiary tables for ++ the longer codes. The time it costs to decode the longer codes is ++ then traded against the time it takes to make longer tables. ++ ++ This results of this trade are in the variables lbits and dbits ++ below. lbits is the number of bits the first level table for literal/ ++ length codes can decode in one step, and dbits is the same thing for ++ the distance codes. Subsequent tables are also less than or equal to ++ those sizes. These values may be adjusted either when all of the ++ codes are shorter than that, in which case the longest code length in ++ bits is used, or when the shortest code is *longer* than the requested ++ table size, in which case the length of the shortest code in bits is ++ used. ++ ++ There are two different values for the two tables, since they code a ++ different number of possibilities each. The literal/length table ++ codes 286 possible values, or in a flat code, a little over eight ++ bits. The distance table codes 30 possible values, or a little less ++ than five bits, flat. The optimum values for speed end up being ++ about one bit more than those, so lbits is 8+1 and dbits is 5+1. ++ The optimum values may differ though from machine to machine, and ++ possibly even between compilers. Your mileage may vary. ++ */ ++ ++ ++/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ ++#define BMAX 15 /* maximum bit length of any code */ ++ ++local int huft_build(b, n, s, d, e, t, m, hp, hn, v) ++uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ ++uInt n; /* number of codes (assumed <= 288) */ ++uInt s; /* number of simple-valued codes (0..s-1) */ ++const uIntf *d; /* list of base values for non-simple codes */ ++const uIntf *e; /* list of extra bits for non-simple codes */ ++inflate_huft * FAR *t; /* result: starting table */ ++uIntf *m; /* maximum lookup bits, returns actual */ ++inflate_huft *hp; /* space for trees */ ++uInt *hn; /* hufts used in space */ ++uIntf *v; /* working area: values in order of bit length */ ++/* Given a list of code lengths and a maximum table size, make a set of ++ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR ++ if the given code set is incomplete (the tables are still built in this ++ case), or Z_DATA_ERROR if the input is invalid. */ ++{ ++ ++ uInt a; /* counter for codes of length k */ ++ uInt c[BMAX+1]; /* bit length count table */ ++ uInt f; /* i repeats in table every f entries */ ++ int g; /* maximum code length */ ++ int h; /* table level */ ++ register uInt i; /* counter, current code */ ++ register uInt j; /* counter */ ++ register int k; /* number of bits in current code */ ++ int l; /* bits per table (returned in m) */ ++ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ ++ register uIntf *p; /* pointer into c[], b[], or v[] */ ++ inflate_huft *q; /* points to current table */ ++ struct inflate_huft_s r; /* table entry for structure assignment */ ++ inflate_huft *u[BMAX]; /* table stack */ ++ register int w; /* bits before this table == (l * h) */ ++ uInt x[BMAX+1]; /* bit offsets, then code stack */ ++ uIntf *xp; /* pointer into x */ ++ int y; /* number of dummy codes added */ ++ uInt z; /* number of entries in current table */ ++ ++ ++ /* Generate counts for each bit length */ ++ p = c; ++#define C0 *p++ = 0; ++#define C2 C0 C0 C0 C0 ++#define C4 C2 C2 C2 C2 ++ C4 /* clear c[]--assume BMAX+1 is 16 */ ++ p = b; i = n; ++ do { ++ c[*p++]++; /* assume all entries <= BMAX */ ++ } while (--i); ++ if (c[0] == n) /* null input--all zero length codes */ ++ { ++ *t = (inflate_huft *)Z_NULL; ++ *m = 0; ++ return Z_OK; ++ } ++ ++ ++ /* Find minimum and maximum length, bound *m by those */ ++ l = *m; ++ for (j = 1; j <= BMAX; j++) ++ if (c[j]) ++ break; ++ k = j; /* minimum code length */ ++ if ((uInt)l < j) ++ l = j; ++ for (i = BMAX; i; i--) ++ if (c[i]) ++ break; ++ g = i; /* maximum code length */ ++ if ((uInt)l > i) ++ l = i; ++ *m = l; ++ ++ ++ /* Adjust last length count to fill out codes, if needed */ ++ for (y = 1 << j; j < i; j++, y <<= 1) ++ if ((y -= c[j]) < 0) ++ return Z_DATA_ERROR; ++ if ((y -= c[i]) < 0) ++ return Z_DATA_ERROR; ++ c[i] += y; ++ ++ ++ /* Generate starting offsets into the value table for each length */ ++ x[1] = j = 0; ++ p = c + 1; xp = x + 2; ++ while (--i) { /* note that i == g from above */ ++ *xp++ = (j += *p++); ++ } ++ ++ ++ /* Make a table of values in order of bit lengths */ ++ p = b; i = 0; ++ do { ++ if ((j = *p++) != 0) ++ v[x[j]++] = i; ++ } while (++i < n); ++ n = x[g]; /* set n to length of v */ ++ ++ ++ /* Generate the Huffman codes and for each, make the table entries */ ++ x[0] = i = 0; /* first Huffman code is zero */ ++ p = v; /* grab values in bit order */ ++ h = -1; /* no tables yet--level -1 */ ++ w = -l; /* bits decoded == (l * h) */ ++ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ ++ q = (inflate_huft *)Z_NULL; /* ditto */ ++ z = 0; /* ditto */ ++ ++ /* go through the bit lengths (k already is bits in shortest code) */ ++ for (; k <= g; k++) ++ { ++ a = c[k]; ++ while (a--) ++ { ++ /* here i is the Huffman code of length k bits for value *p */ ++ /* make tables up to required level */ ++ while (k > w + l) ++ { ++ h++; ++ w += l; /* previous table always l bits */ ++ ++ /* compute minimum size table less than or equal to l bits */ ++ z = g - w; ++ z = z > (uInt)l ? l : z; /* table size upper limit */ ++ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ ++ { /* too few codes for k-w bit table */ ++ f -= a + 1; /* deduct codes from patterns left */ ++ xp = c + k; ++ if (j < z) ++ while (++j < z) /* try smaller tables up to z bits */ ++ { ++ if ((f <<= 1) <= *++xp) ++ break; /* enough codes to use up j bits */ ++ f -= *xp; /* else deduct codes from patterns */ ++ } ++ } ++ z = 1 << j; /* table entries for j-bit table */ ++ ++ /* allocate new table */ ++ if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ ++ return Z_DATA_ERROR; /* overflow of MANY */ ++ u[h] = q = hp + *hn; ++ *hn += z; ++ ++ /* connect to last table, if there is one */ ++ if (h) ++ { ++ x[h] = i; /* save pattern for backing up */ ++ r.bits = (Byte)l; /* bits to dump before this table */ ++ r.exop = (Byte)j; /* bits in this table */ ++ j = i >> (w - l); ++ r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ ++ u[h-1][j] = r; /* connect to last table */ ++ } ++ else ++ *t = q; /* first table is returned result */ ++ } ++ ++ /* set up table entry in r */ ++ r.bits = (Byte)(k - w); ++ if (p >= v + n) ++ r.exop = 128 + 64; /* out of values--invalid code */ ++ else if (*p < s) ++ { ++ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ ++ r.base = *p++; /* simple code is just the value */ ++ } ++ else ++ { ++ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ ++ r.base = d[*p++ - s]; ++ } ++ ++ /* fill code-like entries with r */ ++ f = 1 << (k - w); ++ for (j = i >> w; j < z; j += f) ++ q[j] = r; ++ ++ /* backwards increment the k-bit code i */ ++ for (j = 1 << (k - 1); i & j; j >>= 1) ++ i ^= j; ++ i ^= j; ++ ++ /* backup over finished tables */ ++ mask = (1 << w) - 1; /* needed on HP, cc -O bug */ ++ while ((i & mask) != x[h]) ++ { ++ h--; /* don't need to update q */ ++ w -= l; ++ mask = (1 << w) - 1; ++ } ++ } ++ } ++ ++ ++ /* Return Z_BUF_ERROR if we were given an incomplete table */ ++ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; ++} ++ ++ ++int inflate_trees_bits(c, bb, tb, hp, z) ++uIntf *c; /* 19 code lengths */ ++uIntf *bb; /* bits tree desired/actual depth */ ++inflate_huft * FAR *tb; /* bits tree result */ ++inflate_huft *hp; /* space for trees */ ++z_streamp z; /* for messages */ ++{ ++ int r; ++ uInt hn = 0; /* hufts used in space */ ++ uIntf *v; /* work area for huft_build */ ++ ++ if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) ++ return Z_MEM_ERROR; ++ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, ++ tb, bb, hp, &hn, v); ++ if (r == Z_DATA_ERROR) ++ z->msg = (char*)"oversubscribed dynamic bit lengths tree"; ++ else if (r == Z_BUF_ERROR || *bb == 0) ++ { ++ z->msg = (char*)"incomplete dynamic bit lengths tree"; ++ r = Z_DATA_ERROR; ++ } ++ ZFREE(z, v); ++ return r; ++} ++ ++ ++int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) ++uInt nl; /* number of literal/length codes */ ++uInt nd; /* number of distance codes */ ++uIntf *c; /* that many (total) code lengths */ ++uIntf *bl; /* literal desired/actual bit depth */ ++uIntf *bd; /* distance desired/actual bit depth */ ++inflate_huft * FAR *tl; /* literal/length tree result */ ++inflate_huft * FAR *td; /* distance tree result */ ++inflate_huft *hp; /* space for trees */ ++z_streamp z; /* for messages */ ++{ ++ int r; ++ uInt hn = 0; /* hufts used in space */ ++ uIntf *v; /* work area for huft_build */ ++ ++ /* allocate work area */ ++ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) ++ return Z_MEM_ERROR; ++ ++ /* build literal/length tree */ ++ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); ++ if (r != Z_OK || *bl == 0) ++ { ++ if (r == Z_DATA_ERROR) ++ z->msg = (char*)"oversubscribed literal/length tree"; ++ else if (r != Z_MEM_ERROR) ++ { ++ z->msg = (char*)"incomplete literal/length tree"; ++ r = Z_DATA_ERROR; ++ } ++ ZFREE(z, v); ++ return r; ++ } ++ ++ /* build distance tree */ ++ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); ++ if (r != Z_OK || (*bd == 0 && nl > 257)) ++ { ++ if (r == Z_DATA_ERROR) ++ z->msg = (char*)"oversubscribed distance tree"; ++ else if (r == Z_BUF_ERROR) { ++#ifdef PKZIP_BUG_WORKAROUND ++ r = Z_OK; ++ } ++#else ++ z->msg = (char*)"incomplete distance tree"; ++ r = Z_DATA_ERROR; ++ } ++ else if (r != Z_MEM_ERROR) ++ { ++ z->msg = (char*)"empty distance tree with lengths"; ++ r = Z_DATA_ERROR; ++ } ++ ZFREE(z, v); ++ return r; ++#endif ++ } ++ ++ /* done */ ++ ZFREE(z, v); ++ return Z_OK; ++} ++ ++ ++/* build fixed tables only once--keep them here */ ++#ifdef BUILDFIXED ++local int fixed_built = 0; ++#define FIXEDH 544 /* number of hufts used by fixed tables */ ++local inflate_huft fixed_mem[FIXEDH]; ++local uInt fixed_bl; ++local uInt fixed_bd; ++local inflate_huft *fixed_tl; ++local inflate_huft *fixed_td; ++#else ++#include "inffixed.h" ++#endif ++ ++ ++int inflate_trees_fixed(bl, bd, tl, td, z) ++uIntf *bl; /* literal desired/actual bit depth */ ++uIntf *bd; /* distance desired/actual bit depth */ ++inflate_huft * FAR *tl; /* literal/length tree result */ ++inflate_huft * FAR *td; /* distance tree result */ ++z_streamp z; /* for memory allocation */ ++{ ++#ifdef BUILDFIXED ++ /* build fixed tables if not already */ ++ if (!fixed_built) ++ { ++ int k; /* temporary variable */ ++ uInt f = 0; /* number of hufts used in fixed_mem */ ++ uIntf *c; /* length list for huft_build */ ++ uIntf *v; /* work area for huft_build */ ++ ++ /* allocate memory */ ++ if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) ++ return Z_MEM_ERROR; ++ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) ++ { ++ ZFREE(z, c); ++ return Z_MEM_ERROR; ++ } ++ ++ /* literal table */ ++ for (k = 0; k < 144; k++) ++ c[k] = 8; ++ for (; k < 256; k++) ++ c[k] = 9; ++ for (; k < 280; k++) ++ c[k] = 7; ++ for (; k < 288; k++) ++ c[k] = 8; ++ fixed_bl = 9; ++ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, ++ fixed_mem, &f, v); ++ ++ /* distance table */ ++ for (k = 0; k < 30; k++) ++ c[k] = 5; ++ fixed_bd = 5; ++ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, ++ fixed_mem, &f, v); ++ ++ /* done */ ++ ZFREE(z, v); ++ ZFREE(z, c); ++ fixed_built = 1; ++ } ++#endif ++ *bl = fixed_bl; ++ *bd = fixed_bd; ++ *tl = fixed_tl; ++ *td = fixed_td; ++ return Z_OK; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/inftrees.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,63 @@ ++/* inftrees.h -- header to use inftrees.c ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* WARNING: this file should *not* be used by applications. It is ++ part of the implementation of the compression library and is ++ subject to change. Applications should only use zlib.h. ++ */ ++ ++/* Huffman code lookup table entry--this entry is four bytes for machines ++ that have 16-bit pointers (e.g. PC's in the small or medium model). */ ++ ++#ifndef _INFTREES_H ++#define _INFTREES_H ++ ++typedef struct inflate_huft_s FAR inflate_huft; ++ ++struct inflate_huft_s { ++ union { ++ struct { ++ Byte Exop; /* number of extra bits or operation */ ++ Byte Bits; /* number of bits in this code or subcode */ ++ } what; ++ uInt pad; /* pad structure to a power of 2 (4 bytes for */ ++ } word; /* 16-bit, 8 bytes for 32-bit int's) */ ++ uInt base; /* literal, length base, distance base, ++ or table offset */ ++}; ++ ++/* Maximum size of dynamic tree. The maximum found in a long but non- ++ exhaustive search was 1004 huft structures (850 for length/literals ++ and 154 for distances, the latter actually the result of an ++ exhaustive search). The actual maximum is not known, but the ++ value below is more than safe. */ ++#define MANY 1440 ++ ++extern int inflate_trees_bits OF(( ++ uIntf *, /* 19 code lengths */ ++ uIntf *, /* bits tree desired/actual depth */ ++ inflate_huft * FAR *, /* bits tree result */ ++ inflate_huft *, /* space for trees */ ++ z_streamp)); /* for messages */ ++ ++extern int inflate_trees_dynamic OF(( ++ uInt, /* number of literal/length codes */ ++ uInt, /* number of distance codes */ ++ uIntf *, /* that many (total) code lengths */ ++ uIntf *, /* literal desired/actual bit depth */ ++ uIntf *, /* distance desired/actual bit depth */ ++ inflate_huft * FAR *, /* literal/length tree result */ ++ inflate_huft * FAR *, /* distance tree result */ ++ inflate_huft *, /* space for trees */ ++ z_streamp)); /* for messages */ ++ ++extern int inflate_trees_fixed OF(( ++ uIntf *, /* literal desired/actual bit depth */ ++ uIntf *, /* distance desired/actual bit depth */ ++ inflate_huft * FAR *, /* literal/length tree result */ ++ inflate_huft * FAR *, /* distance tree result */ ++ z_streamp)); /* for memory allocation */ ++ ++#endif /* _INFTREES_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/infutil.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,87 @@ ++/* inflate_util.c -- data and routines common to blocks and codes ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++#include <zlib/zutil.h> ++#include "infblock.h" ++#include "inftrees.h" ++#include "infcodes.h" ++#include "infutil.h" ++ ++struct inflate_codes_state {int dummy;}; /* for buggy compilers */ ++ ++/* And'ing with mask[n] masks the lower n bits */ ++uInt inflate_mask[17] = { ++ 0x0000, ++ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, ++ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff ++}; ++ ++ ++/* copy as much as possible from the sliding window to the output area */ ++int inflate_flush(s, z, r) ++inflate_blocks_statef *s; ++z_streamp z; ++int r; ++{ ++ uInt n; ++ Bytef *p; ++ Bytef *q; ++ ++ /* local copies of source and destination pointers */ ++ p = z->next_out; ++ q = s->read; ++ ++ /* compute number of bytes to copy as far as end of window */ ++ n = (uInt)((q <= s->write ? s->write : s->end) - q); ++ if (n > z->avail_out) n = z->avail_out; ++ if (n && r == Z_BUF_ERROR) r = Z_OK; ++ ++ /* update counters */ ++ z->avail_out -= n; ++ z->total_out += n; ++ ++ /* update check information */ ++ if (s->checkfn != Z_NULL) ++ z->adler = s->check = (*s->checkfn)(s->check, q, n); ++ ++ /* copy as far as end of window */ ++ zmemcpy(p, q, n); ++ p += n; ++ q += n; ++ ++ /* see if more to copy at beginning of window */ ++ if (q == s->end) ++ { ++ /* wrap pointers */ ++ q = s->window; ++ if (s->write == s->end) ++ s->write = s->window; ++ ++ /* compute bytes to copy */ ++ n = (uInt)(s->write - q); ++ if (n > z->avail_out) n = z->avail_out; ++ if (n && r == Z_BUF_ERROR) r = Z_OK; ++ ++ /* update counters */ ++ z->avail_out -= n; ++ z->total_out += n; ++ ++ /* update check information */ ++ if (s->checkfn != Z_NULL) ++ z->adler = s->check = (*s->checkfn)(s->check, q, n); ++ ++ /* copy */ ++ zmemcpy(p, q, n); ++ p += n; ++ q += n; ++ } ++ ++ /* update pointers */ ++ z->next_out = p; ++ s->read = q; ++ ++ /* done */ ++ return r; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/infutil.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,98 @@ ++/* infutil.h -- types and macros common to blocks and codes ++ * Copyright (C) 1995-2002 Mark Adler ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* WARNING: this file should *not* be used by applications. It is ++ part of the implementation of the compression library and is ++ subject to change. Applications should only use zlib.h. ++ */ ++ ++#ifndef _INFUTIL_H ++#define _INFUTIL_H ++ ++typedef enum { ++ TYPE, /* get type bits (3, including end bit) */ ++ LENS, /* get lengths for stored */ ++ STORED, /* processing stored block */ ++ TABLE, /* get table lengths */ ++ BTREE, /* get bit lengths tree for a dynamic block */ ++ DTREE, /* get length, distance trees for a dynamic block */ ++ CODES, /* processing fixed or dynamic block */ ++ DRY, /* output remaining window bytes */ ++ DONE, /* finished last block, done */ ++ BAD} /* got a data error--stuck here */ ++inflate_block_mode; ++ ++/* inflate blocks semi-private state */ ++struct inflate_blocks_state { ++ ++ /* mode */ ++ inflate_block_mode mode; /* current inflate_block mode */ ++ ++ /* mode dependent information */ ++ union { ++ uInt left; /* if STORED, bytes left to copy */ ++ struct { ++ uInt table; /* table lengths (14 bits) */ ++ uInt index; /* index into blens (or border) */ ++ uIntf *blens; /* bit lengths of codes */ ++ uInt bb; /* bit length tree depth */ ++ inflate_huft *tb; /* bit length decoding tree */ ++ } trees; /* if DTREE, decoding info for trees */ ++ struct { ++ inflate_codes_statef ++ *codes; ++ } decode; /* if CODES, current state */ ++ } sub; /* submode */ ++ uInt last; /* true if this block is the last block */ ++ ++ /* mode independent information */ ++ uInt bitk; /* bits in bit buffer */ ++ uLong bitb; /* bit buffer */ ++ inflate_huft *hufts; /* single malloc for tree space */ ++ Bytef *window; /* sliding window */ ++ Bytef *end; /* one byte after sliding window */ ++ Bytef *read; /* window read pointer */ ++ Bytef *write; /* window write pointer */ ++ check_func checkfn; /* check function */ ++ uLong check; /* check on output */ ++ ++}; ++ ++ ++/* defines for inflate input/output */ ++/* update pointers and return */ ++#define UPDBITS {s->bitb=b;s->bitk=k;} ++#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} ++#define UPDOUT {s->write=q;} ++#define UPDATE {UPDBITS UPDIN UPDOUT} ++#define LEAVE {UPDATE return inflate_flush(s,z,r);} ++/* get bytes and bits */ ++#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} ++#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} ++#define NEXTBYTE (n--,*p++) ++#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}} ++#define DUMPBITS(j) {b>>=(j);k-=(j);} ++/* output bytes */ ++#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q) ++#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} ++#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} ++#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} ++#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} ++#define OUTBYTE(a) {*q++=(Byte)(a);m--;} ++/* load local pointers */ ++#define LOAD {LOADIN LOADOUT} ++ ++/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ ++extern uInt inflate_mask[17]; ++ ++/* copy as much as possible from the sliding window to the output area */ ++extern int inflate_flush OF(( ++ inflate_blocks_statef *, ++ z_streamp , ++ int)); ++ ++struct internal_state {int dummy;}; /* for buggy compilers */ ++ ++#endif /* _INFUTIL_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/match586.S Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,357 @@ ++/* match.s -- Pentium-optimized version of longest_match() ++ * Written for zlib 1.1.2 ++ * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com> ++ * ++ * This is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License. ++ */ ++ ++#ifndef NO_UNDERLINE ++#define match_init _ipcomp_match_init ++#define longest_match _ipcomp_longest_match ++#else ++#define match_init ipcomp_match_init ++#define longest_match ipcomp_longest_match ++#endif ++ ++#define MAX_MATCH (258) ++#define MIN_MATCH (3) ++#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) ++#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) ++ ++/* stack frame offsets */ ++ ++#define wmask 0 /* local copy of s->wmask */ ++#define window 4 /* local copy of s->window */ ++#define windowbestlen 8 /* s->window + bestlen */ ++#define chainlenscanend 12 /* high word: current chain len */ ++ /* low word: last bytes sought */ ++#define scanstart 16 /* first two bytes of string */ ++#define scanalign 20 /* dword-misalignment of string */ ++#define nicematch 24 /* a good enough match size */ ++#define bestlen 28 /* size of best match so far */ ++#define scan 32 /* ptr to string wanting match */ ++ ++#define LocalVarsSize (36) ++/* saved ebx 36 */ ++/* saved edi 40 */ ++/* saved esi 44 */ ++/* saved ebp 48 */ ++/* return address 52 */ ++#define deflatestate 56 /* the function arguments */ ++#define curmatch 60 ++ ++/* Offsets for fields in the deflate_state structure. These numbers ++ * are calculated from the definition of deflate_state, with the ++ * assumption that the compiler will dword-align the fields. (Thus, ++ * changing the definition of deflate_state could easily cause this ++ * program to crash horribly, without so much as a warning at ++ * compile time. Sigh.) ++ */ ++#define dsWSize 36 ++#define dsWMask 44 ++#define dsWindow 48 ++#define dsPrev 56 ++#define dsMatchLen 88 ++#define dsPrevMatch 92 ++#define dsStrStart 100 ++#define dsMatchStart 104 ++#define dsLookahead 108 ++#define dsPrevLen 112 ++#define dsMaxChainLen 116 ++#define dsGoodMatch 132 ++#define dsNiceMatch 136 ++ ++ ++.file "match.S" ++ ++.globl match_init, longest_match ++ ++.text ++ ++/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ ++ ++longest_match: ++ ++/* Save registers that the compiler may be using, and adjust %esp to */ ++/* make room for our stack frame. */ ++ ++ pushl %ebp ++ pushl %edi ++ pushl %esi ++ pushl %ebx ++ subl $LocalVarsSize, %esp ++ ++/* Retrieve the function arguments. %ecx will hold cur_match */ ++/* throughout the entire function. %edx will hold the pointer to the */ ++/* deflate_state structure during the function's setup (before */ ++/* entering the main loop). */ ++ ++ movl deflatestate(%esp), %edx ++ movl curmatch(%esp), %ecx ++ ++/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ ++ ++ movl dsNiceMatch(%edx), %eax ++ movl dsLookahead(%edx), %ebx ++ cmpl %eax, %ebx ++ jl LookaheadLess ++ movl %eax, %ebx ++LookaheadLess: movl %ebx, nicematch(%esp) ++ ++/* register Bytef *scan = s->window + s->strstart; */ ++ ++ movl dsWindow(%edx), %esi ++ movl %esi, window(%esp) ++ movl dsStrStart(%edx), %ebp ++ lea (%esi,%ebp), %edi ++ movl %edi, scan(%esp) ++ ++/* Determine how many bytes the scan ptr is off from being */ ++/* dword-aligned. */ ++ ++ movl %edi, %eax ++ negl %eax ++ andl $3, %eax ++ movl %eax, scanalign(%esp) ++ ++/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ ++/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ ++ ++ movl dsWSize(%edx), %eax ++ subl $MIN_LOOKAHEAD, %eax ++ subl %eax, %ebp ++ jg LimitPositive ++ xorl %ebp, %ebp ++LimitPositive: ++ ++/* unsigned chain_length = s->max_chain_length; */ ++/* if (s->prev_length >= s->good_match) { */ ++/* chain_length >>= 2; */ ++/* } */ ++ ++ movl dsPrevLen(%edx), %eax ++ movl dsGoodMatch(%edx), %ebx ++ cmpl %ebx, %eax ++ movl dsMaxChainLen(%edx), %ebx ++ jl LastMatchGood ++ shrl $2, %ebx ++LastMatchGood: ++ ++/* chainlen is decremented once beforehand so that the function can */ ++/* use the sign flag instead of the zero flag for the exit test. */ ++/* It is then shifted into the high word, to make room for the scanend */ ++/* scanend value, which it will always accompany. */ ++ ++ decl %ebx ++ shll $16, %ebx ++ ++/* int best_len = s->prev_length; */ ++ ++ movl dsPrevLen(%edx), %eax ++ movl %eax, bestlen(%esp) ++ ++/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ ++ ++ addl %eax, %esi ++ movl %esi, windowbestlen(%esp) ++ ++/* register ush scan_start = *(ushf*)scan; */ ++/* register ush scan_end = *(ushf*)(scan+best_len-1); */ ++ ++ movw (%edi), %bx ++ movw %bx, scanstart(%esp) ++ movw -1(%edi,%eax), %bx ++ movl %ebx, chainlenscanend(%esp) ++ ++/* Posf *prev = s->prev; */ ++/* uInt wmask = s->w_mask; */ ++ ++ movl dsPrev(%edx), %edi ++ movl dsWMask(%edx), %edx ++ mov %edx, wmask(%esp) ++ ++/* Jump into the main loop. */ ++ ++ jmp LoopEntry ++ ++.balign 16 ++ ++/* do { ++ * match = s->window + cur_match; ++ * if (*(ushf*)(match+best_len-1) != scan_end || ++ * *(ushf*)match != scan_start) continue; ++ * [...] ++ * } while ((cur_match = prev[cur_match & wmask]) > limit ++ * && --chain_length != 0); ++ * ++ * Here is the inner loop of the function. The function will spend the ++ * majority of its time in this loop, and majority of that time will ++ * be spent in the first ten instructions. ++ * ++ * Within this loop: ++ * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend) ++ * %ecx = curmatch ++ * %edx = curmatch & wmask ++ * %esi = windowbestlen - i.e., (window + bestlen) ++ * %edi = prev ++ * %ebp = limit ++ * ++ * Two optimization notes on the choice of instructions: ++ * ++ * The first instruction uses a 16-bit address, which costs an extra, ++ * unpairable cycle. This is cheaper than doing a 32-bit access and ++ * zeroing the high word, due to the 3-cycle misalignment penalty which ++ * would occur half the time. This also turns out to be cheaper than ++ * doing two separate 8-bit accesses, as the memory is so rarely in the ++ * L1 cache. ++ * ++ * The window buffer, however, apparently spends a lot of time in the ++ * cache, and so it is faster to retrieve the word at the end of the ++ * match string with two 8-bit loads. The instructions that test the ++ * word at the beginning of the match string, however, are executed ++ * much less frequently, and there it was cheaper to use 16-bit ++ * instructions, which avoided the necessity of saving off and ++ * subsequently reloading one of the other registers. ++ */ ++LookupLoop: ++ /* 1 U & V */ ++ movw (%edi,%edx,2), %cx /* 2 U pipe */ ++ movl wmask(%esp), %edx /* 2 V pipe */ ++ cmpl %ebp, %ecx /* 3 U pipe */ ++ jbe LeaveNow /* 3 V pipe */ ++ subl $0x00010000, %ebx /* 4 U pipe */ ++ js LeaveNow /* 4 V pipe */ ++LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */ ++ andl %ecx, %edx /* 5 V pipe */ ++ cmpb %bl, %al /* 6 U pipe */ ++ jnz LookupLoop /* 6 V pipe */ ++ movb (%esi,%ecx), %ah ++ cmpb %bh, %ah ++ jnz LookupLoop ++ movl window(%esp), %eax ++ movw (%eax,%ecx), %ax ++ cmpw scanstart(%esp), %ax ++ jnz LookupLoop ++ ++/* Store the current value of chainlen. */ ++ ++ movl %ebx, chainlenscanend(%esp) ++ ++/* Point %edi to the string under scrutiny, and %esi to the string we */ ++/* are hoping to match it up with. In actuality, %esi and %edi are */ ++/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ ++/* initialized to -(MAX_MATCH_8 - scanalign). */ ++ ++ movl window(%esp), %esi ++ movl scan(%esp), %edi ++ addl %ecx, %esi ++ movl scanalign(%esp), %eax ++ movl $(-MAX_MATCH_8), %edx ++ lea MAX_MATCH_8(%edi,%eax), %edi ++ lea MAX_MATCH_8(%esi,%eax), %esi ++ ++/* Test the strings for equality, 8 bytes at a time. At the end, ++ * adjust %edx so that it is offset to the exact byte that mismatched. ++ * ++ * We already know at this point that the first three bytes of the ++ * strings match each other, and they can be safely passed over before ++ * starting the compare loop. So what this code does is skip over 0-3 ++ * bytes, as much as necessary in order to dword-align the %edi ++ * pointer. (%esi will still be misaligned three times out of four.) ++ * ++ * It should be confessed that this loop usually does not represent ++ * much of the total running time. Replacing it with a more ++ * straightforward "rep cmpsb" would not drastically degrade ++ * performance. ++ */ ++LoopCmps: ++ movl (%esi,%edx), %eax ++ movl (%edi,%edx), %ebx ++ xorl %ebx, %eax ++ jnz LeaveLoopCmps ++ movl 4(%esi,%edx), %eax ++ movl 4(%edi,%edx), %ebx ++ xorl %ebx, %eax ++ jnz LeaveLoopCmps4 ++ addl $8, %edx ++ jnz LoopCmps ++ jmp LenMaximum ++LeaveLoopCmps4: addl $4, %edx ++LeaveLoopCmps: testl $0x0000FFFF, %eax ++ jnz LenLower ++ addl $2, %edx ++ shrl $16, %eax ++LenLower: subb $1, %al ++ adcl $0, %edx ++ ++/* Calculate the length of the match. If it is longer than MAX_MATCH, */ ++/* then automatically accept it as the best possible match and leave. */ ++ ++ lea (%edi,%edx), %eax ++ movl scan(%esp), %edi ++ subl %edi, %eax ++ cmpl $MAX_MATCH, %eax ++ jge LenMaximum ++ ++/* If the length of the match is not longer than the best match we */ ++/* have so far, then forget it and return to the lookup loop. */ ++ ++ movl deflatestate(%esp), %edx ++ movl bestlen(%esp), %ebx ++ cmpl %ebx, %eax ++ jg LongerMatch ++ movl chainlenscanend(%esp), %ebx ++ movl windowbestlen(%esp), %esi ++ movl dsPrev(%edx), %edi ++ movl wmask(%esp), %edx ++ andl %ecx, %edx ++ jmp LookupLoop ++ ++/* s->match_start = cur_match; */ ++/* best_len = len; */ ++/* if (len >= nice_match) break; */ ++/* scan_end = *(ushf*)(scan+best_len-1); */ ++ ++LongerMatch: movl nicematch(%esp), %ebx ++ movl %eax, bestlen(%esp) ++ movl %ecx, dsMatchStart(%edx) ++ cmpl %ebx, %eax ++ jge LeaveNow ++ movl window(%esp), %esi ++ addl %eax, %esi ++ movl %esi, windowbestlen(%esp) ++ movl chainlenscanend(%esp), %ebx ++ movw -1(%edi,%eax), %bx ++ movl dsPrev(%edx), %edi ++ movl %ebx, chainlenscanend(%esp) ++ movl wmask(%esp), %edx ++ andl %ecx, %edx ++ jmp LookupLoop ++ ++/* Accept the current string, with the maximum possible length. */ ++ ++LenMaximum: movl deflatestate(%esp), %edx ++ movl $MAX_MATCH, bestlen(%esp) ++ movl %ecx, dsMatchStart(%edx) ++ ++/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ ++/* return s->lookahead; */ ++ ++LeaveNow: ++ movl deflatestate(%esp), %edx ++ movl bestlen(%esp), %ebx ++ movl dsLookahead(%edx), %eax ++ cmpl %eax, %ebx ++ jg LookaheadRet ++ movl %ebx, %eax ++LookaheadRet: ++ ++/* Restore the stack and return from whence we came. */ ++ ++ addl $LocalVarsSize, %esp ++ popl %ebx ++ popl %esi ++ popl %edi ++ popl %ebp ++match_init: ret +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/match686.S Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,330 @@ ++/* match.s -- Pentium-Pro-optimized version of longest_match() ++ * Written for zlib 1.1.2 ++ * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com> ++ * ++ * This is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License. ++ */ ++ ++#ifndef NO_UNDERLINE ++#define match_init _ipcomp_match_init ++#define longest_match _ipcomp_longest_match ++#else ++#define match_init ipcomp_match_init ++#define longest_match ipcomp_longest_match ++#endif ++ ++#define MAX_MATCH (258) ++#define MIN_MATCH (3) ++#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) ++#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) ++ ++/* stack frame offsets */ ++ ++#define chainlenwmask 0 /* high word: current chain len */ ++ /* low word: s->wmask */ ++#define window 4 /* local copy of s->window */ ++#define windowbestlen 8 /* s->window + bestlen */ ++#define scanstart 16 /* first two bytes of string */ ++#define scanend 12 /* last two bytes of string */ ++#define scanalign 20 /* dword-misalignment of string */ ++#define nicematch 24 /* a good enough match size */ ++#define bestlen 28 /* size of best match so far */ ++#define scan 32 /* ptr to string wanting match */ ++ ++#define LocalVarsSize (36) ++/* saved ebx 36 */ ++/* saved edi 40 */ ++/* saved esi 44 */ ++/* saved ebp 48 */ ++/* return address 52 */ ++#define deflatestate 56 /* the function arguments */ ++#define curmatch 60 ++ ++/* Offsets for fields in the deflate_state structure. These numbers ++ * are calculated from the definition of deflate_state, with the ++ * assumption that the compiler will dword-align the fields. (Thus, ++ * changing the definition of deflate_state could easily cause this ++ * program to crash horribly, without so much as a warning at ++ * compile time. Sigh.) ++ */ ++#define dsWSize 36 ++#define dsWMask 44 ++#define dsWindow 48 ++#define dsPrev 56 ++#define dsMatchLen 88 ++#define dsPrevMatch 92 ++#define dsStrStart 100 ++#define dsMatchStart 104 ++#define dsLookahead 108 ++#define dsPrevLen 112 ++#define dsMaxChainLen 116 ++#define dsGoodMatch 132 ++#define dsNiceMatch 136 ++ ++ ++.file "match.S" ++ ++.globl match_init, longest_match ++ ++.text ++ ++/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ ++ ++longest_match: ++ ++/* Save registers that the compiler may be using, and adjust %esp to */ ++/* make room for our stack frame. */ ++ ++ pushl %ebp ++ pushl %edi ++ pushl %esi ++ pushl %ebx ++ subl $LocalVarsSize, %esp ++ ++/* Retrieve the function arguments. %ecx will hold cur_match */ ++/* throughout the entire function. %edx will hold the pointer to the */ ++/* deflate_state structure during the function's setup (before */ ++/* entering the main loop). */ ++ ++ movl deflatestate(%esp), %edx ++ movl curmatch(%esp), %ecx ++ ++/* uInt wmask = s->w_mask; */ ++/* unsigned chain_length = s->max_chain_length; */ ++/* if (s->prev_length >= s->good_match) { */ ++/* chain_length >>= 2; */ ++/* } */ ++ ++ movl dsPrevLen(%edx), %eax ++ movl dsGoodMatch(%edx), %ebx ++ cmpl %ebx, %eax ++ movl dsWMask(%edx), %eax ++ movl dsMaxChainLen(%edx), %ebx ++ jl LastMatchGood ++ shrl $2, %ebx ++LastMatchGood: ++ ++/* chainlen is decremented once beforehand so that the function can */ ++/* use the sign flag instead of the zero flag for the exit test. */ ++/* It is then shifted into the high word, to make room for the wmask */ ++/* value, which it will always accompany. */ ++ ++ decl %ebx ++ shll $16, %ebx ++ orl %eax, %ebx ++ movl %ebx, chainlenwmask(%esp) ++ ++/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ ++ ++ movl dsNiceMatch(%edx), %eax ++ movl dsLookahead(%edx), %ebx ++ cmpl %eax, %ebx ++ jl LookaheadLess ++ movl %eax, %ebx ++LookaheadLess: movl %ebx, nicematch(%esp) ++ ++/* register Bytef *scan = s->window + s->strstart; */ ++ ++ movl dsWindow(%edx), %esi ++ movl %esi, window(%esp) ++ movl dsStrStart(%edx), %ebp ++ lea (%esi,%ebp), %edi ++ movl %edi, scan(%esp) ++ ++/* Determine how many bytes the scan ptr is off from being */ ++/* dword-aligned. */ ++ ++ movl %edi, %eax ++ negl %eax ++ andl $3, %eax ++ movl %eax, scanalign(%esp) ++ ++/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ ++/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ ++ ++ movl dsWSize(%edx), %eax ++ subl $MIN_LOOKAHEAD, %eax ++ subl %eax, %ebp ++ jg LimitPositive ++ xorl %ebp, %ebp ++LimitPositive: ++ ++/* int best_len = s->prev_length; */ ++ ++ movl dsPrevLen(%edx), %eax ++ movl %eax, bestlen(%esp) ++ ++/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ ++ ++ addl %eax, %esi ++ movl %esi, windowbestlen(%esp) ++ ++/* register ush scan_start = *(ushf*)scan; */ ++/* register ush scan_end = *(ushf*)(scan+best_len-1); */ ++/* Posf *prev = s->prev; */ ++ ++ movzwl (%edi), %ebx ++ movl %ebx, scanstart(%esp) ++ movzwl -1(%edi,%eax), %ebx ++ movl %ebx, scanend(%esp) ++ movl dsPrev(%edx), %edi ++ ++/* Jump into the main loop. */ ++ ++ movl chainlenwmask(%esp), %edx ++ jmp LoopEntry ++ ++.balign 16 ++ ++/* do { ++ * match = s->window + cur_match; ++ * if (*(ushf*)(match+best_len-1) != scan_end || ++ * *(ushf*)match != scan_start) continue; ++ * [...] ++ * } while ((cur_match = prev[cur_match & wmask]) > limit ++ * && --chain_length != 0); ++ * ++ * Here is the inner loop of the function. The function will spend the ++ * majority of its time in this loop, and majority of that time will ++ * be spent in the first ten instructions. ++ * ++ * Within this loop: ++ * %ebx = scanend ++ * %ecx = curmatch ++ * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) ++ * %esi = windowbestlen - i.e., (window + bestlen) ++ * %edi = prev ++ * %ebp = limit ++ */ ++LookupLoop: ++ andl %edx, %ecx ++ movzwl (%edi,%ecx,2), %ecx ++ cmpl %ebp, %ecx ++ jbe LeaveNow ++ subl $0x00010000, %edx ++ js LeaveNow ++LoopEntry: movzwl -1(%esi,%ecx), %eax ++ cmpl %ebx, %eax ++ jnz LookupLoop ++ movl window(%esp), %eax ++ movzwl (%eax,%ecx), %eax ++ cmpl scanstart(%esp), %eax ++ jnz LookupLoop ++ ++/* Store the current value of chainlen. */ ++ ++ movl %edx, chainlenwmask(%esp) ++ ++/* Point %edi to the string under scrutiny, and %esi to the string we */ ++/* are hoping to match it up with. In actuality, %esi and %edi are */ ++/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ ++/* initialized to -(MAX_MATCH_8 - scanalign). */ ++ ++ movl window(%esp), %esi ++ movl scan(%esp), %edi ++ addl %ecx, %esi ++ movl scanalign(%esp), %eax ++ movl $(-MAX_MATCH_8), %edx ++ lea MAX_MATCH_8(%edi,%eax), %edi ++ lea MAX_MATCH_8(%esi,%eax), %esi ++ ++/* Test the strings for equality, 8 bytes at a time. At the end, ++ * adjust %edx so that it is offset to the exact byte that mismatched. ++ * ++ * We already know at this point that the first three bytes of the ++ * strings match each other, and they can be safely passed over before ++ * starting the compare loop. So what this code does is skip over 0-3 ++ * bytes, as much as necessary in order to dword-align the %edi ++ * pointer. (%esi will still be misaligned three times out of four.) ++ * ++ * It should be confessed that this loop usually does not represent ++ * much of the total running time. Replacing it with a more ++ * straightforward "rep cmpsb" would not drastically degrade ++ * performance. ++ */ ++LoopCmps: ++ movl (%esi,%edx), %eax ++ xorl (%edi,%edx), %eax ++ jnz LeaveLoopCmps ++ movl 4(%esi,%edx), %eax ++ xorl 4(%edi,%edx), %eax ++ jnz LeaveLoopCmps4 ++ addl $8, %edx ++ jnz LoopCmps ++ jmp LenMaximum ++LeaveLoopCmps4: addl $4, %edx ++LeaveLoopCmps: testl $0x0000FFFF, %eax ++ jnz LenLower ++ addl $2, %edx ++ shrl $16, %eax ++LenLower: subb $1, %al ++ adcl $0, %edx ++ ++/* Calculate the length of the match. If it is longer than MAX_MATCH, */ ++/* then automatically accept it as the best possible match and leave. */ ++ ++ lea (%edi,%edx), %eax ++ movl scan(%esp), %edi ++ subl %edi, %eax ++ cmpl $MAX_MATCH, %eax ++ jge LenMaximum ++ ++/* If the length of the match is not longer than the best match we */ ++/* have so far, then forget it and return to the lookup loop. */ ++ ++ movl deflatestate(%esp), %edx ++ movl bestlen(%esp), %ebx ++ cmpl %ebx, %eax ++ jg LongerMatch ++ movl windowbestlen(%esp), %esi ++ movl dsPrev(%edx), %edi ++ movl scanend(%esp), %ebx ++ movl chainlenwmask(%esp), %edx ++ jmp LookupLoop ++ ++/* s->match_start = cur_match; */ ++/* best_len = len; */ ++/* if (len >= nice_match) break; */ ++/* scan_end = *(ushf*)(scan+best_len-1); */ ++ ++LongerMatch: movl nicematch(%esp), %ebx ++ movl %eax, bestlen(%esp) ++ movl %ecx, dsMatchStart(%edx) ++ cmpl %ebx, %eax ++ jge LeaveNow ++ movl window(%esp), %esi ++ addl %eax, %esi ++ movl %esi, windowbestlen(%esp) ++ movzwl -1(%edi,%eax), %ebx ++ movl dsPrev(%edx), %edi ++ movl %ebx, scanend(%esp) ++ movl chainlenwmask(%esp), %edx ++ jmp LookupLoop ++ ++/* Accept the current string, with the maximum possible length. */ ++ ++LenMaximum: movl deflatestate(%esp), %edx ++ movl $MAX_MATCH, bestlen(%esp) ++ movl %ecx, dsMatchStart(%edx) ++ ++/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ ++/* return s->lookahead; */ ++ ++LeaveNow: ++ movl deflatestate(%esp), %edx ++ movl bestlen(%esp), %ebx ++ movl dsLookahead(%edx), %eax ++ cmpl %eax, %ebx ++ jg LookaheadRet ++ movl %ebx, %eax ++LookaheadRet: ++ ++/* Restore the stack and return from whence we came. */ ++ ++ addl $LocalVarsSize, %esp ++ popl %ebx ++ popl %esi ++ popl %edi ++ popl %ebp ++match_init: ret +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/trees.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1214 @@ ++/* trees.c -- output deflated data using Huffman coding ++ * Copyright (C) 1995-2002 Jean-loup Gailly ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* ++ * ALGORITHM ++ * ++ * The "deflation" process uses several Huffman trees. The more ++ * common source values are represented by shorter bit sequences. ++ * ++ * Each code tree is stored in a compressed form which is itself ++ * a Huffman encoding of the lengths of all the code strings (in ++ * ascending order by source values). The actual code strings are ++ * reconstructed from the lengths in the inflate process, as described ++ * in the deflate specification. ++ * ++ * REFERENCES ++ * ++ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". ++ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc ++ * ++ * Storer, James A. ++ * Data Compression: Methods and Theory, pp. 49-50. ++ * Computer Science Press, 1988. ISBN 0-7167-8156-5. ++ * ++ * Sedgewick, R. ++ * Algorithms, p290. ++ * Addison-Wesley, 1983. ISBN 0-201-06672-6. ++ */ ++ ++/* @(#) $Id: trees.c,v 1.3 2002/04/24 07:36:45 mcr Exp $ */ ++ ++/* #define GEN_TREES_H */ ++ ++#include "deflate.h" ++ ++#ifdef DEBUG ++# include <ctype.h> ++#endif ++ ++/* =========================================================================== ++ * Constants ++ */ ++ ++#define MAX_BL_BITS 7 ++/* Bit length codes must not exceed MAX_BL_BITS bits */ ++ ++#define END_BLOCK 256 ++/* end of block literal code */ ++ ++#define REP_3_6 16 ++/* repeat previous bit length 3-6 times (2 bits of repeat count) */ ++ ++#define REPZ_3_10 17 ++/* repeat a zero length 3-10 times (3 bits of repeat count) */ ++ ++#define REPZ_11_138 18 ++/* repeat a zero length 11-138 times (7 bits of repeat count) */ ++ ++local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ ++ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; ++ ++local const int extra_dbits[D_CODES] /* extra bits for each distance code */ ++ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; ++ ++local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ ++ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; ++ ++local const uch bl_order[BL_CODES] ++ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; ++/* The lengths of the bit length codes are sent in order of decreasing ++ * probability, to avoid transmitting the lengths for unused bit length codes. ++ */ ++ ++#define Buf_size (8 * 2*sizeof(char)) ++/* Number of bits used within bi_buf. (bi_buf might be implemented on ++ * more than 16 bits on some systems.) ++ */ ++ ++/* =========================================================================== ++ * Local data. These are initialized only once. ++ */ ++ ++#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ ++ ++#if defined(GEN_TREES_H) || !defined(STDC) ++/* non ANSI compilers may not accept trees.h */ ++ ++local ct_data static_ltree[L_CODES+2]; ++/* The static literal tree. Since the bit lengths are imposed, there is no ++ * need for the L_CODES extra codes used during heap construction. However ++ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init ++ * below). ++ */ ++ ++local ct_data static_dtree[D_CODES]; ++/* The static distance tree. (Actually a trivial tree since all codes use ++ * 5 bits.) ++ */ ++ ++uch _dist_code[DIST_CODE_LEN]; ++/* Distance codes. The first 256 values correspond to the distances ++ * 3 .. 258, the last 256 values correspond to the top 8 bits of ++ * the 15 bit distances. ++ */ ++ ++uch _length_code[MAX_MATCH-MIN_MATCH+1]; ++/* length code for each normalized match length (0 == MIN_MATCH) */ ++ ++local int base_length[LENGTH_CODES]; ++/* First normalized length for each code (0 = MIN_MATCH) */ ++ ++local int base_dist[D_CODES]; ++/* First normalized distance for each code (0 = distance of 1) */ ++ ++#else ++# include "trees.h" ++#endif /* GEN_TREES_H */ ++ ++struct static_tree_desc_s { ++ const ct_data *static_tree; /* static tree or NULL */ ++ const intf *extra_bits; /* extra bits for each code or NULL */ ++ int extra_base; /* base index for extra_bits */ ++ int elems; /* max number of elements in the tree */ ++ int max_length; /* max bit length for the codes */ ++}; ++ ++local static_tree_desc static_l_desc = ++{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; ++ ++local static_tree_desc static_d_desc = ++{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; ++ ++local static_tree_desc static_bl_desc = ++{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; ++ ++/* =========================================================================== ++ * Local (static) routines in this file. ++ */ ++ ++local void tr_static_init OF((void)); ++local void init_block OF((deflate_state *s)); ++local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); ++local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); ++local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); ++local void build_tree OF((deflate_state *s, tree_desc *desc)); ++local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); ++local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); ++local int build_bl_tree OF((deflate_state *s)); ++local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, ++ int blcodes)); ++local void compress_block OF((deflate_state *s, const ct_data *ltree, ++ const ct_data *dtree)); ++local void set_data_type OF((deflate_state *s)); ++local unsigned bi_reverse OF((unsigned value, int length)); ++local void bi_windup OF((deflate_state *s)); ++local void bi_flush OF((deflate_state *s)); ++local void copy_block OF((deflate_state *s, charf *buf, unsigned len, ++ int header)); ++ ++#ifdef GEN_TREES_H ++local void gen_trees_header OF((void)); ++#endif ++ ++#ifndef DEBUG ++# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) ++ /* Send a code of the given tree. c and tree must not have side effects */ ++ ++#else /* DEBUG */ ++# define send_code(s, c, tree) \ ++ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ ++ send_bits(s, tree[c].Code, tree[c].Len); } ++#endif ++ ++/* =========================================================================== ++ * Output a short LSB first on the stream. ++ * IN assertion: there is enough room in pendingBuf. ++ */ ++#define put_short(s, w) { \ ++ put_byte(s, (uch)((w) & 0xff)); \ ++ put_byte(s, (uch)((ush)(w) >> 8)); \ ++} ++ ++/* =========================================================================== ++ * Send a value on a given number of bits. ++ * IN assertion: length <= 16 and value fits in length bits. ++ */ ++#ifdef DEBUG ++local void send_bits OF((deflate_state *s, int value, int length)); ++ ++local void send_bits(s, value, length) ++ deflate_state *s; ++ int value; /* value to send */ ++ int length; /* number of bits */ ++{ ++ Tracevv((stderr," l %2d v %4x ", length, value)); ++ Assert(length > 0 && length <= 15, "invalid length"); ++ s->bits_sent += (ulg)length; ++ ++ /* If not enough room in bi_buf, use (valid) bits from bi_buf and ++ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) ++ * unused bits in value. ++ */ ++ if (s->bi_valid > (int)Buf_size - length) { ++ s->bi_buf |= (value << s->bi_valid); ++ put_short(s, s->bi_buf); ++ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); ++ s->bi_valid += length - Buf_size; ++ } else { ++ s->bi_buf |= value << s->bi_valid; ++ s->bi_valid += length; ++ } ++} ++#else /* !DEBUG */ ++ ++#define send_bits(s, value, length) \ ++{ int len = length;\ ++ if (s->bi_valid > (int)Buf_size - len) {\ ++ int val = value;\ ++ s->bi_buf |= (val << s->bi_valid);\ ++ put_short(s, s->bi_buf);\ ++ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ ++ s->bi_valid += len - Buf_size;\ ++ } else {\ ++ s->bi_buf |= (value) << s->bi_valid;\ ++ s->bi_valid += len;\ ++ }\ ++} ++#endif /* DEBUG */ ++ ++ ++#define MAX(a,b) (a >= b ? a : b) ++/* the arguments must not have side effects */ ++ ++/* =========================================================================== ++ * Initialize the various 'constant' tables. ++ */ ++local void tr_static_init() ++{ ++#if defined(GEN_TREES_H) || !defined(STDC) ++ static int static_init_done = 0; ++ int n; /* iterates over tree elements */ ++ int bits; /* bit counter */ ++ int length; /* length value */ ++ int code; /* code value */ ++ int dist; /* distance index */ ++ ush bl_count[MAX_BITS+1]; ++ /* number of codes at each bit length for an optimal tree */ ++ ++ if (static_init_done) return; ++ ++ /* For some embedded targets, global variables are not initialized: */ ++ static_l_desc.static_tree = static_ltree; ++ static_l_desc.extra_bits = extra_lbits; ++ static_d_desc.static_tree = static_dtree; ++ static_d_desc.extra_bits = extra_dbits; ++ static_bl_desc.extra_bits = extra_blbits; ++ ++ /* Initialize the mapping length (0..255) -> length code (0..28) */ ++ length = 0; ++ for (code = 0; code < LENGTH_CODES-1; code++) { ++ base_length[code] = length; ++ for (n = 0; n < (1<<extra_lbits[code]); n++) { ++ _length_code[length++] = (uch)code; ++ } ++ } ++ Assert (length == 256, "tr_static_init: length != 256"); ++ /* Note that the length 255 (match length 258) can be represented ++ * in two different ways: code 284 + 5 bits or code 285, so we ++ * overwrite length_code[255] to use the best encoding: ++ */ ++ _length_code[length-1] = (uch)code; ++ ++ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ ++ dist = 0; ++ for (code = 0 ; code < 16; code++) { ++ base_dist[code] = dist; ++ for (n = 0; n < (1<<extra_dbits[code]); n++) { ++ _dist_code[dist++] = (uch)code; ++ } ++ } ++ Assert (dist == 256, "tr_static_init: dist != 256"); ++ dist >>= 7; /* from now on, all distances are divided by 128 */ ++ for ( ; code < D_CODES; code++) { ++ base_dist[code] = dist << 7; ++ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { ++ _dist_code[256 + dist++] = (uch)code; ++ } ++ } ++ Assert (dist == 256, "tr_static_init: 256+dist != 512"); ++ ++ /* Construct the codes of the static literal tree */ ++ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; ++ n = 0; ++ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; ++ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; ++ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; ++ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; ++ /* Codes 286 and 287 do not exist, but we must include them in the ++ * tree construction to get a canonical Huffman tree (longest code ++ * all ones) ++ */ ++ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); ++ ++ /* The static distance tree is trivial: */ ++ for (n = 0; n < D_CODES; n++) { ++ static_dtree[n].Len = 5; ++ static_dtree[n].Code = bi_reverse((unsigned)n, 5); ++ } ++ static_init_done = 1; ++ ++# ifdef GEN_TREES_H ++ gen_trees_header(); ++# endif ++#endif /* defined(GEN_TREES_H) || !defined(STDC) */ ++} ++ ++/* =========================================================================== ++ * Genererate the file trees.h describing the static trees. ++ */ ++#ifdef GEN_TREES_H ++# ifndef DEBUG ++# include <stdio.h> ++# endif ++ ++# define SEPARATOR(i, last, width) \ ++ ((i) == (last)? "\n};\n\n" : \ ++ ((i) % (width) == (width)-1 ? ",\n" : ", ")) ++ ++void gen_trees_header() ++{ ++ FILE *header = fopen("trees.h", "w"); ++ int i; ++ ++ Assert (header != NULL, "Can't open trees.h"); ++ fprintf(header, ++ "/* header created automatically with -DGEN_TREES_H */\n\n"); ++ ++ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); ++ for (i = 0; i < L_CODES+2; i++) { ++ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, ++ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); ++ } ++ ++ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); ++ for (i = 0; i < D_CODES; i++) { ++ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, ++ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); ++ } ++ ++ fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); ++ for (i = 0; i < DIST_CODE_LEN; i++) { ++ fprintf(header, "%2u%s", _dist_code[i], ++ SEPARATOR(i, DIST_CODE_LEN-1, 20)); ++ } ++ ++ fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); ++ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { ++ fprintf(header, "%2u%s", _length_code[i], ++ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); ++ } ++ ++ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); ++ for (i = 0; i < LENGTH_CODES; i++) { ++ fprintf(header, "%1u%s", base_length[i], ++ SEPARATOR(i, LENGTH_CODES-1, 20)); ++ } ++ ++ fprintf(header, "local const int base_dist[D_CODES] = {\n"); ++ for (i = 0; i < D_CODES; i++) { ++ fprintf(header, "%5u%s", base_dist[i], ++ SEPARATOR(i, D_CODES-1, 10)); ++ } ++ ++ fclose(header); ++} ++#endif /* GEN_TREES_H */ ++ ++/* =========================================================================== ++ * Initialize the tree data structures for a new zlib stream. ++ */ ++void _tr_init(s) ++ deflate_state *s; ++{ ++ tr_static_init(); ++ ++ s->l_desc.dyn_tree = s->dyn_ltree; ++ s->l_desc.stat_desc = &static_l_desc; ++ ++ s->d_desc.dyn_tree = s->dyn_dtree; ++ s->d_desc.stat_desc = &static_d_desc; ++ ++ s->bl_desc.dyn_tree = s->bl_tree; ++ s->bl_desc.stat_desc = &static_bl_desc; ++ ++ s->bi_buf = 0; ++ s->bi_valid = 0; ++ s->last_eob_len = 8; /* enough lookahead for inflate */ ++#ifdef DEBUG ++ s->compressed_len = 0L; ++ s->bits_sent = 0L; ++#endif ++ ++ /* Initialize the first block of the first file: */ ++ init_block(s); ++} ++ ++/* =========================================================================== ++ * Initialize a new block. ++ */ ++local void init_block(s) ++ deflate_state *s; ++{ ++ int n; /* iterates over tree elements */ ++ ++ /* Initialize the trees. */ ++ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; ++ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; ++ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; ++ ++ s->dyn_ltree[END_BLOCK].Freq = 1; ++ s->opt_len = s->static_len = 0L; ++ s->last_lit = s->matches = 0; ++} ++ ++#define SMALLEST 1 ++/* Index within the heap array of least frequent node in the Huffman tree */ ++ ++ ++/* =========================================================================== ++ * Remove the smallest element from the heap and recreate the heap with ++ * one less element. Updates heap and heap_len. ++ */ ++#define pqremove(s, tree, top) \ ++{\ ++ top = s->heap[SMALLEST]; \ ++ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ ++ pqdownheap(s, tree, SMALLEST); \ ++} ++ ++/* =========================================================================== ++ * Compares to subtrees, using the tree depth as tie breaker when ++ * the subtrees have equal frequency. This minimizes the worst case length. ++ */ ++#define smaller(tree, n, m, depth) \ ++ (tree[n].Freq < tree[m].Freq || \ ++ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) ++ ++/* =========================================================================== ++ * Restore the heap property by moving down the tree starting at node k, ++ * exchanging a node with the smallest of its two sons if necessary, stopping ++ * when the heap property is re-established (each father smaller than its ++ * two sons). ++ */ ++local void pqdownheap(s, tree, k) ++ deflate_state *s; ++ ct_data *tree; /* the tree to restore */ ++ int k; /* node to move down */ ++{ ++ int v = s->heap[k]; ++ int j = k << 1; /* left son of k */ ++ while (j <= s->heap_len) { ++ /* Set j to the smallest of the two sons: */ ++ if (j < s->heap_len && ++ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { ++ j++; ++ } ++ /* Exit if v is smaller than both sons */ ++ if (smaller(tree, v, s->heap[j], s->depth)) break; ++ ++ /* Exchange v with the smallest son */ ++ s->heap[k] = s->heap[j]; k = j; ++ ++ /* And continue down the tree, setting j to the left son of k */ ++ j <<= 1; ++ } ++ s->heap[k] = v; ++} ++ ++/* =========================================================================== ++ * Compute the optimal bit lengths for a tree and update the total bit length ++ * for the current block. ++ * IN assertion: the fields freq and dad are set, heap[heap_max] and ++ * above are the tree nodes sorted by increasing frequency. ++ * OUT assertions: the field len is set to the optimal bit length, the ++ * array bl_count contains the frequencies for each bit length. ++ * The length opt_len is updated; static_len is also updated if stree is ++ * not null. ++ */ ++local void gen_bitlen(s, desc) ++ deflate_state *s; ++ tree_desc *desc; /* the tree descriptor */ ++{ ++ ct_data *tree = desc->dyn_tree; ++ int max_code = desc->max_code; ++ const ct_data *stree = desc->stat_desc->static_tree; ++ const intf *extra = desc->stat_desc->extra_bits; ++ int base = desc->stat_desc->extra_base; ++ int max_length = desc->stat_desc->max_length; ++ int h; /* heap index */ ++ int n, m; /* iterate over the tree elements */ ++ int bits; /* bit length */ ++ int xbits; /* extra bits */ ++ ush f; /* frequency */ ++ int overflow = 0; /* number of elements with bit length too large */ ++ ++ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; ++ ++ /* In a first pass, compute the optimal bit lengths (which may ++ * overflow in the case of the bit length tree). ++ */ ++ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ ++ ++ for (h = s->heap_max+1; h < HEAP_SIZE; h++) { ++ n = s->heap[h]; ++ bits = tree[tree[n].Dad].Len + 1; ++ if (bits > max_length) bits = max_length, overflow++; ++ tree[n].Len = (ush)bits; ++ /* We overwrite tree[n].Dad which is no longer needed */ ++ ++ if (n > max_code) continue; /* not a leaf node */ ++ ++ s->bl_count[bits]++; ++ xbits = 0; ++ if (n >= base) xbits = extra[n-base]; ++ f = tree[n].Freq; ++ s->opt_len += (ulg)f * (bits + xbits); ++ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); ++ } ++ if (overflow == 0) return; ++ ++ Trace((stderr,"\nbit length overflow\n")); ++ /* This happens for example on obj2 and pic of the Calgary corpus */ ++ ++ /* Find the first bit length which could increase: */ ++ do { ++ bits = max_length-1; ++ while (s->bl_count[bits] == 0) bits--; ++ s->bl_count[bits]--; /* move one leaf down the tree */ ++ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ ++ s->bl_count[max_length]--; ++ /* The brother of the overflow item also moves one step up, ++ * but this does not affect bl_count[max_length] ++ */ ++ overflow -= 2; ++ } while (overflow > 0); ++ ++ /* Now recompute all bit lengths, scanning in increasing frequency. ++ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all ++ * lengths instead of fixing only the wrong ones. This idea is taken ++ * from 'ar' written by Haruhiko Okumura.) ++ */ ++ for (bits = max_length; bits != 0; bits--) { ++ n = s->bl_count[bits]; ++ while (n != 0) { ++ m = s->heap[--h]; ++ if (m > max_code) continue; ++ if (tree[m].Len != (unsigned) bits) { ++ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); ++ s->opt_len += ((long)bits - (long)tree[m].Len) ++ *(long)tree[m].Freq; ++ tree[m].Len = (ush)bits; ++ } ++ n--; ++ } ++ } ++} ++ ++/* =========================================================================== ++ * Generate the codes for a given tree and bit counts (which need not be ++ * optimal). ++ * IN assertion: the array bl_count contains the bit length statistics for ++ * the given tree and the field len is set for all tree elements. ++ * OUT assertion: the field code is set for all tree elements of non ++ * zero code length. ++ */ ++local void gen_codes (tree, max_code, bl_count) ++ ct_data *tree; /* the tree to decorate */ ++ int max_code; /* largest code with non zero frequency */ ++ ushf *bl_count; /* number of codes at each bit length */ ++{ ++ ush next_code[MAX_BITS+1]; /* next code value for each bit length */ ++ ush code = 0; /* running code value */ ++ int bits; /* bit index */ ++ int n; /* code index */ ++ ++ /* The distribution counts are first used to generate the code values ++ * without bit reversal. ++ */ ++ for (bits = 1; bits <= MAX_BITS; bits++) { ++ next_code[bits] = code = (code + bl_count[bits-1]) << 1; ++ } ++ /* Check that the bit counts in bl_count are consistent. The last code ++ * must be all ones. ++ */ ++ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, ++ "inconsistent bit counts"); ++ Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); ++ ++ for (n = 0; n <= max_code; n++) { ++ int len = tree[n].Len; ++ if (len == 0) continue; ++ /* Now reverse the bits */ ++ tree[n].Code = bi_reverse(next_code[len]++, len); ++ ++ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", ++ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); ++ } ++} ++ ++/* =========================================================================== ++ * Construct one Huffman tree and assigns the code bit strings and lengths. ++ * Update the total bit length for the current block. ++ * IN assertion: the field freq is set for all tree elements. ++ * OUT assertions: the fields len and code are set to the optimal bit length ++ * and corresponding code. The length opt_len is updated; static_len is ++ * also updated if stree is not null. The field max_code is set. ++ */ ++local void build_tree(s, desc) ++ deflate_state *s; ++ tree_desc *desc; /* the tree descriptor */ ++{ ++ ct_data *tree = desc->dyn_tree; ++ const ct_data *stree = desc->stat_desc->static_tree; ++ int elems = desc->stat_desc->elems; ++ int n, m; /* iterate over heap elements */ ++ int max_code = -1; /* largest code with non zero frequency */ ++ int node; /* new node being created */ ++ ++ /* Construct the initial heap, with least frequent element in ++ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. ++ * heap[0] is not used. ++ */ ++ s->heap_len = 0, s->heap_max = HEAP_SIZE; ++ ++ for (n = 0; n < elems; n++) { ++ if (tree[n].Freq != 0) { ++ s->heap[++(s->heap_len)] = max_code = n; ++ s->depth[n] = 0; ++ } else { ++ tree[n].Len = 0; ++ } ++ } ++ ++ /* The pkzip format requires that at least one distance code exists, ++ * and that at least one bit should be sent even if there is only one ++ * possible code. So to avoid special checks later on we force at least ++ * two codes of non zero frequency. ++ */ ++ while (s->heap_len < 2) { ++ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); ++ tree[node].Freq = 1; ++ s->depth[node] = 0; ++ s->opt_len--; if (stree) s->static_len -= stree[node].Len; ++ /* node is 0 or 1 so it does not have extra bits */ ++ } ++ desc->max_code = max_code; ++ ++ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, ++ * establish sub-heaps of increasing lengths: ++ */ ++ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); ++ ++ /* Construct the Huffman tree by repeatedly combining the least two ++ * frequent nodes. ++ */ ++ node = elems; /* next internal node of the tree */ ++ do { ++ pqremove(s, tree, n); /* n = node of least frequency */ ++ m = s->heap[SMALLEST]; /* m = node of next least frequency */ ++ ++ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ ++ s->heap[--(s->heap_max)] = m; ++ ++ /* Create a new node father of n and m */ ++ tree[node].Freq = tree[n].Freq + tree[m].Freq; ++ s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); ++ tree[n].Dad = tree[m].Dad = (ush)node; ++#ifdef DUMP_BL_TREE ++ if (tree == s->bl_tree) { ++ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", ++ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); ++ } ++#endif ++ /* and insert the new node in the heap */ ++ s->heap[SMALLEST] = node++; ++ pqdownheap(s, tree, SMALLEST); ++ ++ } while (s->heap_len >= 2); ++ ++ s->heap[--(s->heap_max)] = s->heap[SMALLEST]; ++ ++ /* At this point, the fields freq and dad are set. We can now ++ * generate the bit lengths. ++ */ ++ gen_bitlen(s, (tree_desc *)desc); ++ ++ /* The field len is now set, we can generate the bit codes */ ++ gen_codes ((ct_data *)tree, max_code, s->bl_count); ++} ++ ++/* =========================================================================== ++ * Scan a literal or distance tree to determine the frequencies of the codes ++ * in the bit length tree. ++ */ ++local void scan_tree (s, tree, max_code) ++ deflate_state *s; ++ ct_data *tree; /* the tree to be scanned */ ++ int max_code; /* and its largest code of non zero frequency */ ++{ ++ int n; /* iterates over all tree elements */ ++ int prevlen = -1; /* last emitted length */ ++ int curlen; /* length of current code */ ++ int nextlen = tree[0].Len; /* length of next code */ ++ int count = 0; /* repeat count of the current code */ ++ int max_count = 7; /* max repeat count */ ++ int min_count = 4; /* min repeat count */ ++ ++ if (nextlen == 0) max_count = 138, min_count = 3; ++ tree[max_code+1].Len = (ush)0xffff; /* guard */ ++ ++ for (n = 0; n <= max_code; n++) { ++ curlen = nextlen; nextlen = tree[n+1].Len; ++ if (++count < max_count && curlen == nextlen) { ++ continue; ++ } else if (count < min_count) { ++ s->bl_tree[curlen].Freq += count; ++ } else if (curlen != 0) { ++ if (curlen != prevlen) s->bl_tree[curlen].Freq++; ++ s->bl_tree[REP_3_6].Freq++; ++ } else if (count <= 10) { ++ s->bl_tree[REPZ_3_10].Freq++; ++ } else { ++ s->bl_tree[REPZ_11_138].Freq++; ++ } ++ count = 0; prevlen = curlen; ++ if (nextlen == 0) { ++ max_count = 138, min_count = 3; ++ } else if (curlen == nextlen) { ++ max_count = 6, min_count = 3; ++ } else { ++ max_count = 7, min_count = 4; ++ } ++ } ++} ++ ++/* =========================================================================== ++ * Send a literal or distance tree in compressed form, using the codes in ++ * bl_tree. ++ */ ++local void send_tree (s, tree, max_code) ++ deflate_state *s; ++ ct_data *tree; /* the tree to be scanned */ ++ int max_code; /* and its largest code of non zero frequency */ ++{ ++ int n; /* iterates over all tree elements */ ++ int prevlen = -1; /* last emitted length */ ++ int curlen; /* length of current code */ ++ int nextlen = tree[0].Len; /* length of next code */ ++ int count = 0; /* repeat count of the current code */ ++ int max_count = 7; /* max repeat count */ ++ int min_count = 4; /* min repeat count */ ++ ++ /* tree[max_code+1].Len = -1; */ /* guard already set */ ++ if (nextlen == 0) max_count = 138, min_count = 3; ++ ++ for (n = 0; n <= max_code; n++) { ++ curlen = nextlen; nextlen = tree[n+1].Len; ++ if (++count < max_count && curlen == nextlen) { ++ continue; ++ } else if (count < min_count) { ++ do { send_code(s, curlen, s->bl_tree); } while (--count != 0); ++ ++ } else if (curlen != 0) { ++ if (curlen != prevlen) { ++ send_code(s, curlen, s->bl_tree); count--; ++ } ++ Assert(count >= 3 && count <= 6, " 3_6?"); ++ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); ++ ++ } else if (count <= 10) { ++ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); ++ ++ } else { ++ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); ++ } ++ count = 0; prevlen = curlen; ++ if (nextlen == 0) { ++ max_count = 138, min_count = 3; ++ } else if (curlen == nextlen) { ++ max_count = 6, min_count = 3; ++ } else { ++ max_count = 7, min_count = 4; ++ } ++ } ++} ++ ++/* =========================================================================== ++ * Construct the Huffman tree for the bit lengths and return the index in ++ * bl_order of the last bit length code to send. ++ */ ++local int build_bl_tree(s) ++ deflate_state *s; ++{ ++ int max_blindex; /* index of last bit length code of non zero freq */ ++ ++ /* Determine the bit length frequencies for literal and distance trees */ ++ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); ++ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); ++ ++ /* Build the bit length tree: */ ++ build_tree(s, (tree_desc *)(&(s->bl_desc))); ++ /* opt_len now includes the length of the tree representations, except ++ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. ++ */ ++ ++ /* Determine the number of bit length codes to send. The pkzip format ++ * requires that at least 4 bit length codes be sent. (appnote.txt says ++ * 3 but the actual value used is 4.) ++ */ ++ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { ++ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; ++ } ++ /* Update opt_len to include the bit length tree and counts */ ++ s->opt_len += 3*(max_blindex+1) + 5+5+4; ++ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", ++ s->opt_len, s->static_len)); ++ ++ return max_blindex; ++} ++ ++/* =========================================================================== ++ * Send the header for a block using dynamic Huffman trees: the counts, the ++ * lengths of the bit length codes, the literal tree and the distance tree. ++ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. ++ */ ++local void send_all_trees(s, lcodes, dcodes, blcodes) ++ deflate_state *s; ++ int lcodes, dcodes, blcodes; /* number of codes for each tree */ ++{ ++ int rank; /* index in bl_order */ ++ ++ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); ++ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, ++ "too many codes"); ++ Tracev((stderr, "\nbl counts: ")); ++ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ ++ send_bits(s, dcodes-1, 5); ++ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ ++ for (rank = 0; rank < blcodes; rank++) { ++ Tracev((stderr, "\nbl code %2d ", bl_order[rank])); ++ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); ++ } ++ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); ++ ++ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ ++ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); ++ ++ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ ++ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); ++} ++ ++/* =========================================================================== ++ * Send a stored block ++ */ ++void _tr_stored_block(s, buf, stored_len, eof) ++ deflate_state *s; ++ charf *buf; /* input block */ ++ ulg stored_len; /* length of input block */ ++ int eof; /* true if this is the last block for a file */ ++{ ++ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ ++#ifdef DEBUG ++ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; ++ s->compressed_len += (stored_len + 4) << 3; ++#endif ++ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ ++} ++ ++/* =========================================================================== ++ * Send one empty static block to give enough lookahead for inflate. ++ * This takes 10 bits, of which 7 may remain in the bit buffer. ++ * The current inflate code requires 9 bits of lookahead. If the ++ * last two codes for the previous block (real code plus EOB) were coded ++ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode ++ * the last real code. In this case we send two empty static blocks instead ++ * of one. (There are no problems if the previous block is stored or fixed.) ++ * To simplify the code, we assume the worst case of last real code encoded ++ * on one bit only. ++ */ ++void _tr_align(s) ++ deflate_state *s; ++{ ++ send_bits(s, STATIC_TREES<<1, 3); ++ send_code(s, END_BLOCK, static_ltree); ++#ifdef DEBUG ++ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ ++#endif ++ bi_flush(s); ++ /* Of the 10 bits for the empty block, we have already sent ++ * (10 - bi_valid) bits. The lookahead for the last real code (before ++ * the EOB of the previous block) was thus at least one plus the length ++ * of the EOB plus what we have just sent of the empty static block. ++ */ ++ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { ++ send_bits(s, STATIC_TREES<<1, 3); ++ send_code(s, END_BLOCK, static_ltree); ++#ifdef DEBUG ++ s->compressed_len += 10L; ++#endif ++ bi_flush(s); ++ } ++ s->last_eob_len = 7; ++} ++ ++/* =========================================================================== ++ * Determine the best encoding for the current block: dynamic trees, static ++ * trees or store, and output the encoded block to the zip file. ++ */ ++void _tr_flush_block(s, buf, stored_len, eof) ++ deflate_state *s; ++ charf *buf; /* input block, or NULL if too old */ ++ ulg stored_len; /* length of input block */ ++ int eof; /* true if this is the last block for a file */ ++{ ++ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ ++ int max_blindex = 0; /* index of last bit length code of non zero freq */ ++ ++ /* Build the Huffman trees unless a stored block is forced */ ++ if (s->level > 0) { ++ ++ /* Check if the file is ascii or binary */ ++ if (s->data_type == Z_UNKNOWN) set_data_type(s); ++ ++ /* Construct the literal and distance trees */ ++ build_tree(s, (tree_desc *)(&(s->l_desc))); ++ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, ++ s->static_len)); ++ ++ build_tree(s, (tree_desc *)(&(s->d_desc))); ++ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, ++ s->static_len)); ++ /* At this point, opt_len and static_len are the total bit lengths of ++ * the compressed block data, excluding the tree representations. ++ */ ++ ++ /* Build the bit length tree for the above two trees, and get the index ++ * in bl_order of the last bit length code to send. ++ */ ++ max_blindex = build_bl_tree(s); ++ ++ /* Determine the best encoding. Compute first the block length in bytes*/ ++ opt_lenb = (s->opt_len+3+7)>>3; ++ static_lenb = (s->static_len+3+7)>>3; ++ ++ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", ++ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, ++ s->last_lit)); ++ ++ if (static_lenb <= opt_lenb) opt_lenb = static_lenb; ++ ++ } else { ++ Assert(buf != (char*)0, "lost buf"); ++ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ ++ } ++ ++#ifdef FORCE_STORED ++ if (buf != (char*)0) { /* force stored block */ ++#else ++ if (stored_len+4 <= opt_lenb && buf != (char*)0) { ++ /* 4: two words for the lengths */ ++#endif ++ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. ++ * Otherwise we can't have processed more than WSIZE input bytes since ++ * the last block flush, because compression would have been ++ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to ++ * transform a block into a stored block. ++ */ ++ _tr_stored_block(s, buf, stored_len, eof); ++ ++#ifdef FORCE_STATIC ++ } else if (static_lenb >= 0) { /* force static trees */ ++#else ++ } else if (static_lenb == opt_lenb) { ++#endif ++ send_bits(s, (STATIC_TREES<<1)+eof, 3); ++ compress_block(s, static_ltree, static_dtree); ++#ifdef DEBUG ++ s->compressed_len += 3 + s->static_len; ++#endif ++ } else { ++ send_bits(s, (DYN_TREES<<1)+eof, 3); ++ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, ++ max_blindex+1); ++ compress_block(s, s->dyn_ltree, s->dyn_dtree); ++#ifdef DEBUG ++ s->compressed_len += 3 + s->opt_len; ++#endif ++ } ++ Assert (s->compressed_len == s->bits_sent, "bad compressed size"); ++ /* The above check is made mod 2^32, for files larger than 512 MB ++ * and uLong implemented on 32 bits. ++ */ ++ init_block(s); ++ ++ if (eof) { ++ bi_windup(s); ++#ifdef DEBUG ++ s->compressed_len += 7; /* align on byte boundary */ ++#endif ++ } ++ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, ++ s->compressed_len-7*eof)); ++} ++ ++/* =========================================================================== ++ * Save the match info and tally the frequency counts. Return true if ++ * the current block must be flushed. ++ */ ++int _tr_tally (s, dist, lc) ++ deflate_state *s; ++ unsigned dist; /* distance of matched string */ ++ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ ++{ ++ s->d_buf[s->last_lit] = (ush)dist; ++ s->l_buf[s->last_lit++] = (uch)lc; ++ if (dist == 0) { ++ /* lc is the unmatched char */ ++ s->dyn_ltree[lc].Freq++; ++ } else { ++ s->matches++; ++ /* Here, lc is the match length - MIN_MATCH */ ++ dist--; /* dist = match distance - 1 */ ++ Assert((ush)dist < (ush)MAX_DIST(s) && ++ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && ++ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); ++ ++ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; ++ s->dyn_dtree[d_code(dist)].Freq++; ++ } ++ ++#ifdef TRUNCATE_BLOCK ++ /* Try to guess if it is profitable to stop the current block here */ ++ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { ++ /* Compute an upper bound for the compressed length */ ++ ulg out_length = (ulg)s->last_lit*8L; ++ ulg in_length = (ulg)((long)s->strstart - s->block_start); ++ int dcode; ++ for (dcode = 0; dcode < D_CODES; dcode++) { ++ out_length += (ulg)s->dyn_dtree[dcode].Freq * ++ (5L+extra_dbits[dcode]); ++ } ++ out_length >>= 3; ++ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", ++ s->last_lit, in_length, out_length, ++ 100L - out_length*100L/in_length)); ++ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; ++ } ++#endif ++ return (s->last_lit == s->lit_bufsize-1); ++ /* We avoid equality with lit_bufsize because of wraparound at 64K ++ * on 16 bit machines and because stored blocks are restricted to ++ * 64K-1 bytes. ++ */ ++} ++ ++/* =========================================================================== ++ * Send the block data compressed using the given Huffman trees ++ */ ++local void compress_block(s, ltree, dtree) ++ deflate_state *s; ++ const ct_data *ltree; /* literal tree */ ++ const ct_data *dtree; /* distance tree */ ++{ ++ unsigned dist; /* distance of matched string */ ++ int lc; /* match length or unmatched char (if dist == 0) */ ++ unsigned lx = 0; /* running index in l_buf */ ++ unsigned code; /* the code to send */ ++ int extra; /* number of extra bits to send */ ++ ++ if (s->last_lit != 0) do { ++ dist = s->d_buf[lx]; ++ lc = s->l_buf[lx++]; ++ if (dist == 0) { ++ send_code(s, lc, ltree); /* send a literal byte */ ++ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); ++ } else { ++ /* Here, lc is the match length - MIN_MATCH */ ++ code = _length_code[lc]; ++ send_code(s, code+LITERALS+1, ltree); /* send the length code */ ++ extra = extra_lbits[code]; ++ if (extra != 0) { ++ lc -= base_length[code]; ++ send_bits(s, lc, extra); /* send the extra length bits */ ++ } ++ dist--; /* dist is now the match distance - 1 */ ++ code = d_code(dist); ++ Assert (code < D_CODES, "bad d_code"); ++ ++ send_code(s, code, dtree); /* send the distance code */ ++ extra = extra_dbits[code]; ++ if (extra != 0) { ++ dist -= base_dist[code]; ++ send_bits(s, dist, extra); /* send the extra distance bits */ ++ } ++ } /* literal or match pair ? */ ++ ++ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ ++ Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); ++ ++ } while (lx < s->last_lit); ++ ++ send_code(s, END_BLOCK, ltree); ++ s->last_eob_len = ltree[END_BLOCK].Len; ++} ++ ++/* =========================================================================== ++ * Set the data type to ASCII or BINARY, using a crude approximation: ++ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. ++ * IN assertion: the fields freq of dyn_ltree are set and the total of all ++ * frequencies does not exceed 64K (to fit in an int on 16 bit machines). ++ */ ++local void set_data_type(s) ++ deflate_state *s; ++{ ++ int n = 0; ++ unsigned ascii_freq = 0; ++ unsigned bin_freq = 0; ++ while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; ++ while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; ++ while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; ++ s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); ++} ++ ++/* =========================================================================== ++ * Reverse the first len bits of a code, using straightforward code (a faster ++ * method would use a table) ++ * IN assertion: 1 <= len <= 15 ++ */ ++local unsigned bi_reverse(code, len) ++ unsigned code; /* the value to invert */ ++ int len; /* its bit length */ ++{ ++ register unsigned res = 0; ++ do { ++ res |= code & 1; ++ code >>= 1, res <<= 1; ++ } while (--len > 0); ++ return res >> 1; ++} ++ ++/* =========================================================================== ++ * Flush the bit buffer, keeping at most 7 bits in it. ++ */ ++local void bi_flush(s) ++ deflate_state *s; ++{ ++ if (s->bi_valid == 16) { ++ put_short(s, s->bi_buf); ++ s->bi_buf = 0; ++ s->bi_valid = 0; ++ } else if (s->bi_valid >= 8) { ++ put_byte(s, (Byte)s->bi_buf); ++ s->bi_buf >>= 8; ++ s->bi_valid -= 8; ++ } ++} ++ ++/* =========================================================================== ++ * Flush the bit buffer and align the output on a byte boundary ++ */ ++local void bi_windup(s) ++ deflate_state *s; ++{ ++ if (s->bi_valid > 8) { ++ put_short(s, s->bi_buf); ++ } else if (s->bi_valid > 0) { ++ put_byte(s, (Byte)s->bi_buf); ++ } ++ s->bi_buf = 0; ++ s->bi_valid = 0; ++#ifdef DEBUG ++ s->bits_sent = (s->bits_sent+7) & ~7; ++#endif ++} ++ ++/* =========================================================================== ++ * Copy a stored block, storing first the length and its ++ * one's complement if requested. ++ */ ++local void copy_block(s, buf, len, header) ++ deflate_state *s; ++ charf *buf; /* the input data */ ++ unsigned len; /* its length */ ++ int header; /* true if block header must be written */ ++{ ++ bi_windup(s); /* align on byte boundary */ ++ s->last_eob_len = 8; /* enough lookahead for inflate */ ++ ++ if (header) { ++ put_short(s, (ush)len); ++ put_short(s, (ush)~len); ++#ifdef DEBUG ++ s->bits_sent += 2*16; ++#endif ++ } ++#ifdef DEBUG ++ s->bits_sent += (ulg)len<<3; ++#endif ++ while (len--) { ++ put_byte(s, *buf++); ++ } ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/trees.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,128 @@ ++/* header created automatically with -DGEN_TREES_H */ ++ ++local const ct_data static_ltree[L_CODES+2] = { ++{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, ++{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, ++{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, ++{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, ++{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, ++{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, ++{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, ++{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, ++{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, ++{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, ++{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, ++{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, ++{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, ++{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, ++{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, ++{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, ++{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, ++{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, ++{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, ++{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, ++{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, ++{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, ++{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, ++{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, ++{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, ++{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, ++{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, ++{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, ++{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, ++{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, ++{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, ++{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, ++{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, ++{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, ++{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, ++{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, ++{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, ++{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, ++{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, ++{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, ++{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, ++{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, ++{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, ++{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, ++{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, ++{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, ++{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, ++{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, ++{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, ++{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, ++{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, ++{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, ++{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, ++{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, ++{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, ++{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, ++{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, ++{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} ++}; ++ ++local const ct_data static_dtree[D_CODES] = { ++{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, ++{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, ++{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, ++{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, ++{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, ++{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} ++}; ++ ++const uch _dist_code[DIST_CODE_LEN] = { ++ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, ++ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, ++10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, ++11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, ++12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, ++13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, ++13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, ++14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, ++14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, ++14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, ++15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, ++15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, ++15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, ++18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, ++23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, ++24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, ++26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, ++26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, ++27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, ++27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, ++28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, ++28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, ++28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, ++29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, ++29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, ++29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 ++}; ++ ++const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { ++ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, ++13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, ++17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, ++19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, ++21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, ++22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, ++23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, ++24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, ++25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, ++25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, ++26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, ++26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, ++27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 ++}; ++ ++local const int base_length[LENGTH_CODES] = { ++0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, ++64, 80, 96, 112, 128, 160, 192, 224, 0 ++}; ++ ++local const int base_dist[D_CODES] = { ++ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, ++ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, ++ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 ++}; ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/zconf.h Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,309 @@ ++/* zconf.h -- configuration of the zlib compression library ++ * Copyright (C) 1995-2002 Jean-loup Gailly. ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* @(#) $Id: zconf.h,v 1.3 2002/04/24 07:36:45 mcr Exp $ */ ++ ++#ifndef _ZCONF_H ++#define _ZCONF_H ++ ++/* ++ * If you *really* need a unique prefix for all types and library functions, ++ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. ++ */ ++#ifdef IPCOMP_PREFIX ++# define deflateInit_ ipcomp_deflateInit_ ++# define deflate ipcomp_deflate ++# define deflateEnd ipcomp_deflateEnd ++# define inflateInit_ ipcomp_inflateInit_ ++# define inflate ipcomp_inflate ++# define inflateEnd ipcomp_inflateEnd ++# define deflateInit2_ ipcomp_deflateInit2_ ++# define deflateSetDictionary ipcomp_deflateSetDictionary ++# define deflateCopy ipcomp_deflateCopy ++# define deflateReset ipcomp_deflateReset ++# define deflateParams ipcomp_deflateParams ++# define inflateInit2_ ipcomp_inflateInit2_ ++# define inflateSetDictionary ipcomp_inflateSetDictionary ++# define inflateSync ipcomp_inflateSync ++# define inflateSyncPoint ipcomp_inflateSyncPoint ++# define inflateReset ipcomp_inflateReset ++# define compress ipcomp_compress ++# define compress2 ipcomp_compress2 ++# define uncompress ipcomp_uncompress ++# define adler32 ipcomp_adler32 ++# define crc32 ipcomp_crc32 ++# define get_crc_table ipcomp_get_crc_table ++/* SSS: these also need to be prefixed to avoid clash with ppp_deflate and ext2compression */ ++# define inflate_blocks ipcomp_deflate_blocks ++# define inflate_blocks_free ipcomp_deflate_blocks_free ++# define inflate_blocks_new ipcomp_inflate_blocks_new ++# define inflate_blocks_reset ipcomp_inflate_blocks_reset ++# define inflate_blocks_sync_point ipcomp_inflate_blocks_sync_point ++# define inflate_set_dictionary ipcomp_inflate_set_dictionary ++# define inflate_codes ipcomp_inflate_codes ++# define inflate_codes_free ipcomp_inflate_codes_free ++# define inflate_codes_new ipcomp_inflate_codes_new ++# define inflate_fast ipcomp_inflate_fast ++# define inflate_trees_bits ipcomp_inflate_trees_bits ++# define inflate_trees_dynamic ipcomp_inflate_trees_dynamic ++# define inflate_trees_fixed ipcomp_inflate_trees_fixed ++# define inflate_flush ipcomp_inflate_flush ++# define inflate_mask ipcomp_inflate_mask ++# define _dist_code _ipcomp_dist_code ++# define _length_code _ipcomp_length_code ++# define _tr_align _ipcomp_tr_align ++# define _tr_flush_block _ipcomp_tr_flush_block ++# define _tr_init _ipcomp_tr_init ++# define _tr_stored_block _ipcomp_tr_stored_block ++# define _tr_tally _ipcomp_tr_tally ++# define zError ipcomp_zError ++# define z_errmsg ipcomp_z_errmsg ++# define zlibVersion ipcomp_zlibVersion ++# define match_init ipcomp_match_init ++# define longest_match ipcomp_longest_match ++#endif ++ ++#ifdef Z_PREFIX ++# define Byte z_Byte ++# define uInt z_uInt ++# define uLong z_uLong ++# define Bytef z_Bytef ++# define charf z_charf ++# define intf z_intf ++# define uIntf z_uIntf ++# define uLongf z_uLongf ++# define voidpf z_voidpf ++# define voidp z_voidp ++#endif ++ ++#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) ++# define WIN32 ++#endif ++#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) ++# ifndef __32BIT__ ++# define __32BIT__ ++# endif ++#endif ++#if defined(__MSDOS__) && !defined(MSDOS) ++# define MSDOS ++#endif ++ ++/* ++ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more ++ * than 64k bytes at a time (needed on systems with 16-bit int). ++ */ ++#if defined(MSDOS) && !defined(__32BIT__) ++# define MAXSEG_64K ++#endif ++#ifdef MSDOS ++# define UNALIGNED_OK ++#endif ++ ++#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) ++# define STDC ++#endif ++#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) ++# ifndef STDC ++# define STDC ++# endif ++#endif ++ ++#ifndef STDC ++# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ ++# define const ++# endif ++#endif ++ ++/* Some Mac compilers merge all .h files incorrectly: */ ++#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) ++# define NO_DUMMY_DECL ++#endif ++ ++/* Old Borland C incorrectly complains about missing returns: */ ++#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) ++# define NEED_DUMMY_RETURN ++#endif ++ ++ ++/* Maximum value for memLevel in deflateInit2 */ ++#ifndef MAX_MEM_LEVEL ++# ifdef MAXSEG_64K ++# define MAX_MEM_LEVEL 8 ++# else ++# define MAX_MEM_LEVEL 9 ++# endif ++#endif ++ ++/* Maximum value for windowBits in deflateInit2 and inflateInit2. ++ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files ++ * created by gzip. (Files created by minigzip can still be extracted by ++ * gzip.) ++ */ ++#ifndef MAX_WBITS ++# define MAX_WBITS 15 /* 32K LZ77 window */ ++#endif ++ ++/* The memory requirements for deflate are (in bytes): ++ (1 << (windowBits+2)) + (1 << (memLevel+9)) ++ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) ++ plus a few kilobytes for small objects. For example, if you want to reduce ++ the default memory requirements from 256K to 128K, compile with ++ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" ++ Of course this will generally degrade compression (there's no free lunch). ++ ++ The memory requirements for inflate are (in bytes) 1 << windowBits ++ that is, 32K for windowBits=15 (default value) plus a few kilobytes ++ for small objects. ++*/ ++ ++ /* Type declarations */ ++ ++#ifndef OF /* function prototypes */ ++# ifdef STDC ++# define OF(args) args ++# else ++# define OF(args) () ++# endif ++#endif ++ ++/* The following definitions for FAR are needed only for MSDOS mixed ++ * model programming (small or medium model with some far allocations). ++ * This was tested only with MSC; for other MSDOS compilers you may have ++ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, ++ * just define FAR to be empty. ++ */ ++#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) ++ /* MSC small or medium model */ ++# define SMALL_MEDIUM ++# ifdef _MSC_VER ++# define FAR _far ++# else ++# define FAR far ++# endif ++#endif ++#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) ++# ifndef __32BIT__ ++# define SMALL_MEDIUM ++# define FAR _far ++# endif ++#endif ++ ++/* Compile with -DZLIB_DLL for Windows DLL support */ ++#if defined(ZLIB_DLL) ++# if defined(_WINDOWS) || defined(WINDOWS) ++# ifdef FAR ++# undef FAR ++# endif ++# include <windows.h> ++# define ZEXPORT WINAPI ++# ifdef WIN32 ++# define ZEXPORTVA WINAPIV ++# else ++# define ZEXPORTVA FAR _cdecl _export ++# endif ++# endif ++# if defined (__BORLANDC__) ++# if (__BORLANDC__ >= 0x0500) && defined (WIN32) ++# include <windows.h> ++# define ZEXPORT __declspec(dllexport) WINAPI ++# define ZEXPORTRVA __declspec(dllexport) WINAPIV ++# else ++# if defined (_Windows) && defined (__DLL__) ++# define ZEXPORT _export ++# define ZEXPORTVA _export ++# endif ++# endif ++# endif ++#endif ++ ++#if defined (__BEOS__) ++# if defined (ZLIB_DLL) ++# define ZEXTERN extern __declspec(dllexport) ++# else ++# define ZEXTERN extern __declspec(dllimport) ++# endif ++#endif ++ ++#ifndef ZEXPORT ++# define ZEXPORT ++#endif ++#ifndef ZEXPORTVA ++# define ZEXPORTVA ++#endif ++#ifndef ZEXTERN ++# define ZEXTERN extern ++#endif ++ ++#ifndef FAR ++# define FAR ++#endif ++ ++#if !defined(MACOS) && !defined(TARGET_OS_MAC) ++typedef unsigned char Byte; /* 8 bits */ ++#endif ++typedef unsigned int uInt; /* 16 bits or more */ ++typedef unsigned long uLong; /* 32 bits or more */ ++ ++#ifdef SMALL_MEDIUM ++ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ ++# define Bytef Byte FAR ++#else ++ typedef Byte FAR Bytef; ++#endif ++typedef char FAR charf; ++typedef int FAR intf; ++typedef uInt FAR uIntf; ++typedef uLong FAR uLongf; ++ ++#ifdef STDC ++ typedef void FAR *voidpf; ++ typedef void *voidp; ++#else ++ typedef Byte FAR *voidpf; ++ typedef Byte *voidp; ++#endif ++ ++#ifdef HAVE_UNISTD_H ++# include <sys/types.h> /* for off_t */ ++# include <unistd.h> /* for SEEK_* and off_t */ ++# define z_off_t off_t ++#endif ++#ifndef SEEK_SET ++# define SEEK_SET 0 /* Seek from beginning of file. */ ++# define SEEK_CUR 1 /* Seek from current position. */ ++# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ ++#endif ++#ifndef z_off_t ++# define z_off_t long ++#endif ++ ++/* MVS linker does not support external names larger than 8 bytes */ ++#if defined(__MVS__) ++# pragma map(deflateInit_,"DEIN") ++# pragma map(deflateInit2_,"DEIN2") ++# pragma map(deflateEnd,"DEEND") ++# pragma map(inflateInit_,"ININ") ++# pragma map(inflateInit2_,"ININ2") ++# pragma map(inflateEnd,"INEND") ++# pragma map(inflateSync,"INSY") ++# pragma map(inflateSetDictionary,"INSEDI") ++# pragma map(inflate_blocks,"INBL") ++# pragma map(inflate_blocks_new,"INBLNE") ++# pragma map(inflate_blocks_free,"INBLFR") ++# pragma map(inflate_blocks_reset,"INBLRE") ++# pragma map(inflate_codes_free,"INCOFR") ++# pragma map(inflate_codes,"INCO") ++# pragma map(inflate_fast,"INFA") ++# pragma map(inflate_flush,"INFLU") ++# pragma map(inflate_mask,"INMA") ++# pragma map(inflate_set_dictionary,"INSEDI2") ++# pragma map(ipcomp_inflate_copyright,"INCOPY") ++# pragma map(inflate_trees_bits,"INTRBI") ++# pragma map(inflate_trees_dynamic,"INTRDY") ++# pragma map(inflate_trees_fixed,"INTRFI") ++# pragma map(inflate_trees_free,"INTRFR") ++#endif ++ ++#endif /* _ZCONF_H */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/lib/zlib/zutil.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,227 @@ ++/* zutil.c -- target dependent utility functions for the compression library ++ * Copyright (C) 1995-2002 Jean-loup Gailly. ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++/* @(#) $Id: zutil.c,v 1.4 2002/04/24 07:55:32 mcr Exp $ */ ++ ++#include <zlib/zutil.h> ++ ++#define MY_ZCALLOC ++ ++struct internal_state {int dummy;}; /* for buggy compilers */ ++ ++#ifndef STDC ++extern void exit OF((int)); ++#endif ++ ++const char *z_errmsg[10] = { ++"need dictionary", /* Z_NEED_DICT 2 */ ++"stream end", /* Z_STREAM_END 1 */ ++"", /* Z_OK 0 */ ++"file error", /* Z_ERRNO (-1) */ ++"stream error", /* Z_STREAM_ERROR (-2) */ ++"data error", /* Z_DATA_ERROR (-3) */ ++"insufficient memory", /* Z_MEM_ERROR (-4) */ ++"buffer error", /* Z_BUF_ERROR (-5) */ ++"incompatible version",/* Z_VERSION_ERROR (-6) */ ++""}; ++ ++ ++const char * ZEXPORT zlibVersion() ++{ ++ return ZLIB_VERSION; ++} ++ ++#ifdef DEBUG ++ ++# ifndef verbose ++# define verbose 0 ++# endif ++int z_verbose = verbose; ++ ++void z_error (m) ++ char *m; ++{ ++ fprintf(stderr, "%s\n", m); ++ exit(1); ++} ++#endif ++ ++/* exported to allow conversion of error code to string for compress() and ++ * uncompress() ++ */ ++const char * ZEXPORT zError(err) ++ int err; ++{ ++ return ERR_MSG(err); ++} ++ ++ ++#ifndef HAVE_MEMCPY ++ ++void zmemcpy(dest, source, len) ++ Bytef* dest; ++ const Bytef* source; ++ uInt len; ++{ ++ if (len == 0) return; ++ do { ++ *dest++ = *source++; /* ??? to be unrolled */ ++ } while (--len != 0); ++} ++ ++int zmemcmp(s1, s2, len) ++ const Bytef* s1; ++ const Bytef* s2; ++ uInt len; ++{ ++ uInt j; ++ ++ for (j = 0; j < len; j++) { ++ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; ++ } ++ return 0; ++} ++ ++void zmemzero(dest, len) ++ Bytef* dest; ++ uInt len; ++{ ++ if (len == 0) return; ++ do { ++ *dest++ = 0; /* ??? to be unrolled */ ++ } while (--len != 0); ++} ++#endif ++ ++#ifdef __TURBOC__ ++#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) ++/* Small and medium model in Turbo C are for now limited to near allocation ++ * with reduced MAX_WBITS and MAX_MEM_LEVEL ++ */ ++# define MY_ZCALLOC ++ ++/* Turbo C malloc() does not allow dynamic allocation of 64K bytes ++ * and farmalloc(64K) returns a pointer with an offset of 8, so we ++ * must fix the pointer. Warning: the pointer must be put back to its ++ * original form in order to free it, use zcfree(). ++ */ ++ ++#define MAX_PTR 10 ++/* 10*64K = 640K */ ++ ++local int next_ptr = 0; ++ ++typedef struct ptr_table_s { ++ voidpf org_ptr; ++ voidpf new_ptr; ++} ptr_table; ++ ++local ptr_table table[MAX_PTR]; ++/* This table is used to remember the original form of pointers ++ * to large buffers (64K). Such pointers are normalized with a zero offset. ++ * Since MSDOS is not a preemptive multitasking OS, this table is not ++ * protected from concurrent access. This hack doesn't work anyway on ++ * a protected system like OS/2. Use Microsoft C instead. ++ */ ++ ++voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) ++{ ++ voidpf buf = opaque; /* just to make some compilers happy */ ++ ulg bsize = (ulg)items*size; ++ ++ /* If we allocate less than 65520 bytes, we assume that farmalloc ++ * will return a usable pointer which doesn't have to be normalized. ++ */ ++ if (bsize < 65520L) { ++ buf = farmalloc(bsize); ++ if (*(ush*)&buf != 0) return buf; ++ } else { ++ buf = farmalloc(bsize + 16L); ++ } ++ if (buf == NULL || next_ptr >= MAX_PTR) return NULL; ++ table[next_ptr].org_ptr = buf; ++ ++ /* Normalize the pointer to seg:0 */ ++ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; ++ *(ush*)&buf = 0; ++ table[next_ptr++].new_ptr = buf; ++ return buf; ++} ++ ++void zcfree (voidpf opaque, voidpf ptr) ++{ ++ int n; ++ if (*(ush*)&ptr != 0) { /* object < 64K */ ++ farfree(ptr); ++ return; ++ } ++ /* Find the original pointer */ ++ for (n = 0; n < next_ptr; n++) { ++ if (ptr != table[n].new_ptr) continue; ++ ++ farfree(table[n].org_ptr); ++ while (++n < next_ptr) { ++ table[n-1] = table[n]; ++ } ++ next_ptr--; ++ return; ++ } ++ ptr = opaque; /* just to make some compilers happy */ ++ Assert(0, "zcfree: ptr not found"); ++} ++#endif ++#endif /* __TURBOC__ */ ++ ++ ++#if defined(M_I86) && !defined(__32BIT__) ++/* Microsoft C in 16-bit mode */ ++ ++# define MY_ZCALLOC ++ ++#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) ++# define _halloc halloc ++# define _hfree hfree ++#endif ++ ++voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) ++{ ++ if (opaque) opaque = 0; /* to make compiler happy */ ++ return _halloc((long)items, size); ++} ++ ++void zcfree (voidpf opaque, voidpf ptr) ++{ ++ if (opaque) opaque = 0; /* to make compiler happy */ ++ _hfree(ptr); ++} ++ ++#endif /* MSC */ ++ ++ ++#ifndef MY_ZCALLOC /* Any system without a special alloc function */ ++ ++#ifndef STDC ++extern voidp calloc OF((uInt items, uInt size)); ++extern void free OF((voidpf ptr)); ++#endif ++ ++voidpf zcalloc (opaque, items, size) ++ voidpf opaque; ++ unsigned items; ++ unsigned size; ++{ ++ if (opaque) items += size - size; /* make compiler happy */ ++ return (voidpf)calloc(items, size); ++} ++ ++void zcfree (opaque, ptr) ++ voidpf opaque; ++ voidpf ptr; ++{ ++ free(ptr); ++ if (opaque) return; /* make compiler happy */ ++} ++ ++#endif /* MY_ZCALLOC */ +--- linux/net/Config.in.orig Fri Feb 9 14:34:13 2001 ++++ linux/net/Config.in Thu Feb 22 19:40:08 2001 +@@ -88,4 +88,9 @@ + #bool 'Network code profiler' CONFIG_NET_PROFILE + endmenu + ++tristate 'IP Security Protocol (FreeS/WAN IPSEC)' CONFIG_IPSEC ++if [ "$CONFIG_IPSEC" != "n" ]; then ++ source net/ipsec/Config.in ++fi ++ + endmenu +RCSID $Id: Makefile.fs2_4.patch,v 1.7 2002/07/28 23:12:39 mcr Exp $ +--- linux/net/Makefile.preipsec Mon Jun 11 22:15:27 2001 ++++ linux/net/Makefile Tue Nov 6 21:07:43 2001 +@@ -17,6 +17,7 @@ + subdir-$(CONFIG_NET) += 802 sched + subdir-$(CONFIG_INET) += ipv4 + subdir-$(CONFIG_NETFILTER) += ipv4/netfilter ++subdir-$(CONFIG_IPSEC) += ipsec + subdir-$(CONFIG_UNIX) += unix + subdir-$(CONFIG_IPV6) += ipv6 + +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/Config.in Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,76 @@ ++# ++# IPSEC configuration ++# Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License as published by the ++# Free Software Foundation; either version 2 of the License, or (at your ++# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++# ++# This program is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++# for more details. ++# ++# RCSID $Id: Config.in,v 1.30 2004/06/23 09:49:37 ken Exp $ ++ ++comment 'IPSec options (Openswan)' ++ ++bool ' IPSEC: IP-in-IP encapsulation (tunnel mode)' CONFIG_IPSEC_IPIP ++ ++bool ' IPSEC: Authentication Header' CONFIG_IPSEC_AH ++if [ "$CONFIG_IPSEC_AH" = "y" -o "$CONFIG_IPSEC_ESP" = "y" ]; then ++ bool ' HMAC-MD5 authentication algorithm' CONFIG_IPSEC_AUTH_HMAC_MD5 ++ bool ' HMAC-SHA1 authentication algorithm' CONFIG_IPSEC_AUTH_HMAC_SHA1 ++fi ++ ++bool ' IPSEC: Encapsulating Security Payload' CONFIG_IPSEC_ESP ++if [ "$CONFIG_IPSEC_ESP" = "y" ]; then ++ bool ' 3DES encryption algorithm' CONFIG_IPSEC_ENC_3DES ++ bool ' AES encryption algorithm' CONFIG_IPSEC_ENC_AES ++fi ++ ++bool ' IPSEC Modular Extensions' CONFIG_IPSEC_ALG ++if [ "$CONFIG_IPSEC_ALG" != "n" ]; then ++ source net/ipsec/alg/Config.in ++fi ++ ++bool ' IPSEC: IP Compression' CONFIG_IPSEC_IPCOMP ++ ++bool ' IPSEC Debugging Option' CONFIG_IPSEC_DEBUG ++ ++# ++# ++# $Log: Config.in,v $ ++# Revision 1.30 2004/06/23 09:49:37 ken ++# Free -> Open ++# ++# Revision 1.29 2004/04/06 02:49:25 mcr ++# pullup of algo code from alg-branch. ++# ++# Revision 1.28 2004/02/03 03:12:26 mcr ++# remove NAT-traversal option from IPsec config, ++# as it should be in the kernel configuration if ++# the NAT-T patch is installed. ++# ++# Revision 1.27.2.2 2004/04/05 04:30:46 mcr ++# patches for alg-branch to compile/work with 2.x openswan ++# ++# Revision 1.27.2.1 2003/12/23 12:48:25 jjo ++# Added missing alg part to linux/net/ipsec/Config.in ++# ++# Revision 1.27 2003/12/10 01:14:27 mcr ++# NAT-traversal patches to KLIPS. ++# ++# Revision 1.26 2002/04/24 07:36:26 mcr ++# Moved from ./klips/net/ipsec/Config.in,v ++# ++# Revision 1.25 2002/02/21 19:55:12 mcr ++# removed all traces of IPSEC_CONFIG_REGRESS because it ++# screwed up 2.2's "make menuconfig" scripts. ++# ++# Revision 1.24 2002/01/28 20:24:31 mcr ++# commented out IPSEC_REGRESS option from user visible config. ++# ++# ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/Makefile Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,337 @@ ++# Makefile for KLIPS kernel code as a module ++# Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. ++# Copyright (C) 2002 Michael Richardson <mcr@freeswan.org> ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License as published by the ++# Free Software Foundation; either version 2 of the License, or (at your ++# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++# ++# This program is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++# for more details. ++# ++# RCSID $Id: Makefile,v 1.72 2004/06/22 14:44:07 ken Exp $ ++# ++# Note! Dependencies are done automagically by 'make dep', which also ++# removes any old dependencies. DON'T put your own dependencies here ++# unless it's something special (ie not a .c file). ++# ++ ++ifeq ($(strip $(KLIPSMODULE)),) ++OPENSWANSRCDIR=. ++else ++OPENSWANSRCDIR=../../.. ++endif ++-include ${OPENSWANSRCDIR}/Makefile.ver ++ ++ifeq ($(strip $(KLIPS_TOP)),) ++KLIPS_TOP=../.. ++endif ++ ++ifneq ($(strip $(KLIPSMODULE)),) ++ ++ifndef TOPDIR ++TOPDIR:=/usr/src/linux ++endif ++export TOPDIR ++ ++endif ++ ++# ++# This magic from User-Mode-Linux list. It gets list of -I options, as ++# UML needs some extra, that varry by revision. ++# ++KERNEL_CFLAGS= $(shell $(MAKE) -C $(TOPDIR) --no-print-directory -s -f Makefile ARCH=$(ARCH) MAKEFLAGS= script SCRIPT='@echo $$(CFLAGS)' ) ++ ++MODULE_CFLAGS= $(shell $(MAKE) -C $(TOPDIR) --no-print-directory -s -f Makefile ARCH=$(ARCH) MAKEFLAGS= script SCRIPT='@echo $$(MODFLAGS)' ) ++ ++subdir- := ++subdir-n := ++subdir-y := ++subdir-m := ++ ++ ++MOD_DESTDIR:=net/ipsec ++ ++export TOPDIR ++ ++all: ipsec.o ++ ++foo: ++ echo KERNEL: ${KERNEL_CFLAGS} ++ echo MODULE: ${MODULE_CFLAGS} ++ ++ipsec.o: foo ++ ++O_TARGET := ipsec.o ++obj-y := ipsec_init.o ipsec_sa.o ipsec_radij.o radij.o ++obj-y += ipsec_life.o ipsec_proc.o ++obj-y += ipsec_tunnel.o ipsec_xmit.o ipsec_rcv.o ipsec_ipip.o ++obj-y += sysctl_net_ipsec.o ++obj-y += pfkey_v2.o pfkey_v2_parser.o pfkey_v2_ext_process.o ++obj-y += version.o ++obj-$(CONFIG_IPSEC_AH) += ipsec_ah.o ++obj-$(CONFIG_IPSEC_ESP) += ipsec_esp.o ++obj-$(CONFIG_IPSEC_IPCOMP)+= ipsec_ipcomp.o ++ ++CFLAGS_ipsec_alg.o += -DEXPORT_SYMTAB ++obj-$(CONFIG_IPSEC_ALG) += ipsec_alg.o ++obj-$(CONFIG_IPSEC_ENC_AES) += ipsec_alg_aes.o ++obj-$(CONFIG_IPSEC_ENC_CRYPTOAPI) += ipsec_alg_cryptoapi.o ++ ++export-objs += ipsec_alg.o ++ ++ ++LIBDESDIR=${KLIPS_TOP}/crypto/ciphers/des ++VPATH+= ${LIBDESDIR} ++ ++include ${LIBDESDIR}/Makefile.objs ++ ++LIBFREESWANDIR=${KLIPS_TOP}/lib/libfreeswan ++VPATH+=${LIBFREESWANDIR} ++ ++include ${LIBFREESWANDIR}/Makefile.objs ++ ++# IPcomp stuff ++obj-$(CONFIG_IPSEC_IPCOMP) += ipcomp.o ++ ++LIBZLIBSRCDIR=${KLIPS_TOP}/lib/zlib ++VPATH+=${LIBZLIBSRCDIR} ++ ++LIBAESDIR=$(KLIPS_TOP)/crypto/ciphers/aes ++VPATH+=${LIBAESDIR} ++include ${LIBAESDIR}/Makefile.objs ++ ++# CFLAGS='$(CFLAGS)' \ ++# MODULE_CFLAGS='$(MODULE_CFLAGS)' KERNEL_CFLAGS='$(KERNEL_CFLAGS)' \ ++# ++include ${LIBZLIBSRCDIR}/Makefile.objs ++ ++export-objs := radij.o ++ ++EXTRA_CFLAGS += $(ALGO_FLAGS) ++ ++ ++# include file with .h-style macros that would otherwise be created by ++# config. Must occur before other includes. ++ifneq ($(strip $(MODULE_DEF_INCLUDE)),) ++EXTRA_CFLAGS += -include ${MODULE_DEF_INCLUDE} ++endif ++ ++# 'override CFLAGS' should really be 'EXTRA_CFLAGS' ++#EXTRA_CFLAGS += -nostdinc ++EXTRA_CFLAGS += -I${KLIPS_TOP}/include ++ ++EXTRA_CFLAGS += -I${TOPDIR}/include ++EXTRA_CFLAGS += -I${LIBZLIBSRCDIR} ++ ++ifeq ($(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION),2.4.2-2) ++EXTRA_CFLAGS += -DREDHAT_BOGOSITY ++endif ++ ++ifeq ($(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION),2.4.3-12) ++EXTRA_CFLAGS += -DREDHAT_BOGOSITY ++endif ++ ++ ++#ifeq ($(CONFIG_IPSEC_DEBUG),y) ++#EXTRA_CFLAGS += -g ++#endif ++ ++#ifeq ($(CONFIG_IPSEC_ALG), y) ++EXTRA_CFLAGS += -DCONFIG_IPSEC_ALG ++#endif ++# MOST of these flags are in KERNEL_CFLAGS already! ++ ++EXTRA_CFLAGS += $(KLIPSCOMPILE) ++EXTRA_CFLAGS += -Wall ++#EXTRA_CFLAGS += -Werror ++#EXTRA_CFLAGS += -Wconversion ++#EXTRA_CFLAGS += -Wmissing-prototypes ++# cannot use both -Wpointer-arith and -Werror with CONFIG_HIGHMEM ++# include/linux/highmem.h has an inline function definition that uses void* arithmentic. ++ifeq ($(CONFIG_NOHIGHMEM),y) ++EXTRA_CFLAGS += -Wpointer-arith ++endif ++#EXTRA_CFLAGS += -Wcast-qual ++#EXTRA_CFLAGS += -Wmissing-declarations ++#EXTRA_CFLAGS += -Wstrict-prototypes ++#EXTRA_CFLAGS += -pedantic ++#EXTRA_CFLAGS += -O3 ++#EXTRA_CFLAGS += -W ++#EXTRA_CFLAGS += -Wwrite-strings ++#EXTRA_CFLAGS += -Wbad-function-cast ++ ++ifneq ($(strip $(KLIPSMODULE)),) ++# for when we aren't building in the kernel tree ++EXTRA_CFLAGS += -DARCH=${ARCH} ++EXTRA_CFLAGS += -DMODVERSIONS ++EXTRA_CFLAGS += -include ${TOPDIR}/include/linux/modversions.h ++EXTRA_CFLAGS += ${MODULE_CFLAGS} ++endif ++ ++EXTRA_CFLAGS += ${KERNEL_CFLAGS} ++ ++#EXTRA_CFLAGS += -DRJ_DEBUG -DRJ_DEBUG2 ++ ++ ++# GCC 3.2 (and we presume any other 3.x) wants -falign-functions ++# in place of the traditional -malign-functions. Getting this ++# wrong leads to a warning, which is fatal due to our use of -Werror. ++ifeq ($(patsubst 3.%,3,$(shell $(CC) -dumpversion)),3) ++override CFLAGS:=$(subst -malign-functions=,-falign-functions=,$(CFLAGS)) ++endif ++ ++ ++obj-$(CONFIG_IPSEC_AUTH_HMAC_MD5) += ipsec_md5c.o ++obj-$(CONFIG_IPSEC_AUTH_HMAC_SHA1) += ipsec_sha1.o ++ ++### ++### Pre Rules.make ++### ++# undo O_TARGET, obj-y if no static ++ifneq ($(CONFIG_IPSEC),y) ++O_TARGET := ++ipsec_obj-y := $(obj-y) ++obj-y := ++subdir-y := ++endif ++ ++# Define obj-m if modular ipsec ++ifeq ($(CONFIG_IPSEC),m) ++obj-m += ipsec.o ++endif ++ ++ ++# These rules translate from new to old makefile rules ++# Translate to Rules.make lists. ++multi-used := $(filter $(list-multi), $(obj-y) $(obj-m)) ++multi-objs := $(foreach m, $(multi-used), $($(basename $(m))-objs)) ++active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m)) ++O_OBJS := $(obj-y) ++M_OBJS := $(obj-m) ++MIX_OBJS := $(filter $(export-objs), $(active-objs)) ++OX_OBJS := $(export-objs) ++SUB_DIRS := $(subdir-y) ++ALL_SUB_DIRS := $(subdir-y) $(subdir-m) ++MOD_SUB_DIRS := $(subdir-m) ++ ++# dunno why, but some 2.2 setups may need explicit -DEXPORT_SYMTAB ++# uncomment next line if ipsec_alg.c compilation fails with ++# "parse error before `EXPORT_SYMTAB_not_defined'" --Juanjo ++ ++include $(TOPDIR)/Rules.make ++ ++### ++### Post Rules.make ++### ++# for modular ipsec, no O_TARGET defined => define ipsec.o creation rules ++ifeq ($(CONFIG_IPSEC),m) ++ipsec.o : $(ipsec_obj-y) ++ rm -f $@ ++ $(LD) $(LD_EXTRAFLAGS) -r $(ipsec_obj-y) -o $@ ++endif ++ ++$(ipsec_obj-y) $(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h ++ ++#$(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h ++ ++USE_STANDARD_AS_RULE=true ++ ++clean: ++ $(MAKE) -C alg clean ++ -rm -f *.o ++ -rm -f .*.o.flags ++ -rm -f version.c ++ ++tags TAGS: *.c *.h libfreeswan/*.c libfreeswan/*.h ++ etags *.c ../../include/*.h ../../include/freeswan/*.h ++ ctags *.c ../../include/*.h ../../include/freeswan/*.h ++ ++tar: ++ tar -cvf /dev/f1 . ++ ++# ++# $Log: Makefile,v $ ++# Revision 1.72 2004/06/22 14:44:07 ken ++# Merge nice version of Nate's CryptoAPI patch ++# ++# Revision 1.71 2004/04/18 03:04:21 mcr ++# removed duplicate version.o reference. ++# ++# Revision 1.70 2004/04/14 05:09:39 ken ++# We need to link version.o ++# ++# Revision 1.69 2004/04/12 04:02:39 ken ++# version.o no longer exists ++# ++# Revision 1.68 2004/04/11 17:08:41 mcr ++# moved PASSTHROUGH definitions to openswan.h ++# requirement for internal.h removed. ++# version.c is now generated by patch at patch-time. ++# ++# Revision 1.67 2004/04/06 02:49:25 mcr ++# pullup of algo code from alg-branch. ++# ++# Revision 1.66 2004/04/03 19:44:41 ken ++# FREESWANSRCDIR -> OPENSWANSRCDIR (patch by folken) ++# ++# Revision 1.65 2004/02/09 16:22:07 paul ++# Added -f to rm version.c in clean target to prevent bogus error ++# ++# Revision 1.64 2003/12/22 19:40:57 mcr ++# NAT-T patches 0.6c. ++# ++# Revision 1.63 2003/12/13 19:10:21 mcr ++# refactored rcv and xmit code - same as FS 2.05. ++# ++# Revision 1.62.4.2 2004/04/05 04:30:46 mcr ++# patches for alg-branch to compile/work with 2.x openswan ++# ++# Revision 1.62.4.1 2003/12/22 15:25:52 jjo ++# Merged algo-0.8.1-rc11-test1 into alg-branch ++# ++# Revision 1.62 2003/10/31 02:27:55 mcr ++# pulled up port-selector patches and sa_id elimination. ++# ++# Revision 1.61.4.1 2003/10/29 01:30:41 mcr ++# elimited "struct sa_id". ++# ++# Revision 1.61 2003/06/22 21:07:46 mcr ++# adjusted TAGS target in makefile to be useful in 2.00 source layout. ++# ++# Revision 1.60 2003/05/03 23:45:23 mcr ++# rm .o.flags and generated version.c file. ++# ++# Revision 1.59 2003/02/12 19:32:47 rgb ++# Added ipsec_xmit to the list of object files. ++# ++# Revision 1.58 2003/01/03 00:36:44 rgb ++# ++# Added emacs compile-command. ++# ++# Revision 1.57 2002/11/08 23:49:53 mcr ++# use KERNEL_CFLAGS and MODULE_CFLAGS to get proper list ++# of include directories. ++# This also eliminates some of the guesswork in the kernel ++# configuration file. ++# ++# Revision 1.56 2002/11/08 23:23:18 mcr ++# attempt to guess kernel compilation flags (i.e. list of -I) ++# by using some magic targets in the kernel makefile. ++# ++# Revision 1.55 2002/11/08 10:13:33 mcr ++# added additional include directories for module builds for 2.4.19. ++# ++# Revision 1.54 2002/10/20 06:10:30 build ++# CONFIG_NOHIGHMEM for -Wpointer-arith RPM building issues. ++# ++# (elided rest of log) ++# ++# Local Variables: ++# compile-command: "(cd ../../.. && source umlsetup.sh && make -C ${POOLSPACE} module/ipsec.o)" ++# End Variables: ++# ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/alg/Config.alg_aes.in Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,3 @@ ++if [ "$CONFIG_IPSEC_ALG" = "y" ]; then ++ tristate ' AES encryption algorithm' CONFIG_IPSEC_ALG_AES ++fi +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/alg/Config.alg_cryptoapi.in Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,6 @@ ++if [ "$CONFIG_IPSEC_ALG" = "y" ]; then ++ dep_tristate ' CRYPTOAPI ciphers support (needs cryptoapi patch)' CONFIG_IPSEC_ALG_CRYPTOAPI $CONFIG_CRYPTO ++ if [ "$CONFIG_IPSEC_ALG_CRYPTOAPI" != "n" ]; then ++ bool ' CRYPTOAPI proprietary ciphers ' CONFIG_IPSEC_ALG_NON_LIBRE ++ fi ++fi +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/alg/Config.in Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,3 @@ ++#Placeholder ++source net/ipsec/alg/Config.alg_aes.in ++source net/ipsec/alg/Config.alg_cryptoapi.in +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/alg/Makefile Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,112 @@ ++# Makefile,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp ++ifeq ($(strip $(KLIPSMODULE)),) ++FREESWANSRCDIR=. ++else ++FREESWANSRCDIR=../../../.. ++endif ++ifeq ($(strip $(KLIPS_TOP)),) ++KLIPS_TOP=../../.. ++override EXTRA_CFLAGS += -I$(KLIPS_TOP)/include ++endif ++ ++ifeq ($(CONFIG_IPSEC_DEBUG),y) ++override EXTRA_CFLAGS += -g ++endif ++ ++# LIBCRYPTO normally comes as an argument from "parent" Makefile ++# (this applies both to FS' "make module" and eg. Linux' "make modules" ++# But make dep doest follow same evaluations, so we need this default: ++LIBCRYPTO=$(TOPDIR)/lib/libcrypto ++ ++override EXTRA_CFLAGS += -I$(LIBCRYPTO)/include ++override EXTRA_CFLAGS += -Wall -Wpointer-arith -Wstrict-prototypes ++ ++MOD_LIST_NAME := NET_MISC_MODULES ++ ++#O_TARGET := static_init.o ++ ++subdir- := ++subdir-n := ++subdir-y := ++subdir-m := ++ ++obj-y := static_init.o ++ ++ARCH_ASM-y := ++ARCH_ASM-$(CONFIG_M586) := i586 ++ARCH_ASM-$(CONFIG_M586TSC) := i586 ++ARCH_ASM-$(CONFIG_M586MMX) := i586 ++ARCH_ASM-$(CONFIG_MK6) := i586 ++ARCH_ASM-$(CONFIG_M686) := i686 ++ARCH_ASM-$(CONFIG_MPENTIUMIII) := i686 ++ARCH_ASM-$(CONFIG_MPENTIUM4) := i686 ++ARCH_ASM-$(CONFIG_MK7) := i686 ++ARCH_ASM-$(CONFIG_MCRUSOE) := i586 ++ARCH_ASM-$(CONFIG_MWINCHIPC6) := i586 ++ARCH_ASM-$(CONFIG_MWINCHIP2) := i586 ++ARCH_ASM-$(CONFIG_MWINCHIP3D) := i586 ++ARCH_ASM-$(CONFIG_USERMODE) := i586 ++ ++ARCH_ASM :=$(ARCH_ASM-y) ++ifdef NO_ASM ++ARCH_ASM := ++endif ++ ++# The algorithm makefiles may put dependences, short-circuit them ++null: ++ ++makefiles=$(filter-out %.preipsec, $(wildcard Makefile.alg_*)) ++ifneq ($(makefiles),) ++#include Makefile.alg_aes ++#include Makefile.alg_aes-opt ++include $(makefiles) ++endif ++ ++# These rules translate from new to old makefile rules ++# Translate to Rules.make lists. ++multi-used := $(filter $(list-multi), $(obj-y) $(obj-m)) ++multi-objs := $(foreach m, $(multi-used), $($(basename $(m))-objs)) ++active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m)) ++O_OBJS := $(obj-y) ++M_OBJS := $(obj-m) ++MIX_OBJS := $(filter $(export-objs), $(active-objs)) ++#OX_OBJS := $(export-objs) ++SUB_DIRS := $(subdir-y) ++ALL_SUB_DIRS := $(subdir-y) $(subdir-m) ++MOD_SUB_DIRS := $(subdir-m) ++ ++ ++static_init_mod.o: $(obj-y) ++ rm -f $@ ++ $(LD) $(LD_EXTRAFLAGS) $(obj-y) -r -o $@ ++ ++perlasm: $(LIBCRYPTO)/perlasm ++ ln -sf $? $@ ++ ++$(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h $(KLIPS_TOP)/include/freeswan/ipsec_alg.h ++$(alg_obj-y) $(alg_obj-m): perlasm $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h $(KLIPS_TOP)/include/freeswan/ipsec_alg.h ++ ++ ++all_alg_modules: perlasm $(ALG_MODULES) ++ @echo "ALG_MODULES=$(ALG_MODULES)" ++ ++ ++# ++# Construct alg. init. function: call ipsec_ALGO_init() for every static algo ++# Needed when there are static algos (with static or modular ipsec.o) ++# ++static_init.c: $(TOPDIR)/include/linux/autoconf.h Makefile $(makefiles) scripts/mk-static_init.c.sh ++ @echo "Re-creating $@" ++ $(SHELL) scripts/mk-static_init.c.sh $(static_init-func-y) > $@ ++ ++clean: ++ @for i in $(ALG_SUBDIRS);do test -d $$i && make -C $$i clean;done;exit 0 ++ @find . -type l -exec rm -f {} \; ++ -rm -f perlasm ++ -rm -rf $(ALG_SUBDIRS) ++ -rm -f *.o static_init.c ++ ++ifdef TOPDIR ++include $(TOPDIR)/Rules.make ++endif ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/alg/Makefile.alg_aes Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,23 @@ ++MOD_AES := ipsec_aes.o ++ ++ALG_MODULES += $(MOD_AES) ++ALG_SUBDIRS += libaes ++ ++obj-$(CONFIG_IPSEC_ALG_AES) += $(MOD_AES) ++static_init-func-$(CONFIG_IPSEC_ALG_AES)+= ipsec_aes_init ++alg_obj-$(CONFIG_IPSEC_ALG_AES) += ipsec_alg_aes.o ++ ++AES_OBJS := ipsec_alg_aes.o libaes/libaes.a ++ ++$(MOD_AES): libaes $(AES_OBJS) ++ $(LD) $(EXTRA_LDFLAGS) -r $(AES_OBJS) -o $@ ++ ++libaes: $(LIBCRYPTO)/libaes ++ test -d $@ || mkdir $@ ;exit 0 ++ test -d $@/asm || mkdir $@/asm;exit 0 ++ cd $@ && ln -sf $?/Makefile $?/*.[chS] . ++ cd $@/asm && ln -sf $?/asm/*.S . ++ ++libaes/libaes.a: libaes ++ ( cd libaes && \ ++ $(MAKE) CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' libaes.a ;) +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/alg/Makefile.alg_cryptoapi Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,14 @@ ++MOD_CRYPTOAPI := ipsec_cryptoapi.o ++ ++ifneq ($(wildcard $(TOPDIR)/include/linux/crypto.h),) ++ALG_MODULES += $(MOD_CRYPTOAPI) ++obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += $(MOD_CRYPTOAPI) ++static_init-func-$(CONFIG_IPSEC_ALG_CRYPTOAPI)+= ipsec_cryptoapi_init ++alg_obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += ipsec_alg_cryptoapi.o ++else ++$(warning "Linux CryptoAPI (2.4.22+ or 2.6.x) not found, not building ipsec_cryptoapi.o") ++endif ++ ++CRYPTOAPI_OBJS := ipsec_alg_cryptoapi.o ++$(MOD_CRYPTOAPI): $(CRYPTOAPI_OBJS) ++ $(LD) -r $(CRYPTOAPI_OBJS) -o $@ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/alg/ipsec_alg_aes.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,253 @@ ++/* ++ * ipsec_alg AES cipher stubs ++ * ++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar> ++ * ++ * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * Fixes by: ++ * PK: Pawel Krawczyk <kravietz@aba.krakow.pl> ++ * Fixes list: ++ * PK: make XCBC comply with latest draft (keylength) ++ * ++ */ ++#include <linux/config.h> ++#include <linux/version.h> ++ ++/* ++ * special case: ipsec core modular with this static algo inside: ++ * must avoid MODULE magic for this file ++ */ ++#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_AES ++#undef MODULE ++#endif ++ ++#include <linux/module.h> ++#include <linux/init.h> ++ ++#include <linux/kernel.h> /* printk() */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/string.h> ++ ++/* Check if __exit is defined, if not null it */ ++#ifndef __exit ++#define __exit ++#endif ++ ++/* Low freeswan header coupling */ ++#include "freeswan/ipsec_alg.h" ++#include "libaes/aes_cbc.h" ++ ++#define CONFIG_IPSEC_ALG_AES_MAC 1 ++ ++#define AES_CONTEXT_T aes_context ++MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>"); ++static int debug=0; ++MODULE_PARM(debug, "i"); ++static int test=0; ++MODULE_PARM(test, "i"); ++static int excl=0; ++MODULE_PARM(excl, "i"); ++static int keyminbits=0; ++MODULE_PARM(keyminbits, "i"); ++static int keymaxbits=0; ++MODULE_PARM(keymaxbits, "i"); ++ ++#if CONFIG_IPSEC_ALG_AES_MAC ++#include "libaes/aes_xcbc_mac.h" ++ ++/* ++ * Not IANA number yet (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt). ++ * We use 9 for non-modular algorithm and none for modular, thus ++ * forcing user to specify one on module load. -kravietz ++ */ ++#ifdef MODULE ++static int auth_id=0; ++#else ++static int auth_id=9; ++#endif ++MODULE_PARM(auth_id, "i"); ++#endif ++ ++#define ESP_AES 12 /* truely _constant_ :) */ ++ ++/* 128, 192 or 256 */ ++#define ESP_AES_KEY_SZ_MIN 16 /* 128 bit secret key */ ++#define ESP_AES_KEY_SZ_MAX 32 /* 256 bit secret key */ ++#define ESP_AES_CBC_BLK_LEN 16 /* AES-CBC block size */ ++ ++/* Values according to draft-ietf-ipsec-ciph-aes-xcbc-mac-02.txt ++ * -kravietz ++ */ ++#define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ ++#define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ ++ ++static int _aes_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) { ++ int ret; ++ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; ++ ret=AES_set_key(ctx, key, keysize)!=0? 0: -EINVAL; ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:_aes_set_key:" ++ "ret=%d key_e=%p key=%p keysize=%d\n", ++ ret, key_e, key, keysize); ++ return ret; ++} ++static int _aes_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { ++ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:" ++ "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n", ++ key_e, in, ilen, iv, encrypt); ++ return AES_cbc_encrypt(ctx, in, in, ilen, iv, encrypt); ++} ++#if CONFIG_IPSEC_ALG_AES_MAC ++static int _aes_mac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) { ++ aes_context_mac *ctxm=(aes_context_mac *)key_a; ++ return AES_xcbc_mac_set_key(ctxm, key, keylen)? 0 : -EINVAL; ++} ++static int _aes_mac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) { ++ int ret; ++ char hash_buf[16]; ++ aes_context_mac *ctxm=(aes_context_mac *)key_a; ++ ret=AES_xcbc_mac_hash(ctxm, dat, len, hash_buf); ++ memcpy(hash, hash_buf, hashlen); ++ return ret; ++} ++static struct ipsec_alg_auth ipsec_alg_AES_MAC = { ++ ixt_version: IPSEC_ALG_VERSION, ++ ixt_module: THIS_MODULE, ++ ixt_refcnt: ATOMIC_INIT(0), ++ ixt_alg_type: IPSEC_ALG_TYPE_AUTH, ++ ixt_alg_id: 0, ++ ixt_name: "aes_mac", ++ ixt_blocksize: ESP_AES_MAC_BLK_LEN, ++ ixt_keyminbits: ESP_AES_MAC_KEY_SZ*8, ++ ixt_keymaxbits: ESP_AES_MAC_KEY_SZ*8, ++ ixt_a_keylen: ESP_AES_MAC_KEY_SZ, ++ ixt_a_ctx_size: sizeof(aes_context_mac), ++ ixt_a_hmac_set_key: _aes_mac_set_key, ++ ixt_a_hmac_hash:_aes_mac_hash, ++}; ++#endif /* CONFIG_IPSEC_ALG_AES_MAC */ ++static struct ipsec_alg_enc ipsec_alg_AES = { ++ ixt_version: IPSEC_ALG_VERSION, ++ ixt_module: THIS_MODULE, ++ ixt_refcnt: ATOMIC_INIT(0), ++ ixt_alg_type: IPSEC_ALG_TYPE_ENCRYPT, ++ ixt_alg_id: ESP_AES, ++ ixt_name: "aes", ++ ixt_blocksize: ESP_AES_CBC_BLK_LEN, ++ ixt_keyminbits: ESP_AES_KEY_SZ_MIN*8, ++ ixt_keymaxbits: ESP_AES_KEY_SZ_MAX*8, ++ ixt_e_keylen: ESP_AES_KEY_SZ_MAX, ++ ixt_e_ctx_size: sizeof(AES_CONTEXT_T), ++ ixt_e_set_key: _aes_set_key, ++ ixt_e_cbc_encrypt:_aes_cbc_encrypt, ++}; ++ ++IPSEC_ALG_MODULE_INIT( ipsec_aes_init ) ++{ ++ int ret, test_ret; ++ if (keyminbits) ++ ipsec_alg_AES.ixt_keyminbits=keyminbits; ++ if (keymaxbits) { ++ ipsec_alg_AES.ixt_keymaxbits=keymaxbits; ++ if (keymaxbits*8>ipsec_alg_AES.ixt_keymaxbits) ++ ipsec_alg_AES.ixt_e_keylen=keymaxbits*8; ++ } ++ if (excl) ipsec_alg_AES.ixt_state |= IPSEC_ALG_ST_EXCL; ++ ret=register_ipsec_alg_enc(&ipsec_alg_AES); ++ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", ++ ipsec_alg_AES.ixt_alg_type, ++ ipsec_alg_AES.ixt_alg_id, ++ ipsec_alg_AES.ixt_name, ++ ret); ++ if (ret==0 && test) { ++ test_ret=ipsec_alg_test( ++ ipsec_alg_AES.ixt_alg_type, ++ ipsec_alg_AES.ixt_alg_id, ++ test); ++ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", ++ ipsec_alg_AES.ixt_alg_type, ++ ipsec_alg_AES.ixt_alg_id, ++ test_ret); ++ } ++#if CONFIG_IPSEC_ALG_AES_MAC ++ if (auth_id!=0){ ++ int ret; ++ ipsec_alg_AES_MAC.ixt_alg_id=auth_id; ++ ret=register_ipsec_alg_auth(&ipsec_alg_AES_MAC); ++ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", ++ ipsec_alg_AES_MAC.ixt_alg_type, ++ ipsec_alg_AES_MAC.ixt_alg_id, ++ ipsec_alg_AES_MAC.ixt_name, ++ ret); ++ if (ret==0 && test) { ++ test_ret=ipsec_alg_test( ++ ipsec_alg_AES_MAC.ixt_alg_type, ++ ipsec_alg_AES_MAC.ixt_alg_id, ++ test); ++ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", ++ ipsec_alg_AES_MAC.ixt_alg_type, ++ ipsec_alg_AES_MAC.ixt_alg_id, ++ test_ret); ++ } ++ } else { ++ printk(KERN_DEBUG "klips_debug: experimental ipsec_alg_AES_MAC not registered [Ok] (auth_id=%d)\n", auth_id); ++ } ++#endif /* CONFIG_IPSEC_ALG_AES_MAC */ ++ return ret; ++} ++IPSEC_ALG_MODULE_EXIT( ipsec_aes_fini ) ++{ ++#if CONFIG_IPSEC_ALG_AES_MAC ++ if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC); ++#endif /* CONFIG_IPSEC_ALG_AES_MAC */ ++ unregister_ipsec_alg_enc(&ipsec_alg_AES); ++ return; ++} ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif ++ ++#if 0+NOT_YET ++#ifndef MODULE ++/* ++ * This is intended for static module setups, currently ++ * doesn't work for modular ipsec.o with static algos inside ++ */ ++static int setup_keybits(const char *str) ++{ ++ unsigned aux; ++ char *end; ++ ++ aux = simple_strtoul(str,&end,0); ++ if (aux != 128 && aux != 192 && aux != 256) ++ return 0; ++ keyminbits = aux; ++ ++ if (*end == 0 || *end != ',') ++ return 1; ++ str=end+1; ++ aux = simple_strtoul(str, NULL, 0); ++ if (aux != 128 && aux != 192 && aux != 256) ++ return 0; ++ if (aux >= keyminbits) ++ keymaxbits = aux; ++ return 1; ++} ++__setup("ipsec_aes_keybits=", setup_keybits); ++#endif ++#endif ++EXPORT_NO_SYMBOLS; +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/alg/ipsec_alg_cryptoapi.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,421 @@ ++/* ++ * ipsec_alg to linux cryptoapi GLUE ++ * ++ * Authors: CODE.ar TEAM ++ * Harpo MAxx <harpo@linuxmendoza.org.ar> ++ * JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar> ++ * Luciano Ruete <docemeses@softhome.net> ++ * ++ * ipsec_alg_cryptoapi.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * Example usage: ++ * modinfo -p ipsec_cryptoapi (quite useful info, including supported algos) ++ * modprobe ipsec_cryptoapi ++ * modprobe ipsec_cryptoapi test=1 ++ * modprobe ipsec_cryptoapi excl=1 (exclusive cipher/algo) ++ * modprobe ipsec_cryptoapi noauto=1 aes=1 twofish=1 (only these ciphers) ++ * modprobe ipsec_cryptoapi aes=128,128 (force these keylens) ++ * modprobe ipsec_cryptoapi des_ede3=0 (everything but 3DES) ++ */ ++#include <linux/config.h> ++#include <linux/version.h> ++ ++/* ++ * special case: ipsec core modular with this static algo inside: ++ * must avoid MODULE magic for this file ++ */ ++#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CRYPTOAPI ++#undef MODULE ++#endif ++ ++#include <linux/module.h> ++#include <linux/init.h> ++ ++#include <linux/kernel.h> /* printk() */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/string.h> ++ ++/* Check if __exit is defined, if not null it */ ++#ifndef __exit ++#define __exit ++#endif ++ ++/* warn the innocent */ ++#if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE) ++#warning "No linux CryptoAPI found, install 2.4.22+ or 2.6.x" ++#define NO_CRYPTOAPI_SUPPORT ++#endif ++/* Low freeswan header coupling */ ++#include "freeswan/ipsec_alg.h" ++ ++#include <linux/crypto.h> ++#ifdef CRYPTO_API_VERSION_CODE ++#warning "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported" ++#define NO_CRYPTOAPI_SUPPORT ++#endif ++ ++#ifdef NO_CRYPTOAPI_SUPPORT ++#warning "Building an unusable module :P" ++/* Catch old CryptoAPI by not allowing module to load */ ++IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init ) ++{ ++ printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n"); ++ return -EINVAL; ++} ++#else ++#include <asm/scatterlist.h> ++#include <asm/pgtable.h> ++#include <linux/mm.h> ++ ++#define CIPHERNAME_AES "aes" ++#define CIPHERNAME_3DES "des3_ede" ++#define CIPHERNAME_BLOWFISH "blowfish" ++#define CIPHERNAME_CAST "cast5" ++#define CIPHERNAME_SERPENT "serpent" ++#define CIPHERNAME_TWOFISH "twofish" ++ ++#define ESP_3DES 3 ++#define ESP_AES 12 ++#define ESP_BLOWFISH 7 /* truely _constant_ :) */ ++#define ESP_CAST 6 /* quite constant :) */ ++#define ESP_SERPENT 252 /* from ipsec drafts */ ++#define ESP_TWOFISH 253 /* from ipsec drafts */ ++ ++#define AH_MD5 2 ++#define AH_SHA 3 ++#define DIGESTNAME_MD5 "md5" ++#define DIGESTNAME_SHA1 "sha1" ++ ++MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); ++static int debug=0; ++MODULE_PARM(debug, "i"); ++static int test=0; ++MODULE_PARM(test, "i"); ++static int excl=0; ++MODULE_PARM(excl, "i"); ++ ++static int noauto = 0; ++MODULE_PARM(noauto,"i"); ++MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones"); ++ ++static int des_ede3[] = {-1, -1}; ++static int aes[] = {-1, -1}; ++static int blowfish[] = {-1, -1}; ++static int cast[] = {-1, -1}; ++static int serpent[] = {-1, -1}; ++static int twofish[] = {-1, -1}; ++ ++MODULE_PARM(des_ede3,"1-2i"); ++MODULE_PARM(aes,"1-2i"); ++MODULE_PARM(blowfish,"1-2i"); ++MODULE_PARM(cast,"1-2i"); ++MODULE_PARM(serpent,"1-2i"); ++MODULE_PARM(twofish,"1-2i"); ++MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse"); ++MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens"); ++MODULE_PARM_DESC(blowfish, "0: disable | 1: force_enable | min,max: keybitlens"); ++MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens"); ++MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens"); ++MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens"); ++ ++struct ipsec_alg_capi_cipher { ++ const char *ciphername; /* cryptoapi's ciphername */ ++ unsigned blocksize; ++ unsigned short minbits; ++ unsigned short maxbits; ++ int *parm; /* lkm param for this cipher */ ++ struct ipsec_alg_enc alg; /* note it's not a pointer */ ++}; ++static struct ipsec_alg_capi_cipher alg_capi_carray[] = { ++ { CIPHERNAME_AES , 16, 128, 256, aes , { ixt_alg_id: ESP_AES, }}, ++ { CIPHERNAME_TWOFISH , 16, 128, 256, twofish, { ixt_alg_id: ESP_TWOFISH, }}, ++ { CIPHERNAME_SERPENT , 16, 128, 256, serpent, { ixt_alg_id: ESP_SERPENT, }}, ++ { CIPHERNAME_CAST , 8, 128, 128, cast , { ixt_alg_id: ESP_CAST, }}, ++ { CIPHERNAME_BLOWFISH , 8, 96, 448, blowfish,{ ixt_alg_id: ESP_BLOWFISH, }}, ++ { CIPHERNAME_3DES , 8, 192, 192, des_ede3,{ ixt_alg_id: ESP_3DES, }}, ++ { NULL, 0, 0, 0, NULL, {} } ++}; ++#ifdef NOT_YET ++struct ipsec_alg_capi_digest { ++ const char *digestname; /* cryptoapi's digestname */ ++ struct digest_implementation *di; ++ struct ipsec_alg_auth alg; /* note it's not a pointer */ ++}; ++static struct ipsec_alg_capi_cipher alg_capi_darray[] = { ++ { DIGESTNAME_MD5, NULL, { ixt_alg_id: AH_MD5, }}, ++ { DIGESTNAME_SHA1, NULL, { ixt_alg_id: AH_SHA, }}, ++ { NULL, NULL, {} } ++}; ++#endif ++/* ++ * "generic" linux cryptoapi setup_cipher() function ++ */ ++int setup_cipher(const char *ciphername) ++{ ++ return crypto_alg_available(ciphername, 0); ++} ++ ++/* ++ * setups ipsec_alg_capi_cipher "hyper" struct components, calling ++ * register_ipsec_alg for cointaned ipsec_alg object ++ */ ++static void _capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e); ++static __u8 * _capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen); ++static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt); ++ ++static int ++setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr) ++{ ++ int ret; ++ cptr->alg.ixt_version = IPSEC_ALG_VERSION; ++ cptr->alg.ixt_module = THIS_MODULE; ++ atomic_set (& cptr->alg.ixt_refcnt, 0); ++ strncpy (cptr->alg.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_name)); ++ ++ cptr->alg.ixt_blocksize=cptr->blocksize; ++ cptr->alg.ixt_keyminbits=cptr->minbits; ++ cptr->alg.ixt_keymaxbits=cptr->maxbits; ++ cptr->alg.ixt_state = 0; ++ if (excl) cptr->alg.ixt_state |= IPSEC_ALG_ST_EXCL; ++ cptr->alg.ixt_e_keylen=cptr->alg.ixt_keymaxbits/8; ++ cptr->alg.ixt_e_ctx_size = 0; ++ cptr->alg.ixt_alg_type = IPSEC_ALG_TYPE_ENCRYPT; ++ cptr->alg.ixt_e_new_key = _capi_new_key; ++ cptr->alg.ixt_e_destroy_key = _capi_destroy_key; ++ cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt; ++ cptr->alg.ixt_data = cptr; ++ ++ ret=register_ipsec_alg_enc(&cptr->alg); ++ printk("setup_ipsec_alg_capi_cipher(): " ++ "alg_type=%d alg_id=%d name=%s " ++ "keyminbits=%d keymaxbits=%d, ret=%d\n", ++ cptr->alg.ixt_alg_type, ++ cptr->alg.ixt_alg_id, ++ cptr->alg.ixt_name, ++ cptr->alg.ixt_keyminbits, ++ cptr->alg.ixt_keymaxbits, ++ ret); ++ return ret; ++} ++/* ++ * called in ipsec_sa_wipe() time, will destroy key contexts ++ * and do 1 unbind() ++ */ ++static void ++_capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e) ++{ ++ struct crypto_tfm *tfm=(struct crypto_tfm*)key_e; ++ ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" ++ "name=%s key_e=%p \n", ++ alg->ixt_name, key_e); ++ if (!key_e) { ++ printk(KERN_ERR "klips_debug: _capi_destroy_key:" ++ "name=%s NULL key_e!\n", ++ alg->ixt_name); ++ return; ++ } ++ crypto_free_tfm(tfm); ++} ++ ++/* ++ * create new key context, need alg->ixt_data to know which ++ * (of many) cipher inside this module is the target ++ */ ++static __u8 * ++_capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen) ++{ ++ struct ipsec_alg_capi_cipher *cptr; ++ struct crypto_tfm *tfm=NULL; ++ ++ cptr = alg->ixt_data; ++ if (!cptr) { ++ printk(KERN_ERR "_capi_new_key(): " ++ "NULL ixt_data (?!) for \"%s\" algo\n" ++ , alg->ixt_name); ++ goto err; ++ } ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:_capi_new_key:" ++ "name=%s cptr=%p key=%p keysize=%d\n", ++ alg->ixt_name, cptr, key, keylen); ++ ++ /* ++ * alloc tfm ++ */ ++ tfm = crypto_alloc_tfm(cptr->ciphername, CRYPTO_TFM_MODE_CBC); ++ if (!tfm) { ++ printk(KERN_ERR "_capi_new_key(): " ++ "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n" ++ , alg->ixt_name, cptr->ciphername); ++ goto err; ++ } ++ if (crypto_cipher_setkey(tfm, key, keylen) < 0) { ++ printk(KERN_ERR "_capi_new_key(): " ++ "failed new_key() for \"%s\" cryptoapi algo (keylen=%d)\n" ++ , alg->ixt_name, keylen); ++ crypto_free_tfm(tfm); ++ tfm=NULL; ++ } ++err: ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:_capi_new_key:" ++ "name=%s key=%p keylen=%d tfm=%p\n", ++ alg->ixt_name, key, keylen, tfm); ++ return (__u8 *) tfm; ++} ++/* ++ * core encryption function: will use cx->ci to call actual cipher's ++ * cbc function ++ */ ++static int ++_capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { ++ int error =0; ++ struct crypto_tfm *tfm=(struct crypto_tfm *)key_e; ++ struct scatterlist sg = { ++ .page = virt_to_page(in), ++ .offset = (unsigned long)(in) % PAGE_SIZE, ++ .length=ilen, ++ }; ++ if (debug > 1) ++ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" ++ "key_e=%p " ++ "in=%p out=%p ilen=%d iv=%p encrypt=%d\n" ++ , key_e ++ , in, in, ilen, iv, encrypt); ++ crypto_cipher_set_iv(tfm, iv, crypto_tfm_alg_ivsize(tfm)); ++ if (encrypt) ++ error = crypto_cipher_encrypt (tfm, &sg, &sg, ilen); ++ else ++ error = crypto_cipher_decrypt (tfm, &sg, &sg, ilen); ++ if (debug > 1) ++ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" ++ "error=%d\n" ++ , error); ++ return (error<0)? error : ilen; ++} ++/* ++ * main initialization loop: for each cipher in list, do ++ * 1) setup cryptoapi cipher else continue ++ * 2) register ipsec_alg object ++ */ ++static int ++setup_cipher_list (struct ipsec_alg_capi_cipher* clist) ++{ ++ struct ipsec_alg_capi_cipher *cptr; ++ /* foreach cipher in list ... */ ++ for (cptr=clist;cptr->ciphername;cptr++) { ++ /* ++ * see if cipher has been disabled (0) or ++ * if noauto set and not enabled (1) ++ */ ++ if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) { ++ if (debug>0) ++ printk(KERN_INFO "setup_cipher_list(): " ++ "ciphername=%s skipped at user request: " ++ "noauto=%d parm[0]=%d parm[1]=%d\n" ++ , cptr->ciphername ++ , noauto ++ , cptr->parm[0] ++ , cptr->parm[1]); ++ continue; ++ } ++ /* ++ * use a local ci to avoid touching cptr->ci, ++ * if register ipsec_alg success then bind cipher ++ */ ++ if( setup_cipher(cptr->ciphername) ) { ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:" ++ "setup_cipher_list():" ++ "ciphername=%s found\n" ++ , cptr->ciphername); ++ if (setup_ipsec_alg_capi_cipher(cptr) == 0) { ++ ++ ++ } else { ++ printk(KERN_ERR "klips_debug:" ++ "setup_cipher_list():" ++ "ciphername=%s failed ipsec_alg_register\n" ++ , cptr->ciphername); ++ } ++ } else { ++ if (debug>0) ++ printk(KERN_INFO "setup_cipher_list(): lookup for ciphername=%s: not found \n", ++ cptr->ciphername); ++ } ++ } ++ return 0; ++} ++/* ++ * deregister ipsec_alg objects and unbind ciphers ++ */ ++static int ++unsetup_cipher_list (struct ipsec_alg_capi_cipher* clist) ++{ ++ struct ipsec_alg_capi_cipher *cptr; ++ /* foreach cipher in list ... */ ++ for (cptr=clist;cptr->ciphername;cptr++) { ++ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { ++ unregister_ipsec_alg_enc(&cptr->alg); ++ } ++ } ++ return 0; ++} ++/* ++ * test loop for registered algos ++ */ ++static int ++test_cipher_list (struct ipsec_alg_capi_cipher* clist) ++{ ++ int test_ret; ++ struct ipsec_alg_capi_cipher *cptr; ++ /* foreach cipher in list ... */ ++ for (cptr=clist;cptr->ciphername;cptr++) { ++ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { ++ test_ret=ipsec_alg_test( ++ cptr->alg.ixt_alg_type, ++ cptr->alg.ixt_alg_id, ++ test); ++ printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", ++ cptr->alg.ixt_alg_type, ++ cptr->alg.ixt_alg_id, ++ test_ret); ++ } ++ } ++ return 0; ++} ++ ++IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init ) ++{ ++ int ret, test_ret; ++ if ((ret=setup_cipher_list(alg_capi_carray)) < 0) ++ return -EPROTONOSUPPORT; ++ if (ret==0 && test) { ++ test_ret=test_cipher_list(alg_capi_carray); ++ } ++ return ret; ++} ++IPSEC_ALG_MODULE_EXIT( ipsec_cryptoapi_fini ) ++{ ++ unsetup_cipher_list(alg_capi_carray); ++ return; ++} ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif ++ ++EXPORT_NO_SYMBOLS; ++#endif /* NO_CRYPTOAPI_SUPPORT */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/alg/scripts/mk-static_init.c.sh Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,18 @@ ++#!/bin/sh ++cat << EOF ++#include <linux/kernel.h> ++#include <linux/list.h> ++#include "freeswan/ipsec_alg.h" ++$(for i in $*; do ++ test -z "$i" && continue ++ echo "extern int $i(void);" ++done) ++void ipsec_alg_static_init(void){ ++ int __attribute__ ((unused)) err=0; ++$(for i in $*; do ++ test -z "$i" && continue ++ echo " if ((err=$i()) < 0)" ++ echo " printk(KERN_WARNING \"$i() returned %d\", err);" ++done) ++} ++EOF +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/defconfig Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,146 @@ ++ ++# ++# RCSID $Id: defconfig,v 1.25 2004/07/05 01:03:53 mcr Exp $ ++# ++ ++# ++# FreeS/WAN IPSec implementation, KLIPS kernel config defaults ++# ++ ++# ++# First, lets override stuff already set or not in the kernel config. ++# ++# We can't even think about leaving this off... ++CONFIG_INET=y ++ ++# ++# This must be on for subnet protection. ++CONFIG_IP_FORWARD=y ++ ++# Shut off IPSEC masquerading if it has been enabled, since it will ++# break the compile. IPPROTO_ESP and IPPROTO_AH were included in ++# net/ipv4/ip_masq.c when they should have gone into include/linux/in.h. ++CONFIG_IP_MASQUERADE_IPSEC=n ++ ++# ++# Next, lets set the recommended FreeS/WAN configuration. ++# ++ ++# To config as static (preferred), 'y'. To config as module, 'm'. ++CONFIG_IPSEC=y ++ ++# To do tunnel mode IPSec, this must be enabled. ++CONFIG_IPSEC_IPIP=y ++ ++# To enable authentication, say 'y'. (Highly recommended) ++CONFIG_IPSEC_AH=y ++ ++# Authentication algorithm(s): ++CONFIG_IPSEC_AUTH_HMAC_MD5=y ++CONFIG_IPSEC_AUTH_HMAC_SHA1=y ++ ++# To enable encryption, say 'y'. (Highly recommended) ++CONFIG_IPSEC_ESP=y ++ ++# Encryption algorithm(s): ++CONFIG_IPSEC_ENC_3DES=y ++CONFIG_IPSEC_ENC_AES=y ++ ++# modular algo extensions (and new ALGOs) ++CONFIG_IPSEC_ALG=y ++CONFIG_IPSEC_ENC_3DES=y ++CONFIG_IPSEC_ENC_AES=y ++ ++CONFIG_IPSEC_ALG_TWOFISH=m ++CONFIG_IPSEC_ALG_BLOWFISH=m ++CONFIG_IPSEC_ALG_SERPENT=m ++CONFIG_IPSEC_ALG_MD5=m ++CONFIG_IPSEC_ALG_SHA1=m ++CONFIG_IPSEC_ALG_SHA2=m ++#CONFIG_IPSEC_ALG_CAST=n ++#CONFIG_IPSEC_ALG_NULL=n ++ ++# Use CryptoAPI for ALG? - by default, no. ++CONFIG_IPSEC_ENC_CRYPTOAPI=n ++ ++ ++# IP Compression: new, probably still has minor bugs. ++CONFIG_IPSEC_IPCOMP=y ++ ++# To enable userspace-switchable KLIPS debugging, say 'y'. ++CONFIG_IPSEC_DEBUG=y ++ ++# NAT Traversal ++CONFIG_IPSEC_NAT_TRAVERSAL=y ++ ++# ++# ++# $Log: defconfig,v $ ++# Revision 1.25 2004/07/05 01:03:53 mcr ++# fix for adding cryptoapi code. ++# keep it off for now, since UMLs do not have it yet. ++# ++# Revision 1.24 2004/04/06 02:49:25 mcr ++# pullup of algo code from alg-branch. ++# ++# Revision 1.23.2.2 2004/04/05 04:30:46 mcr ++# patches for alg-branch to compile/work with 2.x openswan ++# ++# Revision 1.23.2.1 2003/12/22 15:25:52 jjo ++# . Merged algo-0.8.1-rc11-test1 into alg-branch ++# ++# Revision 1.23 2003/12/10 01:14:27 mcr ++# NAT-traversal patches to KLIPS. ++# ++# Revision 1.22 2003/02/24 19:37:27 mcr ++# changed default compilation mode to static. ++# ++# Revision 1.21 2002/04/24 07:36:27 mcr ++# Moved from ./klips/net/ipsec/defconfig,v ++# ++# Revision 1.20 2002/04/02 04:07:40 mcr ++# default build is now 'm'odule for KLIPS ++# ++# Revision 1.19 2002/03/08 18:57:17 rgb ++# Added a blank line at the beginning of the file to make it easier for ++# other projects to patch ./arch/i386/defconfig, for example ++# LIDS+grSecurity requested by Jason Pattie. ++# ++# Revision 1.18 2000/11/30 17:26:56 rgb ++# Cleaned out unused options and enabled ipcomp by default. ++# ++# Revision 1.17 2000/09/15 11:37:01 rgb ++# Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk> ++# IPCOMP zlib deflate code. ++# ++# Revision 1.16 2000/09/08 19:12:55 rgb ++# Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++# ++# Revision 1.15 2000/05/24 19:37:13 rgb ++# *** empty log message *** ++# ++# Revision 1.14 2000/05/11 21:14:57 henry ++# just commenting the FOOBAR=y lines out is not enough ++# ++# Revision 1.13 2000/05/10 20:17:58 rgb ++# Comment out netlink defaults, which are no longer needed. ++# ++# Revision 1.12 2000/05/10 19:13:38 rgb ++# Added configure option to shut off no eroute passthrough. ++# ++# Revision 1.11 2000/03/16 07:09:46 rgb ++# Hardcode PF_KEYv2 support. ++# Disable IPSEC_ICMP by default. ++# Remove DES config option from defaults file. ++# ++# Revision 1.10 2000/01/11 03:09:42 rgb ++# Added a default of 'y' to PF_KEYv2 keying I/F. ++# ++# Revision 1.9 1999/05/08 21:23:12 rgb ++# Added support for 2.2.x kernels. ++# ++# Revision 1.8 1999/04/06 04:54:25 rgb ++# Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++# patch shell fixes. ++# ++# +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipcomp.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,725 @@ ++/* ++ * IPCOMP zlib interface code. ++ * Copyright (C) 2000 Svenning Soerensen <svenning@post5.tele.dk> ++ * Copyright (C) 2000, 2001 Richard Guy Briggs <rgb@conscoop.ottawa.on.ca> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++char ipcomp_c_version[] = "RCSID $Id: ipcomp.c,v 1.36 2004/04/06 02:49:25 mcr Exp $"; ++ ++/* SSS */ ++ ++#include <linux/config.h> ++#include <linux/version.h> ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> ++#include <linux/netdevice.h> ++#include <linux/ip.h> ++#include <linux/skbuff.h> ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++ ++#include <openswan.h> ++ ++#ifdef NET_21 ++# include <net/dst.h> ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define proto_priv cb ++#endif /* NET21 */ ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */ ++#include "openswan/ipcomp.h" ++#include "zlib/zlib.h" ++#include "zlib/zutil.h" ++ ++#include <pfkeyv2.h> /* SADB_X_CALG_DEFLATE */ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int sysctl_ipsec_debug_ipcomp = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++static ++struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask); ++ ++static ++voidpf my_zcalloc(voidpf opaque, uInt items, uInt size) ++{ ++ return (voidpf) kmalloc(items*size, GFP_ATOMIC); ++} ++ ++static ++void my_zfree(voidpf opaque, voidpf address) ++{ ++ kfree(address); ++} ++ ++struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags) ++{ ++ struct iphdr *iph; ++ unsigned int iphlen, pyldsz, cpyldsz; ++ unsigned char *buffer; ++ z_stream zs; ++ int zresult; ++ ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: .\n"); ++ ++ if(skb == NULL) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "passed in NULL skb, returning ERROR.\n"); ++ if(flags != NULL) { ++ *flags |= IPCOMP_PARMERROR; ++ } ++ return skb; ++ } ++ ++ if(ips == NULL) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "passed in NULL ipsec_sa needed for cpi, returning ERROR.\n"); ++ if(flags) { ++ *flags |= IPCOMP_PARMERROR; ++ } ++ return skb; ++ } ++ ++ if (flags == NULL) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "passed in NULL flags, returning ERROR.\n"); ++ ipsec_kfree_skb(skb); ++ return NULL; ++ } ++ ++#ifdef NET_21 ++ iph = skb->nh.iph; ++#else /* NET_21 */ ++ iph = skb->ip_hdr; ++#endif /* NET_21 */ ++ ++ switch (iph->protocol) { ++ case IPPROTO_COMP: ++ case IPPROTO_AH: ++ case IPPROTO_ESP: ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "skipping compression of packet with ip protocol %d.\n", ++ iph->protocol); ++ *flags |= IPCOMP_UNCOMPRESSABLE; ++ return skb; ++ } ++ ++ /* Don't compress packets already fragmented */ ++ if (iph->frag_off & __constant_htons(IP_MF | IP_OFFSET)) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "skipping compression of fragmented packet.\n"); ++ *flags |= IPCOMP_UNCOMPRESSABLE; ++ return skb; ++ } ++ ++ iphlen = iph->ihl << 2; ++ pyldsz = ntohs(iph->tot_len) - iphlen; ++ ++ /* Don't compress less than 90 bytes (rfc 2394) */ ++ if (pyldsz < 90) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "skipping compression of tiny packet, len=%d.\n", ++ pyldsz); ++ *flags |= IPCOMP_UNCOMPRESSABLE; ++ return skb; ++ } ++ ++ /* Adaptive decision */ ++ if (ips->ips_comp_adapt_skip) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "skipping compression: ips_comp_adapt_skip=%d.\n", ++ ips->ips_comp_adapt_skip); ++ ips->ips_comp_adapt_skip--; ++ *flags |= IPCOMP_UNCOMPRESSABLE; ++ return skb; ++ } ++ ++ zs.zalloc = my_zcalloc; ++ zs.zfree = my_zfree; ++ zs.opaque = 0; ++ ++ /* We want to use deflateInit2 because we don't want the adler ++ header. */ ++ zresult = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -11, ++ DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); ++ if (zresult != Z_OK) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_compress: " ++ "deflateInit2() returned error %d (%s), " ++ "skipping compression.\n", ++ zresult, ++ zs.msg ? zs.msg : zError(zresult)); ++ *flags |= IPCOMP_COMPRESSIONERROR; ++ return skb; ++ } ++ ++ ++ /* Max output size. Result should be max this size. ++ * Implementation specific tweak: ++ * If it's not at least 32 bytes and 6.25% smaller than ++ * the original packet, it's probably not worth wasting ++ * the receiver's CPU cycles decompressing it. ++ * Your mileage may vary. ++ */ ++ cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4); ++ ++ buffer = kmalloc(cpyldsz, GFP_ATOMIC); ++ if (!buffer) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_compress: " ++ "unable to kmalloc(%d, GFP_ATOMIC), " ++ "skipping compression.\n", ++ cpyldsz); ++ *flags |= IPCOMP_COMPRESSIONERROR; ++ deflateEnd(&zs); ++ return skb; ++ } ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { ++ __u8 *c; ++ int i; ++ ++ c = (__u8*)iph + iphlen; ++ for(i = 0; i < pyldsz; i++, c++) { ++ if(!(i % 16)) { ++ printk(KERN_INFO "skb_compress: before:"); ++ } ++ printk("%02x ", *c); ++ if(!((i + 1) % 16)) { ++ printk("\n"); ++ } ++ } ++ if(i % 16) { ++ printk("\n"); ++ } ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ zs.next_in = (char *) iph + iphlen; /* start of payload */ ++ zs.avail_in = pyldsz; ++ zs.next_out = buffer; /* start of compressed payload */ ++ zs.avail_out = cpyldsz; ++ ++ /* Finish compression in one step */ ++ zresult = deflate(&zs, Z_FINISH); ++ ++ /* Free all dynamically allocated buffers */ ++ deflateEnd(&zs); ++ if (zresult != Z_STREAM_END) { ++ *flags |= IPCOMP_UNCOMPRESSABLE; ++ kfree(buffer); ++ ++ /* Adjust adaptive counters */ ++ if (++(ips->ips_comp_adapt_tries) == IPCOMP_ADAPT_INITIAL_TRIES) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "first %d packets didn't compress, " ++ "skipping next %d\n", ++ IPCOMP_ADAPT_INITIAL_TRIES, ++ IPCOMP_ADAPT_INITIAL_SKIP); ++ ips->ips_comp_adapt_skip = IPCOMP_ADAPT_INITIAL_SKIP; ++ } ++ else if (ips->ips_comp_adapt_tries == IPCOMP_ADAPT_INITIAL_TRIES + IPCOMP_ADAPT_SUBSEQ_TRIES) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "next %d packets didn't compress, " ++ "skipping next %d\n", ++ IPCOMP_ADAPT_SUBSEQ_TRIES, ++ IPCOMP_ADAPT_SUBSEQ_SKIP); ++ ips->ips_comp_adapt_skip = IPCOMP_ADAPT_SUBSEQ_SKIP; ++ ips->ips_comp_adapt_tries = IPCOMP_ADAPT_INITIAL_TRIES; ++ } ++ ++ return skb; ++ } ++ ++ /* resulting compressed size */ ++ cpyldsz -= zs.avail_out; ++ ++ /* Insert IPCOMP header */ ++ ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_nh = iph->protocol; ++ ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_flags = 0; ++ /* use the bottom 16 bits of the spi for the cpi. The top 16 bits are ++ for internal reference only. */ ++ ((struct ipcomphdr*) (((char*)iph) + iphlen))->ipcomp_cpi = htons((__u16)(ntohl(ips->ips_said.spi) & 0x0000ffff)); ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_compress: " ++ "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: raw=%d, comp=%d.\n", ++ ntohl(ips->ips_said.spi), ++ ntohl(ips->ips_said.spi) & 0x0000ffff, ++ ntohs(((struct ipcomphdr*)(((char*)iph)+iphlen))->ipcomp_cpi), ++ pyldsz, ++ cpyldsz); ++ ++ /* Update IP header */ ++ iph->protocol = IPPROTO_COMP; ++ iph->tot_len = htons(iphlen + sizeof(struct ipcomphdr) + cpyldsz); ++#if 1 /* XXX checksum is done by ipsec_tunnel ? */ ++ iph->check = 0; ++ iph->check = ip_fast_csum((char *) iph, iph->ihl); ++#endif ++ ++ /* Copy compressed payload */ ++ memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr), ++ buffer, ++ cpyldsz); ++ kfree(buffer); ++ ++ /* Update skb length/tail by "unputting" the shrinkage */ ++ skb_put(skb, ++ cpyldsz + sizeof(struct ipcomphdr) - pyldsz); ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { ++ __u8 *c; ++ int i; ++ ++ c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr); ++ for(i = 0; i < cpyldsz; i++, c++) { ++ if(!(i % 16)) { ++ printk(KERN_INFO "skb_compress: result:"); ++ } ++ printk("%02x ", *c); ++ if(!((i + 1) % 16)) { ++ printk("\n"); ++ } ++ } ++ if(i % 16) { ++ printk("\n"); ++ } ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ ips->ips_comp_adapt_skip = 0; ++ ips->ips_comp_adapt_tries = 0; ++ ++ return skb; ++} ++ ++struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags) ++{ ++ struct sk_buff *nskb = NULL; ++ ++ /* original ip header */ ++ struct iphdr *oiph, *iph; ++ unsigned int iphlen, pyldsz, cpyldsz; ++ z_stream zs; ++ int zresult; ++ ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_decompress: .\n"); ++ ++ if(!skb) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "passed in NULL skb, returning ERROR.\n"); ++ if (flags) *flags |= IPCOMP_PARMERROR; ++ return skb; ++ } ++ ++ if(!ips && sysctl_ipsec_inbound_policy_check) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "passed in NULL ipsec_sa needed for comp alg, returning ERROR.\n"); ++ if (flags) *flags |= IPCOMP_PARMERROR; ++ return skb; ++ } ++ ++ if (!flags) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "passed in NULL flags, returning ERROR.\n"); ++ ipsec_kfree_skb(skb); ++ return NULL; ++ } ++ ++#ifdef NET_21 ++ oiph = skb->nh.iph; ++#else /* NET_21 */ ++ oiph = skb->ip_hdr; ++#endif /* NET_21 */ ++ ++ iphlen = oiph->ihl << 2; ++ ++ if (oiph->protocol != IPPROTO_COMP) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "called with non-IPCOMP packet (protocol=%d)," ++ "skipping decompression.\n", ++ oiph->protocol); ++ *flags |= IPCOMP_PARMERROR; ++ return skb; ++ } ++ ++ if ( (((struct ipcomphdr*)((char*) oiph + iphlen))->ipcomp_flags != 0) ++ || ((((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi ++ != htons(SADB_X_CALG_DEFLATE)) ++ && sysctl_ipsec_inbound_policy_check ++ && (!ips || (ips && (ips->ips_encalg != SADB_X_CALG_DEFLATE)))) ) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "called with incompatible IPCOMP packet (flags=%d, " ++ "cpi=%d), ips-compalg=%d, skipping decompression.\n", ++ ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_flags), ++ ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi), ++ ips ? ips->ips_encalg : 0); ++ *flags |= IPCOMP_PARMERROR; ++ ++ return skb; ++ } ++ ++ if (ntohs(oiph->frag_off) & ~0x4000) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "called with fragmented IPCOMP packet, " ++ "skipping decompression.\n"); ++ *flags |= IPCOMP_PARMERROR; ++ return skb; ++ } ++ ++ /* original compressed payload size */ ++ cpyldsz = ntohs(oiph->tot_len) - iphlen - sizeof(struct ipcomphdr); ++ ++ zs.zalloc = my_zcalloc; ++ zs.zfree = my_zfree; ++ zs.opaque = 0; ++ ++ zs.next_in = (char *) oiph + iphlen + sizeof(struct ipcomphdr); ++ zs.avail_in = cpyldsz; ++ ++ /* Maybe we should be a bit conservative about memory ++ requirements and use inflateInit2 */ ++ /* Beware, that this might make us unable to decompress packets ++ from other implementations - HINT: check PGPnet source code */ ++ /* We want to use inflateInit2 because we don't want the adler ++ header. */ ++ zresult = inflateInit2(&zs, -15); ++ if (zresult != Z_OK) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "inflateInit2() returned error %d (%s), " ++ "skipping decompression.\n", ++ zresult, ++ zs.msg ? zs.msg : zError(zresult)); ++ *flags |= IPCOMP_DECOMPRESSIONERROR; ++ ++ return skb; ++ } ++ ++ /* We have no way of knowing the exact length of the resulting ++ decompressed output before we have actually done the decompression. ++ For now, we guess that the packet will not be bigger than the ++ attached ipsec device's mtu or 16260, whichever is biggest. ++ This may be wrong, since the sender's mtu may be bigger yet. ++ XXX This must be dealt with later XXX ++ */ ++ ++ /* max payload size */ ++ pyldsz = skb->dev ? (skb->dev->mtu < 16260 ? 16260 : skb->dev->mtu) ++ : (65520 - iphlen); ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_decompress: " ++ "max payload size: %d\n", pyldsz); ++ ++ while (pyldsz > (cpyldsz + sizeof(struct ipcomphdr)) && ++ (nskb = skb_copy_ipcomp(skb, ++ pyldsz - cpyldsz - sizeof(struct ipcomphdr), ++ GFP_ATOMIC)) == NULL) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "unable to skb_copy_ipcomp(skb, %d, GFP_ATOMIC), " ++ "trying with less payload size.\n", ++ (int)(pyldsz - cpyldsz - sizeof(struct ipcomphdr))); ++ pyldsz >>=1; ++ } ++ ++ if (!nskb) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "unable to allocate memory, dropping packet.\n"); ++ *flags |= IPCOMP_DECOMPRESSIONERROR; ++ inflateEnd(&zs); ++ ++ return skb; ++ } ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { ++ __u8 *c; ++ int i; ++ ++ c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr); ++ for(i = 0; i < cpyldsz; i++, c++) { ++ if(!(i % 16)) { ++ printk(KERN_INFO "skb_decompress: before:"); ++ } ++ printk("%02x ", *c); ++ if(!((i + 1) % 16)) { ++ printk("\n"); ++ } ++ } ++ if(i % 16) { ++ printk("\n"); ++ } ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++#ifdef NET_21 ++ iph = nskb->nh.iph; ++#else /* NET_21 */ ++ iph = nskb->ip_hdr; ++#endif /* NET_21 */ ++ zs.next_out = (char *)iph + iphlen; ++ zs.avail_out = pyldsz; ++ ++ zresult = inflate(&zs, Z_SYNC_FLUSH); ++ ++ /* work around a bug in zlib, which sometimes wants to taste an extra ++ * byte when being used in the (undocumented) raw deflate mode. ++ */ ++ if (zresult == Z_OK && !zs.avail_in && zs.avail_out) { ++ __u8 zerostuff = 0; ++ ++ zs.next_in = &zerostuff; ++ zs.avail_in = 1; ++ zresult = inflate(&zs, Z_FINISH); ++ } ++ ++ inflateEnd(&zs); ++ if (zresult != Z_STREAM_END) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_error:skb_decompress: " ++ "inflate() returned error %d (%s), " ++ "skipping decompression.\n", ++ zresult, ++ zs.msg ? zs.msg : zError(zresult)); ++ *flags |= IPCOMP_DECOMPRESSIONERROR; ++ ipsec_kfree_skb(nskb); ++ ++ return skb; ++ } ++ ++ /* Update IP header */ ++ /* resulting decompressed size */ ++ pyldsz -= zs.avail_out; ++ iph->tot_len = htons(iphlen + pyldsz); ++ iph->protocol = ((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_nh; ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_decompress: " ++ "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: comp=%d, raw=%d, nh=%d.\n", ++ ips ? ntohl(ips->ips_said.spi) : 0, ++ ips ? ntohl(ips->ips_said.spi) & 0x0000ffff : 0, ++ ntohs(((struct ipcomphdr*)(((char*)oiph)+iphlen))->ipcomp_cpi), ++ cpyldsz, ++ pyldsz, ++ iph->protocol); ++ ++#if 1 /* XXX checksum is done by ipsec_rcv ? */ ++ iph->check = 0; ++ iph->check = ip_fast_csum((char*) iph, iph->ihl); ++#endif ++ ++ /* Update skb length/tail by "unputting" the unused data area */ ++ skb_put(nskb, -zs.avail_out); ++ ++ ipsec_kfree_skb(skb); ++ ++ if (iph->protocol == IPPROTO_COMP) ++ { ++#ifdef CONFIG_IPSEC_DEBUG ++ if(sysctl_ipsec_debug_ipcomp) ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_decompress: " ++ "Eh? inner packet is also compressed, dropping.\n"); ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ ipsec_kfree_skb(nskb); ++ return NULL; ++ } ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { ++ __u8 *c; ++ int i; ++ ++ c = (__u8*)iph + iphlen; ++ for(i = 0; i < pyldsz; i++, c++) { ++ if(!(i % 16)) { ++ printk(KERN_INFO "skb_decompress: result:"); ++ } ++ printk("%02x ", *c); ++ if(!((i + 1) % 16)) { ++ printk("\n"); ++ } ++ } ++ if(i % 16) { ++ printk("\n"); ++ } ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ return nskb; ++} ++ ++ ++/* this is derived from skb_copy() in linux 2.2.14 */ ++/* May be incompatible with other kernel versions!! */ ++static ++struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask) ++{ ++ struct sk_buff *n; ++ struct iphdr *iph; ++ unsigned long offset; ++ unsigned int iphlen; ++ ++ if(!skb) { ++ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, ++ "klips_debug:skb_copy_ipcomp: " ++ "passed in NULL skb, returning NULL.\n"); ++ return NULL; ++ } ++ ++ /* ++ * Allocate the copy buffer ++ */ ++ ++#ifdef NET_21 ++ iph = skb->nh.iph; ++#else /* NET_21 */ ++ iph = skb->ip_hdr; ++#endif /* NET_21 */ ++ if (!iph) return NULL; ++ iphlen = iph->ihl << 2; ++ ++ n=alloc_skb(skb->end - skb->head + data_growth, gfp_mask); ++ if(n==NULL) ++ return NULL; ++ ++ /* ++ * Shift between the two data areas in bytes ++ */ ++ ++ offset=n->head-skb->head; ++ ++ /* Set the data pointer */ ++ skb_reserve(n,skb->data-skb->head); ++ /* Set the tail pointer and length */ ++ skb_put(n,skb->len+data_growth); ++ /* Copy the bytes up to and including the ip header */ ++ memcpy(n->head, ++ skb->head, ++ ((char *)iph - (char *)skb->head) + iphlen); ++ n->list=NULL; ++ n->next=NULL; ++ n->prev=NULL; ++ n->sk=NULL; ++ n->dev=skb->dev; ++ if (skb->h.raw) ++ n->h.raw=skb->h.raw+offset; ++ else ++ n->h.raw=NULL; ++ n->protocol=skb->protocol; ++#ifdef NET_21 ++ n->csum = 0; ++ n->priority=skb->priority; ++ n->dst=dst_clone(skb->dst); ++ n->nh.raw=skb->nh.raw+offset; ++#ifndef NETDEV_23 ++ n->is_clone=0; ++#endif /* NETDEV_23 */ ++ atomic_set(&n->users, 1); ++ n->destructor = NULL; ++ n->security=skb->security; ++ memcpy(n->cb, skb->cb, sizeof(skb->cb)); ++#ifdef CONFIG_IP_FIREWALL ++ n->fwmark = skb->fwmark; ++#endif ++#else /* NET_21 */ ++ n->link3=NULL; ++ n->when=skb->when; ++ n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset); ++ n->saddr=skb->saddr; ++ n->daddr=skb->daddr; ++ n->raddr=skb->raddr; ++ n->seq=skb->seq; ++ n->end_seq=skb->end_seq; ++ n->ack_seq=skb->ack_seq; ++ n->acked=skb->acked; ++ n->free=1; ++ n->arp=skb->arp; ++ n->tries=0; ++ n->lock=0; ++ n->users=0; ++ memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); ++#endif /* NET_21 */ ++ if (skb->mac.raw) ++ n->mac.raw=skb->mac.raw+offset; ++ else ++ n->mac.raw=NULL; ++#ifndef NETDEV_23 ++ n->used=skb->used; ++#endif /* !NETDEV_23 */ ++ n->pkt_type=skb->pkt_type; ++#ifndef NETDEV_23 ++ n->pkt_bridged=skb->pkt_bridged; ++#endif /* NETDEV_23 */ ++ n->ip_summed=0; ++ n->stamp=skb->stamp; ++#ifndef NETDEV_23 /* this seems to have been removed in 2.4 */ ++#if defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) ++ n->shapelatency=skb->shapelatency; /* Latency on frame */ ++ n->shapeclock=skb->shapeclock; /* Time it should go out */ ++ n->shapelen=skb->shapelen; /* Frame length in clocks */ ++ n->shapestamp=skb->shapestamp; /* Stamp for shaper */ ++ n->shapepend=skb->shapepend; /* Pending */ ++#endif /* defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) */ ++#endif /* NETDEV_23 */ ++#ifdef CONFIG_HIPPI ++ n->private.ifield=skb->private.ifield; ++#endif /* CONFIG_HIPPI */ ++ ++ return n; ++} +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_ah.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,363 @@ ++/* ++ * processing code for AH ++ * Copyright (C) 2003-2004 Michael Richardson <mcr@xelerance.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++char ipsec_ah_c_version[] = "RCSID $Id: ipsec_ah.c,v 1.2 2004/04/06 02:49:25 mcr Exp $"; ++#include <linux/config.h> ++#include <linux/version.h> ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define proto_priv cb ++#endif /* NET21 */ ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_rcv.h" ++#include "openswan/ipsec_xmit.h" ++ ++#include "openswan/ipsec_auth.h" ++ ++#ifdef CONFIG_IPSEC_AH ++#include "openswan/ipsec_ah.h" ++#endif /* CONFIG_IPSEC_AH */ ++ ++#include "openswan/ipsec_proto.h" ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_ah = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++__u32 zeroes[AH_AMAX]; ++ ++#ifdef CONFIG_IPSEC_AH ++enum ipsec_rcv_value ++ipsec_rcv_ah_checks(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb) ++{ ++ int ahminlen; ++ ++ ahminlen = irs->hard_header_len + sizeof(struct iphdr); ++ ++ /* take care not to deref this pointer until we check the minlen though */ ++ irs->protostuff.ahstuff.ahp = (struct ahhdr *) (skb->data + irs->iphlen); ++ ++ if((skb->len < ahminlen+sizeof(struct ahhdr)) || ++ (skb->len < ahminlen+(irs->protostuff.ahstuff.ahp->ah_hl << 2))) { ++ KLIPS_PRINT(debug_rcv & DB_RX_INAU, ++ "klips_debug:ipsec_rcv: " ++ "runt ah packet of skb->len=%d received from %s, dropped.\n", ++ skb->len, ++ irs->ipsaddr_txt); ++ if(irs->stats) { ++ irs->stats->rx_errors++; ++ } ++ return IPSEC_RCV_BADLEN; ++ } ++ ++ irs->said.spi = irs->protostuff.ahstuff.ahp->ah_spi; ++ ++ /* XXX we only support the one 12-byte authenticator for now */ ++ if(irs->protostuff.ahstuff.ahp->ah_hl != ((AHHMAC_HASHLEN+AHHMAC_RPLLEN) >> 2)) { ++ KLIPS_PRINT(debug_rcv & DB_RX_INAU, ++ "klips_debug:ipsec_rcv: " ++ "bad authenticator length %ld, expected %lu from %s.\n", ++ (long)(irs->protostuff.ahstuff.ahp->ah_hl << 2), ++ (unsigned long) sizeof(struct ahhdr), ++ irs->ipsaddr_txt); ++ if(irs->stats) { ++ irs->stats->rx_errors++; ++ } ++ return IPSEC_RCV_BADLEN; ++ } ++ ++ return IPSEC_RCV_OK; ++} ++ ++ ++enum ipsec_rcv_value ++ipsec_rcv_ah_setup_auth(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb, ++ __u32 *replay, ++ unsigned char **authenticator) ++{ ++ struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; ++ ++ *replay = ntohl(ahp->ah_rpl); ++ *authenticator = ahp->ah_data; ++ ++ return IPSEC_RCV_OK; ++} ++ ++enum ipsec_rcv_value ++ipsec_rcv_ah_authcalc(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb) ++{ ++ struct auth_alg *aa; ++ struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; ++ union { ++ MD5_CTX md5; ++ SHA1_CTX sha1; ++ } tctx; ++ struct iphdr ipo; ++ int ahhlen; ++ ++ aa = irs->authfuncs; ++ ++ /* copy the initialized keying material */ ++ memcpy(&tctx, irs->ictx, irs->ictx_len); ++ ++ ipo = *irs->ipp; ++ ipo.tos = 0; /* mutable RFC 2402 3.3.3.1.1.1 */ ++ ipo.frag_off = 0; ++ ipo.ttl = 0; ++ ipo.check = 0; ++ ++ ++ /* do the sanitized header */ ++ (*aa->update)((void*)&tctx, (caddr_t)&ipo, sizeof(struct iphdr)); ++ ++ /* XXX we didn't do the options here! */ ++ ++ /* now do the AH header itself */ ++ ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2); ++ (*aa->update)((void*)&tctx, (caddr_t)ahp, ahhlen - AHHMAC_HASHLEN); ++ ++ /* now, do some zeroes */ ++ (*aa->update)((void*)&tctx, (caddr_t)zeroes, AHHMAC_HASHLEN); ++ ++ /* finally, do the packet contents themselves */ ++ (*aa->update)((void*)&tctx, ++ (caddr_t)skb->data + irs->iphlen + ahhlen, ++ skb->len - irs->iphlen - ahhlen); ++ ++ (*aa->final)(irs->hash, (void *)&tctx); ++ ++ memcpy(&tctx, irs->octx, irs->octx_len); ++ ++ (*aa->update)((void *)&tctx, irs->hash, aa->hashlen); ++ (*aa->final)(irs->hash, (void *)&tctx); ++ ++ return IPSEC_RCV_OK; ++} ++ ++enum ipsec_rcv_value ++ipsec_rcv_ah_decap(struct ipsec_rcv_state *irs) ++{ ++ struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; ++ struct sk_buff *skb; ++ int ahhlen; ++ ++ skb=irs->skb; ++ ++ ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2); ++ ++ irs->ipp->tot_len = htons(ntohs(irs->ipp->tot_len) - ahhlen); ++ irs->next_header = ahp->ah_nh; ++ ++ /* ++ * move the IP header forward by the size of the AH header, which ++ * will remove the the AH header from the packet. ++ */ ++ memmove((void *)(skb->data + ahhlen), ++ (void *)(skb->data), irs->iphlen); ++ ++ ipsec_rcv_dmp("ah postmove", skb->data, skb->len); ++ ++ /* skb_pull below, will move up by ahhlen */ ++ ++ /* XXX not clear how this can happen, as the message indicates */ ++ if(skb->len < ahhlen) { ++ printk(KERN_WARNING ++ "klips_error:ipsec_rcv: " ++ "tried to skb_pull ahhlen=%d, %d available. This should never happen, please report.\n", ++ ahhlen, ++ (int)(skb->len)); ++ return IPSEC_RCV_DECAPFAIL; ++ } ++ skb_pull(skb, ahhlen); ++ ++ irs->ipp = (struct iphdr *)skb->data; ++ ++ ipsec_rcv_dmp("ah postpull", skb->data, skb->len); ++ ++ return IPSEC_RCV_OK; ++} ++ ++enum ipsec_xmit_value ++ipsec_xmit_ah_setup(struct ipsec_xmit_state *ixs) ++{ ++ struct iphdr ipo; ++ struct ahhdr *ahp; ++ __u8 hash[AH_AMAX]; ++ union { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ MD5_CTX md5; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ SHA1_CTX sha1; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ } tctx; ++ unsigned char *dat = (unsigned char *)ixs->iph; ++ ++ ahp = (struct ahhdr *)(dat + ixs->iphlen); ++ ahp->ah_spi = ixs->ipsp->ips_said.spi; ++ ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); ++ ahp->ah_rv = 0; ++ ahp->ah_nh = ixs->iph->protocol; ++ ahp->ah_hl = (sizeof(struct ahhdr) >> 2) - sizeof(__u64)/sizeof(__u32); ++ ixs->iph->protocol = IPPROTO_AH; ++ ipsec_xmit_dmp("ahp", (char*)ahp, sizeof(*ahp)); ++ ++ ipo = *ixs->iph; ++ ipo.tos = 0; ++ ipo.frag_off = 0; ++ ipo.ttl = 0; ++ ipo.check = 0; ++ ipsec_xmit_dmp("ipo", (char*)&ipo, sizeof(ipo)); ++ ++ switch(ixs->ipsp->ips_authalg) { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ case AH_MD5: ++ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; ++ ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); ++ ipsec_xmit_dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, (unsigned char *)ahp, ++ sizeof(struct ahhdr) - sizeof(ahp->ah_data)); ++ ipsec_xmit_dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); ++ ipsec_xmit_dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, dat + ixs->iphlen + sizeof(struct ahhdr), ++ ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr)); ++ ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Final(hash, &tctx.md5); ++ ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash)); ++ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; ++ ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, hash, AHMD596_ALEN); ++ ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Final(hash, &tctx.md5); ++ ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash)); ++ ++ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); ++ ++ /* paranoid */ ++ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); ++ memset((caddr_t)hash, 0, sizeof(*hash)); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ case AH_SHA: ++ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; ++ SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr)); ++ SHA1Update(&tctx.sha1, (unsigned char *)ahp, sizeof(struct ahhdr) - sizeof(ahp->ah_data)); ++ SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); ++ SHA1Update(&tctx.sha1, dat + ixs->iphlen + sizeof(struct ahhdr), ++ ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr)); ++ SHA1Final(hash, &tctx.sha1); ++ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; ++ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); ++ SHA1Final(hash, &tctx.sha1); ++ ++ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); ++ ++ /* paranoid */ ++ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); ++ memset((caddr_t)hash, 0, sizeof(*hash)); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_AH_BADALG; ++ } ++#ifdef NET_21 ++ ixs->skb->h.raw = (unsigned char*)ahp; ++#endif /* NET_21 */ ++ ++ return IPSEC_XMIT_OK; ++} ++ ++struct xform_functions ah_xform_funcs[]={ ++ { rcv_checks: ipsec_rcv_ah_checks, ++ rcv_setup_auth: ipsec_rcv_ah_setup_auth, ++ rcv_calc_auth: ipsec_rcv_ah_authcalc, ++ rcv_decrypt: ipsec_rcv_ah_decap, ++ ++ xmit_setup: ipsec_xmit_ah_setup, ++ xmit_headroom: sizeof(struct ahhdr), ++ xmit_needtailroom: 0, ++ }, ++}; ++ ++struct inet_protocol ah_protocol = ++{ ++ ipsec_rcv, /* AH handler */ ++ NULL, /* TUNNEL error control */ ++#ifdef NETDEV_25 ++ 1, /* no policy */ ++#else ++ 0, /* next */ ++ IPPROTO_AH, /* protocol ID */ ++ 0, /* copy */ ++ NULL, /* data */ ++ "AH" /* name */ ++#endif ++}; ++ ++#endif /* CONFIG_IPSEC_AH */ ++ ++/* ++ * $Log: ipsec_ah.c,v $ ++ * Revision 1.2 2004/04/06 02:49:25 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_alg.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,953 @@ ++/* ++ * Modular extensions service and registration functions ++ * ++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar> ++ * ++ * Version: 0.8.1 ++ * ++ * ipsec_alg.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++#ifdef CONFIG_IPSEC_ALG ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#include <linux/socket.h> ++#include <linux/in.h> ++#include <linux/types.h> ++#include <linux/string.h> /* memcmp() */ ++#include <linux/random.h> /* get_random_bytes() */ ++#include <linux/errno.h> /* error codes */ ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define proto_priv cb ++#endif /* NET21 */ ++#include "openswan/ipsec_param.h" ++#include <openswan.h> ++#include "openswan/ipsec_sa.h" ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_rcv.h" ++#if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) ++# include "openswan/ipsec_ah.h" ++#endif /* defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) */ ++#ifdef CONFIG_IPSEC_ESP ++# include "openswan/ipsec_esp.h" ++#endif /* !CONFIG_IPSEC_ESP */ ++#ifdef CONFIG_IPSEC_IPCOMP ++# include "openswan/ipcomp.h" ++#endif /* CONFIG_IPSEC_COMP */ ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_alg.h" ++ ++#ifndef CONFIG_IPSEC_ALG ++#error This file _MUST_ be compiled with CONFIG_IPSEC_ALG enabled ! ++#endif ++#if SADB_EALG_MAX < 255 ++#warning Compiling with limited ESP support ( SADB_EALG_MAX < 256 ) ++#endif ++ ++static rwlock_t ipsec_alg_lock = RW_LOCK_UNLOCKED; ++#define IPSEC_ALG_HASHSZ 16 /* must be power of 2, even 2^0=1 */ ++static struct list_head ipsec_alg_hash_table[IPSEC_ALG_HASHSZ]; ++ ++/* Old gcc's will fail here */ ++#define barf_out(fmt, args...) do { printk(KERN_ERR "%s: (%s) " fmt, __FUNCTION__, ixt->ixt_name , ## args)\ ++ ; goto out; } while(0) ++ ++/* ++ * Must be already protected by lock ++ */ ++static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) { ++ if (ixt->ixt_module) ++ __MOD_INC_USE_COUNT(ixt->ixt_module); ++ atomic_inc(&ixt->ixt_refcnt); ++} ++static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) { ++ atomic_dec(&ixt->ixt_refcnt); ++ if (ixt->ixt_module) ++ __MOD_DEC_USE_COUNT(ixt->ixt_module); ++} ++/* ++ * simple hash function, optimized for 0-hash (1 list) special ++ * case ++ */ ++#if IPSEC_ALG_HASHSZ > 1 ++static inline unsigned ipsec_alg_hashfn(int alg_type, int alg_id) { ++ return ((alg_type^alg_id)&(IPSEC_ALG_HASHSZ-1)); ++} ++#else ++#define ipsec_alg_hashfn(x,y) (0) ++#endif ++ ++/***************************************************************** ++ * ++ * INTERNAL table handling: insert, delete, find ++ * ++ *****************************************************************/ ++ ++/* ++ * hash table initialization, called from ipsec_alg_init() ++ */ ++static void ipsec_alg_hash_init(void) { ++ struct list_head *head = ipsec_alg_hash_table; ++ int i = IPSEC_ALG_HASHSZ; ++ do { ++ INIT_LIST_HEAD(head); ++ head++; ++ i--; ++ } while (i); ++} ++/* ++ * hash list lookup by {alg_type, alg_id} and table head, ++ * must be already protected by lock ++ */ ++static struct ipsec_alg *__ipsec_alg_find(unsigned alg_type, unsigned alg_id, struct list_head * head) { ++ struct list_head *p; ++ struct ipsec_alg *ixt=NULL; ++ for (p=head->next; p!=head; p=p->next) { ++ ixt = list_entry(p, struct ipsec_alg, ixt_list); ++ if (ixt->ixt_alg_type == alg_type && ixt->ixt_alg_id==alg_id) { ++ goto out; ++ } ++ } ++ ixt=NULL; ++out: ++ return ixt; ++} ++/* ++ * inserts (in front) a new entry in hash table, ++ * called from ipsec_alg_register() when new algorithm is registered. ++ */ ++static int ipsec_alg_insert(struct ipsec_alg *ixt) { ++ int ret=-EINVAL; ++ unsigned hashval=ipsec_alg_hashfn(ixt->ixt_alg_type, ixt->ixt_alg_id); ++ struct list_head *head= ipsec_alg_hash_table + hashval; ++ struct ipsec_alg *ixt_cur; ++ /* new element must be virgin ... */ ++ if (ixt->ixt_list.next != &ixt->ixt_list || ++ ixt->ixt_list.prev != &ixt->ixt_list) { ++ printk(KERN_ERR "ipsec_alg_insert: ixt object \"%s\" " ++ "list head not initialized\n", ++ ixt->ixt_name); ++ return ret; ++ } ++ write_lock_bh(&ipsec_alg_lock); ++ ixt_cur = __ipsec_alg_find(ixt->ixt_alg_type, ixt->ixt_alg_id, head); ++ /* if previous (current) ipsec_alg found check excl flag of _anyone_ */ ++ if (ixt_cur && ((ixt->ixt_state|ixt_cur->ixt_state) & IPSEC_ALG_ST_EXCL)) ++ barf_out("ipsec_alg for alg_type=%d, alg_id=%d already exist. " ++ "Not loaded (ret=%d).\n", ++ ixt->ixt_alg_type, ++ ixt->ixt_alg_id, ret=-EEXIST); ++ list_add(&ixt->ixt_list, head); ++ ixt->ixt_state |= IPSEC_ALG_ST_REGISTERED; ++ ret=0; ++out: ++ write_unlock_bh(&ipsec_alg_lock); ++ return ret; ++} ++/* ++ * deletes an existing entry in hash table, ++ * called from ipsec_alg_unregister() when algorithm is unregistered. ++ */ ++static int ipsec_alg_delete(struct ipsec_alg *ixt) { ++ write_lock_bh(&ipsec_alg_lock); ++ list_del(&ixt->ixt_list); ++ write_unlock_bh(&ipsec_alg_lock); ++ return 0; ++} ++/* ++ * here @user context (read-only when @kernel bh context) ++ * -> no bh disabling ++ * ++ * called from ipsec_sa_init() -> ipsec_alg_sa_init() ++ */ ++static struct ipsec_alg *ipsec_alg_get(int alg_type, int alg_id) { ++ unsigned hashval=ipsec_alg_hashfn(alg_type, alg_id); ++ struct list_head *head= ipsec_alg_hash_table + hashval; ++ struct ipsec_alg *ixt; ++ read_lock(&ipsec_alg_lock); ++ ixt=__ipsec_alg_find(alg_type, alg_id, head); ++ if (ixt) __ipsec_alg_usage_inc(ixt); ++ read_unlock(&ipsec_alg_lock); ++ return ixt; ++} ++ ++static void ipsec_alg_put(struct ipsec_alg *ixt) { ++ __ipsec_alg_usage_dec((struct ipsec_alg *)ixt); ++} ++ ++/***************************************************************** ++ * ++ * INTERFACE for ENC services: key creation, encrypt function ++ * ++ *****************************************************************/ ++ ++/* ++ * main encrypt service entry point ++ * called from ipsec_rcv() with encrypt=IPSEC_ALG_DECRYPT and ++ * ipsec_tunnel_start_xmit with encrypt=IPSEC_ALG_ENCRYPT ++ */ ++int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 * idat, int ilen, const __u8 * iv, int encrypt) { ++ int ret; ++ struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc; ++ KLIPS_PRINT(debug_rcv||debug_tunnel, ++ "klips_debug:ipsec_alg_esp_encrypt: " ++ "entering with encalg=%d, ixt_e=%p\n", ++ sa_p->ips_encalg, ixt_e); ++ if (!ixt_e) { ++ KLIPS_PRINT(debug_rcv||debug_tunnel, ++ "klips_debug:ipsec_alg_esp_encrypt: " ++ "NULL ipsec_alg_enc object\n"); ++ return -1; ++ } ++ KLIPS_PRINT(debug_rcv||debug_tunnel, ++ "klips_debug:ipsec_alg_esp_encrypt: " ++ "calling cbc_encrypt encalg=%d " ++ "ips_key_e=%p idat=%p ilen=%d iv=%p, encrypt=%d\n", ++ sa_p->ips_encalg, ++ sa_p->ips_key_e, idat, ilen, iv, encrypt); ++ ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, sa_p->ips_key_e, idat, ilen, iv, encrypt); ++ KLIPS_PRINT(debug_rcv||debug_tunnel, ++ "klips_debug:ipsec_alg_esp_encrypt: " ++ "returned ret=%d\n", ++ ret); ++ return ret; ++} ++/* ++ * encryption key context creation function ++ * called from pfkey_v2_parser.c:pfkey_ips_init() ++ */ ++int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) { ++ int ret=-EINVAL; ++ int keyminbits, keymaxbits; ++ caddr_t ekp; ++ struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_alg_enc_key_create: " ++ "entering with encalg=%d ixt_e=%p\n", ++ sa_p->ips_encalg, ixt_e); ++ if (!ixt_e) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_alg_enc_key_create: " ++ "NULL ipsec_alg_enc object\n"); ++ return -EPROTO; ++ } ++ ++ /* ++ * grRRR... DES 7bits jurassic stuff ... f*ckk --jjo ++ */ ++ switch(ixt_e->ixt_alg_id) { ++ case ESP_3DES: ++ keyminbits=keymaxbits=192;break; ++ case ESP_DES: ++ keyminbits=keymaxbits=64;break; ++ default: ++ keyminbits=ixt_e->ixt_keyminbits; ++ keymaxbits=ixt_e->ixt_keymaxbits; ++ } ++ if(sa_p->ips_key_bits_e<keyminbits || ++ sa_p->ips_key_bits_e>keymaxbits) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_alg_enc_key_create: " ++ "incorrect encryption key size for id=%d: %d bits -- " ++ "must be between %d,%d bits\n" /*octets (bytes)\n"*/, ++ ixt_e->ixt_alg_id, ++ sa_p->ips_key_bits_e, keyminbits, keymaxbits); ++ ret=-EINVAL; ++ goto ixt_out; ++ } ++ /* save encryption key pointer */ ++ ekp = sa_p->ips_key_e; ++ ++ ++ if (ixt_e->ixt_e_new_key) { ++ sa_p->ips_key_e = ixt_e->ixt_e_new_key(ixt_e, ++ ekp, sa_p->ips_key_bits_e/8); ++ ret = (sa_p->ips_key_e)? 0 : -EINVAL; ++ } else { ++ if((sa_p->ips_key_e = (caddr_t) ++ kmalloc((sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size), ++ GFP_ATOMIC)) == NULL) { ++ ret=-ENOMEM; ++ goto ixt_out; ++ } ++ /* zero-out key_e */ ++ memset(sa_p->ips_key_e, 0, sa_p->ips_key_e_size); ++ ++ /* I cast here to allow more decoupling in alg module */ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_alg_enc_key_create: about to call:" ++ "set_key(key_e=%p, ekp=%p, key_size=%d)\n", ++ (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8); ++ ret = ixt_e->ixt_e_set_key(ixt_e, (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8); ++ } ++ /* paranoid */ ++ memset(ekp, 0, sa_p->ips_key_bits_e/8); ++ kfree(ekp); ++ixt_out: ++ return ret; ++} ++ ++/*************************************************************** ++ * ++ * INTERFACE for AUTH services: key creation, hash functions ++ * ++ ***************************************************************/ ++ ++/* ++ * auth key context creation function ++ * called from pfkey_v2_parser.c:pfkey_ips_init() ++ */ ++int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p) { ++ int ret=-EINVAL; ++ struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth; ++ int keyminbits, keymaxbits; ++ unsigned char *akp; ++ unsigned int aks; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_alg_auth_key_create: " ++ "entering with authalg=%d ixt_a=%p\n", ++ sa_p->ips_authalg, ixt_a); ++ if (!ixt_a) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_alg_auth_key_create: " ++ "NULL ipsec_alg_auth object\n"); ++ return -EPROTO; ++ } ++ keyminbits=ixt_a->ixt_keyminbits; ++ keymaxbits=ixt_a->ixt_keymaxbits; ++ if(sa_p->ips_key_bits_a<keyminbits || sa_p->ips_key_bits_a>keymaxbits) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_alg_auth_key_create: incorrect auth" ++ "key size: %d bits -- must be between %d,%d bits\n"/*octets (bytes)\n"*/, ++ sa_p->ips_key_bits_a, keyminbits, keymaxbits); ++ ret=-EINVAL; ++ goto ixt_out; ++ } ++ /* save auth key pointer */ ++ sa_p->ips_auth_bits = ixt_a->ixt_a_keylen * 8; /* XXX XXX */ ++ akp = sa_p->ips_key_a; ++ aks = sa_p->ips_key_a_size; ++ ++ /* will hold: 2 ctx and a blocksize buffer: kb */ ++ sa_p->ips_key_a_size = ixt_a->ixt_a_ctx_size; ++ if((sa_p->ips_key_a = ++ (caddr_t) kmalloc(sa_p->ips_key_a_size, GFP_ATOMIC)) == NULL) { ++ ret=-ENOMEM; ++ goto ixt_out; ++ } ++ ixt_a->ixt_a_hmac_set_key(ixt_a, sa_p->ips_key_a, akp, sa_p->ips_key_bits_a/8); /* XXX XXX */ ++ ret=0; ++ memset(akp, 0, aks); ++ kfree(akp); ++ ++ixt_out: ++ return ret; ++} ++ ++ ++int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) { ++ struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth; ++ if (!ixt_a) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_sa_esp_hash: " ++ "NULL ipsec_alg_auth object\n"); ++ return -EPROTO; ++ } ++ KLIPS_PRINT(debug_tunnel|debug_rcv, ++ "klips_debug:ipsec_sa_esp_hash: " ++ "hashing %p (%d bytes) to %p (%d bytes)\n", ++ espp, len, ++ hash, hashlen); ++ ixt_a->ixt_a_hmac_hash(ixt_a, ++ sa_p->ips_key_a, ++ espp, len, ++ hash, hashlen); ++ return 0; ++} ++ ++/*************************************************************** ++ * ++ * INTERFACE for module loading,testing, and unloading ++ * ++ ***************************************************************/ ++ ++/* validation for registering (enc) module */ ++static int check_enc(struct ipsec_alg_enc *ixt) { ++ int ret=-EINVAL; ++ if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_EALG_MAX) ++ barf_out("invalid alg_id=%d >= %d\n", ixt->ixt_alg_id, SADB_EALG_MAX); ++ if (ixt->ixt_blocksize==0) /* || ixt->ixt_blocksize%2) need for ESP_NULL */ ++ barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize); ++ if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_e_keylen==0) ++ goto zero_key_ok; ++ if (ixt->ixt_keyminbits==0) ++ barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits); ++ if (ixt->ixt_keymaxbits==0) ++ barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits); ++ if (ixt->ixt_e_keylen==0) ++ barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_e_keylen); ++zero_key_ok: ++ if (ixt->ixt_e_ctx_size==0 && ixt->ixt_e_new_key == NULL) ++ barf_out(KERN_ERR "invalid key_e_size=%d and ixt_e_new_key=NULL\n", ixt->ixt_e_ctx_size); ++ if (ixt->ixt_e_cbc_encrypt==NULL) ++ barf_out(KERN_ERR "e_cbc_encrypt() must be not NULL\n"); ++ ret=0; ++out: ++ return ret; ++} ++ ++/* validation for registering (auth) module */ ++static int check_auth(struct ipsec_alg_auth *ixt) ++{ ++ int ret=-EINVAL; ++ if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_AALG_MAX) ++ barf_out("invalid alg_id=%d > %d (SADB_AALG_MAX)\n", ixt->ixt_alg_id, SADB_AALG_MAX); ++ if (ixt->ixt_blocksize==0 || ixt->ixt_blocksize%2) ++ barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize); ++ if (ixt->ixt_blocksize>AH_BLKLEN_MAX) ++ barf_out(KERN_ERR "sorry blocksize=%d > %d. " ++ "Please increase AH_BLKLEN_MAX and recompile\n", ++ ixt->ixt_blocksize, ++ AH_BLKLEN_MAX); ++ if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_a_keylen==0) ++ goto zero_key_ok; ++ if (ixt->ixt_keyminbits==0) ++ barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits); ++ if (ixt->ixt_keymaxbits==0) ++ barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits); ++ if (ixt->ixt_keymaxbits!=ixt->ixt_keyminbits) ++ barf_out(KERN_ERR "keymaxbits must equal keyminbits (not sure).\n"); ++ if (ixt->ixt_a_keylen==0) ++ barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_a_keylen); ++zero_key_ok: ++ if (ixt->ixt_a_ctx_size==0) ++ barf_out(KERN_ERR "invalid a_ctx_size=%d\n", ixt->ixt_a_ctx_size); ++ if (ixt->ixt_a_hmac_set_key==NULL) ++ barf_out(KERN_ERR "a_hmac_set_key() must be not NULL\n"); ++ if (ixt->ixt_a_hmac_hash==NULL) ++ barf_out(KERN_ERR "a_hmac_hash() must be not NULL\n"); ++ ret=0; ++out: ++ return ret; ++} ++ ++/* ++ * Generic (enc, auth) registration entry point ++ */ ++int register_ipsec_alg(struct ipsec_alg *ixt) { ++ int ret=-EINVAL; ++ /* Validation */ ++ if (ixt==NULL) ++ barf_out("NULL ipsec_alg object passed\n"); ++ if ((ixt->ixt_version&0xffffff00) != (IPSEC_ALG_VERSION&0xffffff00)) ++ barf_out("incorrect version: %d.%d.%d-%d, " ++ "must be %d.%d.%d[-%d]\n", ++ IPSEC_ALG_VERSION_QUAD(ixt->ixt_version), ++ IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION)); ++ switch(ixt->ixt_alg_type) { ++ case IPSEC_ALG_TYPE_AUTH: ++ if ((ret=check_auth((struct ipsec_alg_auth *)ixt)<0)) ++ goto out; ++ break; ++ case IPSEC_ALG_TYPE_ENCRYPT: ++ if ((ret=check_enc((struct ipsec_alg_enc *)ixt)<0)) ++ goto out; ++ /* ++ * Adapted two lines below: ++ * ivlen == 0 is possible (NULL enc has blocksize==1) ++ * ++ * fixed NULL support by David De Reu <DeReu@tComLabs.com> ++ */ ++ if (ixt->ixt_ivlen == 0 && ixt->ixt_blocksize > 1) ++ ixt->ixt_ivlen = ixt->ixt_blocksize*8; ++ break; ++ default: ++ barf_out("alg_type=%d not supported\n", ixt->ixt_alg_type); ++ } ++ INIT_LIST_HEAD(&ixt->ixt_list); ++ ret = ipsec_alg_insert(ixt); ++ if (ret<0) ++ barf_out(KERN_WARNING "ipsec_alg for alg_id=%d failed." ++ "Not loaded (ret=%d).\n", ++ ixt->ixt_alg_id, ret); ++ ++ ret = pfkey_list_insert_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP])); ++ if (ret==0) { ++ ixt->ixt_state |= IPSEC_ALG_ST_SUPP; ++ /* send register event to userspace */ ++ pfkey_register_reply(SADB_SATYPE_ESP, NULL); ++ } else ++ printk(KERN_ERR "pfkey_list_insert_supported returned %d. " ++ "Loading anyway.\n", ret); ++ ret=0; ++out: ++ return ret; ++} ++ ++/* ++ * unregister ipsec_alg object from own tables, if ++ * success => calls pfkey_list_remove_supported() ++ */ ++int unregister_ipsec_alg(struct ipsec_alg *ixt) { ++ int ret= -EINVAL; ++ switch(ixt->ixt_alg_type) { ++ case IPSEC_ALG_TYPE_AUTH: ++ case IPSEC_ALG_TYPE_ENCRYPT: ++ break; ++ default: ++ /* this is not a typo :) */ ++ barf_out("frog found in list (\"%s\"): ixt_p=NULL\n", ++ ixt->ixt_name); ++ } ++ ++ ret=ipsec_alg_delete(ixt); ++ if (ixt->ixt_state&IPSEC_ALG_ST_SUPP) { ++ ixt->ixt_state &= ~IPSEC_ALG_ST_SUPP; ++ pfkey_list_remove_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP])); ++ /* send register event to userspace */ ++ pfkey_register_reply(SADB_SATYPE_ESP, NULL); ++ } ++ ++out: ++ return ret; ++} ++ ++/* ++ * Must be called from user context ++ * used at module load type for testing algo implementation ++ */ ++static int ipsec_alg_test_encrypt(int enc_alg, int test) { ++ int ret; ++ caddr_t buf = NULL; ++ int iv_size, keysize, key_e_size; ++ struct ipsec_alg_enc *ixt_e; ++ void *tmp_key_e = NULL; ++ #define BUFSZ 1024 ++ #define MARGIN 0 ++ #define test_enc (buf+MARGIN) ++ #define test_dec (test_enc+BUFSZ+MARGIN) ++ #define test_tmp (test_dec+BUFSZ+MARGIN) ++ #define test_key_e (test_tmp+BUFSZ+MARGIN) ++ #define test_iv (test_key_e+key_e_size+MARGIN) ++ #define test_key (test_iv+iv_size+MARGIN) ++ #define test_size (BUFSZ*3+key_e_size+iv_size+keysize+MARGIN*7) ++ ixt_e=(struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, enc_alg); ++ if (ixt_e==NULL) { ++ KLIPS_PRINT(1, ++ "klips_debug: ipsec_alg_test_encrypt: " ++ "encalg=%d object not found\n", ++ enc_alg); ++ ret=-EINVAL; ++ goto out; ++ } ++ iv_size=ixt_e->ixt_ivlen / 8; ++ key_e_size=ixt_e->ixt_e_ctx_size; ++ keysize=ixt_e->ixt_e_keylen; ++ KLIPS_PRINT(1, ++ "klips_debug: ipsec_alg_test_encrypt: " ++ "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n", ++ enc_alg, iv_size, key_e_size, keysize); ++ if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) { ++ ret= -ENOMEM; ++ goto out; ++ } ++ get_random_bytes(test_key, keysize); ++ get_random_bytes(test_iv, iv_size); ++ if (ixt_e->ixt_e_new_key) { ++ tmp_key_e = ixt_e->ixt_e_new_key(ixt_e, test_key, keysize); ++ ret = tmp_key_e ? 0 : -EINVAL; ++ } else { ++ tmp_key_e = test_key_e; ++ ret = ixt_e->ixt_e_set_key(ixt_e, test_key_e, test_key, keysize); ++ } ++ if (ret < 0) ++ goto out; ++ get_random_bytes(test_enc, BUFSZ); ++ memcpy(test_tmp, test_enc, BUFSZ); ++ ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_enc, BUFSZ, test_iv, 1); ++ printk(KERN_INFO ++ "klips_info: ipsec_alg_test_encrypt: " ++ "cbc_encrypt=1 ret=%d\n", ++ ret); ++ ret=memcmp(test_enc, test_tmp, BUFSZ); ++ printk(KERN_INFO ++ "klips_info: ipsec_alg_test_encrypt: " ++ "memcmp(enc, tmp) ret=%d: %s\n", ret, ++ ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" ); ++ memcpy(test_dec, test_enc, BUFSZ); ++ ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_dec, BUFSZ, test_iv, 0); ++ printk(KERN_INFO ++ "klips_info: ipsec_alg_test_encrypt: " ++ "cbc_encrypt=0 ret=%d\n", ret); ++ ret=memcmp(test_dec, test_tmp, BUFSZ); ++ printk(KERN_INFO ++ "klips_info: ipsec_alg_test_encrypt: " ++ "memcmp(dec,tmp) ret=%d: %s\n", ret, ++ ret==0? "OK. (encr->decr->SAME)" : "FAIL! (encr->decr->DIFFers)" ); ++ { ++ /* Shamelessly taken from drivers/md sources O:) */ ++ unsigned long now; ++ int i, count, max=0; ++ int encrypt, speed; ++ for (encrypt=0; encrypt <2;encrypt ++) { ++ for (i = 0; i < 5; i++) { ++ now = jiffies; ++ count = 0; ++ while (jiffies == now) { ++ mb(); ++ ixt_e->ixt_e_cbc_encrypt(ixt_e, ++ tmp_key_e, test_tmp, ++ BUFSZ, test_iv, encrypt); ++ mb(); ++ count++; ++ mb(); ++ } ++ if (count > max) ++ max = count; ++ } ++ speed = max * (HZ * BUFSZ / 1024); ++ printk(KERN_INFO ++ "klips_info: ipsec_alg_test_encrypt: " ++ "%s %s speed=%d KB/s\n", ++ ixt_e->ixt_name, ++ encrypt? "encrypt": "decrypt", speed); ++ } ++ } ++out: ++ if (tmp_key_e && ixt_e->ixt_e_destroy_key) ixt_e->ixt_e_destroy_key(ixt_e, tmp_key_e); ++ if (buf) kfree(buf); ++ if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e); ++ return ret; ++ #undef test_enc ++ #undef test_dec ++ #undef test_tmp ++ #undef test_key_e ++ #undef test_iv ++ #undef test_key ++ #undef test_size ++} ++ ++/* ++ * Must be called from user context ++ * used at module load type for testing algo implementation ++ */ ++static int ipsec_alg_test_auth(int auth_alg, int test) { ++ int ret; ++ caddr_t buf = NULL; ++ int blocksize, keysize, key_a_size; ++ struct ipsec_alg_auth *ixt_a; ++ #define BUFSZ 1024 ++ #define MARGIN 0 ++ #define test_auth (buf+MARGIN) ++ #define test_key_a (test_auth+BUFSZ+MARGIN) ++ #define test_key (test_key_a+key_a_size+MARGIN) ++ #define test_hash (test_key+keysize+MARGIN) ++ #define test_size (BUFSZ+key_a_size+keysize+AHHMAC_HASHLEN+MARGIN*4) ++ ixt_a=(struct ipsec_alg_auth *)ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, auth_alg); ++ if (ixt_a==NULL) { ++ KLIPS_PRINT(1, ++ "klips_debug: ipsec_alg_test_auth: " ++ "encalg=%d object not found\n", ++ auth_alg); ++ ret=-EINVAL; ++ goto out; ++ } ++ blocksize=ixt_a->ixt_blocksize; ++ key_a_size=ixt_a->ixt_a_ctx_size; ++ keysize=ixt_a->ixt_a_keylen; ++ KLIPS_PRINT(1, ++ "klips_debug: ipsec_alg_test_auth: " ++ "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n", ++ auth_alg, blocksize, key_a_size, keysize); ++ if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) { ++ ret= -ENOMEM; ++ goto out; ++ } ++ get_random_bytes(test_key, keysize); ++ ret = ixt_a->ixt_a_hmac_set_key(ixt_a, test_key_a, test_key, keysize); ++ if (ret < 0 ) ++ goto out; ++ get_random_bytes(test_auth, BUFSZ); ++ ret=ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); ++ printk(KERN_INFO ++ "klips_info: ipsec_alg_test_auth: " ++ "ret=%d\n", ret); ++ { ++ /* Shamelessly taken from drivers/md sources O:) */ ++ unsigned long now; ++ int i, count, max=0; ++ int speed; ++ for (i = 0; i < 5; i++) { ++ now = jiffies; ++ count = 0; ++ while (jiffies == now) { ++ mb(); ++ ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); ++ mb(); ++ count++; ++ mb(); ++ } ++ if (count > max) ++ max = count; ++ } ++ speed = max * (HZ * BUFSZ / 1024); ++ printk(KERN_INFO ++ "klips_info: ipsec_alg_test_auth: " ++ "%s hash speed=%d KB/s\n", ++ ixt_a->ixt_name, ++ speed); ++ } ++out: ++ if (buf) kfree(buf); ++ if (ixt_a) ipsec_alg_put((struct ipsec_alg *)ixt_a); ++ return ret; ++ #undef test_auth ++ #undef test_key_a ++ #undef test_key ++ #undef test_hash ++ #undef test_size ++} ++ ++int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int test) { ++ switch(alg_type) { ++ case IPSEC_ALG_TYPE_ENCRYPT: ++ return ipsec_alg_test_encrypt(alg_id, test); ++ break; ++ case IPSEC_ALG_TYPE_AUTH: ++ return ipsec_alg_test_auth(alg_id, test); ++ break; ++ } ++ printk(KERN_ERR "klips_info: ipsec_alg_test() called incorrectly: " ++ "alg_type=%d alg_id=%d\n", ++ alg_type, alg_id); ++ return -EINVAL; ++} ++ ++int ipsec_alg_init(void) { ++ KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " ++ "KLIPS alg v=%d.%d.%d-%d (EALG_MAX=%d, AALG_MAX=%d)\n", ++ IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION), ++ SADB_EALG_MAX, SADB_AALG_MAX); ++ /* Initialize tables */ ++ write_lock_bh(&ipsec_alg_lock); ++ ipsec_alg_hash_init(); ++ write_unlock_bh(&ipsec_alg_lock); ++ ++ /* Initialize static algos */ ++ KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " ++ "calling ipsec_alg_static_init()\n"); ++ ++ /* If we are suppose to use our AES, and don't have CryptoAPI enabled... */ ++#if defined(CONFIG_IPSEC_ENC_AES) && CONFIG_IPSEC_ENC_AES && !defined(CONFIG_IPSEC_ENC_AES_MODULE) && !CONFIG_IPSEC_ENC_CRYPTOAPI && !defined(CONFIG_IPSEC_ENC_CRYPTOAPI_MODULE) ++ { ++ extern int ipsec_aes_init(void); ++ ipsec_aes_init(); ++ } ++#endif ++ ++ /* If we are doing CryptoAPI, then init */ ++#if defined(CONFIG_IPSEC_ENC_CRYPTOAPI) && CONFIG_IPSEC_ENC_CRYPTOAPI && !defined(CONFIG_IPSEC_ENC_CRYPTOAPI_MODULE) ++ { ++ extern int ipsec_cryptoapi_init(void); ++ ipsec_cryptoapi_init(); ++ } ++#endif ++ ++ ++ return 0; ++} ++ ++/********************************************** ++ * ++ * INTERFACE for ipsec_sa init and wipe ++ * ++ **********************************************/ ++ ++/* ++ * Called from pluto -> pfkey_v2_parser.c:pfkey_ipsec_sa_init() ++ */ ++int ipsec_alg_sa_init(struct ipsec_sa *sa_p) { ++ struct ipsec_alg_enc *ixt_e; ++ struct ipsec_alg_auth *ixt_a; ++ ++ /* Only ESP for now ... */ ++ if (sa_p->ips_said.proto != IPPROTO_ESP) ++ return -EPROTONOSUPPORT; ++ KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_init() :" ++ "entering for encalg=%d, authalg=%d\n", ++ sa_p->ips_encalg, sa_p->ips_authalg); ++ if ((ixt_e=(struct ipsec_alg_enc *) ++ ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, sa_p->ips_encalg))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug: ipsec_alg_sa_init() :" ++ "found ipsec_alg (ixt_e=%p) for encalg=%d\n", ++ ixt_e, sa_p->ips_encalg); ++ sa_p->ips_alg_enc=ixt_e; ++ } ++ if ((ixt_a=(struct ipsec_alg_auth *) ++ ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, sa_p->ips_authalg))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug: ipsec_alg_sa_init() :" ++ "found ipsec_alg (ixt_a=%p) for auth=%d\n", ++ ixt_a, sa_p->ips_authalg); ++ sa_p->ips_alg_auth=ixt_a; ++ } ++ return 0; ++} ++ ++/* ++ * Called from pluto -> ipsec_sa.c:ipsec_sa_delchain() ++ */ ++int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p) { ++ struct ipsec_alg *ixt; ++ if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_enc)) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" ++ "unlinking for encalg=%d\n", ++ ixt->ixt_alg_id); ++ ipsec_alg_put(ixt); ++ } ++ if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_auth)) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" ++ "unlinking for authalg=%d\n", ++ ixt->ixt_alg_id); ++ ipsec_alg_put(ixt); ++ } ++ return 0; ++} ++ ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_xform_get_info(char *buffer, ++ char **start, ++ off_t offset, ++ int length IPSEC_PROC_LAST_ARG) ++{ ++ int len = 0; ++ off_t begin = 0; ++ int i; ++ struct list_head *head; ++ struct ipsec_alg *ixt; ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_tncfg_get_info: " ++ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", ++ buffer, ++ *start, ++ (int)offset, ++ length); ++ ++ for(i = 0, head = ipsec_alg_hash_table; i< IPSEC_ALG_HASHSZ; i++, head++) ++ { ++ struct list_head *p; ++ for (p=head->next; p!=head; p=p->next) ++ { ++ ixt = list_entry(p, struct ipsec_alg, ixt_list); ++ len += ipsec_snprintf(buffer+len, length-len, ++ "VERSION=%d TYPE=%d ID=%d NAME=%s REFCNT=%d ", ++ ixt->ixt_version, ixt->ixt_alg_type, ixt->ixt_alg_id, ++ ixt->ixt_name, ixt->ixt_refcnt); ++ ++ len += ipsec_snprintf(buffer+len, length-len, ++ "STATE=%08x BLOCKSIZE=%d IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", ++ ixt->ixt_state, ixt->ixt_blocksize, ++ ixt->ixt_ivlen, ixt->ixt_keyminbits, ixt->ixt_keymaxbits); ++ ++ len += ipsec_snprintf(buffer+len, length-len, ++ "IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", ++ ixt->ixt_ivlen, ixt->ixt_keyminbits, ixt->ixt_keymaxbits); ++ ++ switch(ixt->ixt_alg_type) ++ { ++ case IPSEC_ALG_TYPE_AUTH: ++ { ++ struct ipsec_alg_auth *auth = (struct ipsec_alg_auth *)ixt; ++ ++ len += ipsec_snprintf(buffer+len, length-len, ++ "KEYLEN=%d CTXSIZE=%d AUTHLEN=%d ", ++ auth->ixt_a_keylen, auth->ixt_a_ctx_size, ++ auth->ixt_a_authlen); ++ break; ++ } ++ case IPSEC_ALG_TYPE_ENCRYPT: ++ { ++ struct ipsec_alg_enc *enc = (struct ipsec_alg_enc *)ixt; ++ len += ipsec_snprintf(buffer+len, length-len, ++ "KEYLEN=%d CTXSIZE=%d ", ++ enc->ixt_e_keylen, enc->ixt_e_ctx_size); ++ ++ break; ++ } ++ } ++ ++ len += ipsec_snprintf(buffer+len, length-len, "\n"); ++ } ++ } ++ ++ *start = buffer + (offset - begin); /* Start of wanted data */ ++ len -= (offset - begin); /* Start slop */ ++ if (len > length) ++ len = length; ++ return len; ++} ++ ++ ++/* ++ * As the author of this module, I ONLY ALLOW using it from ++ * GPL (or same LICENSE TERMS as kernel source) modules. ++ * ++ * In respect to hardware crypto engines this means: ++ * * Closed-source device drivers ARE NOT ALLOWED to use ++ * this interface. ++ * * Closed-source VHDL/Verilog firmware running on ++ * the crypto hardware device IS ALLOWED to use this interface ++ * via a GPL (or same LICENSE TERMS as kernel source) device driver. ++ * --Juan Jose Ciarlante 20/03/2002 (thanks RGB for the correct wording) ++ */ ++ ++/* ++ * These symbols can only be used from GPL modules ++ * for now, I'm disabling this because it creates false ++ * symbol problems for old modutils. ++ */ ++ ++/* #ifndef EXPORT_SYMBOL_GPL */ ++#undef EXPORT_SYMBOL_GPL ++#define EXPORT_SYMBOL_GPL EXPORT_SYMBOL ++/* #endif */ ++EXPORT_SYMBOL_GPL(register_ipsec_alg); ++EXPORT_SYMBOL_GPL(unregister_ipsec_alg); ++EXPORT_SYMBOL_GPL(ipsec_alg_test); ++#endif /* CONFIG_IPSEC_ALG */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_alg_aes.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,263 @@ ++/* ++ * ipsec_alg AES cipher stubs ++ * ++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar> ++ * ++ * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * Fixes by: ++ * PK: Pawel Krawczyk <kravietz@aba.krakow.pl> ++ * Fixes list: ++ * PK: make XCBC comply with latest draft (keylength) ++ * ++ */ ++#include <linux/config.h> ++#include <linux/version.h> ++ ++/* ++ * special case: ipsec core modular with this static algo inside: ++ * must avoid MODULE magic for this file ++ */ ++#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_AES ++#undef MODULE ++#endif ++ ++#include <linux/module.h> ++#include <linux/init.h> ++ ++#include <linux/kernel.h> /* printk() */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/string.h> ++ ++/* Check if __exit is defined, if not null it */ ++#ifndef __exit ++#define __exit ++#endif ++ ++/* Low freeswan header coupling */ ++#include "openswan/ipsec_alg.h" ++#include "crypto/aes_cbc.h" ++ ++#define CONFIG_IPSEC_ALG_AES_MAC 1 ++ ++#define AES_CONTEXT_T aes_context ++MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>"); ++static int debug=0; ++MODULE_PARM(debug, "i"); ++static int test=0; ++MODULE_PARM(test, "i"); ++static int excl=0; ++MODULE_PARM(excl, "i"); ++static int keyminbits=0; ++MODULE_PARM(keyminbits, "i"); ++static int keymaxbits=0; ++MODULE_PARM(keymaxbits, "i"); ++ ++#if CONFIG_IPSEC_ALG_AES_MAC ++#include "crypto/aes_xcbc_mac.h" ++ ++/* ++ * Not IANA number yet (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt). ++ * We use 9 for non-modular algorithm and none for modular, thus ++ * forcing user to specify one on module load. -kravietz ++ */ ++#ifdef MODULE ++static int auth_id=0; ++#else ++static int auth_id=9; ++#endif ++MODULE_PARM(auth_id, "i"); ++#endif ++ ++#define ESP_AES 12 /* truely _constant_ :) */ ++ ++/* 128, 192 or 256 */ ++#define ESP_AES_KEY_SZ_MIN 16 /* 128 bit secret key */ ++#define ESP_AES_KEY_SZ_MAX 32 /* 256 bit secret key */ ++#define ESP_AES_CBC_BLK_LEN 16 /* AES-CBC block size */ ++ ++/* Values according to draft-ietf-ipsec-ciph-aes-xcbc-mac-02.txt ++ * -kravietz ++ */ ++#define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ ++#define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ ++ ++static int _aes_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) { ++ int ret; ++ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; ++ ret=AES_set_key(ctx, key, keysize)!=0? 0: -EINVAL; ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:_aes_set_key:" ++ "ret=%d key_e=%p key=%p keysize=%d\n", ++ ret, key_e, key, keysize); ++ return ret; ++} ++static int _aes_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { ++ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:" ++ "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n", ++ key_e, in, ilen, iv, encrypt); ++ return AES_cbc_encrypt(ctx, in, in, ilen, iv, encrypt); ++} ++#if CONFIG_IPSEC_ALG_AES_MAC ++static int _aes_mac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) { ++ aes_context_mac *ctxm=(aes_context_mac *)key_a; ++ return AES_xcbc_mac_set_key(ctxm, key, keylen)? 0 : -EINVAL; ++} ++static int _aes_mac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) { ++ int ret; ++ char hash_buf[16]; ++ aes_context_mac *ctxm=(aes_context_mac *)key_a; ++ ret=AES_xcbc_mac_hash(ctxm, dat, len, hash_buf); ++ memcpy(hash, hash_buf, hashlen); ++ return ret; ++} ++static struct ipsec_alg_auth ipsec_alg_AES_MAC = { ++ ixt_version: IPSEC_ALG_VERSION, ++ ixt_module: THIS_MODULE, ++ ixt_refcnt: ATOMIC_INIT(0), ++ ixt_alg_type: IPSEC_ALG_TYPE_AUTH, ++ ixt_alg_id: 0, ++ ixt_name: "aes_mac", ++ ixt_blocksize: ESP_AES_MAC_BLK_LEN, ++ ixt_keyminbits: ESP_AES_MAC_KEY_SZ*8, ++ ixt_keymaxbits: ESP_AES_MAC_KEY_SZ*8, ++ ixt_a_keylen: ESP_AES_MAC_KEY_SZ, ++ ixt_a_ctx_size: sizeof(aes_context_mac), ++ ixt_a_hmac_set_key: _aes_mac_set_key, ++ ixt_a_hmac_hash:_aes_mac_hash, ++}; ++#endif /* CONFIG_IPSEC_ALG_AES_MAC */ ++static struct ipsec_alg_enc ipsec_alg_AES = { ++ ixt_version: IPSEC_ALG_VERSION, ++ ixt_module: THIS_MODULE, ++ ixt_refcnt: ATOMIC_INIT(0), ++ ixt_alg_type: IPSEC_ALG_TYPE_ENCRYPT, ++ ixt_alg_id: ESP_AES, ++ ixt_name: "aes", ++ ixt_blocksize: ESP_AES_CBC_BLK_LEN, ++ ixt_keyminbits: ESP_AES_KEY_SZ_MIN*8, ++ ixt_keymaxbits: ESP_AES_KEY_SZ_MAX*8, ++ ixt_e_keylen: ESP_AES_KEY_SZ_MAX, ++ ixt_e_ctx_size: sizeof(AES_CONTEXT_T), ++ ixt_e_set_key: _aes_set_key, ++ ixt_e_cbc_encrypt:_aes_cbc_encrypt, ++}; ++ ++#if defined(CONFIG_IPSEC_ENC_AES_MODULE) ++IPSEC_ALG_MODULE_INIT_MOD( ipsec_aes_init ) ++#else ++IPSEC_ALG_MODULE_INIT_STATIC( ipsec_aes_init ) ++#endif ++{ ++ int ret, test_ret; ++ ++ if (keyminbits) ++ ipsec_alg_AES.ixt_keyminbits=keyminbits; ++ if (keymaxbits) { ++ ipsec_alg_AES.ixt_keymaxbits=keymaxbits; ++ if (keymaxbits*8>ipsec_alg_AES.ixt_keymaxbits) ++ ipsec_alg_AES.ixt_e_keylen=keymaxbits*8; ++ } ++ if (excl) ipsec_alg_AES.ixt_state |= IPSEC_ALG_ST_EXCL; ++ ret=register_ipsec_alg_enc(&ipsec_alg_AES); ++ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", ++ ipsec_alg_AES.ixt_alg_type, ++ ipsec_alg_AES.ixt_alg_id, ++ ipsec_alg_AES.ixt_name, ++ ret); ++ if (ret==0 && test) { ++ test_ret=ipsec_alg_test( ++ ipsec_alg_AES.ixt_alg_type, ++ ipsec_alg_AES.ixt_alg_id, ++ test); ++ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", ++ ipsec_alg_AES.ixt_alg_type, ++ ipsec_alg_AES.ixt_alg_id, ++ test_ret); ++ } ++#if CONFIG_IPSEC_ALG_AES_MAC ++ if (auth_id!=0){ ++ int ret; ++ ipsec_alg_AES_MAC.ixt_alg_id=auth_id; ++ ret=register_ipsec_alg_auth(&ipsec_alg_AES_MAC); ++ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", ++ ipsec_alg_AES_MAC.ixt_alg_type, ++ ipsec_alg_AES_MAC.ixt_alg_id, ++ ipsec_alg_AES_MAC.ixt_name, ++ ret); ++ if (ret==0 && test) { ++ test_ret=ipsec_alg_test( ++ ipsec_alg_AES_MAC.ixt_alg_type, ++ ipsec_alg_AES_MAC.ixt_alg_id, ++ test); ++ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", ++ ipsec_alg_AES_MAC.ixt_alg_type, ++ ipsec_alg_AES_MAC.ixt_alg_id, ++ test_ret); ++ } ++ } else { ++ printk(KERN_DEBUG "klips_debug: experimental ipsec_alg_AES_MAC not registered [Ok] (auth_id=%d)\n", auth_id); ++ } ++#endif /* CONFIG_IPSEC_ALG_AES_MAC */ ++ return ret; ++} ++ ++#if defined(CONFIG_IPSEC_ENC_AES_MODULE) ++IPSEC_ALG_MODULE_EXIT_MOD( ipsec_aes_fini ) ++#else ++IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_aes_fini ) ++#endif ++{ ++#if CONFIG_IPSEC_ALG_AES_MAC ++ if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC); ++#endif /* CONFIG_IPSEC_ALG_AES_MAC */ ++ unregister_ipsec_alg_enc(&ipsec_alg_AES); ++ return; ++} ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif ++ ++#if 0+NOT_YET ++#ifndef MODULE ++/* ++ * This is intended for static module setups, currently ++ * doesn't work for modular ipsec.o with static algos inside ++ */ ++static int setup_keybits(const char *str) ++{ ++ unsigned aux; ++ char *end; ++ ++ aux = simple_strtoul(str,&end,0); ++ if (aux != 128 && aux != 192 && aux != 256) ++ return 0; ++ keyminbits = aux; ++ ++ if (*end == 0 || *end != ',') ++ return 1; ++ str=end+1; ++ aux = simple_strtoul(str, NULL, 0); ++ if (aux != 128 && aux != 192 && aux != 256) ++ return 0; ++ if (aux >= keyminbits) ++ keymaxbits = aux; ++ return 1; ++} ++__setup("ipsec_aes_keybits=", setup_keybits); ++#endif ++#endif ++EXPORT_NO_SYMBOLS; +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_alg_cryptoapi.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,421 @@ ++/* ++ * ipsec_alg to linux cryptoapi GLUE ++ * ++ * Authors: CODE.ar TEAM ++ * Harpo MAxx <harpo@linuxmendoza.org.ar> ++ * JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar> ++ * Luciano Ruete <docemeses@softhome.net> ++ * ++ * ipsec_alg_cryptoapi.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * Example usage: ++ * modinfo -p ipsec_cryptoapi (quite useful info, including supported algos) ++ * modprobe ipsec_cryptoapi ++ * modprobe ipsec_cryptoapi test=1 ++ * modprobe ipsec_cryptoapi excl=1 (exclusive cipher/algo) ++ * modprobe ipsec_cryptoapi noauto=1 aes=1 twofish=1 (only these ciphers) ++ * modprobe ipsec_cryptoapi aes=128,128 (force these keylens) ++ * modprobe ipsec_cryptoapi des_ede3=0 (everything but 3DES) ++ */ ++#include <linux/config.h> ++#include <linux/version.h> ++ ++/* ++ * special case: ipsec core modular with this static algo inside: ++ * must avoid MODULE magic for this file ++ */ ++#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CRYPTOAPI ++#undef MODULE ++#endif ++ ++#include <linux/module.h> ++#include <linux/init.h> ++ ++#include <linux/kernel.h> /* printk() */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/string.h> ++ ++/* Check if __exit is defined, if not null it */ ++#ifndef __exit ++#define __exit ++#endif ++ ++/* warn the innocent */ ++#if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE) ++#warning "No linux CryptoAPI found, install 2.4.22+ or 2.6.x" ++#define NO_CRYPTOAPI_SUPPORT ++#endif ++/* Low Openswan header coupling */ ++#include "openswan/ipsec_alg.h" ++ ++#include <linux/crypto.h> ++#ifdef CRYPTO_API_VERSION_CODE ++#warning "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported" ++#define NO_CRYPTOAPI_SUPPORT ++#endif ++ ++#ifdef NO_CRYPTOAPI_SUPPORT ++#warning "Building an unusable module :P" ++/* Catch old CryptoAPI by not allowing module to load */ ++IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init ) ++{ ++ printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n"); ++ return -EINVAL; ++} ++#else ++#include <asm/scatterlist.h> ++#include <asm/pgtable.h> ++#include <linux/mm.h> ++ ++#define CIPHERNAME_AES "aes" ++#define CIPHERNAME_3DES "des3_ede" ++#define CIPHERNAME_BLOWFISH "blowfish" ++#define CIPHERNAME_CAST "cast5" ++#define CIPHERNAME_SERPENT "serpent" ++#define CIPHERNAME_TWOFISH "twofish" ++ ++#define ESP_3DES 3 ++#define ESP_AES 12 ++#define ESP_BLOWFISH 7 /* truely _constant_ :) */ ++#define ESP_CAST 6 /* quite constant :) */ ++#define ESP_SERPENT 252 /* from ipsec drafts */ ++#define ESP_TWOFISH 253 /* from ipsec drafts */ ++ ++#define AH_MD5 2 ++#define AH_SHA 3 ++#define DIGESTNAME_MD5 "md5" ++#define DIGESTNAME_SHA1 "sha1" ++ ++MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); ++static int debug=0; ++MODULE_PARM(debug, "i"); ++static int test=0; ++MODULE_PARM(test, "i"); ++static int excl=0; ++MODULE_PARM(excl, "i"); ++ ++static int noauto = 0; ++MODULE_PARM(noauto,"i"); ++MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones"); ++ ++static int des_ede3[] = {-1, -1}; ++static int aes[] = {-1, -1}; ++static int blowfish[] = {-1, -1}; ++static int cast[] = {-1, -1}; ++static int serpent[] = {-1, -1}; ++static int twofish[] = {-1, -1}; ++ ++MODULE_PARM(des_ede3,"1-2i"); ++MODULE_PARM(aes,"1-2i"); ++MODULE_PARM(blowfish,"1-2i"); ++MODULE_PARM(cast,"1-2i"); ++MODULE_PARM(serpent,"1-2i"); ++MODULE_PARM(twofish,"1-2i"); ++MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse"); ++MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens"); ++MODULE_PARM_DESC(blowfish, "0: disable | 1: force_enable | min,max: keybitlens"); ++MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens"); ++MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens"); ++MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens"); ++ ++struct ipsec_alg_capi_cipher { ++ const char *ciphername; /* cryptoapi's ciphername */ ++ unsigned blocksize; ++ unsigned short minbits; ++ unsigned short maxbits; ++ int *parm; /* lkm param for this cipher */ ++ struct ipsec_alg_enc alg; /* note it's not a pointer */ ++}; ++static struct ipsec_alg_capi_cipher alg_capi_carray[] = { ++ { CIPHERNAME_AES , 16, 128, 256, aes , { ixt_alg_id: ESP_AES, }}, ++ { CIPHERNAME_TWOFISH , 16, 128, 256, twofish, { ixt_alg_id: ESP_TWOFISH, }}, ++ { CIPHERNAME_SERPENT , 16, 128, 256, serpent, { ixt_alg_id: ESP_SERPENT, }}, ++ { CIPHERNAME_CAST , 8, 128, 128, cast , { ixt_alg_id: ESP_CAST, }}, ++ { CIPHERNAME_BLOWFISH , 8, 96, 448, blowfish,{ ixt_alg_id: ESP_BLOWFISH, }}, ++ { CIPHERNAME_3DES , 8, 192, 192, des_ede3,{ ixt_alg_id: ESP_3DES, }}, ++ { NULL, 0, 0, 0, NULL, {} } ++}; ++#ifdef NOT_YET ++struct ipsec_alg_capi_digest { ++ const char *digestname; /* cryptoapi's digestname */ ++ struct digest_implementation *di; ++ struct ipsec_alg_auth alg; /* note it's not a pointer */ ++}; ++static struct ipsec_alg_capi_cipher alg_capi_darray[] = { ++ { DIGESTNAME_MD5, NULL, { ixt_alg_id: AH_MD5, }}, ++ { DIGESTNAME_SHA1, NULL, { ixt_alg_id: AH_SHA, }}, ++ { NULL, NULL, {} } ++}; ++#endif ++/* ++ * "generic" linux cryptoapi setup_cipher() function ++ */ ++int setup_cipher(const char *ciphername) ++{ ++ return crypto_alg_available(ciphername, 0); ++} ++ ++/* ++ * setups ipsec_alg_capi_cipher "hyper" struct components, calling ++ * register_ipsec_alg for cointaned ipsec_alg object ++ */ ++static void _capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e); ++static __u8 * _capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen); ++static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt); ++ ++static int ++setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr) ++{ ++ int ret; ++ cptr->alg.ixt_version = IPSEC_ALG_VERSION; ++ cptr->alg.ixt_module = THIS_MODULE; ++ atomic_set (& cptr->alg.ixt_refcnt, 0); ++ strncpy (cptr->alg.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_name)); ++ ++ cptr->alg.ixt_blocksize=cptr->blocksize; ++ cptr->alg.ixt_keyminbits=cptr->minbits; ++ cptr->alg.ixt_keymaxbits=cptr->maxbits; ++ cptr->alg.ixt_state = 0; ++ if (excl) cptr->alg.ixt_state |= IPSEC_ALG_ST_EXCL; ++ cptr->alg.ixt_e_keylen=cptr->alg.ixt_keymaxbits/8; ++ cptr->alg.ixt_e_ctx_size = 0; ++ cptr->alg.ixt_alg_type = IPSEC_ALG_TYPE_ENCRYPT; ++ cptr->alg.ixt_e_new_key = _capi_new_key; ++ cptr->alg.ixt_e_destroy_key = _capi_destroy_key; ++ cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt; ++ cptr->alg.ixt_data = cptr; ++ ++ ret=register_ipsec_alg_enc(&cptr->alg); ++ printk("setup_ipsec_alg_capi_cipher(): " ++ "alg_type=%d alg_id=%d name=%s " ++ "keyminbits=%d keymaxbits=%d, ret=%d\n", ++ cptr->alg.ixt_alg_type, ++ cptr->alg.ixt_alg_id, ++ cptr->alg.ixt_name, ++ cptr->alg.ixt_keyminbits, ++ cptr->alg.ixt_keymaxbits, ++ ret); ++ return ret; ++} ++/* ++ * called in ipsec_sa_wipe() time, will destroy key contexts ++ * and do 1 unbind() ++ */ ++static void ++_capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e) ++{ ++ struct crypto_tfm *tfm=(struct crypto_tfm*)key_e; ++ ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" ++ "name=%s key_e=%p \n", ++ alg->ixt_name, key_e); ++ if (!key_e) { ++ printk(KERN_ERR "klips_debug: _capi_destroy_key:" ++ "name=%s NULL key_e!\n", ++ alg->ixt_name); ++ return; ++ } ++ crypto_free_tfm(tfm); ++} ++ ++/* ++ * create new key context, need alg->ixt_data to know which ++ * (of many) cipher inside this module is the target ++ */ ++static __u8 * ++_capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen) ++{ ++ struct ipsec_alg_capi_cipher *cptr; ++ struct crypto_tfm *tfm=NULL; ++ ++ cptr = alg->ixt_data; ++ if (!cptr) { ++ printk(KERN_ERR "_capi_new_key(): " ++ "NULL ixt_data (?!) for \"%s\" algo\n" ++ , alg->ixt_name); ++ goto err; ++ } ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:_capi_new_key:" ++ "name=%s cptr=%p key=%p keysize=%d\n", ++ alg->ixt_name, cptr, key, keylen); ++ ++ /* ++ * alloc tfm ++ */ ++ tfm = crypto_alloc_tfm(cptr->ciphername, CRYPTO_TFM_MODE_CBC); ++ if (!tfm) { ++ printk(KERN_ERR "_capi_new_key(): " ++ "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n" ++ , alg->ixt_name, cptr->ciphername); ++ goto err; ++ } ++ if (crypto_cipher_setkey(tfm, key, keylen) < 0) { ++ printk(KERN_ERR "_capi_new_key(): " ++ "failed new_key() for \"%s\" cryptoapi algo (keylen=%d)\n" ++ , alg->ixt_name, keylen); ++ crypto_free_tfm(tfm); ++ tfm=NULL; ++ } ++err: ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:_capi_new_key:" ++ "name=%s key=%p keylen=%d tfm=%p\n", ++ alg->ixt_name, key, keylen, tfm); ++ return (__u8 *) tfm; ++} ++/* ++ * core encryption function: will use cx->ci to call actual cipher's ++ * cbc function ++ */ ++static int ++_capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { ++ int error =0; ++ struct crypto_tfm *tfm=(struct crypto_tfm *)key_e; ++ struct scatterlist sg = { ++ .page = virt_to_page(in), ++ .offset = (unsigned long)(in) % PAGE_SIZE, ++ .length=ilen, ++ }; ++ if (debug > 1) ++ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" ++ "key_e=%p " ++ "in=%p out=%p ilen=%d iv=%p encrypt=%d\n" ++ , key_e ++ , in, in, ilen, iv, encrypt); ++ crypto_cipher_set_iv(tfm, iv, crypto_tfm_alg_ivsize(tfm)); ++ if (encrypt) ++ error = crypto_cipher_encrypt (tfm, &sg, &sg, ilen); ++ else ++ error = crypto_cipher_decrypt (tfm, &sg, &sg, ilen); ++ if (debug > 1) ++ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" ++ "error=%d\n" ++ , error); ++ return (error<0)? error : ilen; ++} ++/* ++ * main initialization loop: for each cipher in list, do ++ * 1) setup cryptoapi cipher else continue ++ * 2) register ipsec_alg object ++ */ ++static int ++setup_cipher_list (struct ipsec_alg_capi_cipher* clist) ++{ ++ struct ipsec_alg_capi_cipher *cptr; ++ /* foreach cipher in list ... */ ++ for (cptr=clist;cptr->ciphername;cptr++) { ++ /* ++ * see if cipher has been disabled (0) or ++ * if noauto set and not enabled (1) ++ */ ++ if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) { ++ if (debug>0) ++ printk(KERN_INFO "setup_cipher_list(): " ++ "ciphername=%s skipped at user request: " ++ "noauto=%d parm[0]=%d parm[1]=%d\n" ++ , cptr->ciphername ++ , noauto ++ , cptr->parm[0] ++ , cptr->parm[1]); ++ continue; ++ } ++ /* ++ * use a local ci to avoid touching cptr->ci, ++ * if register ipsec_alg success then bind cipher ++ */ ++ if( setup_cipher(cptr->ciphername) ) { ++ if (debug > 0) ++ printk(KERN_DEBUG "klips_debug:" ++ "setup_cipher_list():" ++ "ciphername=%s found\n" ++ , cptr->ciphername); ++ if (setup_ipsec_alg_capi_cipher(cptr) == 0) { ++ ++ ++ } else { ++ printk(KERN_ERR "klips_debug:" ++ "setup_cipher_list():" ++ "ciphername=%s failed ipsec_alg_register\n" ++ , cptr->ciphername); ++ } ++ } else { ++ if (debug>0) ++ printk(KERN_INFO "setup_cipher_list(): lookup for ciphername=%s: not found \n", ++ cptr->ciphername); ++ } ++ } ++ return 0; ++} ++/* ++ * deregister ipsec_alg objects and unbind ciphers ++ */ ++static int ++unsetup_cipher_list (struct ipsec_alg_capi_cipher* clist) ++{ ++ struct ipsec_alg_capi_cipher *cptr; ++ /* foreach cipher in list ... */ ++ for (cptr=clist;cptr->ciphername;cptr++) { ++ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { ++ unregister_ipsec_alg_enc(&cptr->alg); ++ } ++ } ++ return 0; ++} ++/* ++ * test loop for registered algos ++ */ ++static int ++test_cipher_list (struct ipsec_alg_capi_cipher* clist) ++{ ++ int test_ret; ++ struct ipsec_alg_capi_cipher *cptr; ++ /* foreach cipher in list ... */ ++ for (cptr=clist;cptr->ciphername;cptr++) { ++ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { ++ test_ret=ipsec_alg_test( ++ cptr->alg.ixt_alg_type, ++ cptr->alg.ixt_alg_id, ++ test); ++ printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", ++ cptr->alg.ixt_alg_type, ++ cptr->alg.ixt_alg_id, ++ test_ret); ++ } ++ } ++ return 0; ++} ++ ++IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init ) ++{ ++ int ret, test_ret; ++ if ((ret=setup_cipher_list(alg_capi_carray)) < 0) ++ return -EPROTONOSUPPORT; ++ if (ret==0 && test) { ++ test_ret=test_cipher_list(alg_capi_carray); ++ } ++ return ret; ++} ++IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_cryptoapi_fini ) ++{ ++ unsetup_cipher_list(alg_capi_carray); ++ return; ++} ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif ++ ++EXPORT_NO_SYMBOLS; ++#endif /* NO_CRYPTOAPI_SUPPORT */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_esp.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,558 @@ ++/* ++ * processing code for ESP ++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++char ipsec_esp_c_version[] = "RCSID $Id: ipsec_esp.c,v 1.2 2004/04/06 02:49:25 mcr Exp $"; ++#include <linux/config.h> ++#include <linux/version.h> ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define proto_priv cb ++#endif /* NET21 */ ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_rcv.h" ++#include "openswan/ipsec_xmit.h" ++ ++#include "openswan/ipsec_auth.h" ++ ++#ifdef CONFIG_IPSEC_ESP ++#include "openswan/ipsec_esp.h" ++#endif /* CONFIG_IPSEC_ESP */ ++ ++#include "openswan/ipsec_proto.h" ++#include "openswan/ipsec_alg.h" ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_esp = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ ++#ifdef CONFIG_IPSEC_ESP ++enum ipsec_rcv_value ++ipsec_rcv_esp_checks(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb) ++{ ++ __u8 proto; ++ int len; /* packet length */ ++ ++ len = skb->len; ++ proto = irs->ipp->protocol; ++ ++ /* XXX this will need to be 8 for IPv6 */ ++ if ((proto == IPPROTO_ESP) && ((len - irs->iphlen) % 4)) { ++ printk("klips_error:ipsec_rcv: " ++ "got packet with content length = %d from %s -- should be on 4 octet boundary, packet dropped\n", ++ len - irs->iphlen, ++ irs->ipsaddr_txt); ++ if(irs->stats) { ++ irs->stats->rx_errors++; ++ } ++ return IPSEC_RCV_BADLEN; ++ } ++ ++ if(skb->len < (irs->hard_header_len + sizeof(struct iphdr) + sizeof(struct esphdr))) { ++ KLIPS_PRINT(debug_rcv & DB_RX_INAU, ++ "klips_debug:ipsec_rcv: " ++ "runt esp packet of skb->len=%d received from %s, dropped.\n", ++ skb->len, ++ irs->ipsaddr_txt); ++ if(irs->stats) { ++ irs->stats->rx_errors++; ++ } ++ return IPSEC_RCV_BADLEN; ++ } ++ ++ irs->protostuff.espstuff.espp = (struct esphdr *)(skb->data + irs->iphlen); ++ irs->said.spi = irs->protostuff.espstuff.espp->esp_spi; ++ ++ return IPSEC_RCV_OK; ++} ++ ++enum ipsec_rcv_value ++ipsec_rcv_esp_decrypt_setup(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb, ++ __u32 *replay, ++ unsigned char **authenticator) ++{ ++ struct esphdr *espp = irs->protostuff.espstuff.espp; ++ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "packet from %s received with seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n", ++ irs->ipsaddr_txt, ++ (__u32)ntohl(espp->esp_rpl), ++ (__u32)ntohl(*((__u32 *)(espp->esp_iv) )), ++ (__u32)ntohl(*((__u32 *)(espp->esp_iv) + 1)), ++ irs->len, ++ irs->ilen, ++ irs->sa_len ? irs->sa : " (error)"); ++ ++ *replay = ntohl(espp->esp_rpl); ++ *authenticator = &(skb->data[irs->len - irs->authlen]); ++ ++ return IPSEC_RCV_OK; ++} ++ ++enum ipsec_rcv_value ++ipsec_rcv_esp_authcalc(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb) ++{ ++ struct auth_alg *aa; ++ struct esphdr *espp = irs->protostuff.espstuff.espp; ++ union { ++ MD5_CTX md5; ++ SHA1_CTX sha1; ++ } tctx; ++ ++#ifdef CONFIG_IPSEC_ALG ++ if (irs->ipsp->ips_alg_auth) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "ipsec_alg hashing proto=%d... ", ++ irs->said.proto); ++ if(irs->said.proto == IPPROTO_ESP) { ++ ipsec_alg_sa_esp_hash(irs->ipsp, ++ (caddr_t)espp, irs->ilen, ++ irs->hash, AHHMAC_HASHLEN); ++ return IPSEC_RCV_OK; ++ } ++ return IPSEC_RCV_BADPROTO; ++ } ++#endif ++ aa = irs->authfuncs; ++ ++ /* copy the initialized keying material */ ++ memcpy(&tctx, irs->ictx, irs->ictx_len); ++ ++ (*aa->update)((void *)&tctx, (caddr_t)espp, irs->ilen); ++ ++ (*aa->final)(irs->hash, (void *)&tctx); ++ ++ memcpy(&tctx, irs->octx, irs->octx_len); ++ ++ (*aa->update)((void *)&tctx, irs->hash, aa->hashlen); ++ (*aa->final)(irs->hash, (void *)&tctx); ++ ++ return IPSEC_RCV_OK; ++} ++ ++ ++enum ipsec_rcv_value ++ipsec_rcv_esp_decrypt(struct ipsec_rcv_state *irs) ++{ ++ struct ipsec_sa *ipsp = irs->ipsp; ++ struct esphdr *espp = irs->protostuff.espstuff.espp; ++ int esphlen = 0; ++ __u8 *idat; /* pointer to content to be decrypted/authenticated */ ++ __u32 iv[2]; ++ int pad = 0, padlen; ++ int badpad = 0; ++ int i; ++ struct sk_buff *skb; ++#ifdef CONFIG_IPSEC_ALG ++ struct ipsec_alg_enc *ixt_e=NULL; ++#endif /* CONFIG_IPSEC_ALG */ ++ ++ skb=irs->skb; ++ ++ idat = skb->data + irs->iphlen; ++ ++#ifdef CONFIG_IPSEC_ALG ++ if ((ixt_e=ipsp->ips_alg_enc)) { ++ esphlen = ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "encalg=%d esphlen=%d\n", ++ ipsp->ips_encalg, esphlen); ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ipsp->ips_encalg) { ++ case ESP_3DES: ++ iv[0] = *((__u32 *)(espp->esp_iv) ); ++ iv[1] = *((__u32 *)(espp->esp_iv) + 1); ++ esphlen = sizeof(struct esphdr); ++ break; ++ default: ++ ipsp->ips_errs.ips_alg_errs += 1; ++ if(irs->stats) { ++ irs->stats->rx_errors++; ++ } ++ return IPSEC_RCV_ESP_BADALG; ++ } ++ ++ idat += esphlen; ++ irs->ilen -= esphlen; ++ ++#ifdef CONFIG_IPSEC_ALG ++ if (ixt_e) ++ { ++ if (ipsec_alg_esp_encrypt(ipsp, ++ idat, irs->ilen, espp->esp_iv, ++ IPSEC_ALG_DECRYPT) <= 0) ++ { ++ printk("klips_error:ipsec_rcv: " ++ "got packet with esplen = %d " ++ "from %s -- should be on " ++ "ENC(%d) octet boundary, " ++ "packet dropped\n", ++ irs->ilen, ++ irs->ipsaddr_txt, ++ ipsp->ips_encalg); ++ if(irs->stats) { ++ irs->stats->rx_errors++; ++ } ++ return IPSEC_RCV_BAD_DECRYPT; ++ } ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ipsp->ips_encalg) { ++ case ESP_3DES: ++ if ((irs->ilen) % 8) { ++ ipsp->ips_errs.ips_encsize_errs += 1; ++ printk("klips_error:ipsec_rcv: " ++ "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n", ++ irs->ilen, ++ irs->ipsaddr_txt); ++ if(irs->stats) { ++ irs->stats->rx_errors++; ++ } ++ return IPSEC_RCV_3DES_BADBLOCKING; ++ } ++ des_ede3_cbc_encrypt((des_cblock *)idat, ++ (des_cblock *)idat, ++ irs->ilen, ++ ((struct des_eks *)(ipsp->ips_key_e))[0].ks, ++ ((struct des_eks *)(ipsp->ips_key_e))[1].ks, ++ ((struct des_eks *)(ipsp->ips_key_e))[2].ks, ++ (des_cblock *)iv, 0); ++ break; ++ } ++ ++ ipsec_rcv_dmp("postdecrypt", skb->data, skb->len); ++ ++ irs->next_header = idat[irs->ilen - 1]; ++ padlen = idat[irs->ilen - 2]; ++ pad = padlen + 2 + irs->authlen; ++ ++ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, ++ "klips_debug:ipsec_rcv: " ++ "padlen=%d, contents: 0x<offset>: 0x<value> 0x<value> ...\n", ++ padlen); ++ ++ for (i = 1; i <= padlen; i++) { ++ if((i % 16) == 1) { ++ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, ++ "klips_debug: %02x:", ++ i - 1); ++ } ++ KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, ++ " %02x", ++ idat[irs->ilen - 2 - padlen + i - 1]); ++ if(i != idat[irs->ilen - 2 - padlen + i - 1]) { ++ badpad = 1; ++ } ++ if((i % 16) == 0) { ++ KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, ++ "\n"); ++ } ++ } ++ if((i % 16) != 1) { ++ KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, ++ "\n"); ++ } ++ if(badpad) { ++ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, ++ "klips_debug:ipsec_rcv: " ++ "warning, decrypted packet from %s has bad padding\n", ++ irs->ipsaddr_txt); ++ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, ++ "klips_debug:ipsec_rcv: " ++ "...may be bad decryption -- not dropped\n"); ++ ipsp->ips_errs.ips_encpad_errs += 1; ++ } ++ ++ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, ++ "klips_debug:ipsec_rcv: " ++ "packet decrypted from %s: next_header = %d, padding = %d\n", ++ irs->ipsaddr_txt, ++ irs->next_header, ++ pad - 2 - irs->authlen); ++ ++ irs->ipp->tot_len = htons(ntohs(irs->ipp->tot_len) - (esphlen + pad)); ++ ++ /* ++ * move the IP header forward by the size of the ESP header, which ++ * will remove the the ESP header from the packet. ++ */ ++ memmove((void *)(skb->data + esphlen), ++ (void *)(skb->data), irs->iphlen); ++ ++ ipsec_rcv_dmp("esp postmove", skb->data, skb->len); ++ ++ /* skb_pull below, will move up by esphlen */ ++ ++ /* XXX not clear how this can happen, as the message indicates */ ++ if(skb->len < esphlen) { ++ printk(KERN_WARNING ++ "klips_error:ipsec_rcv: " ++ "tried to skb_pull esphlen=%d, %d available. This should never happen, please report.\n", ++ esphlen, (int)(skb->len)); ++ return IPSEC_RCV_ESP_DECAPFAIL; ++ } ++ skb_pull(skb, esphlen); ++ ++ irs->ipp = (struct iphdr *)skb->data; ++ ++ ipsec_rcv_dmp("esp postpull", skb->data, skb->len); ++ ++ /* now, trip off the padding from the end */ ++ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, ++ "klips_debug:ipsec_rcv: " ++ "trimming to %d.\n", ++ irs->len - esphlen - pad); ++ if(pad + esphlen <= irs->len) { ++ skb_trim(skb, irs->len - esphlen - pad); ++ } else { ++ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, ++ "klips_debug:ipsec_rcv: " ++ "bogus packet, size is zero or negative, dropping.\n"); ++ return IPSEC_RCV_DECAPFAIL; ++ } ++ ++ return IPSEC_RCV_OK; ++} ++ ++enum ipsec_xmit_value ++ipsec_xmit_esp_setup(struct ipsec_xmit_state *ixs) ++{ ++ __u32 iv[2]; ++ struct esphdr *espp; ++ int ilen = 0; ++ int padlen = 0, i; ++ unsigned char *dat; ++ unsigned char *idat, *pad; ++ __u8 hash[AH_AMAX]; ++ union { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ MD5_CTX md5; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ SHA1_CTX sha1; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ } tctx; ++ ++ dat = (unsigned char *)ixs->iph; ++ ++ espp = (struct esphdr *)(dat + ixs->iphlen); ++ espp->esp_spi = ixs->ipsp->ips_said.spi; ++ espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); ++ ++ switch(ixs->ipsp->ips_encalg) { ++#if defined(CONFIG_IPSEC_ENC_3DES) ++#ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ iv[0] = *((__u32*)&(espp->esp_iv) ) = ++ ((__u32*)(ixs->ipsp->ips_iv))[0]; ++ iv[1] = *((__u32*)&(espp->esp_iv) + 1) = ++ ((__u32*)(ixs->ipsp->ips_iv))[1]; ++ break; ++#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_BADALG; ++ } ++ ++ idat = dat + ixs->iphlen + sizeof(struct esphdr); ++ ilen = ixs->skb->len - (ixs->iphlen + sizeof(struct esphdr) + ixs->authlen); ++ ++ /* Self-describing padding */ ++ pad = &dat[ixs->skb->len - ixs->tailroom]; ++ padlen = ixs->tailroom - 2 - ixs->authlen; ++ for (i = 0; i < padlen; i++) { ++ pad[i] = i + 1; ++ } ++ dat[ixs->skb->len - ixs->authlen - 2] = padlen; ++ ++ dat[ixs->skb->len - ixs->authlen - 1] = ixs->iph->protocol; ++ ixs->iph->protocol = IPPROTO_ESP; ++ ++ switch(ixs->ipsp->ips_encalg) { ++#ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++ des_ede3_cbc_encrypt((des_cblock *)idat, ++ (des_cblock *)idat, ++ ilen, ++ ((struct des_eks *)(ixs->ipsp->ips_key_e))[0].ks, ++ ((struct des_eks *)(ixs->ipsp->ips_key_e))[1].ks, ++ ((struct des_eks *)(ixs->ipsp->ips_key_e))[2].ks, ++ (des_cblock *)iv, 1); ++ break; ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_BADALG; ++ } ++ ++ switch(ixs->ipsp->ips_encalg) { ++#if defined(CONFIG_IPSEC_ENC_3DES) ++#ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ /* XXX update IV with the last 8 octets of the encryption */ ++#if KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK ++ ((__u32*)(ixs->ipsp->ips_iv))[0] = ++ ((__u32 *)(idat))[(ilen >> 2) - 2]; ++ ((__u32*)(ixs->ipsp->ips_iv))[1] = ++ ((__u32 *)(idat))[(ilen >> 2) - 1]; ++#else /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ ++ prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, EMT_ESPDES_IV_SZ); ++#endif /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ ++ break; ++#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_BADALG; ++ } ++ ++ switch(ixs->ipsp->ips_authalg) { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ case AH_MD5: ++ ipsec_xmit_dmp("espp", (char*)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); ++ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; ++ ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); ++ ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Final(hash, &tctx.md5); ++ ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash)); ++ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; ++ ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, hash, AHMD596_ALEN); ++ ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Final(hash, &tctx.md5); ++ ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash)); ++ memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen); ++ ++ /* paranoid */ ++ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); ++ memset((caddr_t)hash, 0, sizeof(*hash)); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ case AH_SHA: ++ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; ++ SHA1Update(&tctx.sha1, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); ++ SHA1Final(hash, &tctx.sha1); ++ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; ++ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); ++ SHA1Final(hash, &tctx.sha1); ++ memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen); ++ ++ /* paranoid */ ++ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); ++ memset((caddr_t)hash, 0, sizeof(*hash)); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ case AH_NONE: ++ break; ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_AH_BADALG; ++ } ++#ifdef NET_21 ++ ixs->skb->h.raw = (unsigned char*)espp; ++#endif /* NET_21 */ ++ ++ return IPSEC_XMIT_OK; ++} ++ ++ ++struct xform_functions esp_xform_funcs[]={ ++ { rcv_checks: ipsec_rcv_esp_checks, ++ rcv_setup_auth: ipsec_rcv_esp_decrypt_setup, ++ rcv_calc_auth: ipsec_rcv_esp_authcalc, ++ rcv_decrypt: ipsec_rcv_esp_decrypt, ++ ++ xmit_setup: ipsec_xmit_esp_setup, ++ xmit_headroom: sizeof(struct esphdr), ++ xmit_needtailroom: 1, ++ }, ++}; ++ ++struct inet_protocol esp_protocol = ++{ ++ ipsec_rcv, /* ESP handler */ ++ NULL, /* TUNNEL error control */ ++#ifdef NETDEV_25 ++ 1, /* no policy */ ++#else ++ 0, /* next */ ++ IPPROTO_ESP, /* protocol ID */ ++ 0, /* copy */ ++ NULL, /* data */ ++ "ESP" /* name */ ++#endif ++}; ++ ++ ++ ++#endif /* !CONFIG_IPSEC_ESP */ ++ ++ ++/* ++ * $Log: ipsec_esp.c,v $ ++ * Revision 1.2 2004/04/06 02:49:25 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_init.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,531 @@ ++/* ++ * @(#) Initialization code. ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998 - 2002 Richard Guy Briggs <rgb@freeswan.org> ++ * 2001 - 2004 Michael Richardson <mcr@xelerance.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * /proc system code was split out into ipsec_proc.c after rev. 1.70. ++ * ++ */ ++ ++char ipsec_init_c_version[] = "RCSID $Id: ipsec_init.c,v 1.93 2004/04/06 02:49:26 mcr Exp $"; ++ ++#include <linux/config.h> ++#include <linux/version.h> ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/in.h> /* struct sockaddr_in */ ++#include <linux/skbuff.h> ++#include <linux/random.h> /* get_random_bytes() */ ++#include <openswan.h> ++ ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* 23_SPINLOCK */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* 23_SPINLOCK */ ++#endif /* SPINLOCK */ ++ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++#endif /* NET_21 */ ++ ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#ifdef CONFIG_PROC_FS ++# include <linux/proc_fs.h> ++#endif /* CONFIG_PROC_FS */ ++ ++#ifdef NETLINK_SOCK ++# include <linux/netlink.h> ++#else ++# include <net/netlink.h> ++#endif ++ ++#include "openswan/radij.h" ++ ++#include "openswan/ipsec_life.h" ++#include "openswan/ipsec_stats.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_tunnel.h" ++ ++#include "openswan/ipsec_rcv.h" ++#include "openswan/ipsec_ah.h" ++#include "openswan/ipsec_esp.h" ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++# include "openswan/ipcomp.h" ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#include "openswan/ipsec_proto.h" ++#include "openswan/ipsec_alg.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#if !defined(CONFIG_IPSEC_ESP) && !defined(CONFIG_IPSEC_AH) ++#error "kernel configuration must include ESP or AH" ++#endif ++ ++/* ++ * seems to be present in 2.4.10 (Linus), but also in some RH and other ++ * distro kernels of a lower number. ++ */ ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_eroute = 0; ++int debug_spi = 0; ++int debug_netlink = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++struct prng ipsec_prng; ++ ++extern int ipsec_device_event(struct notifier_block *dnot, unsigned long event, void *ptr); ++/* ++ * the following structure is required so that we receive ++ * event notifications when network devices are enabled and ++ * disabled (ifconfig up and down). ++ */ ++static struct notifier_block ipsec_dev_notifier={ ++ ipsec_device_event, ++ NULL, ++ 0 ++}; ++ ++#ifdef CONFIG_SYSCTL ++extern int ipsec_sysctl_register(void); ++extern void ipsec_sysctl_unregister(void); ++#endif ++ ++static inline int ++openswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol) ++{ ++#ifdef NETDEV_25 ++ return inet_add_protocol(prot, protocol); ++#else ++ inet_add_protocol(prot); ++ return 0; ++#endif ++} ++ ++static inline int ++openswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol) ++{ ++#ifdef NETDEV_25 ++ return inet_del_protocol(prot, protocol); ++#else ++ inet_del_protocol(prot); ++ return 0; ++#endif ++} ++ ++/* void */ ++int ++ipsec_init(void) ++{ ++ int error = 0; ++ unsigned char seed[256]; ++#ifdef CONFIG_IPSEC_ENC_3DES ++ extern int des_check_key; ++ ++ /* turn off checking of keys */ ++ des_check_key=0; ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ ++ KLIPS_PRINT(1, "klips_info:ipsec_init: " ++ "KLIPS startup, Openswan KLIPS IPsec stack version: %s\n", ++ ipsec_version_code()); ++ ++ error |= ipsec_proc_init(); ++ ++#ifdef SPINLOCK ++ ipsec_sadb.sadb_lock = SPIN_LOCK_UNLOCKED; ++#else /* SPINLOCK */ ++ ipsec_sadb.sadb_lock = 0; ++#endif /* SPINLOCK */ ++ ++#ifndef SPINLOCK ++ tdb_lock.lock = 0; ++ eroute_lock.lock = 0; ++#endif /* !SPINLOCK */ ++ ++ error |= ipsec_sadb_init(); ++ error |= ipsec_radijinit(); ++ ++ error |= pfkey_init(); ++ ++ error |= register_netdevice_notifier(&ipsec_dev_notifier); ++ ++#ifdef CONFIG_IPSEC_ESP ++ openswan_inet_add_protocol(&esp_protocol, IPPROTO_ESP); ++#endif /* CONFIG_IPSEC_ESP */ ++ ++#ifdef CONFIG_IPSEC_AH ++ openswan_inet_add_protocol(&ah_protocol, IPPROTO_AH); ++#endif /* CONFIG_IPSEC_AH */ ++ ++/* we never actually link IPCOMP to the stack */ ++#ifdef IPCOMP_USED_ALONE ++#ifdef CONFIG_IPSEC_IPCOMP ++ openswan_inet_add_protocol(&comp_protocol, IPPROTO_COMP); ++#endif /* CONFIG_IPSEC_IPCOMP */ ++#endif ++ ++ error |= ipsec_tunnel_init_devices(); ++ ++ ++#ifdef CONFIG_SYSCTL ++ error |= ipsec_sysctl_register(); ++#endif ++ ++#ifdef CONFIG_IPSEC_ALG ++ ipsec_alg_init(); ++#endif ++ ++ get_random_bytes((void *)seed, sizeof(seed)); ++ prng_init(&ipsec_prng, seed, sizeof(seed)); ++ ++ return error; ++} ++ ++ ++/* void */ ++int ++ipsec_cleanup(void) ++{ ++ int error = 0; ++ ++#ifdef CONFIG_SYSCTL ++ ipsec_sysctl_unregister(); ++#endif ++ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ ++ "klips_debug:ipsec_cleanup: " ++ "calling ipsec_tunnel_cleanup_devices.\n"); ++ error |= ipsec_tunnel_cleanup_devices(); ++ ++ KLIPS_PRINT(debug_netlink, "called ipsec_tunnel_cleanup_devices"); ++ ++/* we never actually link IPCOMP to the stack */ ++#ifdef IPCOMP_USED_ALONE ++#ifdef CONFIG_IPSEC_IPCOMP ++ if (openswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP) < 0) ++ printk(KERN_INFO "klips_debug:ipsec_cleanup: " ++ "comp close: can't remove protocol\n"); ++#endif /* CONFIG_IPSEC_IPCOMP */ ++#endif /* IPCOMP_USED_ALONE */ ++ ++#ifdef CONFIG_IPSEC_AH ++ if (openswan_inet_del_protocol(&ah_protocol, IPPROTO_AH) < 0) ++ printk(KERN_INFO "klips_debug:ipsec_cleanup: " ++ "ah close: can't remove protocol\n"); ++#endif /* CONFIG_IPSEC_AH */ ++ ++#ifdef CONFIG_IPSEC_ESP ++ if (openswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP) < 0) ++ printk(KERN_INFO "klips_debug:ipsec_cleanup: " ++ "esp close: can't remove protocol\n"); ++#endif /* CONFIG_IPSEC_ESP */ ++ ++ error |= unregister_netdevice_notifier(&ipsec_dev_notifier); ++ ++ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ ++ "klips_debug:ipsec_cleanup: " ++ "calling ipsec_sadb_cleanup.\n"); ++ error |= ipsec_sadb_cleanup(0); ++ error |= ipsec_sadb_free(); ++ ++ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ ++ "klips_debug:ipsec_cleanup: " ++ "calling ipsec_radijcleanup.\n"); ++ error |= ipsec_radijcleanup(); ++ ++ KLIPS_PRINT(debug_pfkey, /* debug_tunnel & DB_TN_INIT, */ ++ "klips_debug:ipsec_cleanup: " ++ "calling pfkey_cleanup.\n"); ++ error |= pfkey_cleanup(); ++ ++ ipsec_proc_cleanup(); ++ ++ prng_final(&ipsec_prng); ++ ++ return error; ++} ++ ++#ifdef MODULE ++int ++init_module(void) ++{ ++ int error = 0; ++ ++ error |= ipsec_init(); ++ ++ return error; ++} ++ ++int ++cleanup_module(void) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ ++ "klips_debug:cleanup_module: " ++ "calling ipsec_cleanup.\n"); ++ ++ error |= ipsec_cleanup(); ++ ++ KLIPS_PRINT(1, "klips_info:cleanup_module: " ++ "ipsec module unloaded.\n"); ++ ++ return error; ++} ++#endif /* MODULE */ ++ ++/* ++ * $Log: ipsec_init.c,v $ ++ * Revision 1.93 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.92 2004/03/30 15:30:39 ken ++ * Proper Capitalization ++ * ++ * Revision 1.91 2004/03/22 01:51:51 ken ++ * We are open ++ * ++ * Revision 1.90.4.2 2004/04/05 04:30:46 mcr ++ * patches for alg-branch to compile/work with 2.x openswan ++ * ++ * Revision 1.90.4.1 2003/12/22 15:25:52 jjo ++ * Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.90 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.89.4.1 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.89 2003/07/31 22:47:16 mcr ++ * preliminary (untested by FS-team) 2.5 patches. ++ * ++ * Revision 1.88 2003/06/22 20:05:36 mcr ++ * clarified why IPCOMP was not being registered, and put a new ++ * #ifdef in rather than #if 0. ++ * ++ * Revision 1.87 2002/09/20 15:40:51 rgb ++ * Added a lock to the global ipsec_sadb struct for future use. ++ * Split ipsec_sadb_cleanup from new funciton ipsec_sadb_free to avoid problem ++ * of freeing newly created structures when clearing the reftable upon startup ++ * to start from a known state. ++ * ++ * Revision 1.86 2002/08/15 18:39:15 rgb ++ * Move ipsec_prng outside debug code. ++ * ++ * Revision 1.85 2002/05/14 02:35:29 rgb ++ * Change reference to tdb to ipsa. ++ * ++ * Revision 1.84 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.83 2002/04/24 07:36:28 mcr ++ * Moved from ./klips/net/ipsec/ipsec_init.c,v ++ * ++ * Revision 1.82 2002/04/20 00:12:25 rgb ++ * Added esp IV CBC attack fix, disabled. ++ * ++ * Revision 1.81 2002/04/09 16:13:32 mcr ++ * switch license to straight GPL. ++ * ++ * Revision 1.80 2002/03/24 07:34:08 rgb ++ * Sanity check for at least one of AH or ESP configured. ++ * ++ * Revision 1.79 2002/02/05 22:55:15 mcr ++ * added MODULE_LICENSE declaration. ++ * This macro does not appear in all kernel versions (see comment). ++ * ++ * Revision 1.78 2002/01/29 17:17:55 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.77 2002/01/29 04:00:51 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.76 2002/01/29 02:13:17 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.75 2001/11/26 09:23:48 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.74 2001/11/22 05:44:11 henry ++ * new version stuff ++ * ++ * Revision 1.71.2.2 2001/10/22 20:51:00 mcr ++ * explicitely set des_check_key. ++ * ++ * Revision 1.71.2.1 2001/09/25 02:19:39 mcr ++ * /proc manipulation code moved to new ipsec_proc.c ++ * ++ * Revision 1.73 2001/11/06 19:47:17 rgb ++ * Changed lifetime_packets to uint32 from uint64. ++ * ++ * Revision 1.72 2001/10/18 04:45:19 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/freeswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.71 2001/09/20 15:32:45 rgb ++ * Minor pfkey lifetime fixes. ++ * ++ * Revision 1.70 2001/07/06 19:51:21 rgb ++ * Added inbound policy checking code for IPIP SAs. ++ * ++ * Revision 1.69 2001/06/14 19:33:26 rgb ++ * Silence startup message for console, but allow it to be logged. ++ * Update copyright date. ++ * ++ * Revision 1.68 2001/05/29 05:14:36 rgb ++ * Added PMTU to /proc/net/ipsec_tncfg output. See 'man 5 ipsec_tncfg'. ++ * ++ * Revision 1.67 2001/05/04 16:34:52 rgb ++ * Rremove erroneous checking of return codes for proc_net_* in 2.4. ++ * ++ * Revision 1.66 2001/05/03 19:40:34 rgb ++ * Check error return codes in startup and shutdown. ++ * ++ * Revision 1.65 2001/02/28 05:03:27 rgb ++ * Clean up and rationalise startup messages. ++ * ++ * Revision 1.64 2001/02/27 22:24:53 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.63 2000/11/29 20:14:06 rgb ++ * Add src= to the output of /proc/net/ipsec_spi and delete dst from IPIP. ++ * ++ * Revision 1.62 2000/11/06 04:31:24 rgb ++ * Ditched spin_lock_irqsave in favour of spin_lock_bh. ++ * Fixed longlong for pre-2.4 kernels (Svenning). ++ * Add Svenning's adaptive content compression. ++ * Disabled registration of ipcomp handler. ++ * ++ * Revision 1.61 2000/10/11 13:37:54 rgb ++ * #ifdef out debug print that causes proc/net/ipsec_version to oops. ++ * ++ * Revision 1.60 2000/09/20 03:59:01 rgb ++ * Change static info functions to DEBUG_NO_STATIC to reveal function names ++ * in oopsen. ++ * ++ * Revision 1.59 2000/09/16 01:06:26 rgb ++ * Added cast of var to silence compiler warning about long fed to int ++ * format. ++ * ++ * Revision 1.58 2000/09/15 11:37:01 rgb ++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk> ++ * IPCOMP zlib deflate code. ++ * ++ * Revision 1.57 2000/09/12 03:21:50 rgb ++ * Moved radij_c_version printing to ipsec_version_get_info(). ++ * Reformatted ipsec_version_get_info(). ++ * Added sysctl_{,un}register() calls. ++ * ++ * Revision 1.56 2000/09/08 19:16:50 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * Removed all references to CONFIG_IPSEC_PFKEYv2. ++ * ++ * Revision 1.55 2000/08/30 05:19:03 rgb ++ * Cleaned up no longer used spi_next, netlink register/unregister, other ++ * minor cleanup. ++ * Removed cruft replaced by TDB_XFORM_NAME. ++ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst. ++ * Moved debug version strings to printk when /proc/net/ipsec_version is ++ * called. ++ * ++ * Revision 1.54 2000/08/20 18:31:05 rgb ++ * Changed cosmetic alignment in spi_info. ++ * Changed addtime and usetime to use actual value which is relative ++ * anyways, as intended. (Momchil) ++ * ++ * Revision 1.53 2000/08/18 17:37:03 rgb ++ * Added an (int) cast to shut up the compiler... ++ * ++ * Revision 1.52 2000/08/01 14:51:50 rgb ++ * Removed _all_ remaining traces of DES. ++ * ++ * Revision 1.51 2000/07/25 20:41:22 rgb ++ * Removed duplicate parameter in spi_getinfo. ++ * ++ * Revision 1.50 2000/07/17 03:21:45 rgb ++ * Removed /proc/net/ipsec_spinew. ++ * ++ * Revision 1.49 2000/06/28 05:46:51 rgb ++ * Renamed ivlen to iv_bits for consistency. ++ * Changed output of add and use times to be relative to now. ++ * ++ * Revision 1.48 2000/05/11 18:26:10 rgb ++ * Commented out calls to netlink_attach/detach to avoid activating netlink ++ * in the kenrel config. ++ * ++ * Revision 1.47 2000/05/10 22:35:26 rgb ++ * Comment out most of the startup version information. ++ * ++ * Revision 1.46 2000/03/22 16:15:36 rgb ++ * Fixed renaming of dev_get (MB). ++ * ++ * Revision 1.45 2000/03/16 06:40:48 rgb ++ * Hardcode PF_KEYv2 support. ++ * ++ * Revision 1.44 2000/01/22 23:19:20 rgb ++ * Simplified code to use existing macro TDB_XFORM_NAME(). ++ * ++ * Revision 1.43 2000/01/21 06:14:04 rgb ++ * Print individual stats only if non-zero. ++ * Removed 'bits' from each keylength for brevity. ++ * Shortened lifetimes legend for brevity. ++ * Changed wording from 'last_used' to the clearer 'idle'. ++ * ++ * Revision 1.42 1999/12/31 14:57:19 rgb ++ * MB fix for new dummy-less proc_get_info in 2.3.35. ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_ipcomp.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,276 @@ ++/* ++ * processing code for IPCOMP ++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++char ipsec_ipcomp_c_version[] = "RCSID $Id: ipsec_ipcomp.c,v 1.2 2004/04/06 02:49:26 mcr Exp $"; ++#include <linux/config.h> ++#include <linux/version.h> ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define proto_priv cb ++#endif /* NET21 */ ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_rcv.h" ++#include "openswan/ipsec_xmit.h" ++ ++#include "openswan/ipsec_auth.h" ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++#include "openswan/ipsec_ipcomp.h" ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#include "openswan/ipsec_proto.h" ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_ipcomp = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++enum ipsec_rcv_value ++ipsec_rcv_ipcomp_checks(struct ipsec_rcv_state *irs, ++ struct sk_buff *skb) ++{ ++ int ipcompminlen; ++ ++ ipcompminlen = irs->hard_header_len + sizeof(struct iphdr); ++ ++ if(skb->len < (ipcompminlen + sizeof(struct ipcomphdr))) { ++ KLIPS_PRINT(debug_rcv & DB_RX_INAU, ++ "klips_debug:ipsec_rcv: " ++ "runt comp packet of skb->len=%d received from %s, dropped.\n", ++ skb->len, ++ irs->ipsaddr_txt); ++ if(irs->stats) { ++ irs->stats->rx_errors++; ++ } ++ return IPSEC_RCV_BADLEN; ++ } ++ ++ irs->protostuff.ipcompstuff.compp = (struct ipcomphdr *)(skb->data + irs->iphlen); ++ irs->said.spi = htonl((__u32)ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi)); ++ return IPSEC_RCV_OK; ++} ++ ++enum ipsec_rcv_value ++ipsec_rcv_ipcomp_decomp(struct ipsec_rcv_state *irs) ++{ ++ unsigned int flags = 0; ++ struct ipsec_sa *ipsp = irs->ipsp; ++ struct sk_buff *skb; ++ ++ skb=irs->skb; ++ ++ ipsec_xmit_dmp("ipcomp", skb->data, skb->len); ++ ++ if(ipsp == NULL) { ++ return IPSEC_RCV_SAIDNOTFOUND; ++ } ++ ++#if 0 ++ /* we want to check that this wasn't the first SA on the list, because ++ * we don't support bare IPCOMP, for unexplained reasons. MCR ++ */ ++ if (ipsp->ips_onext != NULL) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "Incoming packet with outer IPCOMP header SA:%s: not yet supported by KLIPS, dropped\n", ++ irs->sa_len ? irs->sa : " (error)"); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ ++ return IPSEC_RCV_IPCOMPALONE; ++ } ++#endif ++ ++ if(sysctl_ipsec_inbound_policy_check && ++ ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) != ntohl(irs->said.spi)) && ++ (ipsp->ips_encalg != ntohl(irs->said.spi)) /* this is a workaround for peer non-compliance with rfc2393 */ ++ ))) { ++ char sa2[SATOT_BUF]; ++ size_t sa_len2 = 0; ++ ++ sa_len2 = satot(&ipsp->ips_said, 0, sa2, sizeof(sa2)); ++ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n", ++ irs->sa_len ? irs->sa : " (error)", ++ ipsp != NULL ? (sa_len2 ? sa2 : " (error)") : "NULL", ++ ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi), ++ (__u32)ntohl(irs->said.spi), ++ ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, ++ ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_SAIDNOTFOUND; ++ } ++ ++ ipsp->ips_comp_ratio_cbytes += ntohs(irs->ipp->tot_len); ++ irs->next_header = irs->protostuff.ipcompstuff.compp->ipcomp_nh; ++ ++ skb = skb_decompress(skb, ipsp, &flags); ++ if (!skb || flags) { ++ spin_unlock(&tdb_lock); ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "skb_decompress() returned error flags=%x, dropped.\n", ++ flags); ++ if (irs->stats) { ++ if (flags) ++ irs->stats->rx_errors++; ++ else ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_IPCOMPFAILED; ++ } ++ ++ /* make sure we update the pointer */ ++ irs->skb = skb; ++ ++#ifdef NET_21 ++ irs->ipp = skb->nh.iph; ++#else /* NET_21 */ ++ irs->ipp = skb->ip_hdr; ++#endif /* NET_21 */ ++ ++ ipsp->ips_comp_ratio_dbytes += ntohs(irs->ipp->tot_len); ++ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n", ++ irs->sa_len ? irs->sa : " (error)", ++ (__u32)ntohl(irs->said.spi), ++ ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, ++ ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0, ++ irs->next_header); ++ KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, irs->ipp); ++ ++ return IPSEC_RCV_OK; ++} ++ ++enum ipsec_xmit_value ++ipsec_xmit_ipcomp_setup(struct ipsec_xmit_state *ixs) ++{ ++ unsigned int flags = 0; ++#ifdef CONFIG_IPSEC_DEBUG ++ unsigned int old_tot_len = ntohs(ixs->iph->tot_len); ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ ixs->ipsp->ips_comp_ratio_dbytes += ntohs(ixs->iph->tot_len); ++ ++ ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags); ++ ++#ifdef NET_21 ++ ixs->iph = ixs->skb->nh.iph; ++#else /* NET_21 */ ++ ixs->iph = ixs->skb->ip_hdr; ++#endif /* NET_21 */ ++ ++ ixs->ipsp->ips_comp_ratio_cbytes += ntohs(ixs->iph->tot_len); ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if (debug_tunnel & DB_TN_CROUT) ++ { ++ if (old_tot_len > ntohs(ixs->iph->tot_len)) ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_once: " ++ "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n", ++ old_tot_len, ntohs(ixs->iph->tot_len), ++ ntohs(((struct ipcomphdr*)(((char*)ixs->iph) + ((ixs->iph->ihl) << 2)))->ipcomp_cpi), ++ ntohl(ixs->ipsp->ips_said.spi), ++ (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff)); ++ else ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_once: " ++ "packet did not compress (flags = %d).\n", ++ flags); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ return IPSEC_XMIT_OK; ++} ++ ++struct xform_functions ipcomp_xform_funcs[]={ ++ {rcv_checks: ipsec_rcv_ipcomp_checks, ++ rcv_decrypt: ipsec_rcv_ipcomp_decomp, ++ xmit_setup: ipsec_xmit_ipcomp_setup, ++ xmit_headroom: 0, ++ xmit_needtailroom: 0, ++ }, ++}; ++ ++#if 0 ++/* We probably don't want to install a pure IPCOMP protocol handler, but ++ only want to handle IPCOMP if it is encapsulated inside an ESP payload ++ (which is already handled) */ ++#ifdef CONFIG_IPSEC_IPCOMP ++struct inet_protocol comp_protocol = ++{ ++ ipsec_rcv, /* COMP handler */ ++ NULL, /* COMP error control */ ++#ifdef NETDEV_25 ++ 1, /* no policy */ ++#else ++ 0, /* next */ ++ IPPROTO_COMP, /* protocol ID */ ++ 0, /* copy */ ++ NULL, /* data */ ++ "COMP" /* name */ ++#endif ++}; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++#endif ++ ++#endif /* CONFIG_IPSEC_IPCOMP */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_ipip.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,133 @@ ++/* ++ * processing code for IPIP ++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++char ipsec_ipip_c_version[] = "RCSID $Id: ipsec_ipip.c,v 1.2 2004/04/06 02:49:26 mcr Exp $"; ++#include <linux/config.h> ++#include <linux/version.h> ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define proto_priv cb ++#endif /* NET21 */ ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_rcv.h" ++#include "openswan/ipsec_xmit.h" ++ ++#include "openswan/ipsec_auth.h" ++#include "openswan/ipsec_ipip.h" ++#include "openswan/ipsec_param.h" ++ ++#include "openswan/ipsec_proto.h" ++ ++enum ipsec_xmit_value ++ipsec_xmit_ipip_setup(struct ipsec_xmit_state *ixs) ++{ ++ ixs->iph->version = 4; ++ ++ switch(sysctl_ipsec_tos) { ++ case 0: ++#ifdef NET_21 ++ ixs->iph->tos = ixs->skb->nh.iph->tos; ++#else /* NET_21 */ ++ ixs->iph->tos = ixs->skb->ip_hdr->tos; ++#endif /* NET_21 */ ++ break; ++ case 1: ++ ixs->iph->tos = 0; ++ break; ++ default: ++ break; ++ } ++#ifdef NET_21 ++#ifdef NETDEV_23 ++ ixs->iph->ttl = sysctl_ip_default_ttl; ++#else /* NETDEV_23 */ ++ ixs->iph->ttl = ip_statistics.IpDefaultTTL; ++#endif /* NETDEV_23 */ ++#else /* NET_21 */ ++ ixs->iph->ttl = 64; /* ip_statistics.IpDefaultTTL; */ ++#endif /* NET_21 */ ++ ixs->iph->frag_off = 0; ++ ixs->iph->saddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr; ++ ixs->iph->daddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr; ++ ixs->iph->protocol = IPPROTO_IPIP; ++ ixs->iph->ihl = sizeof(struct iphdr) >> 2; ++ ++ KLIPS_IP_SELECT_IDENT(ixs->iph, ixs->skb); ++ ++ ixs->newdst = (__u32)ixs->iph->daddr; ++ ixs->newsrc = (__u32)ixs->iph->saddr; ++ ++#ifdef NET_21 ++ ixs->skb->h.ipiph = ixs->skb->nh.iph; ++#endif /* NET_21 */ ++ return IPSEC_XMIT_OK; ++} ++ ++struct xform_functions ipip_xform_funcs[]={ ++ { rcv_checks: NULL, ++ rcv_setup_auth: NULL, ++ rcv_calc_auth: NULL, ++ rcv_decrypt: NULL, ++ ++ xmit_setup: ipsec_xmit_ipip_setup, ++ xmit_headroom: sizeof(struct iphdr), ++ xmit_needtailroom: 0, ++ }, ++}; ++ ++ ++ ++ ++ ++ ++ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_life.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,263 @@ ++/* ++ * @(#) lifetime structure utilities ++ * ++ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org> ++ * and Michael Richardson <mcr@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_life.c,v 1.12 2004/04/23 20:44:35 ken Exp $ ++ * ++ */ ++ ++/* ++ * This provides series of utility functions for dealing with lifetime ++ * structures. ++ * ++ * ipsec_check_lifetime - returns -1 hard lifetime exceeded ++ * 0 soft lifetime exceeded ++ * 1 everything is okay ++ * based upon whether or not the count exceeds hard/soft ++ * ++ */ ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/config.h> /* for CONFIG_IP_FORWARD */ ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#include <linux/netdevice.h> /* struct device, struct net_device_stats and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_life.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_eroute.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_radij.h" ++ ++#include "openswan/ipsec_sa.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_ipe4.h" ++#include "openswan/ipsec_ah.h" ++#include "openswan/ipsec_esp.h" ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++#include "openswan/ipcomp.h" ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_proto.h" ++ ++ ++enum ipsec_life_alive ++ipsec_lifetime_check(struct ipsec_lifetime64 *il64, ++ const char *lifename, ++ const char *saname, ++ enum ipsec_life_type ilt, ++ enum ipsec_direction idir, ++ struct ipsec_sa *ips) ++{ ++ __u64 count; ++ const char *dir; ++ ++ if(saname == NULL) { ++ saname = "unknown-SA"; ++ } ++ ++ if(idir == ipsec_incoming) { ++ dir = "incoming"; ++ } else { ++ dir = "outgoing"; ++ } ++ ++ ++ if(ilt == ipsec_life_timebased) { ++ count = jiffies/HZ - il64->ipl_count; ++ } else { ++ count = il64->ipl_count; ++ } ++ ++ if(il64->ipl_hard && ++ (count > il64->ipl_hard)) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_lifetime_check: " ++ "hard %s lifetime of SA:<%s%s%s> %s has been reached, SA expired, " ++ "%s packet dropped.\n", ++ lifename, ++ IPS_XFORM_NAME(ips), ++ saname, ++ dir); ++ ++ pfkey_expire(ips, 1); ++ return ipsec_life_harddied; ++ } ++ ++ if(il64->ipl_soft && ++ (count > il64->ipl_soft)) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_lifetime_check: " ++ "soft %s lifetime of SA:<%s%s%s> %s has been reached, SA expiring, " ++ "soft expire message sent up, %s packet still processed.\n", ++ lifename, ++ IPS_XFORM_NAME(ips), ++ saname, ++ dir); ++ ++ if(ips->ips_state != SADB_SASTATE_DYING) { ++ pfkey_expire(ips, 0); ++ } ++ ips->ips_state = SADB_SASTATE_DYING; ++ ++ return ipsec_life_softdied; ++ } ++ return ipsec_life_okay; ++} ++ ++ ++/* ++ * This function takes a buffer (with length), a lifetime name and type, ++ * and formats a string to represent the current values of the lifetime. ++ * ++ * It returns the number of bytes that the format took (or would take, ++ * if the buffer were large enough: snprintf semantics). ++ * This is used in /proc routines and in debug output. ++ */ ++int ++ipsec_lifetime_format(char *buffer, ++ int buflen, ++ char *lifename, ++ enum ipsec_life_type timebaselife, ++ struct ipsec_lifetime64 *lifetime) ++{ ++ int len = 0; ++ __u64 count; ++ ++ if(timebaselife == ipsec_life_timebased) { ++ count = jiffies/HZ - lifetime->ipl_count; ++ } else { ++ count = lifetime->ipl_count; ++ } ++ ++ if(lifetime->ipl_count > 1 || ++ lifetime->ipl_soft || ++ lifetime->ipl_hard) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) ++ len = ipsec_snprintf(buffer, buflen, ++ "%s(%Lu,%Lu,%Lu)", ++ lifename, ++ count, ++ lifetime->ipl_soft, ++ lifetime->ipl_hard); ++#else /* XXX high 32 bits are not displayed */ ++ len = ipsec_snprintf(buffer, buflen, ++ "%s(%lu,%lu,%lu)", ++ lifename, ++ (unsigned long)count, ++ (unsigned long)lifetime->ipl_soft, ++ (unsigned long)lifetime->ipl_hard); ++#endif ++ } ++ ++ return len; ++} ++ ++void ++ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime, ++ __u64 newvalue) ++{ ++ if(newvalue && ++ (!lifetime->ipl_hard || ++ (newvalue < lifetime->ipl_hard))) { ++ lifetime->ipl_hard = newvalue; ++ ++ if(!lifetime->ipl_soft && ++ (lifetime->ipl_hard < lifetime->ipl_soft)) { ++ lifetime->ipl_soft = lifetime->ipl_hard; ++ } ++ } ++} ++ ++void ++ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime, ++ __u64 newvalue) ++{ ++ if(newvalue && ++ (!lifetime->ipl_soft || ++ (newvalue < lifetime->ipl_soft))) { ++ lifetime->ipl_soft = newvalue; ++ ++ if(lifetime->ipl_hard && ++ (lifetime->ipl_hard < lifetime->ipl_soft)) { ++ lifetime->ipl_soft = lifetime->ipl_hard; ++ } ++ } ++} ++ ++ ++/* ++ * $Log: ipsec_life.c,v $ ++ * Revision 1.12 2004/04/23 20:44:35 ken ++ * Update comments ++ * ++ * Revision 1.11 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.10 2004/03/30 11:03:10 paul ++ * two more occurances of snprintf, found by Sam from a users oops msg. ++ * ++ * Revision 1.9 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.8.4.1 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.8 2003/02/06 02:00:10 rgb ++ * Fixed incorrect debugging text label ++ * ++ * Revision 1.7 2002/05/23 07:16:26 rgb ++ * Fixed absolute/relative reference to lifetime count printout. ++ * ++ * Revision 1.6 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.5 2002/04/24 07:36:28 mcr ++ * Moved from ./klips/net/ipsec/ipsec_life.c,v ++ * ++ * Revision 1.4 2002/01/29 17:17:55 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.3 2002/01/29 02:13:17 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.2 2001/11/26 09:16:14 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.1.2.1 2001/09/25 02:25:57 mcr ++ * lifetime structure created and common functions created. ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_mast.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1080 @@ ++/* ++ * IPSEC MAST code. ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++char ipsec_mast_c_version[] = "RCSID $Id: ipsec_mast.c,v 1.3 2003/10/31 02:27:55 mcr Exp $"; ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/config.h> /* for CONFIG_IP_FORWARD */ ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "freeswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/tcp.h> /* struct tcphdr */ ++#include <linux/udp.h> /* struct udphdr */ ++#include <linux/skbuff.h> ++#include <freeswan.h> ++#include <asm/uaccess.h> ++#include <linux/in6.h> ++#include <net/dst.h> ++#undef dev_kfree_skb ++#define dev_kfree_skb(a,b) kfree_skb(a) ++#define PHYSDEV_TYPE ++#include <asm/checksum.h> ++#include <net/icmp.h> /* icmp_send() */ ++#include <net/ip.h> ++#include <linux/netfilter_ipv4.h> ++ ++#include <linux/if_arp.h> ++ ++#include "freeswan/radij.h" ++#include "freeswan/ipsec_life.h" ++#include "freeswan/ipsec_xform.h" ++#include "freeswan/ipsec_eroute.h" ++#include "freeswan/ipsec_encap.h" ++#include "freeswan/ipsec_radij.h" ++#include "freeswan/ipsec_sa.h" ++#include "freeswan/ipsec_tunnel.h" ++#include "freeswan/ipsec_mast.h" ++#include "freeswan/ipsec_ipe4.h" ++#include "freeswan/ipsec_ah.h" ++#include "freeswan/ipsec_esp.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "freeswan/ipsec_proto.h" ++ ++int ipsec_maxdevice_count = -1; ++ ++DEBUG_NO_STATIC int ++ipsec_mast_open(struct device *dev) ++{ ++ struct ipsecpriv *prv = dev->priv; ++ ++ /* ++ * Can't open until attached. ++ */ ++ ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_open: " ++ "dev = %s, prv->dev = %s\n", ++ dev->name, prv->dev?prv->dev->name:"NONE"); ++ ++ if (prv->dev == NULL) ++ return -ENODEV; ++ ++ MOD_INC_USE_COUNT; ++ return 0; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_mast_close(struct device *dev) ++{ ++ MOD_DEC_USE_COUNT; ++ return 0; ++} ++ ++static inline int ipsec_mast_xmit2(struct sk_buff *skb) ++{ ++ return ip_send(skb); ++} ++ ++enum ipsec_xmit_value ++ipsec_mast_send(struct ipsec_xmit_state*ixs) ++{ ++ /* new route/dst cache code from James Morris */ ++ ixs->skb->dev = ixs->physdev; ++ /*skb_orphan(ixs->skb);*/ ++ if((ixs->error = ip_route_output(&ixs->route, ++ ixs->skb->nh.iph->daddr, ++ ixs->pass ? 0 : ixs->skb->nh.iph->saddr, ++ RT_TOS(ixs->skb->nh.iph->tos), ++ ixs->physdev->iflink /* rgb: should this be 0? */))) { ++ ixs->stats->tx_errors++; ++ KLIPS_PRINT(debug_mast & DB_MAST_XMIT, ++ "klips_debug:ipsec_xmit_send: " ++ "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n", ++ ixs->error, ++ ixs->route->u.dst.dev->name); ++ return IPSEC_XMIT_ROUTEERR; ++ } ++ if(ixs->dev == ixs->route->u.dst.dev) { ++ ip_rt_put(ixs->route); ++ /* This is recursion, drop it. */ ++ ixs->stats->tx_errors++; ++ KLIPS_PRINT(debug_mast & DB_MAST_XMIT, ++ "klips_debug:ipsec_xmit_send: " ++ "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", ++ ixs->dev->name); ++ return IPSEC_XMIT_RECURSDETECT; ++ } ++ dst_release(ixs->skb->dst); ++ ixs->skb->dst = &ixs->route->u.dst; ++ ixs->stats->tx_bytes += ixs->skb->len; ++ if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { ++ ixs->stats->tx_errors++; ++ printk(KERN_WARNING ++ "klips_error:ipsec_xmit_send: " ++ "tried to __skb_pull nh-data=%ld, %d available. This should never happen, please report.\n", ++ (unsigned long)(ixs->skb->nh.raw - ixs->skb->data), ++ ixs->skb->len); ++ return IPSEC_XMIT_PUSHPULLERR; ++ } ++ __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data); ++#ifdef SKB_RESET_NFCT ++ nf_conntrack_put(ixs->skb->nfct); ++ ixs->skb->nfct = NULL; ++#ifdef CONFIG_NETFILTER_DEBUG ++ ixs->skb->nf_debug = 0; ++#endif /* CONFIG_NETFILTER_DEBUG */ ++#endif /* SKB_RESET_NFCT */ ++ KLIPS_PRINT(debug_mast & DB_MAST_XMIT, ++ "klips_debug:ipsec_xmit_send: " ++ "...done, calling ip_send() on device:%s\n", ++ ixs->skb->dev ? ixs->skb->dev->name : "NULL"); ++ KLIPS_IP_PRINT(debug_mast & DB_MAST_XMIT, ixs->skb->nh.iph); ++ { ++ int err; ++ ++ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev, ++ ipsec_mast_xmit2); ++ if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { ++ if(net_ratelimit()) ++ printk(KERN_ERR ++ "klips_error:ipsec_xmit_send: " ++ "ip_send() failed, err=%d\n", ++ -err); ++ ixs->stats->tx_errors++; ++ ixs->stats->tx_aborted_errors++; ++ ixs->skb = NULL; ++ return IPSEC_XMIT_IPSENDFAILURE; ++ } ++ } ++ ixs->stats->tx_packets++; ++ ++ ixs->skb = NULL; ++ ++ return IPSEC_XMIT_OK; ++} ++ ++void ++ipsec_mast_cleanup(struct ipsec_xmit_state*ixs) ++{ ++#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) ++ netif_wake_queue(ixs->dev); ++#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ ++ ixs->dev->tbusy = 0; ++#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ ++ if(ixs->saved_header) { ++ kfree(ixs->saved_header); ++ } ++ if(ixs->skb) { ++ dev_kfree_skb(ixs->skb, FREE_WRITE); ++ } ++ if(ixs->oskb) { ++ dev_kfree_skb(ixs->oskb, FREE_WRITE); ++ } ++ if (ixs->ips.ips_ident_s.data) { ++ kfree(ixs->ips.ips_ident_s.data); ++ } ++ if (ixs->ips.ips_ident_d.data) { ++ kfree(ixs->ips.ips_ident_d.data); ++ } ++} ++ ++#if 0 ++/* ++ * This function assumes it is being called from dev_queue_xmit() ++ * and that skb is filled properly by that function. ++ */ ++int ++ipsec_mast_start_xmit(struct sk_buff *skb, struct device *dev, IPsecSAref_t SAref) ++{ ++ struct ipsec_xmit_state ixs_mem; ++ struct ipsec_xmit_state *ixs = &ixs_mem; ++ enum ipsec_xmit_value stat = IPSEC_XMIT_OK; ++ ++ /* dev could be a mast device, but should be optional, I think... */ ++ /* SAref is also optional, but one of the two must be present. */ ++ /* I wonder if it could accept no device or saref and guess? */ ++ ++/* ipsec_xmit_sanity_check_dev(ixs); */ ++ ++ ipsec_xmit_sanity_check_skb(ixs); ++ ++ ipsec_xmit_adjust_hard_header(ixs); ++ ++ stat = ipsec_xmit_encap_bundle(ixs); ++ if(stat != IPSEC_XMIT_OK) { ++ /* SA processing failed */ ++ } ++ ++ ipsec_xmit_hard_header_restore(); ++} ++#endif ++ ++DEBUG_NO_STATIC struct net_device_stats * ++ipsec_mast_get_stats(struct device *dev) ++{ ++ return &(((struct ipsecpriv *)(dev->priv))->mystats); ++} ++ ++/* ++ * Revectored calls. ++ * For each of these calls, a field exists in our private structure. ++ */ ++ ++DEBUG_NO_STATIC int ++ipsec_mast_hard_header(struct sk_buff *skb, struct device *dev, ++ unsigned short type, void *daddr, void *saddr, unsigned len) ++{ ++ struct ipsecpriv *prv = dev->priv; ++ struct device *tmp; ++ int ret; ++ struct net_device_stats *stats; /* This device's statistics */ ++ ++ if(skb == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_hard_header: " ++ "no skb...\n"); ++ return -ENODATA; ++ } ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_hard_header: " ++ "no device...\n"); ++ return -ENODEV; ++ } ++ ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_hard_header: " ++ "skb->dev=%s dev=%s.\n", ++ skb->dev ? skb->dev->name : "NULL", ++ dev->name); ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_hard_header: " ++ "no private space associated with dev=%s\n", ++ dev->name ? dev->name : "NULL"); ++ return -ENODEV; ++ } ++ ++ stats = (struct net_device_stats *) &(prv->mystats); ++ ++ if(prv->dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_hard_header: " ++ "no physical device associated with dev=%s\n", ++ dev->name ? dev->name : "NULL"); ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++ /* check if we have to send a IPv6 packet. It might be a Router ++ Solicitation, where the building of the packet happens in ++ reverse order: ++ 1. ll hdr, ++ 2. IPv6 hdr, ++ 3. ICMPv6 hdr ++ -> skb->nh.raw is still uninitialized when this function is ++ called!! If this is no IPv6 packet, we can print debugging ++ messages, otherwise we skip all debugging messages and just ++ build the ll header */ ++ if(type != ETH_P_IPV6) { ++ /* execute this only, if we don't have to build the ++ header for a IPv6 packet */ ++ if(!prv->hard_header) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_hard_header: " ++ "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", ++ saddr, ++ daddr, ++ len, ++ type, ++ dev->name); ++ KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->nh.iph->saddr), ++ (__u32)ntohl(skb->nh.iph->daddr) ); ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++#define da ((struct device *)(prv->dev))->dev_addr ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_hard_header: " ++ "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ", ++ saddr, ++ daddr, ++ len, ++ type, ++ dev->name, ++ prv->dev->name, ++ da[0], da[1], da[2], da[3], da[4], da[5]); ++ KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->nh.iph->saddr), ++ (__u32)ntohl(skb->nh.iph->daddr) ); ++ } else { ++ KLIPS_PRINT(debug_mast, ++ "klips_debug:ipsec_mast_hard_header: " ++ "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); ++ } ++ tmp = skb->dev; ++ skb->dev = prv->dev; ++ ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); ++ skb->dev = tmp; ++ return ret; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_mast_rebuild_header(struct sk_buff *skb) ++{ ++ struct ipsecpriv *prv = skb->dev->priv; ++ struct device *tmp; ++ int ret; ++ struct net_device_stats *stats; /* This device's statistics */ ++ ++ if(skb->dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_rebuild_header: " ++ "no device..."); ++ return -ENODEV; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_rebuild_header: " ++ "no private space associated with dev=%s", ++ skb->dev->name ? skb->dev->name : "NULL"); ++ return -ENODEV; ++ } ++ ++ stats = (struct net_device_stats *) &(prv->mystats); ++ ++ if(prv->dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_rebuild_header: " ++ "no physical device associated with dev=%s", ++ skb->dev->name ? skb->dev->name : "NULL"); ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++ if(!prv->rebuild_header) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_rebuild_header: " ++ "physical device has been detached, packet dropped skb->dev=%s->NULL ", ++ skb->dev->name); ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->nh.iph->saddr), ++ (__u32)ntohl(skb->nh.iph->daddr) ); ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast: " ++ "Revectored rebuild_header dev=%s->%s ", ++ skb->dev->name, prv->dev->name); ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->nh.iph->saddr), ++ (__u32)ntohl(skb->nh.iph->daddr) ); ++ tmp = skb->dev; ++ skb->dev = prv->dev; ++ ++ ret = prv->rebuild_header(skb); ++ skb->dev = tmp; ++ return ret; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_mast_set_mac_address(struct device *dev, void *addr) ++{ ++ struct ipsecpriv *prv = dev->priv; ++ ++ struct net_device_stats *stats; /* This device's statistics */ ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_set_mac_address: " ++ "no device..."); ++ return -ENODEV; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_set_mac_address: " ++ "no private space associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ return -ENODEV; ++ } ++ ++ stats = (struct net_device_stats *) &(prv->mystats); ++ ++ if(prv->dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_set_mac_address: " ++ "no physical device associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++ if(!prv->set_mac_address) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_set_mac_address: " ++ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", ++ dev->name); ++ return -ENODEV; ++ } ++ ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_set_mac_address: " ++ "Revectored dev=%s->%s addr=0p%p\n", ++ dev->name, prv->dev->name, addr); ++ return prv->set_mac_address(prv->dev, addr); ++ ++} ++ ++DEBUG_NO_STATIC void ++ipsec_mast_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr) ++{ ++ struct ipsecpriv *prv = dev->priv; ++ ++ struct net_device_stats *stats; /* This device's statistics */ ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_cache_update: " ++ "no device..."); ++ return; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_cache_update: " ++ "no private space associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ return; ++ } ++ ++ stats = (struct net_device_stats *) &(prv->mystats); ++ ++ if(prv->dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_cache_update: " ++ "no physical device associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ stats->tx_dropped++; ++ return; ++ } ++ ++ if(!prv->header_cache_update) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_cache_update: " ++ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", ++ dev->name); ++ return; ++ } ++ ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast: " ++ "Revectored cache_update\n"); ++ prv->header_cache_update(hh, prv->dev, haddr); ++ return; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_mast_neigh_setup(struct neighbour *n) ++{ ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_neigh_setup:\n"); ++ ++ if (n->nud_state == NUD_NONE) { ++ n->ops = &arp_broken_ops; ++ n->output = n->ops->output; ++ } ++ return 0; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_mast_neigh_setup_dev(struct device *dev, struct neigh_parms *p) ++{ ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_neigh_setup_dev: " ++ "setting up %s\n", ++ dev ? dev->name : "NULL"); ++ ++ if (p->tbl->family == AF_INET) { ++ p->neigh_setup = ipsec_mast_neigh_setup; ++ p->ucast_probes = 0; ++ p->mcast_probes = 0; ++ } ++ return 0; ++} ++ ++/* ++ * We call the attach routine to attach another device. ++ */ ++ ++DEBUG_NO_STATIC int ++ipsec_mast_attach(struct device *dev, struct device *physdev) ++{ ++ int i; ++ struct ipsecpriv *prv = dev->priv; ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_attach: " ++ "no device..."); ++ return -ENODEV; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_attach: " ++ "no private space associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ return -ENODATA; ++ } ++ ++ prv->dev = physdev; ++ prv->hard_start_xmit = physdev->hard_start_xmit; ++ prv->get_stats = physdev->get_stats; ++ ++ if (physdev->hard_header) { ++ prv->hard_header = physdev->hard_header; ++ dev->hard_header = ipsec_mast_hard_header; ++ } else ++ dev->hard_header = NULL; ++ ++ if (physdev->rebuild_header) { ++ prv->rebuild_header = physdev->rebuild_header; ++ dev->rebuild_header = ipsec_mast_rebuild_header; ++ } else ++ dev->rebuild_header = NULL; ++ ++ if (physdev->set_mac_address) { ++ prv->set_mac_address = physdev->set_mac_address; ++ dev->set_mac_address = ipsec_mast_set_mac_address; ++ } else ++ dev->set_mac_address = NULL; ++ ++ if (physdev->header_cache_update) { ++ prv->header_cache_update = physdev->header_cache_update; ++ dev->header_cache_update = ipsec_mast_cache_update; ++ } else ++ dev->header_cache_update = NULL; ++ ++ dev->hard_header_len = physdev->hard_header_len; ++ ++/* prv->neigh_setup = physdev->neigh_setup; */ ++ dev->neigh_setup = ipsec_mast_neigh_setup_dev; ++ dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */ ++ prv->mtu = physdev->mtu; ++ ++#ifdef PHYSDEV_TYPE ++ dev->type = physdev->type; /* ARPHRD_MAST; */ ++#endif /* PHYSDEV_TYPE */ ++ ++ dev->addr_len = physdev->addr_len; ++ for (i=0; i<dev->addr_len; i++) { ++ dev->dev_addr[i] = physdev->dev_addr[i]; ++ } ++#ifdef CONFIG_IPSEC_DEBUG ++ if(debug_mast & DB_MAST_INIT) { ++ printk(KERN_INFO "klips_debug:ipsec_mast_attach: " ++ "physical device %s being attached has HW address: %2x", ++ physdev->name, physdev->dev_addr[0]); ++ for (i=1; i < physdev->addr_len; i++) { ++ printk(":%02x", physdev->dev_addr[i]); ++ } ++ printk("\n"); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ return 0; ++} ++ ++/* ++ * We call the detach routine to detach the ipsec mast from another device. ++ */ ++ ++DEBUG_NO_STATIC int ++ipsec_mast_detach(struct device *dev) ++{ ++ int i; ++ struct ipsecpriv *prv = dev->priv; ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_detach: " ++ "no device..."); ++ return -ENODEV; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, ++ "klips_debug:ipsec_mast_detach: " ++ "no private space associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ return -ENODATA; ++ } ++ ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_detach: " ++ "physical device %s being detached from virtual device %s\n", ++ prv->dev ? prv->dev->name : "NULL", ++ dev->name); ++ ++ prv->dev = NULL; ++ prv->hard_start_xmit = NULL; ++ prv->get_stats = NULL; ++ ++ prv->hard_header = NULL; ++#ifdef DETACH_AND_DOWN ++ dev->hard_header = NULL; ++#endif /* DETACH_AND_DOWN */ ++ ++ prv->rebuild_header = NULL; ++#ifdef DETACH_AND_DOWN ++ dev->rebuild_header = NULL; ++#endif /* DETACH_AND_DOWN */ ++ ++ prv->set_mac_address = NULL; ++#ifdef DETACH_AND_DOWN ++ dev->set_mac_address = NULL; ++#endif /* DETACH_AND_DOWN */ ++ ++ prv->header_cache_update = NULL; ++#ifdef DETACH_AND_DOWN ++ dev->header_cache_update = NULL; ++#endif /* DETACH_AND_DOWN */ ++ ++#ifdef DETACH_AND_DOWN ++ dev->neigh_setup = NULL; ++#endif /* DETACH_AND_DOWN */ ++ ++ dev->hard_header_len = 0; ++#ifdef DETACH_AND_DOWN ++ dev->mtu = 0; ++#endif /* DETACH_AND_DOWN */ ++ prv->mtu = 0; ++ for (i=0; i<MAX_ADDR_LEN; i++) { ++ dev->dev_addr[i] = 0; ++ } ++ dev->addr_len = 0; ++#ifdef PHYSDEV_TYPE ++ dev->type = ARPHRD_VOID; /* ARPHRD_MAST; */ ++#endif /* PHYSDEV_TYPE */ ++ ++ return 0; ++} ++ ++/* ++ * We call the clear routine to detach all ipsec masts from other devices. ++ */ ++DEBUG_NO_STATIC int ++ipsec_mast_clear(void) ++{ ++ int i; ++ struct device *ipsecdev = NULL, *prvdev; ++ struct ipsecpriv *prv; ++ char name[9]; ++ int ret; ++ ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_clear: .\n"); ++ ++ for(i = 0; i < IPSEC_NUM_IF; i++) { ++ sprintf(name, IPSEC_DEV_FORMAT, i); ++ if((ipsecdev = ipsec_dev_get(name)) != NULL) { ++ if((prv = (struct ipsecpriv *)(ipsecdev->priv))) { ++ prvdev = (struct device *)(prv->dev); ++ if(prvdev) { ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_clear: " ++ "physical device for device %s is %s\n", ++ name, prvdev->name); ++ if((ret = ipsec_mast_detach(ipsecdev))) { ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_clear: " ++ "error %d detatching device %s from device %s.\n", ++ ret, name, prvdev->name); ++ return ret; ++ } ++ } ++ } ++ } ++ } ++ return 0; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_mast_ioctl(struct device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct ipsecmastconf *cf = (struct ipsecmastconf *)&ifr->ifr_data; ++ struct ipsecpriv *prv = dev->priv; ++ struct device *them; /* physical device */ ++#ifdef CONFIG_IP_ALIAS ++ char *colon; ++ char realphysname[IFNAMSIZ]; ++#endif /* CONFIG_IP_ALIAS */ ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "device not supplied.\n"); ++ return -ENODEV; ++ } ++ ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "tncfg service call #%d for dev=%s\n", ++ cmd, ++ dev->name ? dev->name : "NULL"); ++ switch (cmd) { ++ /* attach a virtual ipsec? device to a physical device */ ++ case IPSEC_SET_DEV: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "calling ipsec_mast_attatch...\n"); ++#ifdef CONFIG_IP_ALIAS ++ /* If this is an IP alias interface, get its real physical name */ ++ strncpy(realphysname, cf->cf_name, IFNAMSIZ); ++ realphysname[IFNAMSIZ-1] = 0; ++ colon = strchr(realphysname, ':'); ++ if (colon) *colon = 0; ++ them = ipsec_dev_get(realphysname); ++#else /* CONFIG_IP_ALIAS */ ++ them = ipsec_dev_get(cf->cf_name); ++#endif /* CONFIG_IP_ALIAS */ ++ ++ if (them == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "physical device %s requested is null\n", ++ cf->cf_name); ++ return -ENXIO; ++ } ++ ++#if 0 ++ if (them->flags & IFF_UP) { ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "physical device %s requested is not up.\n", ++ cf->cf_name); ++ return -ENXIO; ++ } ++#endif ++ ++ if (prv && prv->dev) { ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "virtual device is already connected to %s.\n", ++ prv->dev->name ? prv->dev->name : "NULL"); ++ return -EBUSY; ++ } ++ return ipsec_mast_attach(dev, them); ++ ++ case IPSEC_DEL_DEV: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "calling ipsec_mast_detatch.\n"); ++ if (! prv->dev) { ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "physical device not connected.\n"); ++ return -ENODEV; ++ } ++ return ipsec_mast_detach(dev); ++ ++ case IPSEC_CLR_DEV: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "calling ipsec_mast_clear.\n"); ++ return ipsec_mast_clear(); ++ ++ default: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_ioctl: " ++ "unknown command %d.\n", ++ cmd); ++ return -EOPNOTSUPP; ++ } ++} ++ ++int ++ipsec_mast_device_event(struct notifier_block *unused, unsigned long event, void *ptr) ++{ ++ struct device *dev = ptr; ++ struct device *ipsec_dev; ++ struct ipsecpriv *priv; ++ char name[9]; ++ int i; ++ ++ if (dev == NULL) { ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "dev=NULL for event type %ld.\n", ++ event); ++ return(NOTIFY_DONE); ++ } ++ ++ /* check for loopback devices */ ++ if (dev && (dev->flags & IFF_LOOPBACK)) { ++ return(NOTIFY_DONE); ++ } ++ ++ switch (event) { ++ case NETDEV_DOWN: ++ /* look very carefully at the scope of these compiler ++ directives before changing anything... -- RGB */ ++ ++ case NETDEV_UNREGISTER: ++ switch (event) { ++ case NETDEV_DOWN: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_DOWN dev=%s flags=%x\n", ++ dev->name, ++ dev->flags); ++ if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) { ++ printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n", ++ dev->name); ++ } ++ break; ++ case NETDEV_UNREGISTER: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_UNREGISTER dev=%s flags=%x\n", ++ dev->name, ++ dev->flags); ++ break; ++ } ++ ++ /* find the attached physical device and detach it. */ ++ for(i = 0; i < IPSEC_NUM_IF; i++) { ++ sprintf(name, IPSEC_DEV_FORMAT, i); ++ ipsec_dev = ipsec_dev_get(name); ++ if(ipsec_dev) { ++ priv = (struct ipsecpriv *)(ipsec_dev->priv); ++ if(priv) { ++ ; ++ if(((struct device *)(priv->dev)) == dev) { ++ /* dev_close(ipsec_dev); */ ++ /* return */ ipsec_mast_detach(ipsec_dev); ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "device '%s' has been detached.\n", ++ ipsec_dev->name); ++ break; ++ } ++ } else { ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "device '%s' has no private data space!\n", ++ ipsec_dev->name); ++ } ++ } ++ } ++ break; ++ case NETDEV_UP: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_UP dev=%s\n", ++ dev->name); ++ break; ++ case NETDEV_REBOOT: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_REBOOT dev=%s\n", ++ dev->name); ++ break; ++ case NETDEV_CHANGE: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_CHANGE dev=%s flags=%x\n", ++ dev->name, ++ dev->flags); ++ break; ++ case NETDEV_REGISTER: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_REGISTER dev=%s\n", ++ dev->name); ++ break; ++ case NETDEV_CHANGEMTU: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_CHANGEMTU dev=%s to mtu=%d\n", ++ dev->name, ++ dev->mtu); ++ break; ++ case NETDEV_CHANGEADDR: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_CHANGEADDR dev=%s\n", ++ dev->name); ++ break; ++ case NETDEV_GOING_DOWN: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_GOING_DOWN dev=%s\n", ++ dev->name); ++ break; ++ case NETDEV_CHANGENAME: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "NETDEV_CHANGENAME dev=%s\n", ++ dev->name); ++ break; ++ default: ++ KLIPS_PRINT(debug_mast & DB_MAST_INIT, ++ "klips_debug:ipsec_mast_device_event: " ++ "event type %ld unrecognised for dev=%s\n", ++ event, ++ dev->name); ++ break; ++ } ++ return NOTIFY_DONE; ++} ++ ++/* ++ * Called when an ipsec mast device is initialized. ++ * The ipsec mast device structure is passed to us. ++ */ ++ ++int ++ipsec_mast_init(struct device *dev) ++{ ++ int i; ++ ++ KLIPS_PRINT(debug_mast, ++ "klips_debug:ipsec_mast_init: " ++ "allocating %lu bytes initialising device: %s\n", ++ (unsigned long) sizeof(struct ipsecpriv), ++ dev->name ? dev->name : "NULL"); ++ ++ /* Add our mast functions to the device */ ++ dev->open = ipsec_mast_open; ++ dev->stop = ipsec_mast_close; ++ dev->hard_start_xmit = ipsec_mast_start_xmit; ++ dev->get_stats = ipsec_mast_get_stats; ++ ++ dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); ++ if (dev->priv == NULL) ++ return -ENOMEM; ++ memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); ++ ++ for(i = 0; i < sizeof(zeroes); i++) { ++ ((__u8*)(zeroes))[i] = 0; ++ } ++ ++ dev->set_multicast_list = NULL; ++ dev->do_ioctl = ipsec_mast_ioctl; ++ dev->hard_header = NULL; ++ dev->rebuild_header = NULL; ++ dev->set_mac_address = NULL; ++ dev->header_cache_update= NULL; ++ dev->neigh_setup = ipsec_mast_neigh_setup_dev; ++ dev->hard_header_len = 0; ++ dev->mtu = 0; ++ dev->addr_len = 0; ++ dev->type = ARPHRD_VOID; /* ARPHRD_MAST; */ /* ARPHRD_ETHER; */ ++ dev->tx_queue_len = 10; /* Small queue */ ++ memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ ++ ++ /* New-style flags. */ ++ dev->flags = IFF_NOARP /* 0 */ /* Petr Novak */; ++ dev_init_buffers(dev); ++ ++ /* We're done. Have I forgotten anything? */ ++ return 0; ++} ++ ++/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ++/* Module specific interface (but it links with the rest of IPSEC) */ ++/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ++ ++int ++ipsec_mast_probe(struct device *dev) ++{ ++ ipsec_mast_init(dev); ++ return 0; ++} ++ ++int ++ipsec_mast_init_devices(void) ++{ ++ return 0; ++} ++ ++/* void */ ++int ++ipsec_mast_cleanup_devices(void) ++{ ++ int error = 0; ++ int i; ++ char name[10]; ++ struct device *dev_mast; ++ ++ for(i = 0; i < ipsec_mastdevice_count; i++) { ++ sprintf(name, MAST_DEV_FORMAT, i); ++ if((dev_mast = ipsec_dev_get(name)) == NULL) { ++ break; ++ } ++ unregister_netdev(dev_mast); ++ kfree(dev_mast->priv); ++ dev_mast->priv=NULL; ++ } ++ return error; ++} ++ ++/* ++ * $Log: ipsec_mast.c,v $ ++ * Revision 1.3 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.2.4.1 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.2 2003/06/22 20:06:17 mcr ++ * refactored mast code still had lots of ipsecX junk in it. ++ * ++ * Revision 1.1 2003/02/12 19:31:12 rgb ++ * Refactored from ipsec_tunnel.c ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_md5c.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,448 @@ ++/* ++ * RCSID $Id: ipsec_md5c.c,v 1.8 2004/04/06 02:49:26 mcr Exp $ ++ */ ++ ++/* ++ * The rest of the code is derived from MD5C.C by RSADSI. Minor cosmetic ++ * changes to accomodate it in the kernel by ji. ++ */ ++ ++#include <asm/byteorder.h> ++#include <linux/string.h> ++ ++#include "openswan/ipsec_md5h.h" ++ ++/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm ++ */ ++ ++/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All ++rights reserved. ++ ++License to copy and use this software is granted provided that it ++is identified as the "RSA Data Security, Inc. MD5 Message-Digest ++Algorithm" in all material mentioning or referencing this software ++or this function. ++ ++License is also granted to make and use derivative works provided ++that such works are identified as "derived from the RSA Data ++Security, Inc. MD5 Message-Digest Algorithm" in all material ++mentioning or referencing the derived work. ++ ++RSA Data Security, Inc. makes no representations concerning either ++the merchantability of this software or the suitability of this ++software for any particular purpose. It is provided "as is" ++without express or implied warranty of any kind. ++ ++These notices must be retained in any copies of any part of this ++documentation and/or software. ++ */ ++ ++/* ++ * Additions by JI ++ * ++ * HAVEMEMCOPY is defined if mem* routines are available ++ * ++ * HAVEHTON is defined if htons() and htonl() can be used ++ * for big/little endian conversions ++ * ++ */ ++ ++#define HAVEMEMCOPY ++#ifdef __LITTLE_ENDIAN ++#define LITTLENDIAN ++#endif ++#ifdef __BIG_ENDIAN ++#define BIGENDIAN ++#endif ++ ++/* Constants for MD5Transform routine. ++ */ ++ ++#define S11 7 ++#define S12 12 ++#define S13 17 ++#define S14 22 ++#define S21 5 ++#define S22 9 ++#define S23 14 ++#define S24 20 ++#define S31 4 ++#define S32 11 ++#define S33 16 ++#define S34 23 ++#define S41 6 ++#define S42 10 ++#define S43 15 ++#define S44 21 ++ ++static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); ++ ++#ifdef LITTLEENDIAN ++#define Encode MD5_memcpy ++#define Decode MD5_memcpy ++#else ++static void Encode PROTO_LIST ++ ((unsigned char *, UINT4 *, unsigned int)); ++static void Decode PROTO_LIST ++ ((UINT4 *, unsigned char *, unsigned int)); ++#endif ++ ++#ifdef HAVEMEMCOPY ++/* no need to include <memory.h> here; <linux/string.h> defines these */ ++#define MD5_memcpy memcpy ++#define MD5_memset memset ++#else ++#ifdef HAVEBCOPY ++#define MD5_memcpy(_a,_b,_c) bcopy((_b),(_a),(_c)) ++#define MD5_memset(_a,_b,_c) bzero((_a),(_c)) ++#else ++static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); ++static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); ++#endif ++#endif ++static unsigned char PADDING[64] = { ++ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++}; ++ ++/* F, G, H and I are basic MD5 functions. ++ */ ++#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) ++#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) ++#define H(x, y, z) ((x) ^ (y) ^ (z)) ++#define I(x, y, z) ((y) ^ ((x) | (~z))) ++ ++/* ROTATE_LEFT rotates x left n bits. ++ */ ++#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) ++ ++/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. ++Rotation is separate from addition to prevent recomputation. ++ */ ++#define FF(a, b, c, d, x, s, ac) { \ ++ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ (a) += (b); \ ++ } ++#define GG(a, b, c, d, x, s, ac) { \ ++ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ (a) += (b); \ ++ } ++#define HH(a, b, c, d, x, s, ac) { \ ++ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ (a) += (b); \ ++ } ++#define II(a, b, c, d, x, s, ac) { \ ++ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ (a) += (b); \ ++ } ++ ++/* ++ * MD5 initialization. Begins an MD5 operation, writing a new context. ++ */ ++void MD5Init(void *vcontext) ++{ ++ MD5_CTX *context = vcontext; ++ ++ context->count[0] = context->count[1] = 0; ++ /* Load magic initialization constants. ++*/ ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xefcdab89; ++ context->state[2] = 0x98badcfe; ++ context->state[3] = 0x10325476; ++} ++ ++/* MD5 block update operation. Continues an MD5 message-digest ++ operation, processing another message block, and updating the ++ context. ++ */ ++void MD5Update (vcontext, input, inputLen) ++ void *vcontext; ++ unsigned char *input; /* input block */ ++ __u32 inputLen; /* length of input block */ ++{ ++ MD5_CTX *context = vcontext; ++ __u32 i; ++ unsigned int index, partLen; ++ ++ /* Compute number of bytes mod 64 */ ++ index = (unsigned int)((context->count[0] >> 3) & 0x3F); ++ ++ /* Update number of bits */ ++ if ((context->count[0] += ((UINT4)inputLen << 3)) ++ < ((UINT4)inputLen << 3)) ++ context->count[1]++; ++ context->count[1] += ((UINT4)inputLen >> 29); ++ ++ partLen = 64 - index; ++ ++ /* Transform as many times as possible. ++*/ ++ if (inputLen >= partLen) { ++ MD5_memcpy ++ ((POINTER)&context->buffer[index], (POINTER)input, partLen); ++ MD5Transform (context->state, context->buffer); ++ ++ for (i = partLen; i + 63 < inputLen; i += 64) ++ MD5Transform (context->state, &input[i]); ++ ++ index = 0; ++ } ++ else ++ i = 0; ++ ++ /* Buffer remaining input */ ++ MD5_memcpy ++ ((POINTER)&context->buffer[index], (POINTER)&input[i], ++ inputLen-i); ++} ++ ++/* MD5 finalization. Ends an MD5 message-digest operation, writing the ++ the message digest and zeroizing the context. ++ */ ++void MD5Final (digest, vcontext) ++unsigned char digest[16]; /* message digest */ ++void *vcontext; /* context */ ++{ ++ MD5_CTX *context = vcontext; ++ unsigned char bits[8]; ++ unsigned int index, padLen; ++ ++ /* Save number of bits */ ++ Encode (bits, context->count, 8); ++ ++ /* Pad out to 56 mod 64. ++*/ ++ index = (unsigned int)((context->count[0] >> 3) & 0x3f); ++ padLen = (index < 56) ? (56 - index) : (120 - index); ++ MD5Update (context, PADDING, padLen); ++ ++ /* Append length (before padding) */ ++ MD5Update (context, bits, 8); ++ ++ if (digest != NULL) /* Bill Simpson's padding */ ++ { ++ /* store state in digest */ ++ Encode (digest, context->state, 16); ++ ++ /* Zeroize sensitive information. ++ */ ++ MD5_memset ((POINTER)context, 0, sizeof (*context)); ++ } ++} ++ ++/* MD5 basic transformation. Transforms state based on block. ++ */ ++static void MD5Transform (state, block) ++UINT4 state[4]; ++unsigned char block[64]; ++{ ++ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; ++ ++ Decode (x, block, 64); ++ ++ /* Round 1 */ ++ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ ++ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ ++ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ ++ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ ++ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ ++ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ ++ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ ++ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ ++ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ ++ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ ++ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ ++ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ ++ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ ++ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ ++ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ ++ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ ++ ++ /* Round 2 */ ++ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ ++ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ ++ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ ++ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ ++ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ ++ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ ++ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ ++ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ ++ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ ++ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ ++ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ ++ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ ++ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ ++ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ ++ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ ++ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ ++ ++ /* Round 3 */ ++ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ ++ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ ++ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ ++ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ ++ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ ++ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ ++ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ ++ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ ++ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ ++ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ ++ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ ++ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ ++ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ ++ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ ++ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ ++ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ ++ ++ /* Round 4 */ ++ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ ++ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ ++ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ ++ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ ++ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ ++ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ ++ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ ++ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ ++ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ ++ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ ++ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ ++ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ ++ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ ++ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ ++ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ ++ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ ++ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++ ++ /* Zeroize sensitive information. ++*/ ++ MD5_memset ((POINTER)x, 0, sizeof (x)); ++} ++ ++#ifndef LITTLEENDIAN ++ ++/* Encodes input (UINT4) into output (unsigned char). Assumes len is ++ a multiple of 4. ++ */ ++static void Encode (output, input, len) ++unsigned char *output; ++UINT4 *input; ++unsigned int len; ++{ ++ unsigned int i, j; ++ ++ for (i = 0, j = 0; j < len; i++, j += 4) { ++ output[j] = (unsigned char)(input[i] & 0xff); ++ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); ++ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); ++ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); ++ } ++} ++ ++/* Decodes input (unsigned char) into output (UINT4). Assumes len is ++ a multiple of 4. ++ */ ++static void Decode (output, input, len) ++UINT4 *output; ++unsigned char *input; ++unsigned int len; ++{ ++ unsigned int i, j; ++ ++ for (i = 0, j = 0; j < len; i++, j += 4) ++ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | ++ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); ++} ++ ++#endif ++ ++#ifndef HAVEMEMCOPY ++#ifndef HAVEBCOPY ++/* Note: Replace "for loop" with standard memcpy if possible. ++ */ ++ ++static void MD5_memcpy (output, input, len) ++POINTER output; ++POINTER input; ++unsigned int len; ++{ ++ unsigned int i; ++ ++ for (i = 0; i < len; i++) ++ ++ output[i] = input[i]; ++} ++ ++/* Note: Replace "for loop" with standard memset if possible. ++ */ ++ ++static void MD5_memset (output, value, len) ++POINTER output; ++int value; ++unsigned int len; ++{ ++ unsigned int i; ++ ++ for (i = 0; i < len; i++) ++ ((char *)output)[i] = (char)value; ++} ++#endif ++#endif ++ ++/* ++ * $Log: ipsec_md5c.c,v $ ++ * Revision 1.8 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.7 2002/09/10 01:45:14 mcr ++ * changed type of MD5_CTX and SHA1_CTX to void * so that ++ * the function prototypes would match, and could be placed ++ * into a pointer to a function. ++ * ++ * Revision 1.6 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.5 2002/04/24 07:36:28 mcr ++ * Moved from ./klips/net/ipsec/ipsec_md5c.c,v ++ * ++ * Revision 1.4 1999/12/13 13:59:12 rgb ++ * Quick fix to argument size to Update bugs. ++ * ++ * Revision 1.3 1999/05/21 18:09:28 henry ++ * unnecessary <memory.h> include causes trouble in 2.2 ++ * ++ * Revision 1.2 1999/04/06 04:54:26 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.1 1998/06/18 21:27:48 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.2 1998/04/23 20:54:02 rgb ++ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when ++ * verified. ++ * ++ * Revision 1.1 1998/04/09 03:06:08 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:04 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.3 1996/11/20 14:48:53 ji ++ * Release update only. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_proc.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1127 @@ ++/* ++ * @(#) /proc file system interface code. ++ * ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs <rgb@freeswan.org> ++ * 2001 Michael Richardson <mcr@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * Split out from ipsec_init.c version 1.70. ++ */ ++ ++char ipsec_proc_c_version[] = "RCSID $Id: ipsec_proc.c,v 1.30 2004/04/25 21:23:11 ken Exp $"; ++ ++ ++#include <linux/config.h> ++#include <linux/version.h> ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/in.h> /* struct sockaddr_in */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef SPINLOCK ++#ifdef SPINLOCK_23 ++#include <linux/spinlock.h> /* *lock* */ ++#else /* SPINLOCK_23 */ ++#include <asm/spinlock.h> /* *lock* */ ++#endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++#include <asm/uaccess.h> ++#include <linux/in6.h> ++#endif /* NET_21 */ ++#include <asm/checksum.h> ++#include <net/ip.h> ++#ifdef CONFIG_PROC_FS ++#include <linux/proc_fs.h> ++#endif /* CONFIG_PROC_FS */ ++#ifdef NETLINK_SOCK ++#include <linux/netlink.h> ++#else ++#include <net/netlink.h> ++#endif ++ ++#include "openswan/radij.h" ++ ++#include "openswan/ipsec_life.h" ++#include "openswan/ipsec_stats.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_xmit.h" ++ ++#include "openswan/ipsec_rcv.h" ++#include "openswan/ipsec_ah.h" ++#include "openswan/ipsec_esp.h" ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++#include "openswan/ipcomp.h" ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#include "openswan/ipsec_proto.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#ifdef CONFIG_PROC_FS ++ ++#ifdef IPSEC_PROC_SUBDIRS ++static struct proc_dir_entry *proc_net_ipsec_dir = NULL; ++static struct proc_dir_entry *proc_eroute_dir = NULL; ++static struct proc_dir_entry *proc_spi_dir = NULL; ++static struct proc_dir_entry *proc_spigrp_dir = NULL; ++static struct proc_dir_entry *proc_birth_dir = NULL; ++static struct proc_dir_entry *proc_stats_dir = NULL; ++#endif ++ ++struct ipsec_birth_reply ipsec_ipv4_birth_packet; ++struct ipsec_birth_reply ipsec_ipv6_birth_packet; ++ ++#define DECREMENT_UNSIGNED(X, amount) ((amount < (X)) ? (X)-amount : 0) ++ ++extern int ipsec_xform_get_info(char *buffer, char **start, ++ off_t offset, int length IPSEC_PROC_LAST_ARG); ++ ++ ++/* ipsec_snprintf: like snprintf except ++ * - size is signed and a negative value is treated as if it were 0 ++ * - the returned result is never negative -- ++ * an error generates a "?" or null output (depending on space). ++ * (Our callers are too lazy to check for an error return.) ++ * ++ * @param buf String buffer ++ * @param size Size of the string ++ * @param fmt printf string ++ * @param ... Variables to be displayed in fmt ++ * @return int Return code ++ */ ++int ipsec_snprintf(char *buf, ssize_t size, const char *fmt, ...) ++{ ++ va_list args; ++ int i; ++ size_t possize = size < 0? 0 : size; ++ va_start(args, fmt); ++ i = vsnprintf(buf,possize,fmt,args); ++ va_end(args); ++ if (i < 0) { ++ /* create empty output in place of error */ ++ i = 0; ++ if (size > 0) { ++ *buf = '\0'; ++ } ++ } ++ return i; ++} ++ ++ ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_eroute_get_info(char *buffer, ++ char **start, ++ off_t offset, ++ int length IPSEC_PROC_LAST_ARG) ++{ ++ struct wsbuf w = {buffer, length, offset, 0, 0}; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if (debug_radij & DB_RJ_DUMPTREES) ++ rj_dumptrees(); /* XXXXXXXXX */ ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_eroute_get_info: " ++ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", ++ buffer, ++ *start, ++ (int)offset, ++ length); ++ ++ spin_lock_bh(&eroute_lock); ++ ++ rj_walktree(rnh, ipsec_rj_walker_procprint, &w); ++/* rj_walktree(mask_rjhead, ipsec_rj_walker_procprint, &w); */ ++ ++ spin_unlock_bh(&eroute_lock); ++ ++ *start = buffer + (offset - w.begin); /* Start of wanted data */ ++ return w.len - (offset - w.begin); ++} ++ ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_spi_get_info(char *buffer, ++ char **start, ++ off_t offset, ++ int length IPSEC_PROC_LAST_ARG) ++{ ++ const int max_content = length > 0? length-1 : 0; ++ int len = 0; ++ off_t begin = 0; ++ int i; ++ struct ipsec_sa *sa_p; ++ char sa[SATOT_BUF]; ++ char buf_s[SUBNETTOA_BUF]; ++ char buf_d[SUBNETTOA_BUF]; ++ size_t sa_len; ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_spi_get_info: " ++ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", ++ buffer, ++ *start, ++ (int)offset, ++ length); ++ ++ spin_lock_bh(&tdb_lock); ++ ++ for (i = 0; i < SADB_HASHMOD; i++) { ++ for (sa_p = ipsec_sadb_hash[i]; ++ sa_p; ++ sa_p = sa_p->ips_hnext) { ++ atomic_inc(&sa_p->ips_refcount); ++ sa_len = satot(&sa_p->ips_said, 'x', sa, sizeof(sa)); ++ len += ipsec_snprintf(buffer+len, length-len, "%s ", ++ sa_len ? sa : " (error)"); ++ ++ len += ipsec_snprintf(buffer+len, length-len, "%s%s%s", ++ IPS_XFORM_NAME(sa_p)); ++ ++ len += ipsec_snprintf(buffer+len, length-len, ": dir=%s", ++ (sa_p->ips_flags & EMT_INBOUND) ? ++ "in " : "out"); ++ ++ if(sa_p->ips_addr_s) { ++ addrtoa(((struct sockaddr_in*)(sa_p->ips_addr_s))->sin_addr, ++ 0, buf_s, sizeof(buf_s)); ++ len += ipsec_snprintf(buffer+len, length-len, " src=%s", ++ buf_s); ++ } ++ ++ if((sa_p->ips_said.proto == IPPROTO_IPIP) ++ && (sa_p->ips_flags & SADB_X_SAFLAGS_INFLOW)) { ++ subnettoa(sa_p->ips_flow_s.u.v4.sin_addr, ++ sa_p->ips_mask_s.u.v4.sin_addr, ++ 0, ++ buf_s, ++ sizeof(buf_s)); ++ ++ subnettoa(sa_p->ips_flow_d.u.v4.sin_addr, ++ sa_p->ips_mask_d.u.v4.sin_addr, ++ 0, ++ buf_d, ++ sizeof(buf_d)); ++ ++ len += ipsec_snprintf(buffer+len, length-len, " policy=%s->%s", ++ buf_s, buf_d); ++ } ++ ++ if(sa_p->ips_iv_bits) { ++ int j; ++ len += ipsec_snprintf(buffer+len, length-len, " iv_bits=%dbits iv=0x", ++ sa_p->ips_iv_bits); ++ ++ for(j = 0; j < sa_p->ips_iv_bits / 8; j++) { ++ len += ipsec_snprintf(buffer+len, length-len, "%02x", ++ (__u32)((__u8*)(sa_p->ips_iv))[j]); ++ } ++ } ++ ++ if(sa_p->ips_encalg || sa_p->ips_authalg) { ++ if(sa_p->ips_replaywin) { ++ len += ipsec_snprintf(buffer+len, length-len, " ooowin=%d", ++ sa_p->ips_replaywin); ++ } ++ if(sa_p->ips_errs.ips_replaywin_errs) { ++ len += ipsec_snprintf(buffer+len, length-len, " ooo_errs=%d", ++ sa_p->ips_errs.ips_replaywin_errs); ++ } ++ if(sa_p->ips_replaywin_lastseq) { ++ len += ipsec_snprintf(buffer+len, length-len, " seq=%d", ++ sa_p->ips_replaywin_lastseq); ++ } ++ if(sa_p->ips_replaywin_bitmap) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ++ len += ipsec_snprintf(buffer+len, length-len, " bit=0x%Lx", ++ sa_p->ips_replaywin_bitmap); ++#else ++ len += ipsec_snprintf(buffer+len, length-len, " bit=0x%x%08x", ++ (__u32)(sa_p->ips_replaywin_bitmap >> 32), ++ (__u32)sa_p->ips_replaywin_bitmap); ++#endif ++ } ++ if(sa_p->ips_replaywin_maxdiff) { ++ len += ipsec_snprintf(buffer+len, length-len, " max_seq_diff=%d", ++ sa_p->ips_replaywin_maxdiff); ++ } ++ } ++ if(sa_p->ips_flags & ~EMT_INBOUND) { ++ len += ipsec_snprintf(buffer+len, length-len, " flags=0x%x", ++ sa_p->ips_flags & ~EMT_INBOUND); ++ len += ipsec_snprintf(buffer+len, length-len, "<"); ++ /* flag printing goes here */ ++ len += ipsec_snprintf(buffer+len, length-len, ">"); ++ } ++ if(sa_p->ips_auth_bits) { ++ len += ipsec_snprintf(buffer+len, length-len, " alen=%d", ++ sa_p->ips_auth_bits); ++ } ++ if(sa_p->ips_key_bits_a) { ++ len += ipsec_snprintf(buffer+len, length-len, " aklen=%d", ++ sa_p->ips_key_bits_a); ++ } ++ if(sa_p->ips_errs.ips_auth_errs) { ++ len += ipsec_snprintf(buffer+len, length-len, " auth_errs=%d", ++ sa_p->ips_errs.ips_auth_errs); ++ } ++ if(sa_p->ips_key_bits_e) { ++ len += ipsec_snprintf(buffer+len, length-len, " eklen=%d", ++ sa_p->ips_key_bits_e); ++ } ++ if(sa_p->ips_errs.ips_encsize_errs) { ++ len += ipsec_snprintf(buffer+len, length-len, " encr_size_errs=%d", ++ sa_p->ips_errs.ips_encsize_errs); ++ } ++ if(sa_p->ips_errs.ips_encpad_errs) { ++ len += ipsec_snprintf(buffer+len, length-len, " encr_pad_errs=%d", ++ sa_p->ips_errs.ips_encpad_errs); ++ } ++ ++ len += ipsec_snprintf(buffer+len, length-len, " life(c,s,h)="); ++ ++ len += ipsec_lifetime_format(buffer + len, ++ length - len, ++ "alloc", ++ ipsec_life_countbased, ++ &sa_p->ips_life.ipl_allocations); ++ ++ len += ipsec_lifetime_format(buffer + len, ++ length - len, ++ "bytes", ++ ipsec_life_countbased, ++ &sa_p->ips_life.ipl_bytes); ++ ++ len += ipsec_lifetime_format(buffer + len, ++ length - len, ++ "addtime", ++ ipsec_life_timebased, ++ &sa_p->ips_life.ipl_addtime); ++ ++ len += ipsec_lifetime_format(buffer + len, ++ length - len, ++ "usetime", ++ ipsec_life_timebased, ++ &sa_p->ips_life.ipl_usetime); ++ ++ len += ipsec_lifetime_format(buffer + len, ++ length - len, ++ "packets", ++ ipsec_life_countbased, ++ &sa_p->ips_life.ipl_packets); ++ ++ if(sa_p->ips_life.ipl_usetime.ipl_last) { /* XXX-MCR should be last? */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ++ len += ipsec_snprintf(buffer+len, length-len, " idle=%Ld", ++ jiffies / HZ - sa_p->ips_life.ipl_usetime.ipl_last); ++#else ++ len += ipsec_snprintf(buffer+len, length-len, " idle=%lu", ++ jiffies / HZ - (unsigned long)sa_p->ips_life.ipl_usetime.ipl_last); ++#endif ++ } ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++ if(sa_p->ips_said.proto == IPPROTO_COMP && ++ (sa_p->ips_comp_ratio_dbytes || ++ sa_p->ips_comp_ratio_cbytes)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ++ len += ipsec_snprintf(buffer+len, length-len, " ratio=%Ld:%Ld", ++ sa_p->ips_comp_ratio_dbytes, ++ sa_p->ips_comp_ratio_cbytes); ++#else ++ len += ipsec_snprintf(buffer+len, length-len, " ratio=%lu:%lu", ++ (unsigned long)sa_p->ips_comp_ratio_dbytes, ++ (unsigned long)sa_p->ips_comp_ratio_cbytes); ++#endif ++ } ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if(sa_p->ips_natt_type != 0) { ++ char *natttype_name; ++ ++ switch(sa_p->ips_natt_type) ++ { ++ case ESPINUDP_WITH_NON_IKE: ++ natttype_name="nonike"; ++ break; ++ case ESPINUDP_WITH_NON_ESP: ++ natttype_name="nonesp"; ++ break; ++ default: ++ natttype_name = "unknown"; ++ break; ++ } ++ ++ len += ipsec_snprintf(buffer + len, length-len, " natencap=%s", ++ natttype_name); ++ ++ len += ipsec_snprintf(buffer + len, length-len, " natsport=%d", ++ sa_p->ips_natt_sport); ++ ++ len += ipsec_snprintf(buffer + len,length-len, " natdport=%d", ++ sa_p->ips_natt_dport); ++ } ++#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ ++ ++ len += ipsec_snprintf(buffer + len,length-len, " refcount=%d", ++ atomic_read(&sa_p->ips_refcount)); ++ ++ len += ipsec_snprintf(buffer+len, length-len, " ref=%d", ++ sa_p->ips_ref); ++#ifdef CONFIG_IPSEC_DEBUG ++ if(debug_xform) { ++ len += ipsec_snprintf(buffer+len, length-len, " reftable=%lu refentry=%lu", ++ (unsigned long)IPsecSAref2table(sa_p->ips_ref), ++ (unsigned long)IPsecSAref2entry(sa_p->ips_ref)); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ len += ipsec_snprintf(buffer+len, length-len, "\n"); ++ ++ atomic_dec(&sa_p->ips_refcount); ++ ++ if (len >= max_content) { ++ /* we've done all that can fit -- stop loops */ ++ len = max_content; /* truncate crap */ ++ goto done_spi_i; ++ } else { ++ const off_t pos = begin + len; /* file position of end of what we've generated */ ++ ++ if (pos <= offset) { ++ /* all is before first interesting character: ++ * discard, but note where we are. ++ */ ++ len = 0; ++ begin = pos; ++ } ++ } ++ } ++ } ++ ++done_spi_i: ++ spin_unlock_bh(&tdb_lock); ++ ++ *start = buffer + (offset - begin); /* Start of wanted data */ ++ return len - (offset - begin); ++} ++ ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_spigrp_get_info(char *buffer, ++ char **start, ++ off_t offset, ++ int length IPSEC_PROC_LAST_ARG) ++{ ++ /* Limit of useful snprintf output */ ++ const int max_content = length > 0? length-1 : 0; ++ ++ int len = 0; ++ off_t begin = 0; ++ int i; ++ struct ipsec_sa *sa_p, *sa_p2; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_spigrp_get_info: " ++ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", ++ buffer, ++ *start, ++ (int)offset, ++ length); ++ ++ spin_lock_bh(&tdb_lock); ++ ++ for (i = 0; i < SADB_HASHMOD; i++) { ++ for (sa_p = ipsec_sadb_hash[i]; ++ sa_p != NULL; ++ sa_p = sa_p->ips_hnext) ++ { ++ atomic_inc(&sa_p->ips_refcount); ++ if(sa_p->ips_inext == NULL) { ++ sa_p2 = sa_p; ++ while(sa_p2 != NULL) { ++ atomic_inc(&sa_p2->ips_refcount); ++ sa_len = satot(&sa_p2->ips_said, ++ 'x', sa, sizeof(sa)); ++ ++ len += ipsec_snprintf(buffer+len, length-len, "%s ", ++ sa_len ? sa : " (error)"); ++ atomic_dec(&sa_p2->ips_refcount); ++ sa_p2 = sa_p2->ips_onext; ++ } ++ len += ipsec_snprintf(buffer+len, length-len, "\n"); ++ } ++ ++ atomic_dec(&sa_p->ips_refcount); ++ ++ if (len >= max_content) { ++ /* we've done all that can fit -- stop loops */ ++ len = max_content; /* truncate crap */ ++ goto done_spigrp_i; ++ } else { ++ const off_t pos = begin + len; ++ ++ if (pos <= offset) { ++ /* all is before first interesting character: ++ * discard, but note where we are. ++ */ ++ len = 0; ++ begin = pos; ++ } ++ } ++ } ++ } ++ ++done_spigrp_i: ++ spin_unlock_bh(&tdb_lock); ++ ++ *start = buffer + (offset - begin); /* Start of wanted data */ ++ return len - (offset - begin); ++} ++ ++ ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_tncfg_get_info(char *buffer, ++ char **start, ++ off_t offset, ++ int length IPSEC_PROC_LAST_ARG) ++{ ++ /* limit of useful snprintf output */ ++ const int max_content = length > 0? length-1 : 0; ++ int len = 0; ++ off_t begin = 0; ++ int i; ++ char name[9]; ++ struct device *dev, *privdev; ++ struct ipsecpriv *priv; ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_tncfg_get_info: " ++ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", ++ buffer, ++ *start, ++ (int)offset, ++ length); ++ ++ for(i = 0; i < IPSEC_NUM_IF; i++) { ++ ipsec_snprintf(name, (ssize_t) sizeof(name), IPSEC_DEV_FORMAT, i); ++ dev = __ipsec_dev_get(name); ++ if(dev) { ++ priv = (struct ipsecpriv *)(dev->priv); ++ len += ipsec_snprintf(buffer+len, length-len, "%s", ++ dev->name); ++ if(priv) { ++ privdev = (struct device *)(priv->dev); ++ len += ipsec_snprintf(buffer+len, length-len, " -> %s", ++ privdev ? privdev->name : "NULL"); ++ len += ipsec_snprintf(buffer+len, length-len, " mtu=%d(%d) -> %d", ++ dev->mtu, ++ priv->mtu, ++ privdev ? privdev->mtu : 0); ++ } else { ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_tncfg_get_info: device '%s' has no private data space!\n", ++ dev->name); ++ } ++ len += ipsec_snprintf(buffer+len, length-len, "\n"); ++ ++ if (len >= max_content) { ++ /* we've done all that can fit -- stop loop */ ++ len = max_content; /* truncate crap */ ++ break; ++ } else { ++ const off_t pos = begin + len; ++ if (pos <= offset) { ++ len = 0; ++ begin = pos; ++ } ++ } ++ } ++ } ++ *start = buffer + (offset - begin); /* Start of wanted data */ ++ len -= (offset - begin); /* Start slop */ ++ if (len > length) ++ len = length; ++ return len; ++} ++ ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_version_get_info(char *buffer, ++ char **start, ++ off_t offset, ++ int length IPSEC_PROC_LAST_ARG) ++{ ++ int len = 0; ++ off_t begin = 0; ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_version_get_info: " ++ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", ++ buffer, ++ *start, ++ (int)offset, ++ length); ++ ++ len += ipsec_snprintf(buffer + len,length-len, "Openswan version: %s\n", ++ ipsec_version_code()); ++#if 0 ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_version_get_info: " ++ "ipsec_init version: %s\n", ++ ipsec_init_c_version); ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_version_get_info: " ++ "ipsec_tunnel version: %s\n", ++ ipsec_tunnel_c_version); ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_version_get_info: " ++ "ipsec_netlink version: %s\n", ++ ipsec_netlink_c_version); ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_version_get_info: " ++ "radij_c_version: %s\n", ++ radij_c_version); ++#endif ++ ++ ++ *start = buffer + (offset - begin); /* Start of wanted data */ ++ len -= (offset - begin); /* Start slop */ ++ if (len > length) ++ len = length; ++ return len; ++} ++ ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_birth_info(char *page, ++ char **start, ++ off_t offset, ++ int count, ++ int *eof, ++ void *data) ++{ ++ struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data; ++ int len; ++ ++ if(offset >= ibr->packet_template_len) { ++ if(eof) { ++ *eof=1; ++ } ++ return 0; ++ } ++ ++ len = ibr->packet_template_len; ++ len -= offset; ++ if (len > count) ++ len = count; ++ ++ memcpy(page + offset, ibr->packet_template+offset, len); ++ ++ return len; ++} ++ ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_birth_set(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data; ++ int len; ++ ++ MOD_INC_USE_COUNT; ++ if(count > IPSEC_BIRTH_TEMPLATE_MAXLEN) { ++ len = IPSEC_BIRTH_TEMPLATE_MAXLEN; ++ } else { ++ len = count; ++ } ++ ++ if(copy_from_user(ibr->packet_template, buffer, len)) { ++ MOD_DEC_USE_COUNT; ++ return -EFAULT; ++ } ++ ibr->packet_template_len = len; ++ ++ MOD_DEC_USE_COUNT; ++ ++ return len; ++} ++ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_klipsdebug_get_info(char *buffer, ++ char **start, ++ off_t offset, ++ int length IPSEC_PROC_LAST_ARG) ++{ ++ int len = 0; ++ off_t begin = 0; ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, ++ "klips_debug:ipsec_klipsdebug_get_info: " ++ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", ++ buffer, ++ *start, ++ (int)offset, ++ length); ++ ++ len += ipsec_snprintf(buffer+len, length-len, "debug_tunnel=%08x.\n", debug_tunnel); ++ len += ipsec_snprintf(buffer+len, length-len, "debug_xform=%08x.\n", debug_xform); ++ len += ipsec_snprintf(buffer+len, length-len, "debug_eroute=%08x.\n", debug_eroute); ++ len += ipsec_snprintf(buffer+len, length-len, "debug_spi=%08x.\n", debug_spi); ++ len += ipsec_snprintf(buffer+len, length-len, "debug_radij=%08x.\n", debug_radij); ++ len += ipsec_snprintf(buffer+len, length-len, "debug_esp=%08x.\n", debug_esp); ++ len += ipsec_snprintf(buffer+len, length-len, "debug_ah=%08x.\n", debug_ah); ++ len += ipsec_snprintf(buffer+len, length-len, "debug_rcv=%08x.\n", debug_rcv); ++ len += ipsec_snprintf(buffer+len, length-len, "debug_pfkey=%08x.\n", debug_pfkey); ++ ++ *start = buffer + (offset - begin); /* Start of wanted data */ ++ len -= (offset - begin); /* Start slop */ ++ if (len > length) ++ len = length; ++ return len; ++} ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++IPSEC_PROCFS_DEBUG_NO_STATIC ++int ++ipsec_stats_get_int_info(char *buffer, ++ char **start, ++ off_t offset, ++ int length, ++ int *eof, ++ void *data) ++{ ++ ++ const int max_content = length > 0? length-1 : 0; ++ int len = 0; ++ int *thing; ++ ++ thing = (int *)data; ++ ++ len = ipsec_snprintf(buffer+len, length-len, "%08x\n", *thing); ++ ++ if (len >= max_content) ++ len = max_content; /* truncate crap */ ++ ++ *start = buffer + offset; /* Start of wanted data */ ++ return len > offset? len - offset : 0; ++ ++} ++ ++#ifndef PROC_FS_2325 ++struct proc_dir_entry ipsec_eroute = ++{ ++ 0, ++ 12, "ipsec_eroute", ++ S_IFREG | S_IRUGO, 1, 0, 0, 0, ++ &proc_net_inode_operations, ++ ipsec_eroute_get_info, ++ NULL, NULL, NULL, NULL, NULL ++}; ++ ++struct proc_dir_entry ipsec_spi = ++{ ++ 0, ++ 9, "ipsec_spi", ++ S_IFREG | S_IRUGO, 1, 0, 0, 0, ++ &proc_net_inode_operations, ++ ipsec_spi_get_info, ++ NULL, NULL, NULL, NULL, NULL ++}; ++ ++struct proc_dir_entry ipsec_spigrp = ++{ ++ 0, ++ 12, "ipsec_spigrp", ++ S_IFREG | S_IRUGO, 1, 0, 0, 0, ++ &proc_net_inode_operations, ++ ipsec_spigrp_get_info, ++ NULL, NULL, NULL, NULL, NULL ++}; ++ ++struct proc_dir_entry ipsec_tncfg = ++{ ++ 0, ++ 11, "ipsec_tncfg", ++ S_IFREG | S_IRUGO, 1, 0, 0, 0, ++ &proc_net_inode_operations, ++ ipsec_tncfg_get_info, ++ NULL, NULL, NULL, NULL, NULL ++}; ++ ++struct proc_dir_entry ipsec_version = ++{ ++ 0, ++ 13, "ipsec_version", ++ S_IFREG | S_IRUGO, 1, 0, 0, 0, ++ &proc_net_inode_operations, ++ ipsec_version_get_info, ++ NULL, NULL, NULL, NULL, NULL ++}; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++struct proc_dir_entry ipsec_klipsdebug = ++{ ++ 0, ++ 16, "ipsec_klipsdebug", ++ S_IFREG | S_IRUGO, 1, 0, 0, 0, ++ &proc_net_inode_operations, ++ ipsec_klipsdebug_get_info, ++ NULL, NULL, NULL, NULL, NULL ++}; ++#endif /* CONFIG_IPSEC_DEBUG */ ++#endif /* !PROC_FS_2325 */ ++#endif /* CONFIG_PROC_FS */ ++ ++#if defined(PROC_FS_2325) ++struct ipsec_proc_list { ++ char *name; ++ struct proc_dir_entry **parent; ++ struct proc_dir_entry **dir; ++ read_proc_t *readthing; ++ write_proc_t *writething; ++ void *data; ++}; ++static struct ipsec_proc_list proc_items[]={ ++#ifdef CONFIG_IPSEC_DEBUG ++ {"klipsdebug", &proc_net_ipsec_dir, NULL, ipsec_klipsdebug_get_info, NULL, NULL}, ++#endif ++ {"eroute", &proc_net_ipsec_dir, &proc_eroute_dir, NULL, NULL, NULL}, ++ {"all", &proc_eroute_dir, NULL, ipsec_eroute_get_info, NULL, NULL}, ++ {"spi", &proc_net_ipsec_dir, &proc_spi_dir, NULL, NULL, NULL}, ++ {"all", &proc_spi_dir, NULL, ipsec_spi_get_info, NULL, NULL}, ++ {"spigrp", &proc_net_ipsec_dir, &proc_spigrp_dir, NULL, NULL, NULL}, ++ {"all", &proc_spigrp_dir, NULL, ipsec_spigrp_get_info, NULL, NULL}, ++ {"birth", &proc_net_ipsec_dir, &proc_birth_dir, NULL, NULL, NULL}, ++ {"ipv4", &proc_birth_dir, NULL, ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv4_birth_packet}, ++ {"ipv6", &proc_birth_dir, NULL, ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv6_birth_packet}, ++ {"tncfg", &proc_net_ipsec_dir, NULL, ipsec_tncfg_get_info, NULL, NULL}, ++ {"xforms", &proc_net_ipsec_dir, NULL, ipsec_xform_get_info, NULL, NULL}, ++ {"stats", &proc_net_ipsec_dir, &proc_stats_dir, NULL, NULL, NULL}, ++ {"trap_count", &proc_stats_dir, NULL, ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_count}, ++ {"trap_sendcount", &proc_stats_dir, NULL, ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_sendcount}, ++ {"version", &proc_net_ipsec_dir, NULL, ipsec_version_get_info, NULL, NULL}, ++ {NULL, NULL, NULL, NULL, NULL, NULL} ++}; ++#endif ++ ++int ++ipsec_proc_init() ++{ ++ int error = 0; ++#ifdef IPSEC_PROC_SUBDIRS ++ struct proc_dir_entry *item; ++#endif ++ ++ /* ++ * just complain because pluto won't run without /proc! ++ */ ++#ifndef CONFIG_PROC_FS ++#error You must have PROC_FS built in to use KLIPS ++#endif ++ ++ /* for 2.0 kernels */ ++#if !defined(PROC_FS_2325) && !defined(PROC_FS_21) ++ error |= proc_register_dynamic(&proc_net, &ipsec_eroute); ++ error |= proc_register_dynamic(&proc_net, &ipsec_spi); ++ error |= proc_register_dynamic(&proc_net, &ipsec_spigrp); ++ error |= proc_register_dynamic(&proc_net, &ipsec_tncfg); ++ error |= proc_register_dynamic(&proc_net, &ipsec_version); ++#ifdef CONFIG_IPSEC_DEBUG ++ error |= proc_register_dynamic(&proc_net, &ipsec_klipsdebug); ++#endif /* CONFIG_IPSEC_DEBUG */ ++#endif ++ ++ /* for 2.2 kernels */ ++#if !defined(PROC_FS_2325) && defined(PROC_FS_21) ++ error |= proc_register(proc_net, &ipsec_eroute); ++ error |= proc_register(proc_net, &ipsec_spi); ++ error |= proc_register(proc_net, &ipsec_spigrp); ++ error |= proc_register(proc_net, &ipsec_tncfg); ++ error |= proc_register(proc_net, &ipsec_version); ++#ifdef CONFIG_IPSEC_DEBUG ++ error |= proc_register(proc_net, &ipsec_klipsdebug); ++#endif /* CONFIG_IPSEC_DEBUG */ ++#endif ++ ++ /* for 2.4 kernels */ ++#if defined(PROC_FS_2325) ++ /* create /proc/net/ipsec */ ++ ++ /* zero these out before we initialize /proc/net/ipsec/birth/stuff */ ++ memset(&ipsec_ipv4_birth_packet, 0, sizeof(struct ipsec_birth_reply)); ++ memset(&ipsec_ipv6_birth_packet, 0, sizeof(struct ipsec_birth_reply)); ++ ++ proc_net_ipsec_dir = proc_mkdir("ipsec", proc_net); ++ if(proc_net_ipsec_dir == NULL) { ++ /* no point in continuing */ ++ return 1; ++ } ++ ++ { ++ struct ipsec_proc_list *it; ++ ++ it=proc_items; ++ while(it->name!=NULL) { ++ if(it->dir) { ++ /* make a dir instead */ ++ item = proc_mkdir(it->name, *it->parent); ++ *it->dir = item; ++ } else { ++ item = create_proc_entry(it->name, 0400, *it->parent); ++ } ++ if(item) { ++ item->read_proc = it->readthing; ++ item->write_proc = it->writething; ++ item->data = it->data; ++#ifdef MODULE ++ item->owner = THIS_MODULE; ++#endif ++ } else { ++ error |= 1; ++ } ++ it++; ++ } ++ } ++ ++ /* now create some symlinks to provide compatibility */ ++ proc_symlink("ipsec_eroute", proc_net, "ipsec/eroute/all"); ++ proc_symlink("ipsec_spi", proc_net, "ipsec/spi/all"); ++ proc_symlink("ipsec_spigrp", proc_net, "ipsec/spigrp/all"); ++ proc_symlink("ipsec_tncfg", proc_net, "ipsec/tncfg"); ++ proc_symlink("ipsec_version",proc_net, "ipsec/version"); ++ proc_symlink("ipsec_klipsdebug",proc_net,"ipsec/klipsdebug"); ++ ++#endif /* !PROC_FS_2325 */ ++ ++ return error; ++} ++ ++void ++ipsec_proc_cleanup() ++{ ++ ++ /* for 2.0 and 2.2 kernels */ ++#if !defined(PROC_FS_2325) ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if (proc_net_unregister(ipsec_klipsdebug.low_ino) != 0) ++ printk("klips_debug:ipsec_cleanup: " ++ "cannot unregister /proc/net/ipsec_klipsdebug\n"); ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ if (proc_net_unregister(ipsec_version.low_ino) != 0) ++ printk("klips_debug:ipsec_cleanup: " ++ "cannot unregister /proc/net/ipsec_version\n"); ++ if (proc_net_unregister(ipsec_eroute.low_ino) != 0) ++ printk("klips_debug:ipsec_cleanup: " ++ "cannot unregister /proc/net/ipsec_eroute\n"); ++ if (proc_net_unregister(ipsec_spi.low_ino) != 0) ++ printk("klips_debug:ipsec_cleanup: " ++ "cannot unregister /proc/net/ipsec_spi\n"); ++ if (proc_net_unregister(ipsec_spigrp.low_ino) != 0) ++ printk("klips_debug:ipsec_cleanup: " ++ "cannot unregister /proc/net/ipsec_spigrp\n"); ++ if (proc_net_unregister(ipsec_tncfg.low_ino) != 0) ++ printk("klips_debug:ipsec_cleanup: " ++ "cannot unregister /proc/net/ipsec_tncfg\n"); ++#endif ++ ++ /* for 2.4 kernels */ ++#if defined(PROC_FS_2325) ++ { ++ struct ipsec_proc_list *it; ++ ++ /* find end of list */ ++ it=proc_items; ++ while(it->name!=NULL) { ++ it++; ++ } ++ it--; ++ ++ do { ++ remove_proc_entry(it->name, *it->parent); ++ it--; ++ } while(it > proc_items); ++ } ++ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ remove_proc_entry("ipsec_klipsdebug", proc_net); ++#endif /* CONFIG_IPSEC_DEBUG */ ++ remove_proc_entry("ipsec_eroute", proc_net); ++ remove_proc_entry("ipsec_spi", proc_net); ++ remove_proc_entry("ipsec_spigrp", proc_net); ++ remove_proc_entry("ipsec_tncfg", proc_net); ++ remove_proc_entry("ipsec_version", proc_net); ++ remove_proc_entry("ipsec", proc_net); ++#endif /* 2.4 kernel */ ++} ++ ++/* ++ * $Log: ipsec_proc.c,v $ ++ * Revision 1.30 2004/04/25 21:23:11 ken ++ * Pull in dhr's changes from FreeS/WAN 2.06 ++ * ++ * Revision 1.29 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.28 2004/03/28 20:29:58 paul ++ * <hugh_> ssize_t, not ssized_t ++ * ++ * Revision 1.27 2004/03/28 20:27:20 paul ++ * Included tested and confirmed fixes mcr made and dhr verified for ++ * snprint statements. Changed one other snprintf to use ipsec_snprintf ++ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with ++ * dhr. (thanks dhr!) ++ * ++ * Revision 1.26 2004/02/09 22:07:06 mcr ++ * added information about nat-traversal setting to spi-output. ++ * ++ * Revision 1.25.4.1 2004/04/05 04:30:46 mcr ++ * patches for alg-branch to compile/work with 2.x openswan ++ * ++ * Revision 1.25 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.24.4.1 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.24 2003/06/20 01:42:21 mcr ++ * added counters to measure how many ACQUIREs we send to pluto, ++ * and how many are successfully sent. ++ * ++ * Revision 1.23 2003/04/03 17:38:09 rgb ++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. ++ * ++ * Revision 1.22 2002/09/20 15:40:57 rgb ++ * Renamed saref macros for consistency and brevity. ++ * ++ * Revision 1.21 2002/09/20 05:01:35 rgb ++ * Print ref and reftable, refentry seperately. ++ * ++ * Revision 1.20 2002/09/19 02:35:39 mcr ++ * do not define structures needed by /proc/net/ipsec/ if we ++ * aren't going create that directory. ++ * ++ * Revision 1.19 2002/09/10 01:43:25 mcr ++ * fixed problem in /-* comment. ++ * ++ * Revision 1.18 2002/09/03 16:22:11 mcr ++ * fixed initialization of birth/stuff values - some simple ++ * screw ups in the code. ++ * removed debugging that was left in by mistake. ++ * ++ * Revision 1.17 2002/09/02 17:54:53 mcr ++ * changed how the table driven /proc entries are created so that ++ * making subdirs is now explicit rather than implicit. ++ * ++ * Revision 1.16 2002/08/30 01:23:37 mcr ++ * reorganized /proc creating code to clear up ifdefs, ++ * make the 2.4 code table driven, and put things into ++ * /proc/net/ipsec subdir. Symlinks are left for compatibility. ++ * ++ * Revision 1.15 2002/08/13 19:01:25 mcr ++ * patches from kenb to permit compilation of FreeSWAN on ia64. ++ * des library patched to use proper DES_LONG type for ia64. ++ * ++ * Revision 1.14 2002/07/26 08:48:31 rgb ++ * Added SA ref table code. ++ * ++ * Revision 1.13 2002/07/24 18:44:54 rgb ++ * Type fiddling to tame ia64 compiler. ++ * ++ * Revision 1.12 2002/05/27 18:56:07 rgb ++ * Convert to dynamic ipsec device allocation. ++ * ++ * Revision 1.11 2002/05/23 07:14:50 rgb ++ * Added refcount code. ++ * Cleaned up %p variants to 0p%p for test suite cleanup. ++ * Convert "usecount" to "refcount" to remove ambiguity. ++ * ++ * Revision 1.10 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.9 2002/04/24 07:36:28 mcr ++ * Moved from ./klips/net/ipsec/ipsec_proc.c,v ++ * ++ * Revision 1.8 2002/01/29 17:17:55 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.7 2002/01/29 04:00:52 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.6 2002/01/29 02:13:17 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.5 2002/01/12 02:54:30 mcr ++ * beginnings of /proc/net/ipsec dir. ++ * ++ * Revision 1.4 2001/12/11 02:21:05 rgb ++ * Don't include module version here, fixing 2.2 compile bug. ++ * ++ * Revision 1.3 2001/12/05 07:19:44 rgb ++ * Fixed extraneous #include "version.c" bug causing modular KLIPS failure. ++ * ++ * Revision 1.2 2001/11/26 09:16:14 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.74 2001/11/22 05:44:11 henry ++ * new version stuff ++ * ++ * Revision 1.1.2.1 2001/09/25 02:19:40 mcr ++ * /proc manipulation code moved to new ipsec_proc.c ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_radij.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,869 @@ ++/* ++ * Interface between the IPSEC code and the radix (radij) tree code ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_radij.c,v 1.70 2004/04/25 21:10:52 ken Exp $ ++ */ ++ ++#include <linux/config.h> ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, struct net_device_stats and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* 23_SPINLOCK */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* 23_SPINLOCK */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++#endif ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include "openswan/ipsec_eroute.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_tunnel.h" /* struct ipsecpriv */ ++#include "openswan/ipsec_xform.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_proto.h" ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_radij = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++struct radij_node_head *rnh = NULL; ++#ifdef SPINLOCK ++spinlock_t eroute_lock = SPIN_LOCK_UNLOCKED; ++#else /* SPINLOCK */ ++spinlock_t eroute_lock; ++#endif /* SPINLOCK */ ++ ++int ++ipsec_radijinit(void) ++{ ++ maj_keylen = sizeof (struct sockaddr_encap); ++ ++ rj_init(); ++ ++ if (rj_inithead((void **)&rnh, /*16*/offsetof(struct sockaddr_encap, sen_type) * sizeof(__u8)) == 0) /* 16 is bit offset of sen_type */ ++ return -1; ++ return 0; ++} ++ ++int ++ipsec_radijcleanup(void) ++{ ++ int error; ++ ++ spin_lock_bh(&eroute_lock); ++ ++ error = radijcleanup(); ++ ++ spin_unlock_bh(&eroute_lock); ++ ++ return error; ++} ++ ++int ++ipsec_cleareroutes(void) ++{ ++ int error; ++ ++ spin_lock_bh(&eroute_lock); ++ ++ error = radijcleartree(); ++ ++ spin_unlock_bh(&eroute_lock); ++ ++ return error; ++} ++ ++int ++ipsec_breakroute(struct sockaddr_encap *eaddr, ++ struct sockaddr_encap *emask, ++ struct sk_buff **first, ++ struct sk_buff **last) ++{ ++ struct eroute *ro; ++ struct radij_node *rn; ++ int error; ++#ifdef CONFIG_IPSEC_DEBUG ++ ++ if (debug_eroute) { ++ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; ++ subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); ++ subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_breakroute: " ++ "attempting to delete eroute for %s:%d->%s:%d %d\n", ++ buf1, ntohs(eaddr->sen_sport), ++ buf2, ntohs(eaddr->sen_dport), eaddr->sen_proto); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ spin_lock_bh(&eroute_lock); ++ ++ if ((error = rj_delete(eaddr, emask, rnh, &rn)) != 0) { ++ spin_unlock_bh(&eroute_lock); ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_breakroute: " ++ "node not found, eroute delete failed.\n"); ++ return error; ++ } ++ ++ spin_unlock_bh(&eroute_lock); ++ ++ ro = (struct eroute *)rn; ++ ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_breakroute: " ++ "deleted eroute=0p%p, ident=0p%p->0p%p, first=0p%p, last=0p%p\n", ++ ro, ++ ro->er_ident_s.data, ++ ro->er_ident_d.data, ++ ro->er_first, ++ ro->er_last); ++ ++ if (ro->er_ident_s.data != NULL) { ++ kfree(ro->er_ident_s.data); ++ } ++ if (ro->er_ident_d.data != NULL) { ++ kfree(ro->er_ident_d.data); ++ } ++ if (ro->er_first != NULL) { ++#if 0 ++ struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_first->dev->priv))->mystats); ++ stats->tx_dropped--; ++#endif ++ *first = ro->er_first; ++ } ++ if (ro->er_last != NULL) { ++#if 0 ++ struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_last->dev->priv))->mystats); ++ stats->tx_dropped--; ++#endif ++ *last = ro->er_last; ++ } ++ ++ if (rn->rj_flags & (RJF_ACTIVE | RJF_ROOT)) ++ panic ("ipsec_breakroute RMT_DELEROUTE root or active node\n"); ++ memset((caddr_t)rn, 0, sizeof (struct eroute)); ++ kfree(rn); ++ ++ return 0; ++} ++ ++int ++ipsec_makeroute(struct sockaddr_encap *eaddr, ++ struct sockaddr_encap *emask, ++ ip_said said, ++ uint32_t pid, ++ struct sk_buff *skb, ++ struct ident *ident_s, ++ struct ident *ident_d) ++{ ++ struct eroute *retrt; ++ int error; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ ++ if (debug_eroute) { ++ ++ { ++ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; ++ ++ subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); ++ subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); ++ sa_len = satot(&said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_makeroute: " ++ "attempting to allocate %lu bytes to insert eroute for %s->%s, SA: %s, PID:%d, skb=0p%p, ident:%s->%s\n", ++ (unsigned long) sizeof(struct eroute), ++ buf1, ++ buf2, ++ sa_len ? sa : " (error)", ++ pid, ++ skb, ++ (ident_s ? (ident_s->data ? ident_s->data : "NULL") : "NULL"), ++ (ident_d ? (ident_d->data ? ident_d->data : "NULL") : "NULL")); ++ } ++ { ++ char buf1[sizeof(struct sockaddr_encap)*2 + 1], ++ buf2[sizeof(struct sockaddr_encap)*2 + 1]; ++ int i; ++ unsigned char *b1 = buf1, ++ *b2 = buf2, ++ *ea = (unsigned char *)eaddr, ++ *em = (unsigned char *)emask; ++ ++ ++ for (i=0; i<sizeof(struct sockaddr_encap); i++) { ++ sprintf(b1, "%02x", ea[i]); ++ sprintf(b2, "%02x", em[i]); ++ b1+=2; ++ b2+=2; ++ } ++ KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: %s / %s \n", buf1, buf2); ++ } ++ ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ retrt = (struct eroute *)kmalloc(sizeof (struct eroute), GFP_ATOMIC); ++ if (retrt == NULL) { ++ printk("klips_error:ipsec_makeroute: " ++ "not able to allocate kernel memory"); ++ return -ENOMEM; ++ } ++ memset((caddr_t)retrt, 0, sizeof (struct eroute)); ++ ++ retrt->er_eaddr = *eaddr; ++ retrt->er_emask = *emask; ++ retrt->er_said = said; ++ retrt->er_pid = pid; ++ retrt->er_count = 0; ++ retrt->er_lasttime = jiffies/HZ; ++ rd_key((&(retrt->er_rjt))) = &(retrt->er_eaddr); ++ ++ if (ident_s && ident_s->type != SADB_IDENTTYPE_RESERVED) { ++ int data_len = ident_s->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); ++ ++ retrt->er_ident_s.type = ident_s->type; ++ retrt->er_ident_s.id = ident_s->id; ++ retrt->er_ident_s.len = ident_s->len; ++ if(data_len) { ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_makeroute: " ++ "attempting to allocate %u bytes for ident_s.\n", ++ data_len); ++ if(!(retrt->er_ident_s.data = kmalloc(data_len, GFP_KERNEL))) { ++ kfree(retrt); ++ printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len); ++ return ENOMEM; ++ } ++ memcpy(retrt->er_ident_s.data, ident_s->data, data_len); ++ } else { ++ retrt->er_ident_s.data = NULL; ++ } ++ } ++ ++ if (ident_d && ident_d->type != SADB_IDENTTYPE_RESERVED) { ++ int data_len = ident_d->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); ++ ++ retrt->er_ident_d.type = ident_d->type; ++ retrt->er_ident_d.id = ident_d->id; ++ retrt->er_ident_d.len = ident_d->len; ++ if(data_len) { ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_makeroute: " ++ "attempting to allocate %u bytes for ident_d.\n", ++ data_len); ++ if(!(retrt->er_ident_d.data = kmalloc(data_len, GFP_KERNEL))) { ++ if (retrt->er_ident_s.data) ++ kfree(retrt->er_ident_s.data); ++ kfree(retrt); ++ printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len); ++ return ENOMEM; ++ } ++ memcpy(retrt->er_ident_d.data, ident_d->data, data_len); ++ } else { ++ retrt->er_ident_d.data = NULL; ++ } ++ } ++ retrt->er_first = skb; ++ retrt->er_last = NULL; ++ ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_makeroute: " ++ "calling rj_addroute now\n"); ++ ++ spin_lock_bh(&eroute_lock); ++ ++ error = rj_addroute(&(retrt->er_eaddr), &(retrt->er_emask), ++ rnh, retrt->er_rjt.rd_nodes); ++ ++ spin_unlock_bh(&eroute_lock); ++ ++ if(error) { ++ sa_len = satot(&said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_makeroute: " ++ "rj_addroute not able to insert eroute for SA:%s (error:%d)\n", ++ sa_len ? sa : " (error)", error); ++ if (retrt->er_ident_s.data) ++ kfree(retrt->er_ident_s.data); ++ if (retrt->er_ident_d.data) ++ kfree(retrt->er_ident_d.data); ++ ++ kfree(retrt); ++ ++ return error; ++ } ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if (debug_eroute) { ++ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; ++/* ++ subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); ++ subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); ++*/ ++ subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_src, rd_mask((&(retrt->er_rjt)))->sen_ip_src, 0, buf1, sizeof(buf1)); ++ subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_dst, rd_mask((&(retrt->er_rjt)))->sen_ip_dst, 0, buf2, sizeof(buf2)); ++ sa_len = satot(&retrt->er_said, 0, sa, sizeof(sa)); ++ ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_makeroute: " ++ "pid=%05d " ++ "count=%10d " ++ "lasttime=%6d " ++ "%-18s -> %-18s => %s\n", ++ retrt->er_pid, ++ retrt->er_count, ++ (int)(jiffies/HZ - retrt->er_lasttime), ++ buf1, ++ buf2, ++ sa_len ? sa : " (error)"); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_makeroute: " ++ "succeeded.\n"); ++ return 0; ++} ++ ++struct eroute * ++ipsec_findroute(struct sockaddr_encap *eaddr) ++{ ++ struct radij_node *rn; ++#ifdef CONFIG_IPSEC_DEBUG ++ char buf1[ADDRTOA_BUF], buf2[ADDRTOA_BUF]; ++ ++ if (debug_radij & DB_RJ_FINDROUTE) { ++ addrtoa(eaddr->sen_ip_src, 0, buf1, sizeof(buf1)); ++ addrtoa(eaddr->sen_ip_dst, 0, buf2, sizeof(buf2)); ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:ipsec_findroute: " ++ "%s:%d->%s:%d %d\n", ++ buf1, ntohs(eaddr->sen_sport), ++ buf2, ntohs(eaddr->sen_dport), ++ eaddr->sen_proto); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ rn = rj_match((caddr_t)eaddr, rnh); ++ if(rn) { ++ KLIPS_PRINT(debug_eroute && sysctl_ipsec_debug_verbose, ++ "klips_debug:ipsec_findroute: " ++ "found, points to proto=%d, spi=%x, dst=%x.\n", ++ ((struct eroute*)rn)->er_said.proto, ++ ntohl(((struct eroute*)rn)->er_said.spi), ++ ntohl(((struct eroute*)rn)->er_said.dst.u.v4.sin_addr.s_addr)); ++ } ++ return (struct eroute *)rn; ++} ++ ++#ifdef CONFIG_PROC_FS ++/** ipsec_rj_walker_procprint: print one line of eroute table output. ++ * ++ * Theoretical BUG: if w->length is less than the length ++ * of some line we should produce, that line will never ++ * be finished. In effect, the "file" will stop part way ++ * through that line. ++ */ ++int ++ipsec_rj_walker_procprint(struct radij_node *rn, void *w0) ++{ ++ struct eroute *ro = (struct eroute *)rn; ++ struct rjtentry *rd = (struct rjtentry *)rn; ++ struct wsbuf *w = (struct wsbuf *)w0; ++ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; ++ char buf3[16]; ++ char sa[SATOT_BUF]; ++ size_t sa_len, buf_len; ++ struct sockaddr_encap *key, *mask; ++ ++ KLIPS_PRINT(debug_radij, ++ "klips_debug:ipsec_rj_walker_procprint: " ++ "rn=0p%p, w0=0p%p\n", ++ rn, ++ w0); ++ if (rn->rj_b >= 0) { ++ return 0; ++ } ++ ++ key = rd_key(rd); ++ mask = rd_mask(rd); ++ ++ if (key == NULL || mask == NULL) { ++ return 0; ++ } ++ ++ buf_len = subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1)); ++ if(key->sen_sport != 0) { ++ sprintf(buf1+buf_len-1, ":%d", ntohs(key->sen_sport)); ++ } ++ ++ buf_len = subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2)); ++ if(key->sen_dport != 0) { ++ sprintf(buf2+buf_len-1, ":%d", ntohs(key->sen_dport)); ++ } ++ ++ buf3[0]='\0'; ++ if(key->sen_proto != 0) { ++ sprintf(buf3, ":%d", key->sen_proto); ++ } ++ ++ sa_len = satot(&ro->er_said, 'x', sa, sizeof(sa)); ++ w->len += ipsec_snprintf(w->buffer + w->len, ++ w->length - w->len, ++ "%-10d " ++ "%-18s -> %-18s => %s%s\n", ++ ro->er_count, ++ buf1, ++ buf2, ++ sa_len ? sa : " (error)", ++ buf3); ++ ++ { ++ /* snprintf can only fill the last character with NUL ++ * so the maximum useful character is w->length-1. ++ * However, if w->length == 0, we cannot go back. ++ * (w->length surely cannot be negative.) ++ */ ++ int max_content = w->length > 0? w->length-1 : 0; ++ ++ if (w->len >= max_content) { ++ /* we've done all that can fit -- stop treewalking */ ++ w->len = max_content; /* truncate crap */ ++ return -ENOBUFS; ++ } else { ++ const off_t pos = w->begin + w->len; /* file position of end of what we've generated */ ++ ++ if (pos <= w->offset) { ++ /* all is before first interesting character: ++ * discard, but note where we are. ++ */ ++ w->len = 0; ++ w->begin = pos; ++ } ++ return 0; ++ } ++ } ++} ++#endif /* CONFIG_PROC_FS */ ++ ++int ++ipsec_rj_walker_delete(struct radij_node *rn, void *w0) ++{ ++ struct eroute *ro; ++ struct rjtentry *rd = (struct rjtentry *)rn; ++ struct radij_node *rn2; ++ int error; ++ struct sockaddr_encap *key, *mask; ++ ++ key = rd_key(rd); ++ mask = rd_mask(rd); ++ ++ if(!key || !mask) { ++ return -ENODATA; ++ } ++#ifdef CONFIG_IPSEC_DEBUG ++ if(debug_radij) { ++ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; ++ subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1)); ++ subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2)); ++ KLIPS_PRINT(debug_radij, ++ "klips_debug:ipsec_rj_walker_delete: " ++ "deleting: %s -> %s\n", ++ buf1, ++ buf2); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ if((error = rj_delete(key, mask, rnh, &rn2))) { ++ KLIPS_PRINT(debug_radij, ++ "klips_debug:ipsec_rj_walker_delete: " ++ "rj_delete failed with error=%d.\n", error); ++ return error; ++ } ++ ++ if(rn2 != rn) { ++ printk("klips_debug:ipsec_rj_walker_delete: " ++ "tried to delete a different node?!? This should never happen!\n"); ++ } ++ ++ ro = (struct eroute *)rn; ++ ++ if (ro->er_ident_s.data) ++ kfree(ro->er_ident_s.data); ++ if (ro->er_ident_d.data) ++ kfree(ro->er_ident_d.data); ++ ++ memset((caddr_t)rn, 0, sizeof (struct eroute)); ++ kfree(rn); ++ ++ return 0; ++} ++ ++/* ++ * $Log: ipsec_radij.c,v $ ++ * Revision 1.70 2004/04/25 21:10:52 ken ++ * Pull in dhr's changes from FreeS/WAN 2.06 ++ * ++ * Revision 1.69 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.68 2004/03/28 20:27:20 paul ++ * Included tested and confirmed fixes mcr made and dhr verified for ++ * snprint statements. Changed one other snprintf to use ipsec_snprintf ++ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with ++ * dhr. (thanks dhr!) ++ * ++ * Revision 1.67.4.1 2004/04/05 04:30:46 mcr ++ * patches for alg-branch to compile/work with 2.x openswan ++ * ++ * Revision 1.67 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.66.24.2 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.66.24.1 2003/09/21 13:59:56 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.66 2002/10/12 23:11:53 dhr ++ * ++ * [KenB + DHR] more 64-bit cleanup ++ * ++ * Revision 1.65 2002/09/20 05:01:40 rgb ++ * Added memory allocation debugging. ++ * ++ * Revision 1.64 2002/05/31 01:46:05 mcr ++ * added && sysctl_ipsec_debug_verbose verbose to ipsec_findroute ++ * as requested in PR#14. ++ * ++ * Revision 1.63 2002/05/23 07:14:11 rgb ++ * Cleaned up %p variants to 0p%p for test suite cleanup. ++ * ++ * Revision 1.62 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.61 2002/04/24 07:36:29 mcr ++ * Moved from ./klips/net/ipsec/ipsec_radij.c,v ++ * ++ * Revision 1.60 2002/02/19 23:59:45 rgb ++ * Removed redundant compiler directives. ++ * ++ * Revision 1.59 2002/02/06 04:13:47 mcr ++ * missing #ifdef CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.58 2002/01/29 17:17:56 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.57 2002/01/29 04:00:52 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.56 2002/01/29 02:13:17 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.55 2001/11/26 09:23:48 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.53.2.1 2001/09/25 02:26:32 mcr ++ * headers adjusted for new usage. ++ * ++ * Revision 1.54 2001/10/18 04:45:20 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/freeswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.53 2001/09/19 17:19:40 rgb ++ * Debug output bugfix for NetCelo's PF_KEY ident patch. ++ * ++ * Revision 1.52 2001/09/19 16:33:37 rgb ++ * Temporarily disable ident fields to /proc/net/ipsec_eroute. ++ * ++ * Revision 1.51 2001/09/15 16:24:04 rgb ++ * Re-inject first and last HOLD packet when an eroute REPLACE is done. ++ * ++ * Revision 1.50 2001/09/14 16:58:36 rgb ++ * Added support for storing the first and last packets through a HOLD. ++ * ++ * Revision 1.49 2001/09/08 21:13:32 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.48 2001/06/15 04:12:56 rgb ++ * Fixed kernel memory allocation error return code polarity bug. ++ * ++ * Revision 1.47 2001/06/14 19:35:09 rgb ++ * Update copyright date. ++ * ++ * Revision 1.46 2001/06/08 08:47:18 rgb ++ * Fixed for debug disabled. ++ * ++ * Revision 1.45 2001/05/27 06:12:11 rgb ++ * Added structures for pid, packet count and last access time to eroute. ++ * Added packet count to beginning of /proc/net/ipsec_eroute. ++ * ++ * Revision 1.44 2001/05/03 19:41:01 rgb ++ * Initialise error return variable. ++ * Use more appropriate return value for ipsec_rj_walker_delete(). ++ * ++ * Revision 1.43 2001/02/27 22:24:54 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.42 2001/02/27 06:21:57 rgb ++ * Added findroute success instrumentation. ++ * ++ * Revision 1.41 2000/11/06 04:32:08 rgb ++ * Ditched spin_lock_irqsave in favour of spin_lock_bh. ++ * ++ * Revision 1.40 2000/09/08 19:12:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.39 2000/08/30 05:25:20 rgb ++ * Correct debug text in ipsec_breakroute() from incorrect ++ * "ipsec_callback". ++ * ++ * Revision 1.38 2000/07/28 14:58:31 rgb ++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. ++ * ++ * Revision 1.37 2000/03/16 14:02:50 rgb ++ * Fixed debug scope to enable compilation with debug off. ++ * ++ * Revision 1.36 2000/01/21 06:14:46 rgb ++ * Added debugging text to ipsec_rj_walker_delete(). ++ * Set return code to negative for consistency. ++ * ++ * Revision 1.35 1999/11/23 23:05:24 rgb ++ * Use provided macro ADDRTOA_BUF instead of hardcoded value. ++ * ++ * Revision 1.34 1999/11/18 04:13:56 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * Added CONFIG_PROC_FS compiler directives in case it is shut off. ++ * ++ * Revision 1.33 1999/11/17 15:53:39 rgb ++ * Changed all occurrences of #include "../../../lib/freeswan.h" ++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the ++ * klips/net/ipsec/Makefile. ++ * ++ * Revision 1.32 1999/10/26 13:58:33 rgb ++ * Put spinlock flags variable declaration outside the debug compiler ++ * directive to enable compilation with debug shut off. ++ * ++ * Revision 1.31 1999/10/15 22:13:29 rgb ++ * Clean out cruft. ++ * Align /proc/net/ipsec_eroute output for easier readability. ++ * Fix double linefeed in radij debug output. ++ * Fix double locking bug that locks up 2.0.36 but not 2.0.38. ++ * ++ * Revision 1.30 1999/10/08 18:37:33 rgb ++ * Fix end-of-line spacing to sate whining PHMs. ++ * ++ * Revision 1.29 1999/10/03 18:52:45 rgb ++ * Spinlock support for 2.0.xx. ++ * Dumb return code spin_unlock fix. ++ * ++ * Revision 1.28 1999/10/01 16:22:24 rgb ++ * Switch from assignment init. to functional init. of spinlocks. ++ * ++ * Revision 1.27 1999/10/01 15:44:53 rgb ++ * Move spinlock header include to 2.1> scope. ++ * ++ * Revision 1.26 1999/10/01 00:01:23 rgb ++ * Added eroute structure locking. ++ * ++ * Revision 1.25 1999/06/10 16:07:30 rgb ++ * Silence delete eroute on no debug. ++ * ++ * Revision 1.24 1999/05/09 03:25:36 rgb ++ * Fix bug introduced by 2.2 quick-and-dirty patch. ++ * ++ * Revision 1.23 1999/05/05 22:02:31 rgb ++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>. ++ * ++ * Revision 1.22 1999/04/29 15:17:23 rgb ++ * Add return values to init and cleanup functions. ++ * Add sanity checking for null pointer arguments. ++ * ++ * Revision 1.21 1999/04/11 00:28:58 henry ++ * GPL boilerplate ++ * ++ * Revision 1.20 1999/04/06 04:54:26 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.19 1999/02/17 16:50:35 rgb ++ * Clean out unused cruft. ++ * Consolidate for space and speed efficiency. ++ * Convert DEBUG_IPSEC to KLIPS_PRINT ++ * ++ * Revision 1.18 1999/01/22 06:22:06 rgb ++ * Cruft clean-out. ++ * 64-bit clean-up. ++ * ++ * Revision 1.17 1998/12/02 03:09:39 rgb ++ * Clean up debug printing conditionals to compile with debugging off. ++ * ++ * Revision 1.16 1998/12/01 13:49:39 rgb ++ * Wrap version info printing in debug switches. ++ * ++ * Revision 1.15 1998/11/30 13:22:54 rgb ++ * Rationalised all the klips kernel file headers. They are much shorter ++ * now and won't conflict under RH5.2. ++ * ++ * Revision 1.14 1998/10/31 06:48:17 rgb ++ * Fixed up comments in #endif directives. ++ * ++ * Revision 1.13 1998/10/27 13:48:09 rgb ++ * Cleaned up /proc/net/ipsec_* filesystem for easy parsing by scripts. ++ * Fixed less(1) truncated output bug. ++ * Code clean-up. ++ * ++ * Revision 1.12 1998/10/25 02:41:36 rgb ++ * Change return type on ipsec_breakroute and ipsec_makeroute and add an ++ * argument to be able to transmit more infomation about errors. ++ * Fix cut-and-paste debug statement identifier. ++ * ++ * Revision 1.11 1998/10/22 06:45:39 rgb ++ * Cleaned up cruft. ++ * Convert to use satoa for printk. ++ * ++ * Revision 1.10 1998/10/19 14:44:28 rgb ++ * Added inclusion of freeswan.h. ++ * sa_id structure implemented and used: now includes protocol. ++ * ++ * Revision 1.9 1998/10/09 04:30:52 rgb ++ * Added 'klips_debug' prefix to all klips printk debug statements. ++ * Deleted old commented out cruft. ++ * ++ * Revision 1.8 1998/08/06 17:24:23 rgb ++ * Fix addrtoa return code bug from stale manpage advice preventing packets ++ * from being erouted. ++ * ++ * Revision 1.7 1998/08/06 07:44:59 rgb ++ * Fixed /proc/net/ipsec_eroute subnettoa and addrtoa return value bug that ++ * ended up in nothing being printed. ++ * ++ * Revision 1.6 1998/08/05 22:16:41 rgb ++ * Cleanup to prevent cosmetic errors (ie. debug output) from being fatal. ++ * ++ * Revision 1.5 1998/07/29 20:38:44 rgb ++ * Debug and fix subnettoa and addrtoa output. ++ * ++ * Revision 1.4 1998/07/28 00:02:39 rgb ++ * Converting to exclusive use of addrtoa. ++ * Fix eroute delete. ++ * ++ * Revision 1.3 1998/07/14 18:21:26 rgb ++ * Add function to clear the eroute table. ++ * ++ * Revision 1.2 1998/06/23 02:59:14 rgb ++ * Added debugging output to eroute add/delete routines. ++ * ++ * Revision 1.9 1998/06/18 21:29:06 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid kernel ++ * build scripts happier in presence of symbolic links ++ * ++ * Revision 1.8 1998/06/05 02:32:26 rgb ++ * Fix spi ntoh kernel debug output. ++ * ++ * Revision 1.7 1998/05/25 20:30:37 rgb ++ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. ++ * ++ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and ++ * add ipsec_rj_walker_delete. ++ * ++ * Revision 1.6 1998/05/21 13:08:57 rgb ++ * Rewrote procinfo subroutines to avoid *bad things* when more that 3k of ++ * information is available for printout. ++ * ++ * Revision 1.5 1998/05/18 21:35:55 rgb ++ * Clean up output for numerical consistency and readability. Zero freed ++ * eroute memory. ++ * ++ * Revision 1.4 1998/04/21 21:28:58 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.3 1998/04/14 17:30:39 rgb ++ * Fix up compiling errors for radij tree memory reclamation. ++ * ++ * Revision 1.2 1998/04/12 22:03:23 rgb ++ * Updated ESP-3DES-HMAC-MD5-96, ++ * ESP-DES-HMAC-MD5-96, ++ * AH-HMAC-MD5-96, ++ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository ++ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. ++ * ++ * Fixed eroute references in /proc/net/ipsec*. ++ * ++ * Started to patch module unloading memory leaks in ipsec_netlink and ++ * radij tree unloading. ++ * ++ * Revision 1.1 1998/04/09 03:06:10 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:03 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * No changes. ++ * ++ * Revision 0.3 1996/11/20 14:39:04 ji ++ * Minor cleanups. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_rcv.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1922 @@ ++/* ++ * receive code ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998-2003 Richard Guy Briggs. ++ * Copyright (C) 2004 Michael Richardson <mcr@xelerance.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++char ipsec_rcv_c_version[] = "RCSID $Id: ipsec_rcv.c,v 1.143.4.2 2004/08/22 03:29:06 mcr Exp $"; ++ ++#include <linux/config.h> ++#include <linux/version.h> ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <net/udp.h> ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define proto_priv cb ++#endif /* NET21 */ ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_rcv.h" ++ ++#include "openswan/ipsec_auth.h" ++ ++#include "openswan/ipsec_esp.h" ++ ++#ifdef CONFIG_IPSEC_AH ++#include "openswan/ipsec_ah.h" ++#endif /* CONFIG_IPSEC_AH */ ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++#include "openswan/ipsec_ipcomp.h" ++#endif /* CONFIG_IPSEC_COMP */ ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_proto.h" ++#include "openswan/ipsec_alg.h" ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_rcv = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++int sysctl_ipsec_inbound_policy_check = 1; ++ ++/* This is a private use protocol, and AT&T should be ashamed. They should have ++ * used protocol # 59, which is "no next header" instead of 0xFE. ++ */ ++#ifndef IPPROTO_ATT_HEARTBEAT ++#define IPPROTO_ATT_HEARTBEAT 0xFE ++#endif ++ ++#ifdef CONFIG_IPSEC_DEBUG ++void ++ipsec_dmp(char *s, caddr_t bb, int len) ++{ ++ int i; ++ unsigned char *b = bb; ++ ++ ++ printk(KERN_INFO "klips_debug:ipsec_tunnel_:dmp: " ++ "at %s, len=%d:", ++ s, ++ len); ++ for (i=0; i < len; i++) { ++ if(!(i%16)){ ++ printk("\nklips_debug: "); ++ } ++ printk(" %02x", *b++); ++ } ++ printk("\n"); ++} ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++/* ++ * Check-replay-window routine, adapted from the original ++ * by J. Hughes, from draft-ietf-ipsec-esp-des-md5-03.txt ++ * ++ * This is a routine that implements a 64 packet window. This is intend- ++ * ed on being an implementation sample. ++ */ ++ ++DEBUG_NO_STATIC int ++ipsec_checkreplaywindow(struct ipsec_sa*ipsp, __u32 seq) ++{ ++ __u32 diff; ++ ++ if (ipsp->ips_replaywin == 0) /* replay shut off */ ++ return 1; ++ if (seq == 0) ++ return 0; /* first == 0 or wrapped */ ++ ++ /* new larger sequence number */ ++ if (seq > ipsp->ips_replaywin_lastseq) { ++ return 1; /* larger is good */ ++ } ++ diff = ipsp->ips_replaywin_lastseq - seq; ++ ++ /* too old or wrapped */ /* if wrapped, kill off SA? */ ++ if (diff >= ipsp->ips_replaywin) { ++ return 0; ++ } ++ /* this packet already seen */ ++ if (ipsp->ips_replaywin_bitmap & (1 << diff)) ++ return 0; ++ return 1; /* out of order but good */ ++} ++ ++DEBUG_NO_STATIC int ++ipsec_updatereplaywindow(struct ipsec_sa*ipsp, __u32 seq) ++{ ++ __u32 diff; ++ ++ if (ipsp->ips_replaywin == 0) /* replay shut off */ ++ return 1; ++ if (seq == 0) ++ return 0; /* first == 0 or wrapped */ ++ ++ /* new larger sequence number */ ++ if (seq > ipsp->ips_replaywin_lastseq) { ++ diff = seq - ipsp->ips_replaywin_lastseq; ++ ++ /* In win, set bit for this pkt */ ++ if (diff < ipsp->ips_replaywin) ++ ipsp->ips_replaywin_bitmap = ++ (ipsp->ips_replaywin_bitmap << diff) | 1; ++ else ++ /* This packet has way larger seq num */ ++ ipsp->ips_replaywin_bitmap = 1; ++ ++ if(seq - ipsp->ips_replaywin_lastseq - 1 > ipsp->ips_replaywin_maxdiff) { ++ ipsp->ips_replaywin_maxdiff = seq - ipsp->ips_replaywin_lastseq - 1; ++ } ++ ipsp->ips_replaywin_lastseq = seq; ++ return 1; /* larger is good */ ++ } ++ diff = ipsp->ips_replaywin_lastseq - seq; ++ ++ /* too old or wrapped */ /* if wrapped, kill off SA? */ ++ if (diff >= ipsp->ips_replaywin) { ++/* ++ if(seq < 0.25*max && ipsp->ips_replaywin_lastseq > 0.75*max) { ++ ipsec_sa_delchain(ipsp); ++ } ++*/ ++ return 0; ++ } ++ /* this packet already seen */ ++ if (ipsp->ips_replaywin_bitmap & (1 << diff)) ++ return 0; ++ ipsp->ips_replaywin_bitmap |= (1 << diff); /* mark as seen */ ++ return 1; /* out of order but good */ ++} ++ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++struct auth_alg ipsec_rcv_md5[]={ ++ {MD5Init, MD5Update, MD5Final, AHMD596_ALEN} ++}; ++ ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++struct auth_alg ipsec_rcv_sha1[]={ ++ {SHA1Init, SHA1Update, SHA1Final, AHSHA196_ALEN} ++}; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++ ++enum ipsec_rcv_value ++ipsec_rcv_decap_once(struct ipsec_rcv_state *irs, struct xform_functions *proto_funcs) ++{ ++ int iphlen; ++ unsigned char *dat; ++ __u8 proto; ++ struct in_addr ipsaddr; ++ struct in_addr ipdaddr; ++ int replay = 0; /* replay value in AH or ESP packet */ ++ struct ipsec_sa* ipsnext = NULL; /* next SA towards inside of packet */ ++ struct ipsec_sa *newipsp; ++ struct iphdr *ipp; ++ struct sk_buff *skb; ++#ifdef CONFIG_IPSEC_ALG ++ struct ipsec_alg_auth *ixt_a=NULL; ++#endif /* CONFIG_IPSEC_ALG */ ++ ++ skb = irs->skb; ++ irs->len = skb->len; ++ dat = skb->data; ++ ipp = irs->ipp; ++ proto = ipp->protocol; ++ ipsaddr.s_addr = ipp->saddr; ++ addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt)); ++ ipdaddr.s_addr = ipp->daddr; ++ addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt)); ++ ++ iphlen = ipp->ihl << 2; ++ irs->iphlen=iphlen; ++ ipp->check = 0; /* we know the sum is good */ ++ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv_decap_once: " ++ "decap (%d) from %s -> %s\n", ++ proto, irs->ipsaddr_txt, irs->ipdaddr_txt); ++ ++ /* ++ * Find tunnel control block and (indirectly) call the ++ * appropriate tranform routine. The resulting sk_buf ++ * is a valid IP packet ready to go through input processing. ++ */ ++ ++ irs->said.dst.u.v4.sin_addr.s_addr = ipp->daddr; ++ irs->said.dst.u.v4.sin_family = AF_INET; ++ ++ if(proto_funcs->rcv_checks) { ++ enum ipsec_rcv_value retval = ++ (*proto_funcs->rcv_checks)(irs, skb); ++ ++ if(retval < 0) { ++ return retval; ++ } ++ } ++ ++ irs->said.proto = proto; ++ irs->sa_len = satot(&irs->said, 0, irs->sa, sizeof(irs->sa)); ++ if(irs->sa_len == 0) { ++ strcpy(irs->sa, "(error)"); ++ } ++ ++ newipsp = ipsec_sa_getbyid(&irs->said); ++ if (newipsp == NULL) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "no ipsec_sa for SA:%s: incoming packet with no SA dropped\n", ++ irs->sa_len ? irs->sa : " (error)"); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_SAIDNOTFOUND; ++ } ++ ++ /* MCR - XXX this is bizarre. ipsec_sa_getbyid returned it, having incremented the refcount, ++ * why in the world would we decrement it here? ++ ++ ipsec_sa_put(irs->ipsp);*/ /* incomplete */ ++ ++ /* If it is in larval state, drop the packet, we cannot process yet. */ ++ if(newipsp->ips_state == SADB_SASTATE_LARVAL) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "ipsec_sa in larval state, cannot be used yet, dropping packet.\n"); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ ipsec_sa_put(newipsp); ++ return IPSEC_RCV_SAIDNOTLIVE; ++ } ++ ++ if(newipsp->ips_state == SADB_SASTATE_DEAD) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "ipsec_sa in dead state, cannot be used any more, dropping packet.\n"); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ ipsec_sa_put(newipsp); ++ return IPSEC_RCV_SAIDNOTLIVE; ++ } ++ ++ if(sysctl_ipsec_inbound_policy_check) { ++ if(irs->ipp->saddr != ((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n", ++ irs->sa_len ? irs->sa : " (error)", ++ irs->ipsaddr_txt); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ ipsec_sa_put(newipsp); ++ return IPSEC_RCV_FAILEDINBOUND; ++ } ++ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s, src=%s of pkt agrees with expected SA source address policy.\n", ++ irs->sa_len ? irs->sa : " (error)", ++ irs->ipsaddr_txt); ++ ++ /* ++ * at this point, we have looked up a new SA, and we want to make sure that if this ++ * isn't the first SA in the list, that the previous SA actually points at this one. ++ */ ++ if(irs->ipsp) { ++ if(irs->ipsp->ips_inext != newipsp) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "unexpected SA:%s: does not agree with ips->inext policy, dropped\n", ++ irs->sa_len ? irs->sa : " (error)"); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ ipsec_sa_put(newipsp); ++ return IPSEC_RCV_FAILEDINBOUND; ++ } ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s grouping from previous SA is OK.\n", ++ irs->sa_len ? irs->sa : " (error)"); ++ } else { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s First SA in group.\n", ++ irs->sa_len ? irs->sa : " (error)"); ++ } ++ ++ /* ++ * previously, at this point, we checked if the back pointer from the new SA that ++ * we just found matched the back pointer. But, we won't do this check anymore, ++ * because we want to be able to nest SAs ++ */ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "natt_type=%u tdbp->ips_natt_type=%u : %s\n", ++ irs->natt_type, newipsp->ips_natt_type, ++ (irs->natt_type==newipsp->ips_natt_type)?"ok":"bad"); ++ if (irs->natt_type != newipsp->ips_natt_type) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s does not agree with expected NAT-T policy.\n", ++ irs->sa_len ? irs->sa : " (error)"); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ ipsec_sa_put(newipsp); ++ return IPSEC_RCV_FAILEDINBOUND; ++ } ++#endif ++ } ++ ++ /* okay, SA checks out, so free any previous SA, and record a new one */ ++ ++ if(irs->ipsp) { ++ ipsec_sa_put(irs->ipsp); ++ } ++ irs->ipsp=newipsp; ++ ++ /* note that the outer code will free the irs->ipsp if there is an error */ ++ ++ ++ /* now check the lifetimes */ ++ if(ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_bytes, "bytes", ++ irs->sa, ipsec_life_countbased, ipsec_incoming, ++ irs->ipsp) == ipsec_life_harddied || ++ ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "addtime", ++ irs->sa, ipsec_life_timebased, ipsec_incoming, ++ irs->ipsp) == ipsec_life_harddied || ++ ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "usetime", ++ irs->sa, ipsec_life_timebased, ipsec_incoming, ++ irs->ipsp) == ipsec_life_harddied || ++ ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_packets, "packets", ++ irs->sa, ipsec_life_countbased, ipsec_incoming, ++ irs->ipsp) == ipsec_life_harddied) { ++ ipsec_sa_delchain(irs->ipsp); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv_decap_once: " ++ "decap (%d) failed lifetime check\n", ++ proto); ++ ++ return IPSEC_RCV_LIFETIMEFAILED; ++ } ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if ((irs->natt_type) && ++ ( (irs->ipp->saddr != (((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr)) || ++ (irs->natt_sport != newipsp->ips_natt_sport) ++ )) { ++ struct sockaddr sipaddr; ++ /** Advertise NAT-T addr change to pluto **/ ++ sipaddr.sa_family = AF_INET; ++ ((struct sockaddr_in*)&sipaddr)->sin_addr.s_addr = irs->ipp->saddr; ++ ((struct sockaddr_in*)&sipaddr)->sin_port = htons(irs->natt_sport); ++ pfkey_nat_t_new_mapping(newipsp, &sipaddr, irs->natt_sport); ++ /** ++ * Then allow or block packet depending on ++ * sysctl_ipsec_inbound_policy_check. ++ * ++ * In all cases, pluto will update SA if new mapping is ++ * accepted. ++ */ ++ if (sysctl_ipsec_inbound_policy_check) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s, src=%s:%u of pkt does not agree with expected " ++ "SA source address policy (pluto has been informed).\n", ++ irs->sa_len ? irs->sa : " (error)", ++ irs->ipsaddr_txt, irs->natt_sport); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ ipsec_sa_put(newipsp); ++ return IPSEC_RCV_FAILEDINBOUND; ++ } ++ } ++#endif ++ ++ irs->authfuncs=NULL; ++ /* authenticate, if required */ ++#ifdef CONFIG_IPSEC_ALG ++ if ((ixt_a=irs->ipsp->ips_alg_auth)) { ++ irs->authlen = AHHMAC_HASHLEN; ++ irs->authfuncs = NULL; ++ irs->ictx = NULL; ++ irs->octx = NULL; ++ irs->ictx_len = 0; ++ irs->octx_len = 0; ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "authalg=%d authlen=%d\n", ++ irs->ipsp->ips_authalg, ++ irs->authlen); ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(irs->ipsp->ips_authalg) { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ case AH_MD5: ++ irs->authlen = AHHMAC_HASHLEN; ++ irs->authfuncs = ipsec_rcv_md5; ++ irs->ictx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx; ++ irs->octx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx; ++ irs->ictx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx); ++ irs->octx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ case AH_SHA: ++ irs->authlen = AHHMAC_HASHLEN; ++ irs->authfuncs = ipsec_rcv_sha1; ++ irs->ictx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx; ++ irs->octx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx; ++ irs->ictx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx); ++ irs->octx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ case AH_NONE: ++ irs->authlen = 0; ++ irs->authfuncs = NULL; ++ irs->ictx = NULL; ++ irs->octx = NULL; ++ irs->ictx_len = 0; ++ irs->octx_len = 0; ++ break; ++ default: ++ irs->ipsp->ips_errs.ips_alg_errs += 1; ++ if(irs->stats) { ++ irs->stats->rx_errors++; ++ } ++ return IPSEC_RCV_BADAUTH; ++ } ++ ++ irs->ilen = irs->len - iphlen - irs->authlen; ++ if(irs->ilen <= 0) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "runt %s packet with no data, dropping.\n", ++ (proto == IPPROTO_ESP ? "esp" : "ah")); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_BADLEN; ++ } ++ ++#ifdef CONFIG_IPSEC_ALG ++ if(irs->authfuncs || ixt_a) { ++#else ++ if(irs->authfuncs) { ++#endif ++ unsigned char *authenticator = NULL; ++ ++ if(proto_funcs->rcv_setup_auth) { ++ enum ipsec_rcv_value retval ++ = (*proto_funcs->rcv_setup_auth)(irs, skb, ++ &replay, ++ &authenticator); ++ if(retval < 0) { ++ return retval; ++ } ++ } ++ ++ if(!authenticator) { ++ irs->ipsp->ips_errs.ips_auth_errs += 1; ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_BADAUTH; ++ } ++ ++ if(!ipsec_checkreplaywindow(irs->ipsp, replay)) { ++ irs->ipsp->ips_errs.ips_replaywin_errs += 1; ++ KLIPS_PRINT(debug_rcv & DB_RX_REPLAY, ++ "klips_debug:ipsec_rcv: " ++ "duplicate frame from %s, packet dropped\n", ++ irs->ipsaddr_txt); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_REPLAYFAILED; ++ } ++ ++ /* ++ * verify authenticator ++ */ ++ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "encalg = %d, authalg = %d.\n", ++ irs->ipsp->ips_encalg, ++ irs->ipsp->ips_authalg); ++ ++ /* calculate authenticator */ ++ if(proto_funcs->rcv_calc_auth == NULL) { ++ return IPSEC_RCV_BADAUTH; ++ } ++ (*proto_funcs->rcv_calc_auth)(irs, skb); ++ ++ if (memcmp(irs->hash, authenticator, irs->authlen)) { ++ irs->ipsp->ips_errs.ips_auth_errs += 1; ++ KLIPS_PRINT(debug_rcv & DB_RX_INAU, ++ "klips_debug:ipsec_rcv: " ++ "auth failed on incoming packet from %s: hash=%08x%08x%08x auth=%08x%08x%08x, dropped\n", ++ irs->ipsaddr_txt, ++ ntohl(*(__u32*)&irs->hash[0]), ++ ntohl(*(__u32*)&irs->hash[4]), ++ ntohl(*(__u32*)&irs->hash[8]), ++ ntohl(*(__u32*)authenticator), ++ ntohl(*((__u32*)authenticator + 1)), ++ ntohl(*((__u32*)authenticator + 2))); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_AUTHFAILED; ++ } else { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "authentication successful.\n"); ++ } ++ ++ /* Crypto hygiene: clear memory used to calculate autheticator. ++ * The length varies with the algorithm. ++ */ ++ memset(irs->hash, 0, irs->authlen); ++ ++ /* If the sequence number == 0, expire SA, it had rolled */ ++ if(irs->ipsp->ips_replaywin && !replay /* !irs->ipsp->ips_replaywin_lastseq */) { ++ ipsec_sa_delchain(irs->ipsp); ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "replay window counter rolled, expiring SA.\n"); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_REPLAYROLLED; ++ } ++ ++ /* now update the replay counter */ ++ if (!ipsec_updatereplaywindow(irs->ipsp, replay)) { ++ irs->ipsp->ips_errs.ips_replaywin_errs += 1; ++ KLIPS_PRINT(debug_rcv & DB_RX_REPLAY, ++ "klips_debug:ipsec_rcv: " ++ "duplicate frame from %s, packet dropped\n", ++ irs->ipsaddr_txt); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_REPLAYROLLED; ++ } ++ } ++ ++ if(proto_funcs->rcv_decrypt) { ++ enum ipsec_rcv_value retval = ++ (*proto_funcs->rcv_decrypt)(irs); ++ ++ if(retval != IPSEC_RCV_OK) { ++ return retval; ++ } ++ } ++ ++ /* ++ * Adjust pointers ++ */ ++ skb = irs->skb; ++ irs->len = skb->len; ++ dat = skb->data; ++ ++#ifdef NET_21 ++/* skb->h.ipiph=(struct iphdr *)skb->data; */ ++ skb->nh.raw = skb->data; ++ skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2); ++ ++ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); ++#else /* NET_21 */ ++ skb->h.iph=(struct iphdr *)skb->data; ++ skb->ip_hdr=(struct iphdr *)skb->data; ++ memset(skb->proto_priv, 0, sizeof(struct options)); ++#endif /* NET_21 */ ++ ++ ipp = (struct iphdr *)dat; ++ ipsaddr.s_addr = ipp->saddr; ++ addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt)); ++ ipdaddr.s_addr = ipp->daddr; ++ addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt)); ++ /* ++ * Discard the original ESP/AH header ++ */ ++ ipp->protocol = irs->next_header; ++ ++ ipp->check = 0; /* NOTE: this will be included in checksum */ ++ ipp->check = ip_fast_csum((unsigned char *)dat, iphlen >> 2); ++ ++ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, ++ "klips_debug:ipsec_rcv: " ++ "after <%s%s%s>, SA:%s:\n", ++ IPS_XFORM_NAME(irs->ipsp), ++ irs->sa_len ? irs->sa : " (error)"); ++ KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp); ++ ++ skb->protocol = htons(ETH_P_IP); ++ skb->ip_summed = 0; ++ ++ ipsnext = irs->ipsp->ips_inext; ++ if(sysctl_ipsec_inbound_policy_check) { ++ if(ipsnext) { ++ if( ++ ipp->protocol != IPPROTO_AH ++ && ipp->protocol != IPPROTO_ESP ++#ifdef CONFIG_IPSEC_IPCOMP ++ && ipp->protocol != IPPROTO_COMP ++ && (ipsnext->ips_said.proto != IPPROTO_COMP ++ || ipsnext->ips_inext) ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ && ipp->protocol != IPPROTO_IPIP ++ && ipp->protocol != 0xFE /* added to support heartbeats to AT&T SIG/GIG */ ++ ) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "packet with incomplete policy dropped, last successful SA:%s.\n", ++ irs->sa_len ? irs->sa : " (error)"); ++ if(irs->stats) { ++ irs->stats->rx_dropped++; ++ } ++ return IPSEC_RCV_FAILEDINBOUND; ++ } ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s, Another IPSEC header to process.\n", ++ irs->sa_len ? irs->sa : " (error)"); ++ } else { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "No ips_inext from this SA:%s.\n", ++ irs->sa_len ? irs->sa : " (error)"); ++ } ++ } ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++ /* update ipcomp ratio counters, even if no ipcomp packet is present */ ++ if (ipsnext ++ && ipsnext->ips_said.proto == IPPROTO_COMP ++ && ipp->protocol != IPPROTO_COMP) { ++ ipsnext->ips_comp_ratio_cbytes += ntohs(ipp->tot_len); ++ ipsnext->ips_comp_ratio_dbytes += ntohs(ipp->tot_len); ++ } ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++ irs->ipsp->ips_life.ipl_bytes.ipl_count += irs->len; ++ irs->ipsp->ips_life.ipl_bytes.ipl_last = irs->len; ++ ++ if(!irs->ipsp->ips_life.ipl_usetime.ipl_count) { ++ irs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; ++ } ++ irs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; ++ irs->ipsp->ips_life.ipl_packets.ipl_count += 1; ++ ++#ifdef CONFIG_NETFILTER ++ if(proto == IPPROTO_ESP || proto == IPPROTO_AH) { ++ skb->nfmark = (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_MASK)))) ++ | IPsecSAref2NFmark(IPsecSA2SAref(irs->ipsp)); ++ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, ++ "klips_debug:ipsec_rcv: " ++ "%s SA sets skb->nfmark=0x%x.\n", ++ proto == IPPROTO_ESP ? "ESP" : "AH", ++ (unsigned)skb->nfmark); ++ } ++#endif /* CONFIG_NETFILTER */ ++ ++ return IPSEC_RCV_OK; ++} ++ ++ ++int ++#ifdef PROTO_HANDLER_SINGLE_PARM ++ipsec_rcv(struct sk_buff *skb) ++#else /* PROTO_HANDLER_SINGLE_PARM */ ++#ifdef NET_21 ++ipsec_rcv(struct sk_buff *skb, unsigned short xlen) ++#else /* NET_21 */ ++ipsec_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, ++ __u32 daddr_unused, unsigned short xlen, __u32 saddr, ++ int redo, struct inet_protocol *protocol) ++#endif /* NET_21 */ ++#endif /* PROTO_HANDLER_SINGLE_PARM */ ++{ ++#ifdef NET_21 ++#ifdef CONFIG_IPSEC_DEBUG ++ struct device *dev = skb->dev; ++#endif /* CONFIG_IPSEC_DEBUG */ ++#endif /* NET_21 */ ++ unsigned char protoc; ++ struct iphdr *ipp; ++ struct ipsec_sa *ipsp = NULL; ++ struct net_device_stats *stats = NULL; /* This device's statistics */ ++ struct device *ipsecdev = NULL, *prvdev; ++ struct ipsecpriv *prv; ++ char name[9]; ++ int i; ++ struct in_addr ipsaddr; ++ struct in_addr ipdaddr; ++ ++ struct ipsec_sa* ipsnext = NULL; /* next SA towards inside of packet */ ++ struct ipsec_rcv_state irs; ++ ++ /* Don't unlink in the middle of a turnaround */ ++ MOD_INC_USE_COUNT; ++ ++ memset(&irs, 0, sizeof(struct ipsec_rcv_state)); ++ ++ if (skb == NULL) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NULL skb passed in.\n"); ++ goto rcvleave; ++ } ++ ++ if (skb->data == NULL) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NULL skb->data passed in, packet is bogus, dropping.\n"); ++ goto rcvleave; ++ } ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if (skb->sk && skb->nh.iph && skb->nh.iph->protocol==IPPROTO_UDP) { ++ /** ++ * Packet comes from udp_queue_rcv_skb so it is already defrag, ++ * checksum verified, ... (ie safe to use) ++ * ++ * If the packet is not for us, return -1 and udp_queue_rcv_skb ++ * will continue to handle it (do not kfree skb !!). ++ */ ++#ifndef UDP_OPT_IN_SOCK ++ struct udp_opt { ++ __u32 esp_in_udp; ++ }; ++ struct udp_opt *tp = (struct udp_opt *)&(skb->sk->tp_pinfo.af_tcp); ++#else ++ struct udp_opt *tp = &(skb->sk->tp_pinfo.af_udp); ++#endif ++ struct iphdr *ip = (struct iphdr *)skb->nh.iph; ++ struct udphdr *udp = (struct udphdr *)((__u32 *)ip+ip->ihl); ++ __u8 *udpdata = (__u8 *)udp + sizeof(struct udphdr); ++ __u32 *udpdata32 = (__u32 *)udpdata; ++ ++ irs.natt_sport = ntohs(udp->source); ++ irs.natt_dport = ntohs(udp->dest); ++ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "suspected ESPinUDP packet (NAT-Traversal) [%d].\n", ++ tp->esp_in_udp); ++ KLIPS_IP_PRINT(debug_rcv, ip); ++ ++ if (udpdata < skb->tail) { ++ unsigned int len = skb->tail - udpdata; ++ if ((len==1) && (udpdata[0]==0xff)) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ /* not IPv6 compliant message */ ++ "NAT-keepalive from %d.%d.%d.%d.\n", NIPQUAD(ip->saddr)); ++ goto rcvleave; ++ } ++ else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_IKE) && ++ (len > (2*sizeof(__u32) + sizeof(struct esphdr))) && ++ (udpdata32[0]==0) && (udpdata32[1]==0) ) { ++ /* ESP Packet with Non-IKE header */ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "ESPinUDP pkt with Non-IKE - spi=0x%x\n", ++ ntohl(udpdata32[2])); ++ irs.natt_type = ESPINUDP_WITH_NON_IKE; ++ irs.natt_len = sizeof(struct udphdr)+(2*sizeof(__u32)); ++ } ++ else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_ESP) && ++ (len > sizeof(struct esphdr)) && ++ (udpdata32[0]!=0) ) { ++ /* ESP Packet without Non-ESP header */ ++ irs.natt_type = ESPINUDP_WITH_NON_ESP; ++ irs.natt_len = sizeof(struct udphdr); ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "ESPinUDP pkt without Non-ESP - spi=0x%x\n", ++ ntohl(udpdata32[0])); ++ } ++ else { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "IKE packet - not handled here\n"); ++ MOD_DEC_USE_COUNT; ++ return -1; ++ } ++ } ++ else { ++ MOD_DEC_USE_COUNT; ++ return -1; ++ } ++ } ++#endif ++ ++#ifdef IPH_is_SKB_PULLED ++ /* In Linux 2.4.4, the IP header has been skb_pull()ed before the ++ packet is passed to us. So we'll skb_push() to get back to it. */ ++ if (skb->data == skb->h.raw) { ++ skb_push(skb, skb->h.raw - skb->nh.raw); ++ } ++#endif /* IPH_is_SKB_PULLED */ ++ ++ /* dev->hard_header_len is unreliable and should not be used */ ++ irs.hard_header_len = skb->mac.raw ? (skb->data - skb->mac.raw) : 0; ++ if((irs.hard_header_len < 0) || (irs.hard_header_len > skb_headroom(skb))) ++ irs.hard_header_len = 0; ++ ++#ifdef NET_21 ++ /* if skb was cloned (most likely due to a packet sniffer such as ++ tcpdump being momentarily attached to the interface), make ++ a copy of our own to modify */ ++ if(skb_cloned(skb)) { ++ /* include any mac header while copying.. */ ++ if(skb_headroom(skb) < irs.hard_header_len) { ++ printk(KERN_WARNING "klips_error:ipsec_rcv: " ++ "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", ++ irs.hard_header_len, ++ skb_headroom(skb)); ++ goto rcvleave; ++ } ++ skb_push(skb, irs.hard_header_len); ++ if ++#ifdef SKB_COW_NEW ++ (skb_cow(skb, skb_headroom(skb)) != 0) ++#else /* SKB_COW_NEW */ ++ ((skb = skb_cow(skb, skb_headroom(skb))) == NULL) ++#endif /* SKB_COW_NEW */ ++ { ++ goto rcvleave; ++ } ++ if(skb->len < irs.hard_header_len) { ++ printk(KERN_WARNING "klips_error:ipsec_rcv: " ++ "tried to skb_pull hhlen=%d, %d available. This should never happen, please report.\n", ++ irs.hard_header_len, ++ skb->len); ++ goto rcvleave; ++ } ++ skb_pull(skb, irs.hard_header_len); ++ } ++ ++#endif /* NET_21 */ ++ ++#if IP_FRAGMENT_LINEARIZE ++ /* In Linux 2.4.4, we may have to reassemble fragments. They are ++ not assembled automatically to save TCP from having to copy ++ twice. ++ */ ++ if (skb_is_nonlinear(skb)) { ++ if (skb_linearize(skb, GFP_ATOMIC) != 0) { ++ goto rcvleave; ++ } ++ } ++#endif /* IP_FRAGMENT_LINEARIZE */ ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if (irs.natt_len) { ++ /** ++ * Now, we are sure packet is ESPinUDP. Remove natt_len bytes from ++ * packet and modify protocol to ESP. ++ */ ++ if (((unsigned char *)skb->data > (unsigned char *)skb->nh.iph) && ++ ((unsigned char *)skb->nh.iph > (unsigned char *)skb->head)) { ++ unsigned int _len = (unsigned char *)skb->data - ++ (unsigned char *)skb->nh.iph; ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: adjusting skb: skb_push(%u)\n", ++ _len); ++ skb_push(skb, _len); ++ } ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "removing %d bytes from ESPinUDP packet\n", irs.natt_len); ++ ipp = (struct iphdr *)skb->data; ++ irs.iphlen = ipp->ihl << 2; ++ ipp->tot_len = htons(ntohs(ipp->tot_len) - irs.natt_len); ++ if (skb->len < irs.iphlen + irs.natt_len) { ++ printk(KERN_WARNING ++ "klips_error:ipsec_rcv: " ++ "ESPinUDP packet is too small (%d < %d+%d). " ++ "This should never happen, please report.\n", ++ (int)(skb->len), irs.iphlen, irs.natt_len); ++ goto rcvleave; ++ } ++ memmove(skb->data + irs.natt_len, skb->data, irs.iphlen); ++ skb_pull(skb, irs.natt_len); ++ ++ /* update nh.iph */ ++ ipp = skb->nh.iph = (struct iphdr *)skb->data; ++ ++ /* modify protocol */ ++ ipp->protocol = IPPROTO_ESP; ++ ++ skb->sk = NULL; ++ ++ KLIPS_IP_PRINT(debug_rcv, skb->nh.iph); ++ } ++#endif ++ ++ ipp = skb->nh.iph; ++ ipsaddr.s_addr = ipp->saddr; ++ addrtoa(ipsaddr, 0, irs.ipsaddr_txt, sizeof(irs.ipsaddr_txt)); ++ ipdaddr.s_addr = ipp->daddr; ++ addrtoa(ipdaddr, 0, irs.ipdaddr_txt, sizeof(irs.ipdaddr_txt)); ++ irs.iphlen = ipp->ihl << 2; ++ ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "<<< Info -- "); ++ KLIPS_PRINTMORE(debug_rcv && skb->dev, "skb->dev=%s ", ++ skb->dev->name ? skb->dev->name : "NULL"); ++ KLIPS_PRINTMORE(debug_rcv && dev, "dev=%s ", ++ dev->name ? dev->name : "NULL"); ++ KLIPS_PRINTMORE(debug_rcv, "\n"); ++ ++ KLIPS_PRINT(debug_rcv && !(skb->dev && dev && (skb->dev == dev)), ++ "klips_debug:ipsec_rcv: " ++ "Informational -- **if this happens, find out why** skb->dev:%s is not equal to dev:%s\n", ++ skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL", ++ dev ? (dev->name ? dev->name : "NULL") : "NULL"); ++ ++ protoc = ipp->protocol; ++#ifndef NET_21 ++ if((!protocol) || (protocol->protocol != protoc)) { ++ KLIPS_PRINT(debug_rcv & DB_RX_IPSA, ++ "klips_debug:ipsec_rcv: " ++ "protocol arg is NULL or unequal to the packet contents, this is odd, using value in packet.\n"); ++ } ++#endif /* !NET_21 */ ++ ++ if( (protoc != IPPROTO_AH) && ++#ifdef CONFIG_IPSEC_IPCOMP_disabled_until_we_register_IPCOMP_HANDLER ++ (protoc != IPPROTO_COMP) && ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ (protoc != IPPROTO_ESP) ) { ++ KLIPS_PRINT(debug_rcv & DB_RX_IPSA, ++ "klips_debug:ipsec_rcv: Why the hell is someone " ++ "passing me a non-ipsec protocol = %d packet? -- dropped.\n", ++ protoc); ++ goto rcvleave; ++ } ++ ++ if(skb->dev) { ++ for(i = 0; i < IPSEC_NUM_IF; i++) { ++ sprintf(name, IPSEC_DEV_FORMAT, i); ++ if(!strcmp(name, skb->dev->name)) { ++ prv = (struct ipsecpriv *)(skb->dev->priv); ++ if(prv) { ++ stats = (struct net_device_stats *) &(prv->mystats); ++ } ++ ipsecdev = skb->dev; ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "Info -- pkt already proc'ed a group of ipsec headers, processing next group of ipsec headers.\n"); ++ break; ++ } ++ if((ipsecdev = __ipsec_dev_get(name)) == NULL) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_error:ipsec_rcv: " ++ "device %s does not exist\n", ++ name); ++ } ++ prv = ipsecdev ? (struct ipsecpriv *)(ipsecdev->priv) : NULL; ++ prvdev = prv ? (struct device *)(prv->dev) : NULL; ++ ++#if 0 ++ KLIPS_PRINT(debug_rcv && prvdev, ++ "klips_debug:ipsec_rcv: " ++ "physical device for device %s is %s\n", ++ name, ++ prvdev->name); ++#endif ++ if(prvdev && skb->dev && ++ !strcmp(prvdev->name, skb->dev->name)) { ++ stats = prv ? ((struct net_device_stats *) &(prv->mystats)) : NULL; ++ skb->dev = ipsecdev; ++ KLIPS_PRINT(debug_rcv && prvdev, ++ "klips_debug:ipsec_rcv: " ++ "assigning packet ownership to virtual device %s from physical device %s.\n", ++ name, prvdev->name); ++ if(stats) { ++ stats->rx_packets++; ++ } ++ break; ++ } ++ } ++ } else { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "device supplied with skb is NULL\n"); ++ } ++ ++ if(stats == NULL) { ++ KLIPS_PRINT((debug_rcv), ++ "klips_error:ipsec_rcv: " ++ "packet received from physical I/F (%s) not connected to ipsec I/F. Cannot record stats. May not have SA for decoding. Is IPSEC traffic expected on this I/F? Check routing.\n", ++ skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL"); ++ } ++ ++ KLIPS_IP_PRINT(debug_rcv, ipp); ++ ++ /* begin decapsulating loop here */ ++ ++ /* ++ The spinlock is to prevent any other process from ++ accessing or deleting the ipsec_sa hash table or any of the ++ ipsec_sa s while we are using and updating them. ++ ++ This is not optimal, but was relatively straightforward ++ at the time. A better way to do it has been planned for ++ more than a year, to lock the hash table and put reference ++ counts on each ipsec_sa instead. This is not likely to happen ++ in KLIPS1 unless a volunteer contributes it, but will be ++ designed into KLIPS2. ++ */ ++ spin_lock(&tdb_lock); ++ ++ /* set up for decap loop */ ++ irs.stats= stats; ++ irs.ipp = ipp; ++ irs.ipsp = NULL; ++ irs.ilen = 0; ++ irs.authlen=0; ++ irs.authfuncs=NULL; ++ irs.skb = skb; ++ ++ do { ++ int decap_stat; ++ struct xform_functions *proto_funcs; ++ ++ switch(irs.ipp->protocol) { ++ case IPPROTO_ESP: ++ proto_funcs = esp_xform_funcs; ++ break; ++ ++#ifdef CONFIG_IPSEC_AH ++ case IPPROTO_AH: ++ proto_funcs = ah_xform_funcs; ++ break; ++#endif /* !CONFIG_IPSEC_AH */ ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++ case IPPROTO_COMP: ++ proto_funcs = ipcomp_xform_funcs; ++ break; ++#endif /* !CONFIG_IPSEC_IPCOMP */ ++ default: ++ if(irs.stats) { ++ irs.stats->rx_errors++; ++ } ++ decap_stat = IPSEC_RCV_BADPROTO; ++ goto rcvleave; ++ } ++ ++ decap_stat = ipsec_rcv_decap_once(&irs, proto_funcs); ++ ++ if(decap_stat != IPSEC_RCV_OK) { ++ spin_unlock(&tdb_lock); ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: decap_once failed: %d\n", ++ decap_stat); ++ ++ goto rcvleave; ++ } ++ /* end decapsulation loop here */ ++ } while( (irs.ipp->protocol == IPPROTO_ESP ) ++ || (irs.ipp->protocol == IPPROTO_AH ) ++#ifdef CONFIG_IPSEC_IPCOMP ++ || (irs.ipp->protocol == IPPROTO_COMP) ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ); ++ ++ /* set up for decap loop */ ++ ipp =irs.ipp; ++ ipsp =irs.ipsp; ++ ipsnext = ipsp->ips_inext; ++ skb = irs.skb; ++ ++ /* if there is an IPCOMP, but we don't have an IPPROTO_COMP, ++ * then we can just skip it ++ */ ++#ifdef CONFIG_IPSEC_IPCOMP ++ if(ipsnext && ipsnext->ips_said.proto == IPPROTO_COMP) { ++ ipsp = ipsnext; ++ ipsnext = ipsp->ips_inext; ++ } ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if ((irs.natt_type) && (ipp->protocol != IPPROTO_IPIP)) { ++ /** ++ * NAT-Traversal and Transport Mode: ++ * we need to correct TCP/UDP checksum ++ * ++ * If we've got NAT-OA, we can fix checksum without recalculation. ++ */ ++ __u32 natt_oa = ipsp->ips_natt_oa ? ++ ((struct sockaddr_in*)(ipsp->ips_natt_oa))->sin_addr.s_addr : 0; ++ __u16 pkt_len = skb->tail - (unsigned char *)ipp; ++ __u16 data_len = pkt_len - (ipp->ihl << 2); ++ ++ switch (ipp->protocol) { ++ case IPPROTO_TCP: ++ if (data_len >= sizeof(struct tcphdr)) { ++ struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ipp+ipp->ihl); ++ if (natt_oa) { ++ __u32 buff[2] = { ~natt_oa, ipp->saddr }; ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NAT-T & TRANSPORT: " ++ "fix TCP checksum using NAT-OA\n"); ++ tcp->check = csum_fold( ++ csum_partial((unsigned char *)buff, sizeof(buff), ++ tcp->check^0xffff)); ++ } ++ else { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NAT-T & TRANSPORT: recalc TCP checksum\n"); ++ if (pkt_len > (ntohs(ipp->tot_len))) ++ data_len -= (pkt_len - ntohs(ipp->tot_len)); ++ tcp->check = 0; ++ tcp->check = csum_tcpudp_magic(ipp->saddr, ipp->daddr, ++ data_len, IPPROTO_TCP, ++ csum_partial((unsigned char *)tcp, data_len, 0)); ++ } ++ } ++ else { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NAT-T & TRANSPORT: can't fix TCP checksum\n"); ++ } ++ break; ++ case IPPROTO_UDP: ++ if (data_len >= sizeof(struct udphdr)) { ++ struct udphdr *udp = (struct udphdr *)((__u32 *)ipp+ipp->ihl); ++ if (udp->check == 0) { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NAT-T & TRANSPORT: UDP checksum already 0\n"); ++ } ++ else if (natt_oa) { ++ __u32 buff[2] = { ~natt_oa, ipp->saddr }; ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NAT-T & TRANSPORT: " ++ "fix UDP checksum using NAT-OA\n"); ++ udp->check = csum_fold( ++ csum_partial((unsigned char *)buff, sizeof(buff), ++ udp->check^0xffff)); ++ } ++ else { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NAT-T & TRANSPORT: zero UDP checksum\n"); ++ udp->check = 0; ++ } ++ } ++ else { ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NAT-T & TRANSPORT: can't fix UDP checksum\n"); ++ } ++ break; ++ default: ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n"); ++ break; ++ } ++ } ++#endif ++ ++ /* ++ * XXX this needs to be locked from when it was first looked ++ * up in the decapsulation loop. Perhaps it is better to put ++ * the IPIP decap inside the loop. ++ */ ++ if(ipsnext) { ++ ipsp = ipsnext; ++ irs.sa_len = satot(&irs.said, 0, irs.sa, sizeof(irs.sa)); ++ if((ipp->protocol != IPPROTO_IPIP) && ++ ( 0xFE != ipp->protocol)) { /* added to support AT&T heartbeats to SIG/GIG */ ++ spin_unlock(&tdb_lock); ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s, Hey! How did this get through? Dropped.\n", ++ irs.sa_len ? irs.sa : " (error)"); ++ if(stats) { ++ stats->rx_dropped++; ++ } ++ goto rcvleave; ++ } ++ if(sysctl_ipsec_inbound_policy_check) { ++ if((ipsnext = ipsp->ips_inext)) { ++ char sa2[SATOT_BUF]; ++ size_t sa_len2; ++ sa_len2 = satot(&ipsnext->ips_said, 0, sa2, sizeof(sa2)); ++ spin_unlock(&tdb_lock); ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "unexpected SA:%s after IPIP SA:%s\n", ++ sa_len2 ? sa2 : " (error)", ++ irs.sa_len ? irs.sa : " (error)"); ++ if(stats) { ++ stats->rx_dropped++; ++ } ++ goto rcvleave; ++ } ++ if(ipp->saddr != ((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr.s_addr) { ++ spin_unlock(&tdb_lock); ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n", ++ irs.sa_len ? irs.sa : " (error)", ++ irs.ipsaddr_txt); ++ if(stats) { ++ stats->rx_dropped++; ++ } ++ goto rcvleave; ++ } ++ } ++ ++ if(ipp->protocol == IPPROTO_IPIP) /* added to support AT&T heartbeats to SIG/GIG */ ++ { ++ /* ++ * XXX this needs to be locked from when it was first looked ++ * up in the decapsulation loop. Perhaps it is better to put ++ * the IPIP decap inside the loop. ++ */ ++ ipsp->ips_life.ipl_bytes.ipl_count += skb->len; ++ ipsp->ips_life.ipl_bytes.ipl_last = skb->len; ++ ++ if(!ipsp->ips_life.ipl_usetime.ipl_count) { ++ ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; ++ } ++ ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; ++ ipsp->ips_life.ipl_packets.ipl_count += 1; ++ ++ if(skb->len < irs.iphlen) { ++ spin_unlock(&tdb_lock); ++ printk(KERN_WARNING "klips_debug:ipsec_rcv: " ++ "tried to skb_pull iphlen=%d, %d available. This should never happen, please report.\n", ++ irs.iphlen, ++ (int)(skb->len)); ++ ++ goto rcvleave; ++ } ++ skb_pull(skb, irs.iphlen); ++ ++#ifdef NET_21 ++ ipp = (struct iphdr *)skb->nh.raw = skb->data; ++ skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2); ++ ++ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); ++#else /* NET_21 */ ++ ipp = skb->ip_hdr = skb->h.iph = (struct iphdr *)skb->data; ++ ++ memset(skb->proto_priv, 0, sizeof(struct options)); ++#endif /* NET_21 */ ++ ipsaddr.s_addr = ipp->saddr; ++ addrtoa(ipsaddr, 0, irs.ipsaddr_txt, sizeof(irs.ipsaddr_txt)); ++ ipdaddr.s_addr = ipp->daddr; ++ addrtoa(ipdaddr, 0, irs.ipdaddr_txt, sizeof(irs.ipdaddr_txt)); ++ ++ skb->protocol = htons(ETH_P_IP); ++ skb->ip_summed = 0; ++ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, ++ "klips_debug:ipsec_rcv: " ++ "IPIP tunnel stripped.\n"); ++ KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp); ++ } ++ ++ if(sysctl_ipsec_inbound_policy_check ++ /* ++ Note: "xor" (^) logically replaces "not equal" ++ (!=) and "bitwise or" (|) logically replaces ++ "boolean or" (||). This is done to speed up ++ execution by doing only bitwise operations and ++ no branch operations ++ */ ++ && (((ipp->saddr & ipsp->ips_mask_s.u.v4.sin_addr.s_addr) ++ ^ ipsp->ips_flow_s.u.v4.sin_addr.s_addr) ++ | ((ipp->daddr & ipsp->ips_mask_d.u.v4.sin_addr.s_addr) ++ ^ ipsp->ips_flow_d.u.v4.sin_addr.s_addr)) ) ++ { ++ char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF]; ++ ++ subnettoa(ipsp->ips_flow_s.u.v4.sin_addr, ++ ipsp->ips_mask_s.u.v4.sin_addr, ++ 0, sflow_txt, sizeof(sflow_txt)); ++ subnettoa(ipsp->ips_flow_d.u.v4.sin_addr, ++ ipsp->ips_mask_d.u.v4.sin_addr, ++ 0, dflow_txt, sizeof(dflow_txt)); ++ spin_unlock(&tdb_lock); ++ KLIPS_PRINT(debug_rcv, ++ "klips_debug:ipsec_rcv: " ++ "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n", ++ irs.sa_len ? irs.sa : " (error)", ++ sflow_txt, ++ dflow_txt, ++ irs.ipsaddr_txt, ++ irs.ipdaddr_txt); ++ if(stats) { ++ stats->rx_dropped++; ++ } ++ goto rcvleave; ++ } ++#ifdef CONFIG_NETFILTER ++ skb->nfmark = (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_TABLE_MASK)))) ++ | IPsecSAref2NFmark(IPsecSA2SAref(ipsp)); ++ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, ++ "klips_debug:ipsec_rcv: " ++ "IPIP SA sets skb->nfmark=0x%x.\n", ++ (unsigned)skb->nfmark); ++#endif /* CONFIG_NETFILTER */ ++ } ++ ++ spin_unlock(&tdb_lock); ++ ++#ifdef NET_21 ++ if(stats) { ++ stats->rx_bytes += skb->len; ++ } ++ if(skb->dst) { ++ dst_release(skb->dst); ++ skb->dst = NULL; ++ } ++ skb->pkt_type = PACKET_HOST; ++ if(irs.hard_header_len && ++ (skb->mac.raw != (skb->data - irs.hard_header_len)) && ++ (irs.hard_header_len <= skb_headroom(skb))) { ++ /* copy back original MAC header */ ++ memmove(skb->data - irs.hard_header_len, skb->mac.raw, irs.hard_header_len); ++ skb->mac.raw = skb->data - irs.hard_header_len; ++ } ++#endif /* NET_21 */ ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++ if(ipp->protocol == IPPROTO_COMP) { ++ unsigned int flags = 0; ++ ++ if(sysctl_ipsec_inbound_policy_check) { ++ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, ++ "klips_debug:ipsec_rcv: " ++ "inbound policy checking enabled, IPCOMP follows IPIP, dropped.\n"); ++ if (stats) { ++ stats->rx_errors++; ++ } ++ goto rcvleave; ++ } ++ /* ++ XXX need a ipsec_sa for updating ratio counters but it is not ++ following policy anyways so it is not a priority ++ */ ++ skb = skb_decompress(skb, NULL, &flags); ++ if (!skb || flags) { ++ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, ++ "klips_debug:ipsec_rcv: " ++ "skb_decompress() returned error flags: %d, dropped.\n", ++ flags); ++ if (stats) { ++ stats->rx_errors++; ++ } ++ goto rcvleave; ++ } ++ } ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#ifdef SKB_RESET_NFCT ++ nf_conntrack_put(skb->nfct); ++ skb->nfct = NULL; ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug = 0; ++#endif /* CONFIG_NETFILTER_DEBUG */ ++#endif /* SKB_RESET_NFCT */ ++ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, ++ "klips_debug:ipsec_rcv: " ++ "netif_rx() called.\n"); ++ netif_rx(skb); ++ ++ MOD_DEC_USE_COUNT; ++ return(0); ++ ++ rcvleave: ++ if(skb) { ++ ipsec_kfree_skb(skb); ++ } ++ ++ MOD_DEC_USE_COUNT; ++ return(0); ++} ++ ++/* ++ * $Log: ipsec_rcv.c,v $ ++ * Revision 1.143.4.2 2004/08/22 03:29:06 mcr ++ * include udp.h regardless of nat-t support. ++ * ++ * Revision 1.143.4.1 2004/08/21 02:14:58 ken ++ * Patch from Jochen Eisinger for AT&T MTS Heartbeat packet support ++ * ++ * Revision 1.143 2004/05/10 22:27:00 mcr ++ * fix for ESP-3DES-noauth test case. ++ * ++ * Revision 1.142 2004/05/10 22:25:57 mcr ++ * reformat of calls to ipsec_lifetime_check(). ++ * ++ * Revision 1.141 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.140 2004/02/03 03:12:53 mcr ++ * removed erroneously, double patched code. ++ * ++ * Revision 1.139 2004/01/05 23:21:29 mcr ++ * initialize sin_family in ipsec_rcv.c ++ * ++ * Revision 1.138 2003/12/24 19:46:52 mcr ++ * if sock.h patch has not been applied, then define appropriate ++ * structure so we can use it. This is serious inferior, and ++ * depends upon the concept that the structure in question is ++ * smaller than the other members of that union. ++ * getting rid of differing methods is a better solution. ++ * ++ * Revision 1.137 2003/12/22 19:40:57 mcr ++ * NAT-T patches 0.6c. ++ * ++ * Revision 1.136 2003/12/15 18:13:12 mcr ++ * when compiling with NAT traversal, don't assume that the ++ * kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP ++ * is set. ++ * ++ * Revision 1.135 2003/12/13 19:10:21 mcr ++ * refactored rcv and xmit code - same as FS 2.05. ++ * ++ * Revision 1.134.2.1 2003/12/22 15:25:52 jjo ++ * Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.134 2003/12/10 01:14:27 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.133 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.132.2.1 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.132 2003/09/02 19:51:48 mcr ++ * fixes for PR#252. ++ * ++ * Revision 1.131 2003/07/31 22:47:16 mcr ++ * preliminary (untested by FS-team) 2.5 patches. ++ * ++ * Revision 1.130 2003/04/03 17:38:25 rgb ++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. ++ * Clarified logic for non-connected devices. ++ * ++ * Revision 1.129 2003/02/06 02:21:34 rgb ++ * ++ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . ++ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". ++ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. ++ * ++ * Revision 1.128 2002/12/13 20:58:03 rgb ++ * Relegated MCR's recent "_dmp" routine to debug_verbose. ++ * Cleaned up printing of source and destination addresses in debug output. ++ * ++ * Revision 1.127 2002/12/04 16:00:16 rgb ++ * ++ * Fixed AH decapsulation pointer update bug and added some comments and ++ * debugging. ++ * This bug was caught by west-ah-0[12]. ++ * ++ * Revision 1.126 2002/11/04 05:03:43 mcr ++ * fixes for IPCOMP. There were two problems: ++ * 1) the irs->ipp pointer was not being updated properly after ++ * the ESP descryption. The meant nothing for IPIP, as the ++ * later IP header overwrote the earlier one. ++ * 2) the more serious problem was that skb_decompress will ++ * usually allocate a new SKB, so we have to make sure that ++ * it doesn't get lost. ++ * #2 meant removing the skb argument from the ->decrypt routine ++ * and moving it to the irs->skb, so it could be value/result. ++ * ++ * Revision 1.125 2002/11/01 01:53:35 dhr ++ * ++ * fix typo ++ * ++ * Revision 1.124 2002/10/31 22:49:01 dhr ++ * ++ * - eliminate unused variable "hash" ++ * - reduce scope of variable "authenticator" ++ * - add comment on a couple of tricky bits ++ * ++ * Revision 1.123 2002/10/31 22:39:56 dhr ++ * ++ * use correct type for result of function calls ++ * ++ * Revision 1.122 2002/10/31 22:36:25 dhr ++ * ++ * simplify complex test ++ * ++ * Revision 1.121 2002/10/31 22:34:04 dhr ++ * ++ * ipsprev is never used: ditch it ++ * ++ * Revision 1.120 2002/10/31 22:30:21 dhr ++ * ++ * eliminate redundant assignments ++ * ++ * Revision 1.119 2002/10/31 22:27:43 dhr ++ * ++ * make whitespace canonical ++ * ++ * Revision 1.118 2002/10/30 05:47:17 rgb ++ * Fixed cut-and-paste error mis-identifying comp runt as ah. ++ * ++ * Revision 1.117 2002/10/17 16:37:45 rgb ++ * Remove compp intermediate variable and in-line its contents ++ * where used ++ * ++ * Revision 1.116 2002/10/12 23:11:53 dhr ++ * ++ * [KenB + DHR] more 64-bit cleanup ++ * ++ * Revision 1.115 2002/10/07 19:06:58 rgb ++ * Minor fixups and activation to west-rcv-nfmark-set-01 test to check for SA reference properly set on incoming. ++ * ++ * Revision 1.114 2002/10/07 18:31:31 rgb ++ * Set saref on incoming packets. ++ * ++ * Revision 1.113 2002/09/16 21:28:12 mcr ++ * adjust hash length for HMAC calculation - must look at whether ++ * it is MD5 or SHA1. ++ * ++ * Revision 1.112 2002/09/16 21:19:15 mcr ++ * fixes for west-ah-icmp-01 - length of AH header must be ++ * calculated properly, and next_header field properly copied. ++ * ++ * Revision 1.111 2002/09/10 02:45:56 mcr ++ * re-factored the ipsec_rcv function into several functions, ++ * ipsec_rcv_decap_once, and a set of functions for AH, ESP and IPCOMP. ++ * In addition, the MD5 and SHA1 functions are replaced with pointers. ++ * ++ * Revision 1.110 2002/08/30 06:34:33 rgb ++ * Fix scope of shift in AH header length check. ++ * ++ * Revision 1.109 2002/08/27 16:49:20 rgb ++ * Fixed ESP short packet DOS (and AH and IPCOMP). ++ * ++ * Revision 1.108 2002/07/24 18:44:54 rgb ++ * Type fiddling to tame ia64 compiler. ++ * ++ * Revision 1.107 2002/05/27 18:58:18 rgb ++ * Convert to dynamic ipsec device allocation. ++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. ++ * ++ * Revision 1.106 2002/05/23 07:15:21 rgb ++ * Pointer clean-up. ++ * Added refcount code. ++ * ++ * Revision 1.105 2002/05/14 02:35:06 rgb ++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, ++ * ipsec_sa or ipsec_sa. ++ * Change references to _TDB to _IPSA. ++ * ++ * Revision 1.104 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.103 2002/04/24 07:36:30 mcr ++ * Moved from ./klips/net/ipsec/ipsec_rcv.c,v ++ * ++ * Revision 1.102 2002/01/29 17:17:56 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.101 2002/01/29 04:00:52 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.100 2002/01/29 02:13:17 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.99 2002/01/28 21:40:59 mcr ++ * should use #if to test boolean option rather than #ifdef. ++ * ++ * Revision 1.98 2002/01/20 20:19:36 mcr ++ * renamed option to IP_FRAGMENT_LINEARIZE. ++ * ++ * Revision 1.97 2002/01/12 02:55:36 mcr ++ * fix for post-2.4.4 to linearize skb's when ESP packet ++ * was assembled from fragments. ++ * ++ * Revision 1.96 2001/11/26 09:23:49 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.93.2.2 2001/10/22 20:54:07 mcr ++ * include des.h, removed phony prototypes and fixed calling ++ * conventions to match real prototypes. ++ * ++ * Revision 1.93.2.1 2001/09/25 02:22:22 mcr ++ * struct tdb -> struct ipsec_sa. ++ * lifetime checks moved to ipsec_life.c ++ * some sa(tdb) manipulation functions renamed. ++ * ++ * Revision 1.95 2001/11/06 19:49:07 rgb ++ * Added variable descriptions. ++ * Removed unauthenticated sequence==0 check to prevent DoS. ++ * ++ * Revision 1.94 2001/10/18 04:45:20 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/freeswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.93 2001/09/07 22:17:24 rgb ++ * Fix for removal of transport layer protocol handler arg in 2.4.4. ++ * Fix to accomodate peer non-conformance to IPCOMP rfc2393. ++ * ++ * Revision 1.92 2001/08/27 19:44:41 rgb ++ * Fix error in comment. ++ * ++ * Revision 1.91 2001/07/20 19:31:48 dhr ++ * [DHR] fix source and destination subnets of policy in diagnostic ++ * ++ * Revision 1.90 2001/07/06 19:51:09 rgb ++ * Added inbound policy checking code for IPIP SAs. ++ * Renamed unused function argument for ease and intuitive naming. ++ * ++ * Revision 1.89 2001/06/22 19:35:23 rgb ++ * Disable ipcomp processing if we are handed a ipcomp packet with no esp ++ * or ah header. ++ * Print protocol if we are handed a non-ipsec packet. ++ * ++ * Revision 1.88 2001/06/20 06:30:47 rgb ++ * Fixed transport mode IPCOMP policy check bug. ++ * ++ * Revision 1.87 2001/06/13 20:58:40 rgb ++ * Added parentheses around assignment used as truth value to silence ++ * compiler. ++ * ++ * Revision 1.86 2001/06/07 22:25:23 rgb ++ * Added a source address policy check for tunnel mode. It still does ++ * not check client addresses and masks. ++ * Only decapsulate IPIP if it is expected. ++ * ++ * Revision 1.85 2001/05/30 08:14:02 rgb ++ * Removed vestiges of esp-null transforms. ++ * ++ * Revision 1.84 2001/05/27 06:12:11 rgb ++ * Added structures for pid, packet count and last access time to eroute. ++ * Added packet count to beginning of /proc/net/ipsec_eroute. ++ * ++ * Revision 1.83 2001/05/04 16:45:47 rgb ++ * Remove unneeded code. ipp is not used after this point. ++ * ++ * Revision 1.82 2001/05/04 16:36:00 rgb ++ * Fix skb_cow() call for 2.4.4. (SS) ++ * ++ * Revision 1.81 2001/05/02 14:46:53 rgb ++ * Fix typo for compiler directive to pull IPH back. ++ * ++ * Revision 1.80 2001/04/30 19:46:34 rgb ++ * Update for 2.4.4. We now receive the skb with skb->data pointing to ++ * h.raw. ++ * ++ * Revision 1.79 2001/04/23 15:01:15 rgb ++ * Added spin_lock() check to prevent double-locking for multiple ++ * transforms and hence kernel lock-ups with SMP kernels. ++ * Minor spin_unlock() adjustments to unlock before non-dependant prints ++ * and IPSEC device stats updates. ++ * ++ * Revision 1.78 2001/04/21 23:04:24 rgb ++ * Check if soft expire has already been sent before sending another to ++ * prevent ACQUIRE flooding. ++ * ++ * Revision 1.77 2001/03/16 07:35:20 rgb ++ * Ditch extra #if 1 around now permanent policy checking code. ++ * ++ * Revision 1.76 2001/02/27 22:24:54 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.75 2001/02/19 22:28:30 rgb ++ * Minor change to virtual device discovery code to assert which I/F has ++ * been found. ++ * ++ * Revision 1.74 2000/11/25 03:50:36 rgb ++ * Oops fix by minor re-arrangement of code to avoid accessing a freed tdb. ++ * ++ * Revision 1.73 2000/11/09 20:52:15 rgb ++ * More spinlock shuffling, locking earlier and unlocking later in rcv to ++ * include ipcomp and prevent races, renaming some tdb variables that got ++ * forgotten, moving some unlocks to include tdbs and adding a missing ++ * unlock. Thanks to Svenning for some of these. ++ * ++ * Revision 1.72 2000/11/09 20:11:22 rgb ++ * Minor shuffles to fix non-standard kernel config option selection. ++ * ++ * Revision 1.71 2000/11/06 04:36:18 rgb ++ * Ditched spin_lock_irqsave in favour of spin_lock. ++ * Minor initial protocol check rewrite. ++ * Clean up debug printing. ++ * Clean up tdb handling on ipcomp. ++ * Fixed transport mode null pointer de-reference without ipcomp. ++ * Add Svenning's adaptive content compression. ++ * Disabled registration of ipcomp handler. ++ * ++ * Revision 1.70 2000/10/30 23:41:43 henry ++ * Hans-Joerg Hoexer's null-pointer fix ++ * ++ * Revision 1.69 2000/10/10 18:54:16 rgb ++ * Added a fix for incoming policy check with ipcomp enabled but ++ * uncompressible. ++ * ++ * Revision 1.68 2000/09/22 17:53:12 rgb ++ * Fixed ipcomp tdb pointers update for policy checking. ++ * ++ * Revision 1.67 2000/09/21 03:40:58 rgb ++ * Added more debugging to try and track down the cpi outward copy problem. ++ * ++ * Revision 1.66 2000/09/20 04:00:10 rgb ++ * Changed static functions to DEBUG_NO_STATIC to reveal function names for ++ * debugging oopsen. ++ * ++ * Revision 1.65 2000/09/19 07:07:16 rgb ++ * Added debugging to inbound policy check for ipcomp. ++ * Added missing spin_unlocks (thanks Svenning!). ++ * Fixed misplaced tdbnext pointers causing mismatched ipip policy check. ++ * Protect ipcomp policy check following ipip decap with sysctl switch. ++ * ++ * Revision 1.64 2000/09/18 21:27:29 rgb ++ * 2.0 fixes. ++ * ++ * Revision 1.63 2000/09/18 02:35:50 rgb ++ * Added policy checking to ipcomp and re-enabled policy checking by ++ * default. ++ * Optimised satoa calls. ++ * ++ * Revision 1.62 2000/09/17 21:02:32 rgb ++ * Clean up debugging, removing slow timestamp debug code. ++ * ++ * Revision 1.61 2000/09/16 01:07:55 rgb ++ * Fixed erroneous ref from struct ipcomp to struct ipcomphdr. ++ * ++ * Revision 1.60 2000/09/15 11:37:01 rgb ++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk> ++ * IPCOMP zlib deflate code. ++ * ++ * Revision 1.59 2000/09/15 04:56:20 rgb ++ * Remove redundant satoa() call, reformat comment. ++ * ++ * Revision 1.58 2000/09/13 08:00:52 rgb ++ * Flick on inbound policy checking. ++ * ++ * Revision 1.57 2000/09/12 03:22:19 rgb ++ * Converted inbound_policy_check to sysctl. ++ * Re-enabled policy backcheck. ++ * Moved policy checks to top and within tdb lock. ++ * ++ * Revision 1.56 2000/09/08 19:12:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.55 2000/08/28 18:15:46 rgb ++ * Added MB's nf-debug reset patch. ++ * ++ * Revision 1.54 2000/08/27 01:41:26 rgb ++ * More minor tweaks to the bad padding debug code. ++ * ++ * Revision 1.53 2000/08/24 16:54:16 rgb ++ * Added KLIPS_PRINTMORE macro to continue lines without KERN_INFO level ++ * info. ++ * Tidied up device reporting at the start of ipsec_rcv. ++ * Tidied up bad padding debugging and processing. ++ * ++ * Revision 1.52 2000/08/20 21:36:03 rgb ++ * Activated pfkey_expire() calls. ++ * Added a hard/soft expiry parameter to pfkey_expire(). ++ * Added sanity checking to avoid propagating zero or smaller-length skbs ++ * from a bogus decryption. ++ * Re-arranged the order of soft and hard expiry to conform to RFC2367. ++ * Clean up references to CONFIG_IPSEC_PFKEYv2. ++ * ++ * Revision 1.51 2000/08/18 21:23:30 rgb ++ * Improve bad padding warning so that the printk buffer doesn't get ++ * trampled. ++ * ++ * Revision 1.50 2000/08/01 14:51:51 rgb ++ * Removed _all_ remaining traces of DES. ++ * ++ * Revision 1.49 2000/07/28 13:50:53 rgb ++ * Changed enet_statistics to net_device_stats and added back compatibility ++ * for pre-2.1.19. ++ * ++ * Revision 1.48 2000/05/10 19:14:40 rgb ++ * Only check usetime against soft and hard limits if the tdb has been ++ * used. ++ * Cast output of ntohl so that the broken prototype doesn't make our ++ * compile noisy. ++ * ++ * Revision 1.47 2000/05/09 17:45:43 rgb ++ * Fix replay bitmap corruption bug upon receipt of bogus packet ++ * with correct SPI. This was a DoS. ++ * ++ * Revision 1.46 2000/03/27 02:31:58 rgb ++ * Fixed authentication failure printout bug. ++ * ++ * Revision 1.45 2000/03/22 16:15:37 rgb ++ * Fixed renaming of dev_get (MB). ++ * ++ * Revision 1.44 2000/03/16 08:17:24 rgb ++ * Hardcode PF_KEYv2 support. ++ * Fixed minor bug checking AH header length. ++ * ++ * Revision 1.43 2000/03/14 12:26:59 rgb ++ * Added skb->nfct support for clearing netfilter conntrack bits (MB). ++ * ++ * Revision 1.42 2000/01/26 10:04:04 rgb ++ * Fixed inbound policy checking on transport mode bug. ++ * Fixed noisy 2.0 printk arguments. ++ * ++ * Revision 1.41 2000/01/24 20:58:02 rgb ++ * Improve debugging/reporting support for (disabled) inbound ++ * policy checking. ++ * ++ * Revision 1.40 2000/01/22 23:20:10 rgb ++ * Fixed up inboud policy checking code. ++ * Cleaned out unused crud. ++ * ++ * Revision 1.39 2000/01/21 06:15:29 rgb ++ * Added sanity checks on skb_push(), skb_pull() to prevent panics. ++ * Fixed cut-and-paste debug_tunnel to debug_rcv. ++ * Added inbound policy checking code, disabled. ++ * Simplified output code by updating ipp to post-IPIP decapsulation. ++ * ++ * elided pre-2000 comments. Use "cvs log" ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_sa.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1383 @@ ++/* ++ * Common routines for IPsec SA maintenance routines. ++ * ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_sa.c,v 1.23 2004/04/06 02:49:26 mcr Exp $ ++ * ++ * This is the file formerly known as "ipsec_xform.h" ++ * ++ */ ++ ++#include <linux/config.h> ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/vmalloc.h> /* vmalloc() */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef SPINLOCK ++#ifdef SPINLOCK_23 ++#include <linux/spinlock.h> /* *lock* */ ++#else /* SPINLOCK_23 */ ++#include <asm/spinlock.h> /* *lock* */ ++#endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++#include <asm/uaccess.h> ++#include <linux/in6.h> ++#endif ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include "openswan/radij.h" ++ ++#include "openswan/ipsec_stats.h" ++#include "openswan/ipsec_life.h" ++#include "openswan/ipsec_sa.h" ++#include "openswan/ipsec_xform.h" ++ ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_ipe4.h" ++#include "openswan/ipsec_ah.h" ++#include "openswan/ipsec_esp.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_proto.h" ++#include "openswan/ipsec_alg.h" ++ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_xform = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) ++ ++struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD]; ++#ifdef SPINLOCK ++spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED; ++#else /* SPINLOCK */ ++spinlock_t tdb_lock; ++#endif /* SPINLOCK */ ++ ++struct ipsec_sadb ipsec_sadb; ++ ++#if IPSEC_SA_REF_CODE ++ ++/* the sub table must be narrower (or equal) in bits than the variable type ++ in the main table to count the number of unused entries in it. */ ++typedef struct { ++ int testSizeOf_refSubTable : ++ ((sizeof(IPsecRefTableUnusedCount) * 8) < IPSEC_SA_REF_SUBTABLE_IDX_WIDTH ? -1 : 1); ++} dummy; ++ ++ ++/* The field where the saref will be hosted in the skb must be wide enough to ++ accomodate the information it needs to store. */ ++typedef struct { ++ int testSizeOf_refField : ++ (IPSEC_SA_REF_HOST_FIELD_WIDTH < IPSEC_SA_REF_TABLE_IDX_WIDTH ? -1 : 1 ); ++} dummy2; ++ ++ ++#define IPS_HASH(said) (((said)->spi + (said)->dst.u.v4.sin_addr.s_addr + (said)->proto) % SADB_HASHMOD) ++ ++ ++void ++ipsec_SAtest(void) ++{ ++ IPsecSAref_t SAref = 258; ++ struct ipsec_sa ips; ++ ips.ips_ref = 772; ++ ++ printk("klips_debug:ipsec_SAtest: " ++ "IPSEC_SA_REF_SUBTABLE_IDX_WIDTH=%u\n" ++ "IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES=%u\n" ++ "IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES=%u\n" ++ "IPSEC_SA_REF_HOST_FIELD_WIDTH=%lu\n" ++ "IPSEC_SA_REF_TABLE_MASK=%x\n" ++ "IPSEC_SA_REF_ENTRY_MASK=%x\n" ++ "IPsecSAref2table(%d)=%u\n" ++ "IPsecSAref2entry(%d)=%u\n" ++ "IPsecSAref2NFmark(%d)=%u\n" ++ "IPsecSAref2SA(%d)=%p\n" ++ "IPsecSA2SAref(%p)=%d\n" ++ , ++ IPSEC_SA_REF_SUBTABLE_IDX_WIDTH, ++ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES, ++ IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES, ++ (unsigned long) IPSEC_SA_REF_HOST_FIELD_WIDTH, ++ IPSEC_SA_REF_TABLE_MASK, ++ IPSEC_SA_REF_ENTRY_MASK, ++ SAref, IPsecSAref2table(SAref), ++ SAref, IPsecSAref2entry(SAref), ++ SAref, IPsecSAref2NFmark(SAref), ++ SAref, IPsecSAref2SA(SAref), ++ (&ips), IPsecSA2SAref((&ips)) ++ ); ++ return; ++} ++ ++int ++ipsec_SAref_recycle(void) ++{ ++ int table; ++ int entry; ++ int error = 0; ++ ++ ipsec_sadb.refFreeListHead = -1; ++ ipsec_sadb.refFreeListTail = -1; ++ ++ if(ipsec_sadb.refFreeListCont == IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_recycle: " ++ "end of table reached, continuing at start..\n"); ++ ipsec_sadb.refFreeListCont = 0; ++ } ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_recycle: " ++ "recycling, continuing from SAref=%d (0p%p), table=%d, entry=%d.\n", ++ ipsec_sadb.refFreeListCont, ++ (ipsec_sadb.refTable[IPsecSAref2table(ipsec_sadb.refFreeListCont)] != NULL) ? IPsecSAref2SA(ipsec_sadb.refFreeListCont) : NULL, ++ IPsecSAref2table(ipsec_sadb.refFreeListCont), ++ IPsecSAref2entry(ipsec_sadb.refFreeListCont)); ++ ++ for(table = IPsecSAref2table(ipsec_sadb.refFreeListCont); ++ table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; ++ table++) { ++ if(ipsec_sadb.refTable[table] == NULL) { ++ error = ipsec_SArefSubTable_alloc(table); ++ if(error) { ++ return error; ++ } ++ } ++ for(entry = IPsecSAref2entry(ipsec_sadb.refFreeListCont); ++ entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; ++ entry++) { ++ if(ipsec_sadb.refTable[table]->entry[entry] == NULL) { ++ ipsec_sadb.refFreeList[++ipsec_sadb.refFreeListTail] = IPsecSArefBuild(table, entry); ++ if(ipsec_sadb.refFreeListTail == (IPSEC_SA_REF_FREELIST_NUM_ENTRIES - 1)) { ++ ipsec_sadb.refFreeListHead = 0; ++ ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_recycle: " ++ "SArefFreeList refilled.\n"); ++ return 0; ++ } ++ } ++ } ++ } ++ ++ if(ipsec_sadb.refFreeListTail == -1) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_recycle: " ++ "out of room in the SArefTable.\n"); ++ ++ return(-ENOSPC); ++ } ++ ++ ipsec_sadb.refFreeListHead = 0; ++ ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_recycle: " ++ "SArefFreeList partly refilled to %d of %d.\n", ++ ipsec_sadb.refFreeListTail, ++ IPSEC_SA_REF_FREELIST_NUM_ENTRIES); ++ return 0; ++} ++ ++int ++ipsec_SArefSubTable_alloc(unsigned table) ++{ ++ unsigned entry; ++ struct IPsecSArefSubTable* SArefsub; ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SArefSubTable_alloc: " ++ "allocating %lu bytes for table %u of %u.\n", ++ (unsigned long) (IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)), ++ table, ++ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); ++ ++ /* allocate another sub-table */ ++ SArefsub = vmalloc(IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)); ++ if(SArefsub == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SArefSubTable_alloc: " ++ "error allocating memory for table %u of %u!\n", ++ table, ++ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); ++ return -ENOMEM; ++ } ++ ++ /* add this sub-table to the main table */ ++ ipsec_sadb.refTable[table] = SArefsub; ++ ++ /* initialise each element to NULL */ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SArefSubTable_alloc: " ++ "initialising %u elements (2 ^ %u) of table %u.\n", ++ IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES, ++ IPSEC_SA_REF_SUBTABLE_IDX_WIDTH, ++ table); ++ for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { ++ SArefsub->entry[entry] = NULL; ++ } ++ ++ return 0; ++} ++#endif /* IPSEC_SA_REF_CODE */ ++ ++int ++ipsec_saref_freelist_init(void) ++{ ++ int i; ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_saref_freelist_init: " ++ "initialising %u elements of FreeList.\n", ++ IPSEC_SA_REF_FREELIST_NUM_ENTRIES); ++ ++ for(i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) { ++ ipsec_sadb.refFreeList[i] = IPSEC_SAREF_NULL; ++ } ++ ipsec_sadb.refFreeListHead = -1; ++ ipsec_sadb.refFreeListCont = 0; ++ ipsec_sadb.refFreeListTail = -1; ++ ++ return 0; ++} ++ ++int ++ipsec_sadb_init(void) ++{ ++ int error = 0; ++ unsigned i; ++ ++ for(i = 0; i < SADB_HASHMOD; i++) { ++ ipsec_sadb_hash[i] = NULL; ++ } ++ /* parts above are for the old style SADB hash table */ ++ ++ ++#if IPSEC_SA_REF_CODE ++ /* initialise SA reference table */ ++ ++ /* initialise the main table */ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_init: " ++ "initialising main table of size %u (2 ^ %u).\n", ++ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES, ++ IPSEC_SA_REF_MAINTABLE_IDX_WIDTH); ++ { ++ unsigned table; ++ for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { ++ ipsec_sadb.refTable[table] = NULL; ++ } ++ } ++ ++ /* allocate the first sub-table */ ++ error = ipsec_SArefSubTable_alloc(0); ++ if(error) { ++ return error; ++ } ++ ++ error = ipsec_saref_freelist_init(); ++#endif /* IPSEC_SA_REF_CODE */ ++ return error; ++} ++ ++#if IPSEC_SA_REF_CODE ++IPsecSAref_t ++ipsec_SAref_alloc(int*error) /* pass in error var by pointer */ ++{ ++ IPsecSAref_t SAref; ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_alloc: " ++ "SAref requested... head=%d, cont=%d, tail=%d, listsize=%d.\n", ++ ipsec_sadb.refFreeListHead, ++ ipsec_sadb.refFreeListCont, ++ ipsec_sadb.refFreeListTail, ++ IPSEC_SA_REF_FREELIST_NUM_ENTRIES); ++ ++ if(ipsec_sadb.refFreeListHead == -1) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_alloc: " ++ "FreeList empty, recycling...\n"); ++ *error = ipsec_SAref_recycle(); ++ if(*error) { ++ return IPSEC_SAREF_NULL; ++ } ++ } ++ ++ SAref = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead]; ++ if(SAref == IPSEC_SAREF_NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_alloc: " ++ "unexpected error, refFreeListHead = %d points to invalid entry.\n", ++ ipsec_sadb.refFreeListHead); ++ *error = -ESPIPE; ++ return IPSEC_SAREF_NULL; ++ } ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_alloc: " ++ "allocating SAref=%d, table=%u, entry=%u of %u.\n", ++ SAref, ++ IPsecSAref2table(SAref), ++ IPsecSAref2entry(SAref), ++ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES); ++ ++ ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead] = IPSEC_SAREF_NULL; ++ ipsec_sadb.refFreeListHead++; ++ if(ipsec_sadb.refFreeListHead > ipsec_sadb.refFreeListTail) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_SAref_alloc: " ++ "last FreeList entry allocated, resetting list head to empty.\n"); ++ ipsec_sadb.refFreeListHead = -1; ++ } ++ ++ return SAref; ++} ++#endif /* IPSEC_SA_REF_CODE */ ++ ++int ++ipsec_sa_print(struct ipsec_sa *ips) ++{ ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ ++ printk(KERN_INFO "klips_debug: SA:"); ++ if(ips == NULL) { ++ printk("NULL\n"); ++ return -ENOENT; ++ } ++ printk(" ref=%d", ips->ips_ref); ++ printk(" refcount=%d", atomic_read(&ips->ips_refcount)); ++ if(ips->ips_hnext != NULL) { ++ printk(" hnext=0p%p", ips->ips_hnext); ++ } ++ if(ips->ips_inext != NULL) { ++ printk(" inext=0p%p", ips->ips_inext); ++ } ++ if(ips->ips_onext != NULL) { ++ printk(" onext=0p%p", ips->ips_onext); ++ } ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ printk(" said=%s", sa_len ? sa : " (error)"); ++ if(ips->ips_seq) { ++ printk(" seq=%u", ips->ips_seq); ++ } ++ if(ips->ips_pid) { ++ printk(" pid=%u", ips->ips_pid); ++ } ++ if(ips->ips_authalg) { ++ printk(" authalg=%u", ips->ips_authalg); ++ } ++ if(ips->ips_encalg) { ++ printk(" encalg=%u", ips->ips_encalg); ++ } ++ printk(" XFORM=%s%s%s", IPS_XFORM_NAME(ips)); ++ if(ips->ips_replaywin) { ++ printk(" ooowin=%u", ips->ips_replaywin); ++ } ++ if(ips->ips_flags) { ++ printk(" flags=%u", ips->ips_flags); ++ } ++ if(ips->ips_addr_s) { ++ char buf[SUBNETTOA_BUF]; ++ addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, ++ 0, buf, sizeof(buf)); ++ printk(" src=%s", buf); ++ } ++ if(ips->ips_addr_d) { ++ char buf[SUBNETTOA_BUF]; ++ addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, ++ 0, buf, sizeof(buf)); ++ printk(" dst=%s", buf); ++ } ++ if(ips->ips_addr_p) { ++ char buf[SUBNETTOA_BUF]; ++ addrtoa(((struct sockaddr_in*)(ips->ips_addr_p))->sin_addr, ++ 0, buf, sizeof(buf)); ++ printk(" proxy=%s", buf); ++ } ++ if(ips->ips_key_bits_a) { ++ printk(" key_bits_a=%u", ips->ips_key_bits_a); ++ } ++ if(ips->ips_key_bits_e) { ++ printk(" key_bits_e=%u", ips->ips_key_bits_e); ++ } ++ ++ printk("\n"); ++ return 0; ++} ++ ++struct ipsec_sa* ++ipsec_sa_alloc(int*error) /* pass in error var by pointer */ ++{ ++ struct ipsec_sa* ips; ++ ++ if((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_alloc: " ++ "memory allocation error\n"); ++ *error = -ENOMEM; ++ return NULL; ++ } ++ memset((caddr_t)ips, 0, sizeof(*ips)); ++#if IPSEC_SA_REF_CODE ++ ips->ips_ref = ipsec_SAref_alloc(error); /* pass in error return by pointer */ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_alloc: " ++ "allocated %lu bytes for ipsec_sa struct=0p%p ref=%d.\n", ++ (unsigned long) sizeof(*ips), ++ ips, ++ ips->ips_ref); ++ if(ips->ips_ref == IPSEC_SAREF_NULL) { ++ kfree(ips); ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_alloc: " ++ "SAref allocation error\n"); ++ return NULL; ++ } ++ ++ atomic_inc(&ips->ips_refcount); ++ IPsecSAref2SA(ips->ips_ref) = ips; ++#endif /* IPSEC_SA_REF_CODE */ ++ ++ *error = 0; ++ return(ips); ++} ++ ++int ++ipsec_sa_free(struct ipsec_sa* ips) ++{ ++ return ipsec_sa_wipe(ips); ++} ++ ++struct ipsec_sa * ++ipsec_sa_getbyid(ip_said *said) ++{ ++ int hashval; ++ struct ipsec_sa *ips; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ ++ if(said == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_error:ipsec_sa_getbyid: " ++ "null pointer passed in!\n"); ++ return NULL; ++ } ++ ++ sa_len = satot(said, 0, sa, sizeof(sa)); ++ ++ hashval = IPS_HASH(said); ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_getbyid: " ++ "linked entry in ipsec_sa table for hash=%d of SA:%s requested.\n", ++ hashval, ++ sa_len ? sa : " (error)"); ++ ++ if((ips = ipsec_sadb_hash[hashval]) == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_getbyid: " ++ "no entries in ipsec_sa table for hash=%d of SA:%s.\n", ++ hashval, ++ sa_len ? sa : " (error)"); ++ return NULL; ++ } ++ ++ for (; ips; ips = ips->ips_hnext) { ++ if ((ips->ips_said.spi == said->spi) && ++ (ips->ips_said.dst.u.v4.sin_addr.s_addr == said->dst.u.v4.sin_addr.s_addr) && ++ (ips->ips_said.proto == said->proto)) { ++ atomic_inc(&ips->ips_refcount); ++ return ips; ++ } ++ } ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_getbyid: " ++ "no entry in linked list for hash=%d of SA:%s.\n", ++ hashval, ++ sa_len ? sa : " (error)"); ++ return NULL; ++} ++ ++int ++ipsec_sa_put(struct ipsec_sa *ips) ++{ ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ ++ if(ips == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_error:ipsec_sa_put: " ++ "null pointer passed in!\n"); ++ return -1; ++ } ++ ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_put: " ++ "ipsec_sa SA:%s, ref:%d reference count decremented.\n", ++ sa_len ? sa : " (error)", ++ ips->ips_ref); ++ ++ atomic_dec(&ips->ips_refcount); ++ ++ return 0; ++} ++ ++/* ++ The ipsec_sa table better *NOT* be locked before it is handed in, or SMP locks will happen ++*/ ++int ++ipsec_sa_add(struct ipsec_sa *ips) ++{ ++ int error = 0; ++ unsigned int hashval; ++ ++ if(ips == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_error:ipsec_sa_add: " ++ "null pointer passed in!\n"); ++ return -ENODATA; ++ } ++ hashval = IPS_HASH(&ips->ips_said); ++ ++ atomic_inc(&ips->ips_refcount); ++ spin_lock_bh(&tdb_lock); ++ ++ ips->ips_hnext = ipsec_sadb_hash[hashval]; ++ ipsec_sadb_hash[hashval] = ips; ++ ++ spin_unlock_bh(&tdb_lock); ++ ++ return error; ++} ++ ++/* ++ The ipsec_sa table better be locked before it is handed in, or races might happen ++*/ ++int ++ipsec_sa_del(struct ipsec_sa *ips) ++{ ++ unsigned int hashval; ++ struct ipsec_sa *ipstp; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ ++ if(ips == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_error:ipsec_sa_del: " ++ "null pointer passed in!\n"); ++ return -ENODATA; ++ } ++ ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ if(ips->ips_inext || ips->ips_onext) { ++ KLIPS_PRINT(debug_xform, ++ "klips_error:ipsec_sa_del: " ++ "SA:%s still linked!\n", ++ sa_len ? sa : " (error)"); ++ return -EMLINK; ++ } ++ ++ hashval = IPS_HASH(&ips->ips_said); ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_del: " ++ "deleting SA:%s, hashval=%d.\n", ++ sa_len ? sa : " (error)", ++ hashval); ++ if(ipsec_sadb_hash[hashval] == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_del: " ++ "no entries in ipsec_sa table for hash=%d of SA:%s.\n", ++ hashval, ++ sa_len ? sa : " (error)"); ++ return -ENOENT; ++ } ++ ++ if (ips == ipsec_sadb_hash[hashval]) { ++ ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; ++ ips->ips_hnext = NULL; ++ atomic_dec(&ips->ips_refcount); ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_del: " ++ "successfully deleted first ipsec_sa in chain.\n"); ++ return 0; ++ } else { ++ for (ipstp = ipsec_sadb_hash[hashval]; ++ ipstp; ++ ipstp = ipstp->ips_hnext) { ++ if (ipstp->ips_hnext == ips) { ++ ipstp->ips_hnext = ips->ips_hnext; ++ ips->ips_hnext = NULL; ++ atomic_dec(&ips->ips_refcount); ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_del: " ++ "successfully deleted link in ipsec_sa chain.\n"); ++ return 0; ++ } ++ } ++ } ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_del: " ++ "no entries in linked list for hash=%d of SA:%s.\n", ++ hashval, ++ sa_len ? sa : " (error)"); ++ return -ENOENT; ++} ++ ++/* ++ The ipsec_sa table better be locked before it is handed in, or races ++ might happen ++*/ ++int ++ipsec_sa_delchain(struct ipsec_sa *ips) ++{ ++ struct ipsec_sa *ipsdel; ++ int error = 0; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ ++ if(ips == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_error:ipsec_sa_delchain: " ++ "null pointer passed in!\n"); ++ return -ENODATA; ++ } ++ ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_delchain: " ++ "passed SA:%s\n", ++ sa_len ? sa : " (error)"); ++ while(ips->ips_onext != NULL) { ++ ips = ips->ips_onext; ++ } ++ ++ while(ips) { ++ /* XXX send a pfkey message up to advise of deleted ipsec_sa */ ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_delchain: " ++ "unlinking and delting SA:%s", ++ sa_len ? sa : " (error)"); ++ ipsdel = ips; ++ ips = ips->ips_inext; ++ if(ips != NULL) { ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ ", inext=%s", ++ sa_len ? sa : " (error)"); ++ atomic_dec(&ipsdel->ips_refcount); ++ ipsdel->ips_inext = NULL; ++ atomic_dec(&ips->ips_refcount); ++ ips->ips_onext = NULL; ++ } ++ KLIPS_PRINT(debug_xform, ++ ".\n"); ++ if((error = ipsec_sa_del(ipsdel))) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_delchain: " ++ "ipsec_sa_del returned error %d.\n", -error); ++ return error; ++ } ++ if((error = ipsec_sa_wipe(ipsdel))) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_delchain: " ++ "ipsec_sa_wipe returned error %d.\n", -error); ++ return error; ++ } ++ } ++ return error; ++} ++ ++int ++ipsec_sadb_cleanup(__u8 proto) ++{ ++ unsigned i; ++ int error = 0; ++ struct ipsec_sa *ips, **ipsprev, *ipsdel; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_cleanup: " ++ "cleaning up proto=%d.\n", ++ proto); ++ ++ spin_lock_bh(&tdb_lock); ++ ++ for (i = 0; i < SADB_HASHMOD; i++) { ++ ipsprev = &(ipsec_sadb_hash[i]); ++ ips = ipsec_sadb_hash[i]; ++ if(ips != NULL) { ++ atomic_inc(&ips->ips_refcount); ++ } ++ for(; ips != NULL;) { ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_cleanup: " ++ "checking SA:%s, hash=%d, ref=%d", ++ sa_len ? sa : " (error)", ++ i, ++ ips->ips_ref); ++ ipsdel = ips; ++ ips = ipsdel->ips_hnext; ++ if(ips != NULL) { ++ atomic_inc(&ips->ips_refcount); ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ ", hnext=%s", ++ sa_len ? sa : " (error)"); ++ } ++ if(*ipsprev != NULL) { ++ sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ ", *ipsprev=%s", ++ sa_len ? sa : " (error)"); ++ if((*ipsprev)->ips_hnext) { ++ sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ ", *ipsprev->ips_hnext=%s", ++ sa_len ? sa : " (error)"); ++ } ++ } ++ KLIPS_PRINT(debug_xform, ++ ".\n"); ++ if(proto == 0 || (proto == ipsdel->ips_said.proto)) { ++ sa_len = satot(&ipsdel->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_cleanup: " ++ "deleting SA chain:%s.\n", ++ sa_len ? sa : " (error)"); ++ if((error = ipsec_sa_delchain(ipsdel))) { ++ SENDERR(-error); ++ } ++ ipsprev = &(ipsec_sadb_hash[i]); ++ ips = ipsec_sadb_hash[i]; ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_cleanup: " ++ "deleted SA chain:%s", ++ sa_len ? sa : " (error)"); ++ if(ips != NULL) { ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ ", ipsec_sadb_hash[%d]=%s", ++ i, ++ sa_len ? sa : " (error)"); ++ } ++ if(*ipsprev != NULL) { ++ sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ ", *ipsprev=%s", ++ sa_len ? sa : " (error)"); ++ if((*ipsprev)->ips_hnext != NULL) { ++ sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ ", *ipsprev->ips_hnext=%s", ++ sa_len ? sa : " (error)"); ++ } ++ } ++ KLIPS_PRINT(debug_xform, ++ ".\n"); ++ } else { ++ ipsprev = &ipsdel; ++ } ++ if(ipsdel != NULL) { ++ ipsec_sa_put(ipsdel); ++ } ++ } ++ } ++ errlab: ++ ++ spin_unlock_bh(&tdb_lock); ++ ++ ++#if IPSEC_SA_REF_CODE ++ /* clean up SA reference table */ ++ ++ /* go through the ref table and clean out all the SAs */ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_cleanup: " ++ "removing SAref entries and tables."); ++ { ++ unsigned table, entry; ++ for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_cleanup: " ++ "cleaning SAref table=%u.\n", ++ table); ++ if(ipsec_sadb.refTable[table] == NULL) { ++ printk("\n"); ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_cleanup: " ++ "cleaned %u used refTables.\n", ++ table); ++ break; ++ } ++ for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { ++ if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { ++ ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); ++ ipsec_sadb.refTable[table]->entry[entry] = NULL; ++ } ++ } ++ } ++ } ++#endif /* IPSEC_SA_REF_CODE */ ++ ++ return(error); ++} ++ ++int ++ipsec_sadb_free(void) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_free: " ++ "freeing SArefTable memory.\n"); ++ ++ /* clean up SA reference table */ ++ ++ /* go through the ref table and clean out all the SAs if any are ++ left and free table memory */ ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_free: " ++ "removing SAref entries and tables.\n"); ++ { ++ unsigned table, entry; ++ for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_free: " ++ "removing SAref table=%u.\n", ++ table); ++ if(ipsec_sadb.refTable[table] == NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sadb_free: " ++ "removed %u used refTables.\n", ++ table); ++ break; ++ } ++ for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { ++ if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { ++ ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); ++ ipsec_sadb.refTable[table]->entry[entry] = NULL; ++ } ++ } ++ vfree(ipsec_sadb.refTable[table]); ++ ipsec_sadb.refTable[table] = NULL; ++ } ++ } ++ ++ return(error); ++} ++ ++int ++ipsec_sa_wipe(struct ipsec_sa *ips) ++{ ++ if(ips == NULL) { ++ return -ENODATA; ++ } ++ ++ /* if(atomic_dec_and_test(ips)) { ++ }; */ ++ ++#if IPSEC_SA_REF_CODE ++ /* remove me from the SArefTable */ ++ { ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_wipe: " ++ "removing SA=%s(0p%p), SAref=%d, table=%d(0p%p), entry=%d from the refTable.\n", ++ sa_len ? sa : " (error)", ++ ips, ++ ips->ips_ref, ++ IPsecSAref2table(IPsecSA2SAref(ips)), ++ ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))], ++ IPsecSAref2entry(IPsecSA2SAref(ips))); ++ } ++ if(ips->ips_ref == IPSEC_SAREF_NULL) { ++ KLIPS_PRINT(debug_xform, ++ "klips_debug:ipsec_sa_wipe: " ++ "why does this SA not have a valid SAref?.\n"); ++ } ++ ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))]->entry[IPsecSAref2entry(IPsecSA2SAref(ips))] = NULL; ++ ips->ips_ref = IPSEC_SAREF_NULL; ++ ipsec_sa_put(ips); ++#endif /* IPSEC_SA_REF_CODE */ ++ ++ /* paranoid clean up */ ++ if(ips->ips_addr_s != NULL) { ++ memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size); ++ kfree(ips->ips_addr_s); ++ } ++ ips->ips_addr_s = NULL; ++ ++ if(ips->ips_addr_d != NULL) { ++ memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size); ++ kfree(ips->ips_addr_d); ++ } ++ ips->ips_addr_d = NULL; ++ ++ if(ips->ips_addr_p != NULL) { ++ memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size); ++ kfree(ips->ips_addr_p); ++ } ++ ips->ips_addr_p = NULL; ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if(ips->ips_natt_oa) { ++ memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size); ++ kfree(ips->ips_natt_oa); ++ } ++ ips->ips_natt_oa = NULL; ++#endif ++ ++ if(ips->ips_key_a != NULL) { ++ memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size); ++ kfree(ips->ips_key_a); ++ } ++ ips->ips_key_a = NULL; ++ ++ if(ips->ips_key_e != NULL) { ++#ifdef CONFIG_IPSEC_ALG ++ if (ips->ips_alg_enc&&ips->ips_alg_enc->ixt_e_destroy_key) { ++ ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc, ++ ips->ips_key_e); ++ } else { ++#endif /* CONFIG_IPSEC_ALG */ ++ memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); ++ kfree(ips->ips_key_e); ++#ifdef CONFIG_IPSEC_ALG ++ } ++#endif /* CONFIG_IPSEC_ALG */ ++ } ++ ips->ips_key_e = NULL; ++ ++ if(ips->ips_iv != NULL) { ++ memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size); ++ kfree(ips->ips_iv); ++ } ++ ips->ips_iv = NULL; ++ ++ if(ips->ips_ident_s.data != NULL) { ++ memset((caddr_t)(ips->ips_ident_s.data), ++ 0, ++ ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); ++ kfree(ips->ips_ident_s.data); ++ } ++ ips->ips_ident_s.data = NULL; ++ ++ if(ips->ips_ident_d.data != NULL) { ++ memset((caddr_t)(ips->ips_ident_d.data), ++ 0, ++ ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); ++ kfree(ips->ips_ident_d.data); ++ } ++ ips->ips_ident_d.data = NULL; ++ ++#ifdef CONFIG_IPSEC_ALG ++ if (ips->ips_alg_enc||ips->ips_alg_auth) { ++ ipsec_alg_sa_wipe(ips); ++ } ++#endif /* CONFIG_IPSEC_ALG */ ++ ++ memset((caddr_t)ips, 0, sizeof(*ips)); ++ kfree(ips); ++ ips = NULL; ++ ++ return 0; ++} ++ ++/* ++ * $Log: ipsec_sa.c,v $ ++ * Revision 1.23 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.22.2.1 2003/12/22 15:25:52 jjo ++ * . Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.22 2003/12/10 01:14:27 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.21 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.20.4.1 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.20 2003/02/06 01:50:34 rgb ++ * Fixed initialisation bug for first sadb hash bucket that would only manifest itself on platforms where NULL != 0. ++ * ++ * Revision 1.19 2003/01/30 02:32:22 rgb ++ * ++ * Rename SAref table macro names for clarity. ++ * Transmit error code through to caller from callee for better diagnosis of problems. ++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. ++ * ++ * Revision 1.18 2002/10/12 23:11:53 dhr ++ * ++ * [KenB + DHR] more 64-bit cleanup ++ * ++ * Revision 1.17 2002/10/07 18:31:43 rgb ++ * Move field width sanity checks to ipsec_sa.c ++ * ++ * Revision 1.16 2002/09/20 15:41:02 rgb ++ * Re-wrote most of the SAref code to eliminate Entry pointers. ++ * Added SAref code compiler directive switch. ++ * Added a saref test function for testing macros. ++ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). ++ * Split ipsec_sadb_cleanup from new funciton ipsec_sadb_free to avoid problem ++ * of freeing newly created structures when clearing the reftable upon startup ++ * to start from a known state. ++ * Place all ipsec sadb globals into one struct. ++ * Rework saref freelist. ++ * Added memory allocation debugging. ++ * ++ * Revision 1.15 2002/09/20 05:01:44 rgb ++ * Update copyright date. ++ * ++ * Revision 1.14 2002/08/13 19:01:25 mcr ++ * patches from kenb to permit compilation of FreeSWAN on ia64. ++ * des library patched to use proper DES_LONG type for ia64. ++ * ++ * Revision 1.13 2002/07/29 03:06:20 mcr ++ * get rid of variable not used warnings. ++ * ++ * Revision 1.12 2002/07/26 08:48:31 rgb ++ * Added SA ref table code. ++ * ++ * Revision 1.11 2002/06/04 16:48:49 rgb ++ * Tidied up pointer code for processor independance. ++ * ++ * Revision 1.10 2002/05/23 07:16:17 rgb ++ * Added ipsec_sa_put() for releasing an ipsec_sa refcount. ++ * Pointer clean-up. ++ * Added refcount code. ++ * Convert "usecount" to "refcount" to remove ambiguity. ++ * ++ * Revision 1.9 2002/05/14 02:34:49 rgb ++ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion ++ * with "put" usage in the kernel. ++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, ++ * ipsec_sa or ipsec_sa. ++ * Added some preliminary refcount code. ++ * ++ * Revision 1.8 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.7 2002/04/24 07:36:30 mcr ++ * Moved from ./klips/net/ipsec/ipsec_sa.c,v ++ * ++ * Revision 1.6 2002/04/20 00:12:25 rgb ++ * Added esp IV CBC attack fix, disabled. ++ * ++ * Revision 1.5 2002/01/29 17:17:56 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.4 2002/01/29 04:00:52 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.3 2002/01/29 02:13:18 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.2 2001/11/26 09:16:15 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.1.2.2 2001/10/22 21:05:41 mcr ++ * removed phony prototype for des_set_key. ++ * ++ * Revision 1.1.2.1 2001/09/25 02:24:57 mcr ++ * struct tdb -> struct ipsec_sa. ++ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c ++ * ipsec_xform.c removed. header file still contains useful things. ++ * ++ * ++ * ++ * CLONED from ipsec_xform.c: ++ * Revision 1.53 2001/09/08 21:13:34 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.52 2001/06/14 19:35:11 rgb ++ * Update copyright date. ++ * ++ * Revision 1.51 2001/05/30 08:14:03 rgb ++ * Removed vestiges of esp-null transforms. ++ * ++ * Revision 1.50 2001/05/03 19:43:18 rgb ++ * Initialise error return variable. ++ * Update SENDERR macro. ++ * Fix sign of error return code for ipsec_tdbcleanup(). ++ * Use more appropriate return code for ipsec_tdbwipe(). ++ * ++ * Revision 1.49 2001/04/19 18:56:17 rgb ++ * Fixed tdb table locking comments. ++ * ++ * Revision 1.48 2001/02/27 22:24:55 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.47 2000/11/06 04:32:08 rgb ++ * Ditched spin_lock_irqsave in favour of spin_lock_bh. ++ * ++ * Revision 1.46 2000/09/20 16:21:57 rgb ++ * Cleaned up ident string alloc/free. ++ * ++ * Revision 1.45 2000/09/08 19:16:51 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * Removed all references to CONFIG_IPSEC_PFKEYv2. ++ * ++ * Revision 1.44 2000/08/30 05:29:04 rgb ++ * Compiler-define out no longer used tdb_init() in ipsec_xform.c. ++ * ++ * Revision 1.43 2000/08/18 21:30:41 rgb ++ * Purged all tdb_spi, tdb_proto and tdb_dst macros. They are unclear. ++ * ++ * Revision 1.42 2000/08/01 14:51:51 rgb ++ * Removed _all_ remaining traces of DES. ++ * ++ * Revision 1.41 2000/07/28 14:58:31 rgb ++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. ++ * ++ * Revision 1.40 2000/06/28 05:50:11 rgb ++ * Actually set iv_bits. ++ * ++ * Revision 1.39 2000/05/10 23:11:09 rgb ++ * Added netlink debugging output. ++ * Added a cast to quiet down the ntohl bug. ++ * ++ * Revision 1.38 2000/05/10 19:18:42 rgb ++ * Cast output of ntohl so that the broken prototype doesn't make our ++ * compile noisy. ++ * ++ * Revision 1.37 2000/03/16 14:04:59 rgb ++ * Hardwired CONFIG_IPSEC_PFKEYv2 on. ++ * ++ * Revision 1.36 2000/01/26 10:11:28 rgb ++ * Fixed spacing in error text causing run-in words. ++ * ++ * Revision 1.35 2000/01/21 06:17:16 rgb ++ * Tidied up compiler directive indentation for readability. ++ * Added ictx,octx vars for simplification.(kravietz) ++ * Added macros for HMAC padding magic numbers.(kravietz) ++ * Fixed missing key length reporting bug. ++ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in. ++ * ++ * Revision 1.34 1999/12/08 00:04:19 rgb ++ * Fixed SA direction overwriting bug for netlink users. ++ * ++ * Revision 1.33 1999/12/01 22:16:44 rgb ++ * Minor formatting changes in ESP MD5 initialisation. ++ * ++ * Revision 1.32 1999/11/25 09:06:36 rgb ++ * Fixed error return messages, should be returning negative numbers. ++ * Implemented SENDERR macro for propagating error codes. ++ * Added debug message and separate error code for algorithms not compiled ++ * in. ++ * ++ * Revision 1.31 1999/11/23 23:06:26 rgb ++ * Sort out pfkey and freeswan headers, putting them in a library path. ++ * ++ * Revision 1.30 1999/11/18 04:09:20 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * ++ * Revision 1.29 1999/11/17 15:53:40 rgb ++ * Changed all occurrences of #include "../../../lib/freeswan.h" ++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the ++ * klips/net/ipsec/Makefile. ++ * ++ * Revision 1.28 1999/10/18 20:04:01 rgb ++ * Clean-out unused cruft. ++ * ++ * Revision 1.27 1999/10/03 19:01:03 rgb ++ * Spinlock support for 2.3.xx and 2.0.xx kernels. ++ * ++ * Revision 1.26 1999/10/01 16:22:24 rgb ++ * Switch from assignment init. to functional init. of spinlocks. ++ * ++ * Revision 1.25 1999/10/01 15:44:54 rgb ++ * Move spinlock header include to 2.1> scope. ++ * ++ * Revision 1.24 1999/10/01 00:03:46 rgb ++ * Added tdb structure locking. ++ * Minor formatting changes. ++ * Add function to initialize tdb hash table. ++ * ++ * Revision 1.23 1999/05/25 22:42:12 rgb ++ * Add deltdbchain() debugging. ++ * ++ * Revision 1.22 1999/05/25 21:24:31 rgb ++ * Add debugging statements to deltdbchain(). ++ * ++ * Revision 1.21 1999/05/25 03:51:48 rgb ++ * Refix error return code. ++ * ++ * Revision 1.20 1999/05/25 03:34:07 rgb ++ * Fix error return for flush. ++ * ++ * Revision 1.19 1999/05/09 03:25:37 rgb ++ * Fix bug introduced by 2.2 quick-and-dirty patch. ++ * ++ * Revision 1.18 1999/05/05 22:02:32 rgb ++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>. ++ * ++ * Revision 1.17 1999/04/29 15:20:16 rgb ++ * Change gettdb parameter to a pointer to reduce stack loading and ++ * facilitate parameter sanity checking. ++ * Add sanity checking for null pointer arguments. ++ * Add debugging instrumentation. ++ * Add function deltdbchain() which will take care of unlinking, ++ * zeroing and deleting a chain of tdbs. ++ * Add a parameter to tdbcleanup to be able to delete a class of SAs. ++ * tdbwipe now actually zeroes the tdb as well as any of its pointed ++ * structures. ++ * ++ * Revision 1.16 1999/04/16 15:36:29 rgb ++ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing. ++ * ++ * Revision 1.15 1999/04/11 00:29:01 henry ++ * GPL boilerplate ++ * ++ * Revision 1.14 1999/04/06 04:54:28 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.13 1999/02/19 18:23:01 rgb ++ * Nix debug off compile warning. ++ * ++ * Revision 1.12 1999/02/17 16:52:16 rgb ++ * Consolidate satoa()s for space and speed efficiency. ++ * Convert DEBUG_IPSEC to KLIPS_PRINT ++ * Clean out unused cruft. ++ * Ditch NET_IPIP dependancy. ++ * Loop for 3des key setting. ++ * ++ * Revision 1.11 1999/01/26 02:09:05 rgb ++ * Remove ah/esp/IPIP switching on include files. ++ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. ++ * Removed dead code. ++ * Clean up debug code when switched off. ++ * Remove references to INET_GET_PROTOCOL. ++ * Added code exclusion macros to reduce code from unused algorithms. ++ * ++ * Revision 1.10 1999/01/22 06:28:55 rgb ++ * Cruft clean-out. ++ * Put random IV generation in kernel. ++ * Added algorithm switch code. ++ * Enhanced debugging. ++ * 64-bit clean-up. ++ * ++ * Revision 1.9 1998/11/30 13:22:55 rgb ++ * Rationalised all the klips kernel file headers. They are much shorter ++ * now and won't conflict under RH5.2. ++ * ++ * Revision 1.8 1998/11/25 04:59:06 rgb ++ * Add conditionals for no IPIP tunnel code. ++ * Delete commented out code. ++ * ++ * Revision 1.7 1998/10/31 06:50:41 rgb ++ * Convert xform ASCII names to no spaces. ++ * Fixed up comments in #endif directives. ++ * ++ * Revision 1.6 1998/10/19 14:44:28 rgb ++ * Added inclusion of freeswan.h. ++ * sa_id structure implemented and used: now includes protocol. ++ * ++ * Revision 1.5 1998/10/09 04:32:19 rgb ++ * Added 'klips_debug' prefix to all klips printk debug statements. ++ * ++ * Revision 1.4 1998/08/12 00:11:31 rgb ++ * Added new xform functions to the xform table. ++ * Fixed minor debug output spelling error. ++ * ++ * Revision 1.3 1998/07/09 17:45:31 rgb ++ * Clarify algorithm not available message. ++ * ++ * Revision 1.2 1998/06/23 03:00:51 rgb ++ * Check for presence of IPIP protocol if it is setup one way (we don't ++ * know what has been set up the other way and can only assume it will be ++ * symmetrical with the exception of keys). ++ * ++ * Revision 1.1 1998/06/18 21:27:51 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.3 1998/06/11 05:54:59 rgb ++ * Added transform version string pointer to xformsw initialisations. ++ * ++ * Revision 1.2 1998/04/21 21:28:57 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.1 1998/04/09 03:06:13 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:02 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.5 1997/06/03 04:24:48 ji ++ * Added ESP-3DES-MD5-96 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * Added new transforms. ++ * ++ * Revision 0.3 1996/11/20 14:39:04 ji ++ * Minor cleanups. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_sha1.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,219 @@ ++/* ++ * RCSID $Id: ipsec_sha1.c,v 1.9 2004/04/06 02:49:26 mcr Exp $ ++ */ ++ ++/* ++ * The rest of the code is derived from sha1.c by Steve Reid, which is ++ * public domain. ++ * Minor cosmetic changes to accomodate it in the Linux kernel by ji. ++ */ ++ ++#include <asm/byteorder.h> ++#include <linux/string.h> ++ ++#include "openswan/ipsec_sha1.h" ++ ++#if defined(rol) ++#undef rol ++#endif ++ ++#define SHA1HANDSOFF ++ ++#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) ++ ++/* blk0() and blk() perform the initial expand. */ ++/* I got the idea of expanding during the round function from SSLeay */ ++#ifdef __LITTLE_ENDIAN ++#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ ++ |(rol(block->l[i],8)&0x00FF00FF)) ++#else ++#define blk0(i) block->l[i] ++#endif ++#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ ++ ^block->l[(i+2)&15]^block->l[i&15],1)) ++ ++/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ ++#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); ++#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); ++#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); ++#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); ++#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); ++ ++ ++/* Hash a single 512-bit block. This is the core of the algorithm. */ ++ ++void SHA1Transform(__u32 state[5], __u8 buffer[64]) ++{ ++__u32 a, b, c, d, e; ++typedef union { ++ unsigned char c[64]; ++ __u32 l[16]; ++} CHAR64LONG16; ++CHAR64LONG16* block; ++#ifdef SHA1HANDSOFF ++static unsigned char workspace[64]; ++ block = (CHAR64LONG16*)workspace; ++ memcpy(block, buffer, 64); ++#else ++ block = (CHAR64LONG16*)buffer; ++#endif ++ /* Copy context->state[] to working vars */ ++ a = state[0]; ++ b = state[1]; ++ c = state[2]; ++ d = state[3]; ++ e = state[4]; ++ /* 4 rounds of 20 operations each. Loop unrolled. */ ++ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); ++ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); ++ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); ++ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); ++ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); ++ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); ++ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); ++ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); ++ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); ++ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); ++ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); ++ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); ++ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); ++ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); ++ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); ++ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); ++ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); ++ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); ++ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); ++ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); ++ /* Add the working vars back into context.state[] */ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++ state[4] += e; ++ /* Wipe variables */ ++ a = b = c = d = e = 0; ++} ++ ++ ++/* SHA1Init - Initialize new context */ ++ ++void SHA1Init(void *vcontext) ++{ ++ SHA1_CTX* context = vcontext; ++ ++ /* SHA1 initialization constants */ ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xEFCDAB89; ++ context->state[2] = 0x98BADCFE; ++ context->state[3] = 0x10325476; ++ context->state[4] = 0xC3D2E1F0; ++ context->count[0] = context->count[1] = 0; ++} ++ ++ ++/* Run your data through this. */ ++ ++void SHA1Update(void *vcontext, unsigned char* data, __u32 len) ++{ ++ SHA1_CTX* context = vcontext; ++ __u32 i, j; ++ ++ j = context->count[0]; ++ if ((context->count[0] += len << 3) < j) ++ context->count[1]++; ++ context->count[1] += (len>>29); ++ j = (j >> 3) & 63; ++ if ((j + len) > 63) { ++ memcpy(&context->buffer[j], data, (i = 64-j)); ++ SHA1Transform(context->state, context->buffer); ++ for ( ; i + 63 < len; i += 64) { ++ SHA1Transform(context->state, &data[i]); ++ } ++ j = 0; ++ } ++ else i = 0; ++ memcpy(&context->buffer[j], &data[i], len - i); ++} ++ ++ ++/* Add padding and return the message digest. */ ++ ++void SHA1Final(unsigned char digest[20], void *vcontext) ++{ ++ __u32 i, j; ++ unsigned char finalcount[8]; ++ SHA1_CTX* context = vcontext; ++ ++ for (i = 0; i < 8; i++) { ++ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] ++ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ ++ } ++ SHA1Update(context, (unsigned char *)"\200", 1); ++ while ((context->count[0] & 504) != 448) { ++ SHA1Update(context, (unsigned char *)"\0", 1); ++ } ++ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ ++ for (i = 0; i < 20; i++) { ++ digest[i] = (unsigned char) ++ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); ++ } ++ /* Wipe variables */ ++ i = j = 0; ++ memset(context->buffer, 0, 64); ++ memset(context->state, 0, 20); ++ memset(context->count, 0, 8); ++ memset(&finalcount, 0, 8); ++#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ ++ SHA1Transform(context->state, context->buffer); ++#endif ++} ++ ++ ++/* ++ * $Log: ipsec_sha1.c,v $ ++ * Revision 1.9 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.8 2002/09/10 01:45:14 mcr ++ * changed type of MD5_CTX and SHA1_CTX to void * so that ++ * the function prototypes would match, and could be placed ++ * into a pointer to a function. ++ * ++ * Revision 1.7 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.6 2002/04/24 07:36:30 mcr ++ * Moved from ./klips/net/ipsec/ipsec_sha1.c,v ++ * ++ * Revision 1.5 1999/12/13 13:59:13 rgb ++ * Quick fix to argument size to Update bugs. ++ * ++ * Revision 1.4 1999/04/11 00:29:00 henry ++ * GPL boilerplate ++ * ++ * Revision 1.3 1999/04/06 04:54:27 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.2 1999/01/22 06:55:50 rgb ++ * 64-bit clean-up. ++ * ++ * Revision 1.1 1998/06/18 21:27:50 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.2 1998/04/23 20:54:04 rgb ++ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when ++ * verified. ++ * ++ * Revision 1.1 1998/04/09 03:06:11 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:05 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * New transform ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_tunnel.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,2645 @@ ++/* ++ * IPSEC Tunneling code. Heavily based on drivers/net/new_tunnel.c ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++char ipsec_tunnel_c_version[] = "RCSID $Id: ipsec_tunnel.c,v 1.220 2004/04/06 02:49:26 mcr Exp $"; ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/config.h> /* for CONFIG_IP_FORWARD */ ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/tcp.h> /* struct tcphdr */ ++#include <linux/udp.h> /* struct udphdr */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define ip_chk_addr inet_addr_type ++# define IS_MYADDR RTN_LOCAL ++# include <net/dst.h> ++# undef dev_kfree_skb ++# define dev_kfree_skb(a,b) kfree_skb(a) ++# define PHYSDEV_TYPE ++#endif /* NET_21 */ ++#include <asm/checksum.h> ++#include <net/icmp.h> /* icmp_send() */ ++#include <net/ip.h> ++#ifdef NETDEV_23 ++# include <linux/netfilter_ipv4.h> ++#endif /* NETDEV_23 */ ++ ++#include <linux/if_arp.h> ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_life.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_eroute.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_sa.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_xmit.h" ++#include "openswan/ipsec_ipe4.h" ++#include "openswan/ipsec_ah.h" ++#include "openswan/ipsec_esp.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_proto.h" ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++#include <linux/udp.h> ++#endif ++ ++static __u32 zeroes[64]; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_tunnel = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++DEBUG_NO_STATIC int ++ipsec_tunnel_open(struct device *dev) ++{ ++ struct ipsecpriv *prv = dev->priv; ++ ++ /* ++ * Can't open until attached. ++ */ ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_open: " ++ "dev = %s, prv->dev = %s\n", ++ dev->name, prv->dev?prv->dev->name:"NONE"); ++ ++ if (prv->dev == NULL) ++ return -ENODEV; ++ ++ MOD_INC_USE_COUNT; ++ return 0; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_tunnel_close(struct device *dev) ++{ ++ MOD_DEC_USE_COUNT; ++ return 0; ++} ++ ++#ifdef NETDEV_23 ++static inline int ipsec_tunnel_xmit2(struct sk_buff *skb) ++{ ++#ifdef NETDEV_25 /* 2.6 kernels */ ++ return dst_output(skb); ++#else ++ return ip_send(skb); ++#endif ++} ++#endif /* NETDEV_23 */ ++ ++enum ipsec_xmit_value ++ipsec_tunnel_strip_hard_header(struct ipsec_xmit_state *ixs) ++{ ++ /* ixs->physdev->hard_header_len is unreliable and should not be used */ ++ ixs->hard_header_len = (unsigned char *)(ixs->iph) - ixs->skb->data; ++ ++ if(ixs->hard_header_len < 0) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_error:ipsec_xmit_strip_hard_header: " ++ "Negative hard_header_len (%d)?!\n", ixs->hard_header_len); ++ ixs->stats->tx_dropped++; ++ return IPSEC_XMIT_BADHHLEN; ++ } ++ ++ /* while ixs->physdev->hard_header_len is unreliable and ++ * should not be trusted, it accurate and required for ATM, GRE and ++ * some other interfaces to work. Thanks to Willy Tarreau ++ * <willy@w.ods.org>. ++ */ ++ if(ixs->hard_header_len == 0) { /* no hard header present */ ++ ixs->hard_header_stripped = 1; ++ ixs->hard_header_len = ixs->physdev->hard_header_len; ++ } ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if (debug_tunnel & DB_TN_XMIT) { ++ int i; ++ char c; ++ ++ printk(KERN_INFO "klips_debug:ipsec_xmit_strip_hard_header: " ++ ">>> skb->len=%ld hard_header_len:%d", ++ (unsigned long int)ixs->skb->len, ixs->hard_header_len); ++ c = ' '; ++ for (i=0; i < ixs->hard_header_len; i++) { ++ printk("%c%02x", c, ixs->skb->data[i]); ++ c = ':'; ++ } ++ printk(" \n"); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_strip_hard_header: " ++ "Original head,tailroom: %d,%d\n", ++ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); ++ ++ return IPSEC_XMIT_OK; ++} ++ ++enum ipsec_xmit_value ++ipsec_tunnel_SAlookup(struct ipsec_xmit_state *ixs) ++{ ++ /* ++ * First things first -- look us up in the erouting tables. ++ */ ++ ixs->matcher.sen_len = sizeof (struct sockaddr_encap); ++ ixs->matcher.sen_family = AF_ENCAP; ++ ixs->matcher.sen_type = SENT_IP4; ++ ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr; ++ ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr; ++ ixs->matcher.sen_proto = ixs->iph->protocol; ++ ipsec_extract_ports(ixs->iph, &ixs->matcher); ++ ++ /* ++ * The spinlock is to prevent any other process from accessing or deleting ++ * the eroute while we are using and updating it. ++ */ ++ spin_lock(&eroute_lock); ++ ++ ixs->eroute = ipsec_findroute(&ixs->matcher); ++ ++ if(ixs->iph->protocol == IPPROTO_UDP) { ++ if(ixs->skb->sk) { ++ ixs->sport=ntohs(ixs->skb->sk->sport); ++ ixs->dport=ntohs(ixs->skb->sk->dport); ++ } else if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 && ++ ((ixs->skb->len - ixs->hard_header_len) >= ++ ((ixs->iph->ihl << 2) + sizeof(struct udphdr)))) { ++ ixs->sport=ntohs(((struct udphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2)))->source); ++ ixs->dport=ntohs(((struct udphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl<<2)))->dest); ++ } else { ++ ixs->sport=0; ixs->dport=0; ++ } ++ } ++ ++ /* default to a %drop eroute */ ++ ixs->outgoing_said.proto = IPPROTO_INT; ++ ixs->outgoing_said.spi = htonl(SPI_DROP); ++ ixs->outgoing_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY; ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_SAlookup: " ++ "checking for local udp/500 IKE packet " ++ "saddr=%x, er=0p%p, daddr=%x, er_dst=%x, proto=%d sport=%d dport=%d\n", ++ ntohl((unsigned int)ixs->iph->saddr), ++ ixs->eroute, ++ ntohl((unsigned int)ixs->iph->daddr), ++ ixs->eroute ? ntohl((unsigned int)ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr) : 0, ++ ixs->iph->protocol, ++ ixs->sport, ++ ixs->dport); ++ ++ /* ++ * Quick cheat for now...are we udp/500? If so, let it through ++ * without interference since it is most likely an IKE packet. ++ */ ++ ++ if (ip_chk_addr((unsigned long)ixs->iph->saddr) == IS_MYADDR ++ && (!ixs->eroute ++ || ixs->iph->daddr == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr ++ || INADDR_ANY == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr) ++ ++ && ((ixs->sport == 500) || (ixs->sport == 4500))) { ++ /* Whatever the eroute, this is an IKE message ++ * from us (i.e. not being forwarded). ++ * Furthermore, if there is a tunnel eroute, ++ * the destination is the peer for this eroute. ++ * So %pass the packet: modify the default %drop. ++ */ ++ ixs->outgoing_said.spi = htonl(SPI_PASS); ++ if(!(ixs->skb->sk) && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0)) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_SAlookup: " ++ "local UDP/500 (probably IKE) passthrough: base fragment, rest of fragments will probably get filtered.\n"); ++ } ++ } else if (ixs->eroute) { ++ ixs->eroute->er_count++; ++ ixs->eroute->er_lasttime = jiffies/HZ; ++ if(ixs->eroute->er_said.proto==IPPROTO_INT ++ && ixs->eroute->er_said.spi==htonl(SPI_HOLD)) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_SAlookup: " ++ "shunt SA of HOLD: skb stored in HOLD.\n"); ++ if(ixs->eroute->er_last != NULL) { ++ kfree_skb(ixs->eroute->er_last); ++ } ++ ixs->eroute->er_last = ixs->skb; ++ ixs->skb = NULL; ++ ixs->stats->tx_dropped++; ++ spin_unlock(&eroute_lock); ++ return IPSEC_XMIT_STOLEN; ++ } ++ ixs->outgoing_said = ixs->eroute->er_said; ++ ixs->eroute_pid = ixs->eroute->er_pid; ++ /* Copy of the ident for the TRAP/TRAPSUBNET eroutes */ ++ if(ixs->outgoing_said.proto==IPPROTO_INT ++ && (ixs->outgoing_said.spi==htonl(SPI_TRAP) ++ || (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)))) { ++ int len; ++ ++ ixs->ips.ips_ident_s.type = ixs->eroute->er_ident_s.type; ++ ixs->ips.ips_ident_s.id = ixs->eroute->er_ident_s.id; ++ ixs->ips.ips_ident_s.len = ixs->eroute->er_ident_s.len; ++ if (ixs->ips.ips_ident_s.len) { ++ len = ixs->ips.ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_SAlookup: " ++ "allocating %d bytes for ident_s shunt SA of HOLD: skb stored in HOLD.\n", ++ len); ++ if ((ixs->ips.ips_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) { ++ printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " ++ "Failed, tried to allocate %d bytes for source ident.\n", ++ len); ++ ixs->stats->tx_dropped++; ++ spin_unlock(&eroute_lock); ++ return IPSEC_XMIT_ERRMEMALLOC; ++ } ++ memcpy(ixs->ips.ips_ident_s.data, ixs->eroute->er_ident_s.data, len); ++ } ++ ixs->ips.ips_ident_d.type = ixs->eroute->er_ident_d.type; ++ ixs->ips.ips_ident_d.id = ixs->eroute->er_ident_d.id; ++ ixs->ips.ips_ident_d.len = ixs->eroute->er_ident_d.len; ++ if (ixs->ips.ips_ident_d.len) { ++ len = ixs->ips.ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_SAlookup: " ++ "allocating %d bytes for ident_d shunt SA of HOLD: skb stored in HOLD.\n", ++ len); ++ if ((ixs->ips.ips_ident_d.data = kmalloc(len, GFP_ATOMIC)) == NULL) { ++ printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " ++ "Failed, tried to allocate %d bytes for dest ident.\n", ++ len); ++ ixs->stats->tx_dropped++; ++ spin_unlock(&eroute_lock); ++ return IPSEC_XMIT_ERRMEMALLOC; ++ } ++ memcpy(ixs->ips.ips_ident_d.data, ixs->eroute->er_ident_d.data, len); ++ } ++ } ++ } ++ ++ spin_unlock(&eroute_lock); ++ return IPSEC_XMIT_OK; ++} ++ ++enum ipsec_xmit_value ++ipsec_tunnel_restore_hard_header(struct ipsec_xmit_state*ixs) ++{ ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_restore_hard_header: " ++ "After recursive xforms -- head,tailroom: %d,%d\n", ++ skb_headroom(ixs->skb), ++ skb_tailroom(ixs->skb)); ++ ++ if(ixs->saved_header) { ++ if(skb_headroom(ixs->skb) < ixs->hard_header_len) { ++ printk(KERN_WARNING ++ "klips_error:ipsec_xmit_restore_hard_header: " ++ "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", ++ ixs->hard_header_len, ++ skb_headroom(ixs->skb)); ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_PUSHPULLERR; ++ ++ } ++ skb_push(ixs->skb, ixs->hard_header_len); ++ { ++ int i; ++ for (i = 0; i < ixs->hard_header_len; i++) { ++ ixs->skb->data[i] = ixs->saved_header[i]; ++ } ++ } ++ } ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if (ixs->natt_type && ixs->natt_head) { ++ struct iphdr *ipp = ixs->skb->nh.iph; ++ struct udphdr *udp; ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "encapsuling packet into UDP (NAT-Traversal) (%d %d)\n", ++ ixs->natt_type, ixs->natt_head); ++ ++ ixs->iphlen = ipp->ihl << 2; ++ ipp->tot_len = ++ htons(ntohs(ipp->tot_len) + ixs->natt_head); ++ if(skb_tailroom(ixs->skb) < ixs->natt_head) { ++ printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: " ++ "tried to skb_put %d, %d available. " ++ "This should never happen, please report.\n", ++ ixs->natt_head, ++ skb_tailroom(ixs->skb)); ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESPUDP; ++ } ++ skb_put(ixs->skb, ixs->natt_head); ++ ++ udp = (struct udphdr *)((char *)ipp + ixs->iphlen); ++ ++ /* move ESP hdr after UDP hdr */ ++ memmove((void *)((char *)udp + ixs->natt_head), ++ (void *)(udp), ++ ntohs(ipp->tot_len) - ixs->iphlen - ixs->natt_head); ++ ++ /* clear UDP & Non-IKE Markers (if any) */ ++ memset(udp, 0, ixs->natt_head); ++ ++ /* fill UDP with usefull informations ;-) */ ++ udp->source = htons(ixs->natt_sport); ++ udp->dest = htons(ixs->natt_dport); ++ udp->len = htons(ntohs(ipp->tot_len) - ixs->iphlen); ++ ++ /* set protocol */ ++ ipp->protocol = IPPROTO_UDP; ++ ++ /* fix IP checksum */ ++ ipp->check = 0; ++ ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); ++ } ++#endif ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_restore_hard_header: " ++ "With hard_header, final head,tailroom: %d,%d\n", ++ skb_headroom(ixs->skb), ++ skb_tailroom(ixs->skb)); ++ ++ return IPSEC_XMIT_OK; ++} ++ ++enum ipsec_xmit_value ++ipsec_tunnel_send(struct ipsec_xmit_state*ixs) ++{ ++#ifdef NETDEV_25 ++ struct flowi fl; ++#endif ++ ++#ifdef NET_21 /* 2.2 and 2.4 kernels */ ++ /* new route/dst cache code from James Morris */ ++ ixs->skb->dev = ixs->physdev; ++#ifdef NETDEV_25 ++ fl.oif = ixs->physdev->iflink; ++ fl.nl_u.ip4_u.daddr = ixs->skb->nh.iph->daddr; ++ fl.nl_u.ip4_u.saddr = ixs->pass ? 0 : ixs->skb->nh.iph->saddr; ++ fl.nl_u.ip4_u.tos = RT_TOS(ixs->skb->nh.iph->tos); ++ fl.proto = ixs->skb->nh.iph->protocol; ++ if ((ixs->error = ip_route_output_key(&ixs->route, &fl))) { ++#else ++ /*skb_orphan(ixs->skb);*/ ++ if((ixs->error = ip_route_output(&ixs->route, ++ ixs->skb->nh.iph->daddr, ++ ixs->pass ? 0 : ixs->skb->nh.iph->saddr, ++ RT_TOS(ixs->skb->nh.iph->tos), ++ /* mcr->rgb: should this be 0 instead? */ ++ ixs->physdev->iflink))) { ++#endif ++ ixs->stats->tx_errors++; ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_send: " ++ "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n", ++ ixs->error, ++ ixs->route->u.dst.dev->name); ++ return IPSEC_XMIT_ROUTEERR; ++ } ++ if(ixs->dev == ixs->route->u.dst.dev) { ++ ip_rt_put(ixs->route); ++ /* This is recursion, drop it. */ ++ ixs->stats->tx_errors++; ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_send: " ++ "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", ++ ixs->dev->name); ++ return IPSEC_XMIT_RECURSDETECT; ++ } ++ dst_release(ixs->skb->dst); ++ ixs->skb->dst = &ixs->route->u.dst; ++ ixs->stats->tx_bytes += ixs->skb->len; ++ if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { ++ ixs->stats->tx_errors++; ++ printk(KERN_WARNING ++ "klips_error:ipsec_xmit_send: " ++ "tried to __skb_pull nh-data=%ld, %d available. This should never happen, please report.\n", ++ (unsigned long)(ixs->skb->nh.raw - ixs->skb->data), ++ ixs->skb->len); ++ return IPSEC_XMIT_PUSHPULLERR; ++ } ++ __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data); ++#ifdef SKB_RESET_NFCT ++ if(!ixs->pass) { ++ nf_conntrack_put(ixs->skb->nfct); ++ ixs->skb->nfct = NULL; ++ } ++#ifdef CONFIG_NETFILTER_DEBUG ++ ixs->skb->nf_debug = 0; ++#endif /* CONFIG_NETFILTER_DEBUG */ ++#endif /* SKB_RESET_NFCT */ ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_send: " ++ "...done, calling ip_send() on device:%s\n", ++ ixs->skb->dev ? ixs->skb->dev->name : "NULL"); ++ KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->skb->nh.iph); ++#ifdef NETDEV_23 /* 2.4 kernels */ ++ { ++ int err; ++ ++ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev, ++ ipsec_tunnel_xmit2); ++ if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { ++ if(net_ratelimit()) ++ printk(KERN_ERR ++ "klips_error:ipsec_xmit_send: " ++ "ip_send() failed, err=%d\n", ++ -err); ++ ixs->stats->tx_errors++; ++ ixs->stats->tx_aborted_errors++; ++ ixs->skb = NULL; ++ return IPSEC_XMIT_IPSENDFAILURE; ++ } ++ } ++#else /* NETDEV_23 */ /* 2.2 kernels */ ++ ip_send(ixs->skb); ++#endif /* NETDEV_23 */ ++#else /* NET_21 */ /* 2.0 kernels */ ++ ixs->skb->arp = 1; ++ /* ISDN/ASYNC PPP from Matjaz Godec. */ ++ /* skb->protocol = htons(ETH_P_IP); */ ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_send: " ++ "...done, calling dev_queue_xmit() or ip_fragment().\n"); ++ IP_SEND(ixs->skb, ixs->physdev); ++#endif /* NET_21 */ ++ ixs->stats->tx_packets++; ++ ++ ixs->skb = NULL; ++ ++ return IPSEC_XMIT_OK; ++} ++ ++void ++ipsec_tunnel_cleanup(struct ipsec_xmit_state*ixs) ++{ ++#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) ++ netif_wake_queue(ixs->dev); ++#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ ++ ixs->dev->tbusy = 0; ++#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ ++ if(ixs->saved_header) { ++ kfree(ixs->saved_header); ++ } ++ if(ixs->skb) { ++ dev_kfree_skb(ixs->skb, FREE_WRITE); ++ } ++ if(ixs->oskb) { ++ dev_kfree_skb(ixs->oskb, FREE_WRITE); ++ } ++ if (ixs->ips.ips_ident_s.data) { ++ kfree(ixs->ips.ips_ident_s.data); ++ } ++ if (ixs->ips.ips_ident_d.data) { ++ kfree(ixs->ips.ips_ident_d.data); ++ } ++} ++ ++/* ++ * This function assumes it is being called from dev_queue_xmit() ++ * and that skb is filled properly by that function. ++ */ ++int ++ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev) ++{ ++ struct ipsec_xmit_state ixs_mem; ++ struct ipsec_xmit_state *ixs = &ixs_mem; ++ enum ipsec_xmit_value stat; ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ ixs->natt_type = 0, ixs->natt_head = 0; ++ ixs->natt_sport = 0, ixs->natt_dport = 0; ++#endif ++ ++ memset((caddr_t)ixs, 0, sizeof(*ixs)); ++ ixs->oskb = NULL; ++ ixs->saved_header = NULL; /* saved copy of the hard header */ ++ ixs->route = NULL; ++ memset((caddr_t)&(ixs->ips), 0, sizeof(ixs->ips)); ++ ixs->dev = dev; ++ ixs->skb = skb; ++ ++ stat = ipsec_xmit_sanity_check_dev(ixs); ++ if(stat != IPSEC_XMIT_OK) { ++ goto cleanup; ++ } ++ ++ stat = ipsec_xmit_sanity_check_skb(ixs); ++ if(stat != IPSEC_XMIT_OK) { ++ goto cleanup; ++ } ++ ++ stat = ipsec_tunnel_strip_hard_header(ixs); ++ if(stat != IPSEC_XMIT_OK) { ++ goto cleanup; ++ } ++ ++ stat = ipsec_tunnel_SAlookup(ixs); ++ if(stat != IPSEC_XMIT_OK) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_tunnel_start_xmit: SAlookup failed: %d\n", ++ stat); ++ goto cleanup; ++ } ++ ++ ixs->innersrc = ixs->iph->saddr; ++ /* start encapsulation loop here XXX */ ++ do { ++ stat = ipsec_xmit_encap_bundle(ixs); ++ if(stat != IPSEC_XMIT_OK) { ++ if(stat == IPSEC_XMIT_PASS) { ++ goto bypass; ++ } ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_tunnel_start_xmit: encap_bundle failed: %d\n", ++ stat); ++ goto cleanup; ++ } ++ ++ ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr; ++ ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr; ++ ixs->matcher.sen_proto = ixs->iph->protocol; ++ ipsec_extract_ports(ixs->iph, &ixs->matcher); ++ ++ spin_lock(&eroute_lock); ++ ixs->eroute = ipsec_findroute(&ixs->matcher); ++ if(ixs->eroute) { ++ ixs->outgoing_said = ixs->eroute->er_said; ++ ixs->eroute_pid = ixs->eroute->er_pid; ++ ixs->eroute->er_count++; ++ ixs->eroute->er_lasttime = jiffies/HZ; ++ } ++ spin_unlock(&eroute_lock); ++ ++ KLIPS_PRINT((debug_tunnel & DB_TN_XMIT) && ++ /* ((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc)) */ ++ (ixs->orgedst != ixs->outgoing_said.dst.u.v4.sin_addr.s_addr) && ++ ixs->outgoing_said.dst.u.v4.sin_addr.s_addr && ++ ixs->eroute, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "We are recursing here.\n"); ++ ++ } while(/*((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc))*/ ++ (ixs->orgedst != ixs->outgoing_said.dst.u.v4.sin_addr.s_addr) && ++ ixs->outgoing_said.dst.u.v4.sin_addr.s_addr && ++ ixs->eroute); ++ ++ stat = ipsec_tunnel_restore_hard_header(ixs); ++ if(stat != IPSEC_XMIT_OK) { ++ goto cleanup; ++ } ++ ++ bypass: ++ stat = ipsec_tunnel_send(ixs); ++ ++ cleanup: ++ ipsec_tunnel_cleanup(ixs); ++ ++ return 0; ++} ++ ++DEBUG_NO_STATIC struct net_device_stats * ++ipsec_tunnel_get_stats(struct device *dev) ++{ ++ return &(((struct ipsecpriv *)(dev->priv))->mystats); ++} ++ ++/* ++ * Revectored calls. ++ * For each of these calls, a field exists in our private structure. ++ */ ++ ++DEBUG_NO_STATIC int ++ipsec_tunnel_hard_header(struct sk_buff *skb, struct device *dev, ++ unsigned short type, void *daddr, void *saddr, unsigned len) ++{ ++ struct ipsecpriv *prv = dev->priv; ++ struct device *tmp; ++ int ret; ++ struct net_device_stats *stats; /* This device's statistics */ ++ ++ if(skb == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_hard_header: " ++ "no skb...\n"); ++ return -ENODATA; ++ } ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_hard_header: " ++ "no device...\n"); ++ return -ENODEV; ++ } ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_hard_header: " ++ "skb->dev=%s dev=%s.\n", ++ skb->dev ? skb->dev->name : "NULL", ++ dev->name); ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_hard_header: " ++ "no private space associated with dev=%s\n", ++ dev->name ? dev->name : "NULL"); ++ return -ENODEV; ++ } ++ ++ stats = (struct net_device_stats *) &(prv->mystats); ++ ++ if(prv->dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_hard_header: " ++ "no physical device associated with dev=%s\n", ++ dev->name ? dev->name : "NULL"); ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++ /* check if we have to send a IPv6 packet. It might be a Router ++ Solicitation, where the building of the packet happens in ++ reverse order: ++ 1. ll hdr, ++ 2. IPv6 hdr, ++ 3. ICMPv6 hdr ++ -> skb->nh.raw is still uninitialized when this function is ++ called!! If this is no IPv6 packet, we can print debugging ++ messages, otherwise we skip all debugging messages and just ++ build the ll header */ ++ if(type != ETH_P_IPV6) { ++ /* execute this only, if we don't have to build the ++ header for a IPv6 packet */ ++ if(!prv->hard_header) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_hard_header: " ++ "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", ++ saddr, ++ daddr, ++ len, ++ type, ++ dev->name); ++#ifdef NET_21 ++ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->nh.iph->saddr), ++ (__u32)ntohl(skb->nh.iph->daddr) ); ++#else /* NET_21 */ ++ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->ip_hdr->saddr), ++ (__u32)ntohl(skb->ip_hdr->daddr) ); ++#endif /* NET_21 */ ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++#define da ((struct device *)(prv->dev))->dev_addr ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_hard_header: " ++ "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ", ++ saddr, ++ daddr, ++ len, ++ type, ++ dev->name, ++ prv->dev->name, ++ da[0], da[1], da[2], da[3], da[4], da[5]); ++#ifdef NET_21 ++ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->nh.iph->saddr), ++ (__u32)ntohl(skb->nh.iph->daddr) ); ++#else /* NET_21 */ ++ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->ip_hdr->saddr), ++ (__u32)ntohl(skb->ip_hdr->daddr) ); ++#endif /* NET_21 */ ++ } else { ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_hard_header: " ++ "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); ++ } ++ tmp = skb->dev; ++ skb->dev = prv->dev; ++ ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); ++ skb->dev = tmp; ++ return ret; ++} ++ ++DEBUG_NO_STATIC int ++#ifdef NET_21 ++ipsec_tunnel_rebuild_header(struct sk_buff *skb) ++#else /* NET_21 */ ++ipsec_tunnel_rebuild_header(void *buff, struct device *dev, ++ unsigned long raddr, struct sk_buff *skb) ++#endif /* NET_21 */ ++{ ++ struct ipsecpriv *prv = skb->dev->priv; ++ struct device *tmp; ++ int ret; ++ struct net_device_stats *stats; /* This device's statistics */ ++ ++ if(skb->dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_rebuild_header: " ++ "no device..."); ++ return -ENODEV; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_rebuild_header: " ++ "no private space associated with dev=%s", ++ skb->dev->name ? skb->dev->name : "NULL"); ++ return -ENODEV; ++ } ++ ++ stats = (struct net_device_stats *) &(prv->mystats); ++ ++ if(prv->dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_rebuild_header: " ++ "no physical device associated with dev=%s", ++ skb->dev->name ? skb->dev->name : "NULL"); ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++ if(!prv->rebuild_header) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_rebuild_header: " ++ "physical device has been detached, packet dropped skb->dev=%s->NULL ", ++ skb->dev->name); ++#ifdef NET_21 ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->nh.iph->saddr), ++ (__u32)ntohl(skb->nh.iph->daddr) ); ++#else /* NET_21 */ ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->ip_hdr->saddr), ++ (__u32)ntohl(skb->ip_hdr->daddr) ); ++#endif /* NET_21 */ ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel: " ++ "Revectored rebuild_header dev=%s->%s ", ++ skb->dev->name, prv->dev->name); ++#ifdef NET_21 ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->nh.iph->saddr), ++ (__u32)ntohl(skb->nh.iph->daddr) ); ++#else /* NET_21 */ ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "ip=%08x->%08x\n", ++ (__u32)ntohl(skb->ip_hdr->saddr), ++ (__u32)ntohl(skb->ip_hdr->daddr) ); ++#endif /* NET_21 */ ++ tmp = skb->dev; ++ skb->dev = prv->dev; ++ ++#ifdef NET_21 ++ ret = prv->rebuild_header(skb); ++#else /* NET_21 */ ++ ret = prv->rebuild_header(buff, prv->dev, raddr, skb); ++#endif /* NET_21 */ ++ skb->dev = tmp; ++ return ret; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_tunnel_set_mac_address(struct device *dev, void *addr) ++{ ++ struct ipsecpriv *prv = dev->priv; ++ ++ struct net_device_stats *stats; /* This device's statistics */ ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_set_mac_address: " ++ "no device..."); ++ return -ENODEV; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_set_mac_address: " ++ "no private space associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ return -ENODEV; ++ } ++ ++ stats = (struct net_device_stats *) &(prv->mystats); ++ ++ if(prv->dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_set_mac_address: " ++ "no physical device associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ stats->tx_dropped++; ++ return -ENODEV; ++ } ++ ++ if(!prv->set_mac_address) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_set_mac_address: " ++ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", ++ dev->name); ++ return -ENODEV; ++ } ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_set_mac_address: " ++ "Revectored dev=%s->%s addr=0p%p\n", ++ dev->name, prv->dev->name, addr); ++ return prv->set_mac_address(prv->dev, addr); ++ ++} ++ ++#ifndef NET_21 ++DEBUG_NO_STATIC void ++ipsec_tunnel_cache_bind(struct hh_cache **hhp, struct device *dev, ++ unsigned short htype, __u32 daddr) ++{ ++ struct ipsecpriv *prv = dev->priv; ++ ++ struct net_device_stats *stats; /* This device's statistics */ ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_cache_bind: " ++ "no device..."); ++ return; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_cache_bind: " ++ "no private space associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ return; ++ } ++ ++ stats = (struct net_device_stats *) &(prv->mystats); ++ ++ if(prv->dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_cache_bind: " ++ "no physical device associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ stats->tx_dropped++; ++ return; ++ } ++ ++ if(!prv->header_cache_bind) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_cache_bind: " ++ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", ++ dev->name); ++ stats->tx_dropped++; ++ return; ++ } ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_cache_bind: " ++ "Revectored \n"); ++ prv->header_cache_bind(hhp, prv->dev, htype, daddr); ++ return; ++} ++#endif /* !NET_21 */ ++ ++ ++DEBUG_NO_STATIC void ++ipsec_tunnel_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr) ++{ ++ struct ipsecpriv *prv = dev->priv; ++ ++ struct net_device_stats *stats; /* This device's statistics */ ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_cache_update: " ++ "no device..."); ++ return; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_cache_update: " ++ "no private space associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ return; ++ } ++ ++ stats = (struct net_device_stats *) &(prv->mystats); ++ ++ if(prv->dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_cache_update: " ++ "no physical device associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ stats->tx_dropped++; ++ return; ++ } ++ ++ if(!prv->header_cache_update) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_cache_update: " ++ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", ++ dev->name); ++ return; ++ } ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel: " ++ "Revectored cache_update\n"); ++ prv->header_cache_update(hh, prv->dev, haddr); ++ return; ++} ++ ++#ifdef NET_21 ++DEBUG_NO_STATIC int ++ipsec_tunnel_neigh_setup(struct neighbour *n) ++{ ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_neigh_setup:\n"); ++ ++ if (n->nud_state == NUD_NONE) { ++ n->ops = &arp_broken_ops; ++ n->output = n->ops->output; ++ } ++ return 0; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_tunnel_neigh_setup_dev(struct device *dev, struct neigh_parms *p) ++{ ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_neigh_setup_dev: " ++ "setting up %s\n", ++ dev ? dev->name : "NULL"); ++ ++ if (p->tbl->family == AF_INET) { ++ p->neigh_setup = ipsec_tunnel_neigh_setup; ++ p->ucast_probes = 0; ++ p->mcast_probes = 0; ++ } ++ return 0; ++} ++#endif /* NET_21 */ ++ ++/* ++ * We call the attach routine to attach another device. ++ */ ++ ++DEBUG_NO_STATIC int ++ipsec_tunnel_attach(struct device *dev, struct device *physdev) ++{ ++ int i; ++ struct ipsecpriv *prv = dev->priv; ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_attach: " ++ "no device..."); ++ return -ENODEV; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_attach: " ++ "no private space associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ return -ENODATA; ++ } ++ ++ prv->dev = physdev; ++ prv->hard_start_xmit = physdev->hard_start_xmit; ++ prv->get_stats = physdev->get_stats; ++ ++ if (physdev->hard_header) { ++ prv->hard_header = physdev->hard_header; ++ dev->hard_header = ipsec_tunnel_hard_header; ++ } else ++ dev->hard_header = NULL; ++ ++ if (physdev->rebuild_header) { ++ prv->rebuild_header = physdev->rebuild_header; ++ dev->rebuild_header = ipsec_tunnel_rebuild_header; ++ } else ++ dev->rebuild_header = NULL; ++ ++ if (physdev->set_mac_address) { ++ prv->set_mac_address = physdev->set_mac_address; ++ dev->set_mac_address = ipsec_tunnel_set_mac_address; ++ } else ++ dev->set_mac_address = NULL; ++ ++#ifndef NET_21 ++ if (physdev->header_cache_bind) { ++ prv->header_cache_bind = physdev->header_cache_bind; ++ dev->header_cache_bind = ipsec_tunnel_cache_bind; ++ } else ++ dev->header_cache_bind = NULL; ++#endif /* !NET_21 */ ++ ++ if (physdev->header_cache_update) { ++ prv->header_cache_update = physdev->header_cache_update; ++ dev->header_cache_update = ipsec_tunnel_cache_update; ++ } else ++ dev->header_cache_update = NULL; ++ ++ dev->hard_header_len = physdev->hard_header_len; ++ ++#ifdef NET_21 ++/* prv->neigh_setup = physdev->neigh_setup; */ ++ dev->neigh_setup = ipsec_tunnel_neigh_setup_dev; ++#endif /* NET_21 */ ++ dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */ ++ prv->mtu = physdev->mtu; ++ ++#ifdef PHYSDEV_TYPE ++ dev->type = physdev->type; /* ARPHRD_TUNNEL; */ ++#endif /* PHYSDEV_TYPE */ ++ ++ dev->addr_len = physdev->addr_len; ++ for (i=0; i<dev->addr_len; i++) { ++ dev->dev_addr[i] = physdev->dev_addr[i]; ++ } ++#ifdef CONFIG_IPSEC_DEBUG ++ if(debug_tunnel & DB_TN_INIT) { ++ printk(KERN_INFO "klips_debug:ipsec_tunnel_attach: " ++ "physical device %s being attached has HW address: %2x", ++ physdev->name, physdev->dev_addr[0]); ++ for (i=1; i < physdev->addr_len; i++) { ++ printk(":%02x", physdev->dev_addr[i]); ++ } ++ printk("\n"); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ return 0; ++} ++ ++/* ++ * We call the detach routine to detach the ipsec tunnel from another device. ++ */ ++ ++DEBUG_NO_STATIC int ++ipsec_tunnel_detach(struct device *dev) ++{ ++ int i; ++ struct ipsecpriv *prv = dev->priv; ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_detach: " ++ "no device..."); ++ return -ENODEV; ++ } ++ ++ if(prv == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, ++ "klips_debug:ipsec_tunnel_detach: " ++ "no private space associated with dev=%s", ++ dev->name ? dev->name : "NULL"); ++ return -ENODATA; ++ } ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_detach: " ++ "physical device %s being detached from virtual device %s\n", ++ prv->dev ? prv->dev->name : "NULL", ++ dev->name); ++ ++ ipsec_dev_put(prv->dev); ++ prv->dev = NULL; ++ prv->hard_start_xmit = NULL; ++ prv->get_stats = NULL; ++ ++ prv->hard_header = NULL; ++#ifdef DETACH_AND_DOWN ++ dev->hard_header = NULL; ++#endif /* DETACH_AND_DOWN */ ++ ++ prv->rebuild_header = NULL; ++#ifdef DETACH_AND_DOWN ++ dev->rebuild_header = NULL; ++#endif /* DETACH_AND_DOWN */ ++ ++ prv->set_mac_address = NULL; ++#ifdef DETACH_AND_DOWN ++ dev->set_mac_address = NULL; ++#endif /* DETACH_AND_DOWN */ ++ ++#ifndef NET_21 ++ prv->header_cache_bind = NULL; ++#ifdef DETACH_AND_DOWN ++ dev->header_cache_bind = NULL; ++#endif /* DETACH_AND_DOWN */ ++#endif /* !NET_21 */ ++ ++ prv->header_cache_update = NULL; ++#ifdef DETACH_AND_DOWN ++ dev->header_cache_update = NULL; ++#endif /* DETACH_AND_DOWN */ ++ ++#ifdef NET_21 ++/* prv->neigh_setup = NULL; */ ++#ifdef DETACH_AND_DOWN ++ dev->neigh_setup = NULL; ++#endif /* DETACH_AND_DOWN */ ++#endif /* NET_21 */ ++ dev->hard_header_len = 0; ++#ifdef DETACH_AND_DOWN ++ dev->mtu = 0; ++#endif /* DETACH_AND_DOWN */ ++ prv->mtu = 0; ++ for (i=0; i<MAX_ADDR_LEN; i++) { ++ dev->dev_addr[i] = 0; ++ } ++ dev->addr_len = 0; ++#ifdef PHYSDEV_TYPE ++ dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ ++#endif /* PHYSDEV_TYPE */ ++ ++ return 0; ++} ++ ++/* ++ * We call the clear routine to detach all ipsec tunnels from other devices. ++ */ ++DEBUG_NO_STATIC int ++ipsec_tunnel_clear(void) ++{ ++ int i; ++ struct device *ipsecdev = NULL, *prvdev; ++ struct ipsecpriv *prv; ++ char name[9]; ++ int ret; ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_clear: .\n"); ++ ++ for(i = 0; i < IPSEC_NUM_IF; i++) { ++ ipsecdev = ipsecdevices[i]; ++ if(ipsecdev != NULL) { ++ if((prv = (struct ipsecpriv *)(ipsecdev->priv))) { ++ prvdev = (struct device *)(prv->dev); ++ if(prvdev) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_clear: " ++ "physical device for device %s is %s\n", ++ name, prvdev->name); ++ if((ret = ipsec_tunnel_detach(ipsecdev))) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_clear: " ++ "error %d detatching device %s from device %s.\n", ++ ret, name, prvdev->name); ++ return ret; ++ } ++ } ++ } ++ } ++ } ++ return 0; ++} ++ ++DEBUG_NO_STATIC int ++ipsec_tunnel_ioctl(struct device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data; ++ struct ipsecpriv *prv = dev->priv; ++ struct device *them; /* physical device */ ++#ifdef CONFIG_IP_ALIAS ++ char *colon; ++ char realphysname[IFNAMSIZ]; ++#endif /* CONFIG_IP_ALIAS */ ++ ++ if(dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "device not supplied.\n"); ++ return -ENODEV; ++ } ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "tncfg service call #%d for dev=%s\n", ++ cmd, ++ dev->name ? dev->name : "NULL"); ++ switch (cmd) { ++ /* attach a virtual ipsec? device to a physical device */ ++ case IPSEC_SET_DEV: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "calling ipsec_tunnel_attatch...\n"); ++#ifdef CONFIG_IP_ALIAS ++ /* If this is an IP alias interface, get its real physical name */ ++ strncpy(realphysname, cf->cf_name, IFNAMSIZ); ++ realphysname[IFNAMSIZ-1] = 0; ++ colon = strchr(realphysname, ':'); ++ if (colon) *colon = 0; ++ them = ipsec_dev_get(realphysname); ++#else /* CONFIG_IP_ALIAS */ ++ them = ipsec_dev_get(cf->cf_name); ++#endif /* CONFIG_IP_ALIAS */ ++ ++ if (them == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "physical device %s requested is null\n", ++ cf->cf_name); ++ ipsec_dev_put(them); ++ return -ENXIO; ++ } ++ ++#if 0 ++ if (them->flags & IFF_UP) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "physical device %s requested is not up.\n", ++ cf->cf_name); ++ ipsec_dev_put(them); ++ return -ENXIO; ++ } ++#endif ++ ++ if (prv && prv->dev) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "virtual device is already connected to %s.\n", ++ prv->dev->name ? prv->dev->name : "NULL"); ++ ipsec_dev_put(them); ++ return -EBUSY; ++ } ++ return ipsec_tunnel_attach(dev, them); ++ ++ case IPSEC_DEL_DEV: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "calling ipsec_tunnel_detatch.\n"); ++ if (! prv->dev) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "physical device not connected.\n"); ++ return -ENODEV; ++ } ++ return ipsec_tunnel_detach(dev); ++ ++ case IPSEC_CLR_DEV: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "calling ipsec_tunnel_clear.\n"); ++ return ipsec_tunnel_clear(); ++ ++ default: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_ioctl: " ++ "unknown command %d.\n", ++ cmd); ++ return -EOPNOTSUPP; ++ } ++} ++ ++int ++ipsec_device_event(struct notifier_block *unused, unsigned long event, void *ptr) ++{ ++ struct device *dev = ptr; ++ struct device *ipsec_dev; ++ struct ipsecpriv *priv; ++ int i; ++ ++ if (dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "dev=NULL for event type %ld.\n", ++ event); ++ return(NOTIFY_DONE); ++ } ++ ++ /* check for loopback devices */ ++ if (dev && (dev->flags & IFF_LOOPBACK)) { ++ return(NOTIFY_DONE); ++ } ++ ++ switch (event) { ++ case NETDEV_DOWN: ++ /* look very carefully at the scope of these compiler ++ directives before changing anything... -- RGB */ ++#ifdef NET_21 ++ case NETDEV_UNREGISTER: ++ switch (event) { ++ case NETDEV_DOWN: ++#endif /* NET_21 */ ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_DOWN dev=%s flags=%x\n", ++ dev->name, ++ dev->flags); ++ if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) { ++ printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n", ++ dev->name); ++ } ++#ifdef NET_21 ++ break; ++ case NETDEV_UNREGISTER: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_UNREGISTER dev=%s flags=%x\n", ++ dev->name, ++ dev->flags); ++ break; ++ } ++#endif /* NET_21 */ ++ ++ /* find the attached physical device and detach it. */ ++ for(i = 0; i < IPSEC_NUM_IF; i++) { ++ ipsec_dev = ipsecdevices[i]; ++ ++ if(ipsec_dev) { ++ priv = (struct ipsecpriv *)(ipsec_dev->priv); ++ if(priv) { ++ ; ++ if(((struct device *)(priv->dev)) == dev) { ++ /* dev_close(ipsec_dev); */ ++ /* return */ ipsec_tunnel_detach(ipsec_dev); ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "device '%s' has been detached.\n", ++ ipsec_dev->name); ++ break; ++ } ++ } else { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "device '%s' has no private data space!\n", ++ ipsec_dev->name); ++ } ++ } ++ } ++ break; ++ case NETDEV_UP: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_UP dev=%s\n", ++ dev->name); ++ break; ++#ifdef NET_21 ++ case NETDEV_REBOOT: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_REBOOT dev=%s\n", ++ dev->name); ++ break; ++ case NETDEV_CHANGE: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_CHANGE dev=%s flags=%x\n", ++ dev->name, ++ dev->flags); ++ break; ++ case NETDEV_REGISTER: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_REGISTER dev=%s\n", ++ dev->name); ++ break; ++ case NETDEV_CHANGEMTU: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_CHANGEMTU dev=%s to mtu=%d\n", ++ dev->name, ++ dev->mtu); ++ break; ++ case NETDEV_CHANGEADDR: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_CHANGEADDR dev=%s\n", ++ dev->name); ++ break; ++ case NETDEV_GOING_DOWN: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_GOING_DOWN dev=%s\n", ++ dev->name); ++ break; ++ case NETDEV_CHANGENAME: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "NETDEV_CHANGENAME dev=%s\n", ++ dev->name); ++ break; ++#endif /* NET_21 */ ++ default: ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_device_event: " ++ "event type %ld unrecognised for dev=%s\n", ++ event, ++ dev->name); ++ break; ++ } ++ return NOTIFY_DONE; ++} ++ ++/* ++ * Called when an ipsec tunnel device is initialized. ++ * The ipsec tunnel device structure is passed to us. ++ */ ++ ++int ++ipsec_tunnel_init(struct device *dev) ++{ ++ int i; ++ ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_init: " ++ "allocating %lu bytes initialising device: %s\n", ++ (unsigned long) sizeof(struct ipsecpriv), ++ dev->name ? dev->name : "NULL"); ++ ++ /* Add our tunnel functions to the device */ ++ dev->open = ipsec_tunnel_open; ++ dev->stop = ipsec_tunnel_close; ++ dev->hard_start_xmit = ipsec_tunnel_start_xmit; ++ dev->get_stats = ipsec_tunnel_get_stats; ++ ++ dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); ++ if (dev->priv == NULL) ++ return -ENOMEM; ++ memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); ++ ++ for(i = 0; i < sizeof(zeroes); i++) { ++ ((__u8*)(zeroes))[i] = 0; ++ } ++ ++#ifndef NET_21 ++ /* Initialize the tunnel device structure */ ++ for (i = 0; i < DEV_NUMBUFFS; i++) ++ skb_queue_head_init(&dev->buffs[i]); ++#endif /* !NET_21 */ ++ ++ dev->set_multicast_list = NULL; ++ dev->do_ioctl = ipsec_tunnel_ioctl; ++ dev->hard_header = NULL; ++ dev->rebuild_header = NULL; ++ dev->set_mac_address = NULL; ++#ifndef NET_21 ++ dev->header_cache_bind = NULL; ++#endif /* !NET_21 */ ++ dev->header_cache_update= NULL; ++ ++#ifdef NET_21 ++/* prv->neigh_setup = NULL; */ ++ dev->neigh_setup = ipsec_tunnel_neigh_setup_dev; ++#endif /* NET_21 */ ++ dev->hard_header_len = 0; ++ dev->mtu = 0; ++ dev->addr_len = 0; ++ dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ /* ARPHRD_ETHER; */ ++ dev->tx_queue_len = 10; /* Small queue */ ++ memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ ++ ++ /* New-style flags. */ ++ dev->flags = IFF_NOARP /* 0 */ /* Petr Novak */; ++#ifdef NET_21 ++ dev_init_buffers(dev); ++#else /* NET_21 */ ++ dev->family = AF_INET; ++ dev->pa_addr = 0; ++ dev->pa_brdaddr = 0; ++ dev->pa_mask = 0; ++ dev->pa_alen = 4; ++#endif /* NET_21 */ ++ ++ /* We're done. Have I forgotten anything? */ ++ return 0; ++} ++ ++/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ++/* Module specific interface (but it links with the rest of IPSEC) */ ++/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ++ ++int ++ipsec_tunnel_probe(struct device *dev) ++{ ++ ipsec_tunnel_init(dev); ++ return 0; ++} ++ ++struct device *ipsecdevices[IPSEC_NUM_IF]; ++ ++int ++ipsec_tunnel_init_devices(void) ++{ ++ int i; ++ char name[IFNAMSIZ]; ++ struct device *dev_ipsec; ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_init_devices: " ++ "creating and registering IPSEC_NUM_IF=%u devices, allocating %lu per device, IFNAMSIZ=%u.\n", ++ IPSEC_NUM_IF, ++ (unsigned long) (sizeof(struct device) + IFNAMSIZ), ++ IFNAMSIZ); ++ ++ for(i = 0; i < IPSEC_NUM_IF; i++) { ++ sprintf(name, IPSEC_DEV_FORMAT, i); ++ dev_ipsec = (struct device*)kmalloc(sizeof(struct device), GFP_KERNEL); ++ if (dev_ipsec == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_init_devices: " ++ "failed to allocate memory for device %s, quitting device init.\n", ++ name); ++ return -ENOMEM; ++ } ++ memset((caddr_t)dev_ipsec, 0, sizeof(struct device)); ++#ifdef NETDEV_23 ++ strncpy(dev_ipsec->name, name, sizeof(dev_ipsec->name)); ++#else /* NETDEV_23 */ ++ dev_ipsec->name = (char*)kmalloc(IFNAMSIZ, GFP_KERNEL); ++ if (dev_ipsec->name == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_init_devices: " ++ "failed to allocate memory for device %s name, quitting device init.\n", ++ name); ++ return -ENOMEM; ++ } ++ memset((caddr_t)dev_ipsec->name, 0, IFNAMSIZ); ++ strncpy(dev_ipsec->name, name, IFNAMSIZ); ++#endif /* NETDEV_23 */ ++ dev_ipsec->next = NULL; ++ dev_ipsec->init = &ipsec_tunnel_probe; ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_init_devices: " ++ "registering device %s\n", ++ dev_ipsec->name); ++ ++ /* reference and hold the device reference */ ++ dev_hold(dev_ipsec); ++ ipsecdevices[i]=dev_ipsec; ++ ++ if (register_netdev(dev_ipsec) != 0) { ++ KLIPS_PRINT(1 || debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_init_devices: " ++ "registering device %s failed, quitting device init.\n", ++ dev_ipsec->name); ++ return -EIO; ++ } else { ++ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, ++ "klips_debug:ipsec_tunnel_init_devices: " ++ "registering device %s succeeded, continuing...\n", ++ dev_ipsec->name); ++ } ++ } ++ return 0; ++} ++ ++/* void */ ++int ++ipsec_tunnel_cleanup_devices(void) ++{ ++ int error = 0; ++ int i; ++ char name[32]; ++ struct device *dev_ipsec; ++ ++ for(i = 0; i < IPSEC_NUM_IF; i++) { ++ dev_ipsec = ipsecdevices[i]; ++ if(dev_ipsec == NULL) { ++ continue; ++ } ++ ++ /* release reference */ ++ ipsecdevices[i]=NULL; ++ ipsec_dev_put(dev_ipsec); ++ ++ KLIPS_PRINT(debug_tunnel, "Unregistering %s (refcnt=%d)\n", ++ name, ++ atomic_read(&dev_ipsec->refcnt)); ++ unregister_netdev(dev_ipsec); ++ KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", name); ++#ifndef NETDEV_23 ++ kfree(dev_ipsec->name); ++ dev_ipsec->name=NULL; ++#endif /* !NETDEV_23 */ ++ kfree(dev_ipsec->priv); ++ dev_ipsec->priv=NULL; ++ } ++ return error; ++} ++ ++/* ++ * $Log: ipsec_tunnel.c,v $ ++ * Revision 1.220 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.219 2004/02/03 03:13:17 mcr ++ * minor edits for readability, and error reporting. ++ * ++ * Revision 1.218 2004/01/27 20:29:20 mcr ++ * fix for unregister_netdev() problem for underlying eth0. ++ * ++ * Revision 1.217 2003/12/10 01:14:27 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.216 2003/12/04 23:01:17 mcr ++ * removed ipsec_netlink.h ++ * ++ * Revision 1.215 2003/12/04 16:35:16 ken ++ * Fix for ATM devices where physdev->hard_header_len *is* correct ++ * ++ * Revision 1.214 2003/11/25 23:52:37 mcr ++ * fix typo in patch - ixs-> needed. ++ * ++ * Revision 1.213 2003/11/24 18:25:49 mcr ++ * patch from willy@w.ods.org to fix problems with ATM interfaces. ++ * ++ * Revision 1.212 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.211.2.2 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.211.2.1 2003/09/21 13:59:56 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.211 2003/09/10 16:46:30 mcr ++ * patches for 2.4 backport/2.6 existence. ++ * ++ * Revision 1.210 2003/07/31 22:47:16 mcr ++ * preliminary (untested by FS-team) 2.5 patches. ++ * ++ * Revision 1.209 2003/06/22 21:28:43 mcr ++ * inability to unload module was caused by calls to dev_get ++ * (ipsec_dev_get), to gather a device from a name. There is ++ * simply no reason to look the devices up - they should be kept ++ * in a nice array, ready for use. ++ * ++ * Revision 1.208 2003/06/22 21:25:07 mcr ++ * all staticly counted ipsecXXX device support removed. ++ * ++ * Revision 1.207 2003/04/02 20:15:37 mcr ++ * fix for PR#204 - do not clear connection tracking info if we ++ * the packet is being sent in the clear. ++ * ++ * Revision 1.206 2003/02/12 19:32:51 rgb ++ * Refactored file to: ++ * ipsec_xmit.c ++ * ipsec_xmit.h ++ * ipsec_mast.c ++ * ++ * Revision 1.205 2003/02/06 17:47:00 rgb ++ * ++ * Remove unused ipsec_tunnel_lock() and ipsec_tunnel_unlock() code. ++ * Refactor ipsec_tunnel_start_xmit() further into: ++ * ipsec_xmit_sanity_check_dev() ++ * ipsec_xmit_sanity_check_skb() ++ * ipsec_xmit_strip_hard_header() ++ * ipsec_xmit_restore_hard_header() ++ * ipsec_xmit_send() ++ * ipsec_xmit_cleanup() ++ * and start a skeletal ipsec_mast_start_xmit() . ++ * ++ * Revision 1.204 2003/02/06 06:43:46 rgb ++ * ++ * Refactor ipsec_tunnel_start_xmit, bringing out: ++ * ipsec_xmit_SAlookup ++ * ipsec_xmit_encap_once ++ * ipsec_xmit_encap_bundle ++ * ++ * Revision 1.203 2003/02/06 02:21:34 rgb ++ * ++ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . ++ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". ++ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. ++ * ++ * Revision 1.202 2003/01/03 07:38:01 rgb ++ * ++ * Start to refactor ipsec_tunnel_start_xmit() by putting local variables ++ * into struct ipsec_xmit_state and renaming a few variables to give more ++ * unique or searchable names. ++ * ++ * Revision 1.201 2003/01/03 00:31:28 rgb ++ * ++ * Clean up memset usage, including fixing 2 places where keys were not ++ * properly wiped. ++ * ++ * Revision 1.200 2002/12/06 02:24:02 mcr ++ * patches for compiling against SUSE 8.1 kernels. Requires ++ * an additional -DSUSE_LINUX_2_4_19_IS_STUPID. ++ * ++ * Revision 1.199 2002/10/12 23:11:53 dhr ++ * ++ * [KenB + DHR] more 64-bit cleanup ++ * ++ * Revision 1.198 2002/10/05 05:02:58 dhr ++ * ++ * C labels go on statements ++ * ++ * Revision 1.197 2002/09/20 05:01:50 rgb ++ * Added compiler directive to switch on IP options and fix IP options bug. ++ * Make ip->ihl treatment consistent using shifts rather than multiplications. ++ * Check for large enough packet before accessing udp header for IKE bypass. ++ * Added memory allocation debugging. ++ * Fixed potential memory allocation failure-induced oops. ++ * ++ * Revision 1.196 2002/07/24 18:44:54 rgb ++ * Type fiddling to tame ia64 compiler. ++ * ++ * Revision 1.195 2002/07/23 03:36:07 rgb ++ * Fixed 2.2 device initialisation hang. ++ * ++ * Revision 1.194 2002/05/27 21:40:34 rgb ++ * Set unused ipsec devices to ARPHRD_VOID to avoid confusing iproute2. ++ * Cleaned up intermediate step to dynamic device allocation. ++ * ++ * Revision 1.193 2002/05/27 19:31:36 rgb ++ * Convert to dynamic ipsec device allocation. ++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. ++ * ++ * Revision 1.192 2002/05/23 07:14:28 rgb ++ * Added refcount code. ++ * Cleaned up %p variants to 0p%p for test suite cleanup. ++ * ++ * Revision 1.191 2002/05/14 02:34:37 rgb ++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, ++ * ipsec_sa or ipsec_sa. ++ * ++ * Revision 1.190 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.189 2002/04/24 07:36:32 mcr ++ * Moved from ./klips/net/ipsec/ipsec_tunnel.c,v ++ * ++ * Revision 1.188 2002/04/20 00:12:25 rgb ++ * Added esp IV CBC attack fix, disabled. ++ * ++ * Revision 1.187 2002/03/23 19:55:17 rgb ++ * Fix for 2.2 local IKE fragmentation blackhole. Still won't work if ++ * iptraf or another pcap app is running. ++ * ++ * Revision 1.186 2002/03/19 03:26:22 rgb ++ * Applied DHR's tunnel patch to streamline IKE/specialSA processing. ++ * ++ * Revision 1.185 2002/02/20 04:13:05 rgb ++ * Send back ICMP_PKT_FILTERED upon %reject. ++ * ++ * Revision 1.184 2002/01/29 17:17:56 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.183 2002/01/29 04:00:53 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.182 2002/01/29 02:13:18 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.181 2002/01/07 20:00:33 rgb ++ * Added IKE destination port debugging. ++ * ++ * Revision 1.180 2001/12/21 21:49:54 rgb ++ * Fixed bug as a result of moving IKE bypass above %trap/%hold code. ++ * ++ * Revision 1.179 2001/12/19 21:08:14 rgb ++ * Added transport protocol ports to ipsec_print_ip(). ++ * Update eroute info for non-SA targets. ++ * Added obey DF code disabled. ++ * Fixed formatting bugs in ipsec_tunnel_hard_header(). ++ * ++ * Revision 1.178 2001/12/05 09:36:10 rgb ++ * Moved the UDP/500 IKE check just above the %hold/%trap checks to avoid ++ * IKE packets being stolen by the %hold (and returned to the sending KMd ++ * in an ACQUIRE, ironically ;-). ++ * ++ * Revision 1.177 2001/11/26 09:23:50 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.170.2.1 2001/09/25 02:28:27 mcr ++ * struct tdb -> struct ipsec_sa. ++ * lifetime checks moved to common routines. ++ * cleaned up includes. ++ * ++ * Revision 1.170.2.2 2001/10/22 21:08:01 mcr ++ * include des.h, removed phony prototypes and fixed calling ++ * conventions to match real prototypes. ++ * ++ * Revision 1.176 2001/11/09 18:32:31 rgb ++ * Added Hans Schultz' fragmented UDP/500 IKE socket port selector. ++ * ++ * Revision 1.175 2001/11/06 20:47:00 rgb ++ * Added Eric Espie's TRAPSUBNET fix, minus spin-lock-bh dabbling. ++ * ++ * Revision 1.174 2001/11/06 19:50:43 rgb ++ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for ++ * use also by pfkey_v2_parser.c ++ * ++ * Revision 1.173 2001/10/29 21:53:44 henry ++ * tone down the device-down message slightly, until we can make it smarter ++ * ++ * Revision 1.172 2001/10/26 04:59:37 rgb ++ * Added a critical level syslog message if an ipsec device goes down. ++ * ++ * Revision 1.171 2001/10/18 04:45:21 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/freeswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.170 2001/09/25 00:09:50 rgb ++ * Added NetCelo's TRAPSUBNET code to convert a new type TRAPSUBNET into a ++ * HOLD. ++ * ++ * Revision 1.169 2001/09/15 16:24:05 rgb ++ * Re-inject first and last HOLD packet when an eroute REPLACE is done. ++ * ++ * Revision 1.168 2001/09/14 16:58:37 rgb ++ * Added support for storing the first and last packets through a HOLD. ++ * ++ * Revision 1.167 2001/09/08 21:13:33 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.166 2001/08/27 19:47:59 rgb ++ * Clear tdb before usage. ++ * Added comment: clear IF before calling routing? ++ * ++ * Revision 1.165 2001/07/03 01:23:53 rgb ++ * Send back ICMP iff DF set, !ICMP, offset==0, sysctl_icmp, iph->tot_len > ++ * emtu, and don't drop. ++ * ++ * Revision 1.164 2001/06/14 19:35:10 rgb ++ * Update copyright date. ++ * ++ * Revision 1.163 2001/06/06 20:28:51 rgb ++ * Added sanity checks for NULL skbs and devices. ++ * Added more debugging output to various functions. ++ * Removed redundant dev->priv argument to ipsec_tunnel_{at,de}tach(). ++ * Renamed ipsec_tunnel_attach() virtual and physical device arguments. ++ * Corrected neigh_setup() device function assignment. ++ * Keep valid pointers to ipsec_tunnel_*() on detach. ++ * Set dev->type to the originally-initiallised value. ++ * ++ * Revision 1.162 2001/06/01 07:28:04 rgb ++ * Added sanity checks for detached devices. Don't down virtual devices ++ * to prevent packets going out in the clear if the detached device comes ++ * back up. ++ * ++ * Revision 1.161 2001/05/30 08:14:52 rgb ++ * Removed vestiges of esp-null transforms. ++ * NetDev Notifier instrumentation to track down disappearing devices. ++ * ++ * Revision 1.160 2001/05/29 05:15:12 rgb ++ * Added SS' PMTU patch which notifies sender if packet doesn't fit ++ * physical MTU (if it wasn't ICMP) and then drops it. ++ * ++ * Revision 1.159 2001/05/27 06:12:12 rgb ++ * Added structures for pid, packet count and last access time to eroute. ++ * Added packet count to beginning of /proc/net/ipsec_eroute. ++ * ++ * Revision 1.158 2001/05/24 05:39:33 rgb ++ * Applied source zeroing to 2.2 ip_route_output() call as well to enable ++ * PASS eroutes for opportunism. ++ * ++ * Revision 1.157 2001/05/23 22:35:28 rgb ++ * 2.4 source override simplification. ++ * ++ * Revision 1.156 2001/05/23 21:41:31 rgb ++ * Added error return code printing on ip_route_output(). ++ * ++ * Revision 1.155 2001/05/23 05:09:13 rgb ++ * Fixed incorrect ip_route_output() failure message. ++ * ++ * Revision 1.154 2001/05/21 14:53:31 rgb ++ * Added debug statement for case when ip_route_output() fails, causing ++ * packet to be dropped, but log looked ok. ++ * ++ * Revision 1.153 2001/05/19 02:37:54 rgb ++ * Fixed missing comment termination. ++ * ++ * Revision 1.152 2001/05/19 02:35:50 rgb ++ * Debug code optimisation for non-debug speed. ++ * Kernel version compiler define comments. ++ * 2.2 and 2.4 kernel ip_send device and ip debug output added. ++ * ++ * Revision 1.151 2001/05/18 16:17:35 rgb ++ * Changed reference from "magic" to "shunt" SAs. ++ * ++ * Revision 1.150 2001/05/18 16:12:19 rgb ++ * Changed UDP/500 bypass test from 3 nested ifs to one anded if. ++ * ++ * Revision 1.149 2001/05/16 04:39:33 rgb ++ * Add default == eroute.dest to IKE bypass conditions for magic eroutes. ++ * ++ * Revision 1.148 2001/05/05 03:31:41 rgb ++ * IP frag debugging updates and enhancements. ++ * ++ * Revision 1.147 2001/05/03 19:41:40 rgb ++ * Added SS' skb_cow fix for 2.4.4. ++ * ++ * Revision 1.146 2001/04/30 19:28:16 rgb ++ * Update for 2.4.4. ip_select_ident() now has 3 args. ++ * ++ * Revision 1.145 2001/04/23 14:56:10 rgb ++ * Added spin_lock() check to prevent double-locking for multiple ++ * transforms and hence kernel lock-ups with SMP kernels. ++ * ++ * Revision 1.144 2001/04/21 23:04:45 rgb ++ * Define out skb->used for 2.4 kernels. ++ * Check if soft expire has already been sent before sending another to ++ * prevent ACQUIRE flooding. ++ * ++ * Revision 1.143 2001/03/16 07:37:21 rgb ++ * Added comments to all #endifs. ++ * ++ * Revision 1.142 2001/02/28 05:03:27 rgb ++ * Clean up and rationalise startup messages. ++ * ++ * Revision 1.141 2001/02/27 22:24:54 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.140 2001/02/27 06:40:12 rgb ++ * Fixed TRAP->HOLD eroute byte order. ++ * ++ * Revision 1.139 2001/02/26 20:38:59 rgb ++ * Added compiler defines for 2.4.x-specific code. ++ * ++ * Revision 1.138 2001/02/26 19:57:27 rgb ++ * Implement magic SAs %drop, %reject, %trap, %hold, %pass as part ++ * of the new SPD and to support opportunistic. ++ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs. ++ * ++ * Revision 1.137 2001/02/19 22:29:49 rgb ++ * Fixes for presence of active ipv6 segments which share ipsec physical ++ * device (gg). ++ * ++ * Revision 1.136 2001/01/29 22:30:38 rgb ++ * Fixed minor acquire debug printing bug. ++ * ++ * Revision 1.135 2001/01/29 22:19:45 rgb ++ * Zero source address for 2.4 bypass route lookup. ++ * ++ * Revision 1.134 2001/01/23 20:19:49 rgb ++ * 2.4 fix to remove removed is_clone member. ++ * ++ * Revision 1.133 2000/12/09 22:08:35 rgb ++ * Fix NET_23 bug, should be NETDEV_23. ++ * ++ * Revision 1.132 2000/12/01 06:54:50 rgb ++ * Fix for new 2.4 IP TTL default variable name. ++ * ++ * Revision 1.131 2000/11/09 20:52:15 rgb ++ * More spinlock shuffling, locking earlier and unlocking later in rcv to ++ * include ipcomp and prevent races, renaming some tdb variables that got ++ * forgotten, moving some unlocks to include tdbs and adding a missing ++ * unlock. Thanks to Svenning for some of these. ++ * ++ * Revision 1.130 2000/11/09 20:11:22 rgb ++ * Minor shuffles to fix non-standard kernel config option selection. ++ * ++ * Revision 1.129 2000/11/06 04:32:49 rgb ++ * Clean up debug printing. ++ * Copy skb->protocol for all kernel versions. ++ * Ditched spin_lock_irqsave in favour of spin_lock. ++ * Disabled TTL decrement, done in ip_forward. ++ * Added debug printing before pfkey_acquire(). ++ * Fixed printk-deltdbchain-spin_lock races (Svenning). ++ * Use defaultTTL for 2.1+ kernels. ++ * Add Svenning's adaptive content compression. ++ * Fix up debug display arguments. ++ * ++ * Revision 1.128 2000/09/28 00:58:57 rgb ++ * Moved the IKE passthrough check after the eroute lookup so we can pass ++ * IKE through intermediate tunnels. ++ * ++ * Revision 1.127 2000/09/22 17:52:11 rgb ++ * Fixed misleading ipcomp debug output. ++ * ++ * Revision 1.126 2000/09/22 04:22:56 rgb ++ * Fixed dumb spi->cpi conversion error. ++ * ++ * Revision 1.125 2000/09/21 04:34:48 rgb ++ * A few debug-specific things should be hidden under ++ * CONFIG_IPSEC_DEBUG.(MB) ++ * Improved ip_send() error handling.(MB) ++ * ++ * Revision 1.124 2000/09/21 03:40:58 rgb ++ * Added more debugging to try and track down the cpi outward copy problem. ++ * ++ * Revision 1.123 2000/09/19 07:08:49 rgb ++ * Added debugging to outgoing compression report. ++ * ++ * Revision 1.122 2000/09/18 19:21:26 henry ++ * RGB-supplied fix for RH5.2 problem ++ * ++ * Revision 1.121 2000/09/17 21:05:09 rgb ++ * Added tdb to skb_compress call to write in cpi. ++ * ++ * Revision 1.120 2000/09/17 16:57:16 rgb ++ * Added Svenning's patch to remove restriction of ipcomp to innermost ++ * transform. ++ * ++ * Revision 1.119 2000/09/15 11:37:01 rgb ++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk> ++ * IPCOMP zlib deflate code. ++ * ++ * Revision 1.118 2000/09/15 04:57:16 rgb ++ * Moved debug output after sanity check. ++ * Added tos copy sysctl. ++ * ++ * Revision 1.117 2000/09/12 03:22:51 rgb ++ * Converted ipsec_icmp, no_eroute_pass, opportunistic and #if0 debugs to ++ * sysctl. ++ * ++ * Revision 1.116 2000/09/08 19:18:19 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * Added outgoing opportunistic hook, ifdef'ed out. ++ * ++ * Revision 1.115 2000/08/30 05:27:29 rgb ++ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst. ++ * Kill remainder of tdb_xform, tdb_xdata, xformsw. ++ * ++ * Revision 1.114 2000/08/28 18:15:46 rgb ++ * Added MB's nf-debug reset patch. ++ * ++ * Revision 1.113 2000/08/27 02:26:40 rgb ++ * Send all no-eroute-bypass, pluto-bypass and passthrough packets through ++ * fragmentation machinery for 2.0, 2.2 and 2.4 kernels. ++ * ++ * Revision 1.112 2000/08/20 21:37:33 rgb ++ * Activated pfkey_expire() calls. ++ * Added a hard/soft expiry parameter to pfkey_expire(). (Momchil) ++ * Re-arranged the order of soft and hard expiry to conform to RFC2367. ++ * Clean up references to CONFIG_IPSEC_PFKEYv2. ++ * ++ * Revision 1.111 2000/08/01 14:51:51 rgb ++ * Removed _all_ remaining traces of DES. ++ * ++ * Revision 1.110 2000/07/28 14:58:31 rgb ++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. ++ * ++ * Revision 1.109 2000/07/28 13:50:54 rgb ++ * Changed enet_statistics to net_device_stats and added back compatibility ++ * for pre-2.1.19. ++ * ++ * Revision 1.108 2000/05/16 03:03:11 rgb ++ * Updates for 2.3.99pre8 from MB. ++ * ++ * Revision 1.107 2000/05/10 23:08:21 rgb ++ * Print a debug warning about bogus packets received by the outgoing ++ * processing machinery only when klipsdebug is not set to none. ++ * Comment out the device initialisation informational messages. ++ * ++ * Revision 1.106 2000/05/10 19:17:14 rgb ++ * Define an IP_SEND macro, intending to have all packet passthroughs ++ * use fragmentation. This didn't quite work, but is a step in the ++ * right direction. ++ * Added buffer allocation debugging statements. ++ * Added configure option to shut off no eroute passthrough. ++ * Only check usetime against soft and hard limits if the tdb has been ++ * used. ++ * Cast output of ntohl so that the broken prototype doesn't make our ++ * compile noisy. ++ * ++ * Revision 1.105 2000/03/22 16:15:37 rgb ++ * Fixed renaming of dev_get (MB). ++ * ++ * Revision 1.104 2000/03/16 14:04:15 rgb ++ * Indented headers for readability. ++ * Fixed debug scope to enable compilation with debug off. ++ * Added macros for ip_chk_addr and IS_MYADDR for identifying self. ++ * ++ * Revision 1.103 2000/03/16 07:11:07 rgb ++ * Hardcode PF_KEYv2 support. ++ * Fixed bug which allowed UDP/500 packet from another machine ++ * through in the clear. ++ * Added disabled skb->protocol fix for ISDN/ASYNC PPP from Matjaz Godec. ++ * ++ * Revision 1.102 2000/03/14 12:26:59 rgb ++ * Added skb->nfct support for clearing netfilter conntrack bits (MB). ++ * ++ * Revision 1.101 2000/02/14 21:05:22 rgb ++ * Added MB's netif_queue fix for kernels 2.3.43+. ++ * ++ * Revision 1.100 2000/01/26 10:04:57 rgb ++ * Fixed noisy 2.0 printk arguments. ++ * ++ * Revision 1.99 2000/01/21 06:16:25 rgb ++ * Added sanity checks on skb_push(), skb_pull() to prevent panics. ++ * Switched to AF_ENCAP macro. ++ * Shortened debug output per packet and re-arranging debug_tunnel ++ * bitmap flags, while retaining necessary information to avoid ++ * trampling the kernel print ring buffer. ++ * Reformatted recursion switch code. ++ * Changed all references to tdb_proto to tdb_said.proto for clarity. ++ * ++ * Revision 1.98 2000/01/13 08:09:31 rgb ++ * Shuffled debug_tunnel switches to focus output. ++ * Fixed outgoing recursion bug, limiting to recursing only if the remote ++ * SG changes and if it is valid, ie. not passthrough. ++ * Clarified a number of debug messages. ++ * ++ * Revision 1.97 2000/01/10 16:37:16 rgb ++ * MB support for new ip_select_ident() upon disappearance of ++ * ip_id_count in 2.3.36+. ++ * ++ * Revision 1.96 1999/12/31 14:59:08 rgb ++ * MB fix to use new skb_copy_expand in kernel 2.3.35. ++ * ++ * Revision 1.95 1999/12/29 21:15:44 rgb ++ * Fix tncfg to aliased device bug. ++ * ++ * Revision 1.94 1999/12/22 04:26:06 rgb ++ * Converted all 'static' functions to 'DEBUG_NO_STATIC' to enable ++ * debugging by providing external labels to all functions with debugging ++ * turned on. ++ * ++ * Revision 1.93 1999/12/13 13:30:14 rgb ++ * Changed MTU reports and HW address reporting back to debug only. ++ * ++ * Revision 1.92 1999/12/07 18:57:56 rgb ++ * Fix PFKEY symbol compile error (SADB_*) without pfkey enabled. ++ * ++ * Revision 1.91 1999/12/01 22:15:36 rgb ++ * Add checks for LARVAL and DEAD SAs. ++ * Change state of SA from MATURE to DYING when a soft lifetime is ++ * reached and print debug warning. ++ * ++ * Revision 1.90 1999/11/23 23:04:04 rgb ++ * Use provided macro ADDRTOA_BUF instead of hardcoded value. ++ * Sort out pfkey and freeswan headers, putting them in a library path. ++ * ++ * Revision 1.89 1999/11/18 18:50:59 rgb ++ * Changed all device registrations for static linking to ++ * dynamic to reduce the number and size of patches. ++ * ++ * Revision 1.88 1999/11/18 04:09:19 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * ++ * Revision 1.87 1999/11/17 15:53:40 rgb ++ * Changed all occurrences of #include "../../../lib/freeswan.h" ++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the ++ * klips/net/ipsec/Makefile. ++ * ++ * Revision 1.86 1999/10/16 18:25:37 rgb ++ * Moved SA lifetime expiry checks before packet processing. ++ * Expire SA on replay counter rollover. ++ * ++ * Revision 1.85 1999/10/16 04:24:31 rgb ++ * Add stats for time since last packet. ++ * ++ * Revision 1.84 1999/10/16 00:30:47 rgb ++ * Added SA lifetime counting. ++ * ++ * Revision 1.83 1999/10/15 22:15:57 rgb ++ * Clean out cruft. ++ * Add debugging. ++ * ++ * Revision 1.82 1999/10/08 18:26:19 rgb ++ * Fix 2.0.3x outgoing fragmented packet memory leak. ++ * ++ * Revision 1.81 1999/10/05 02:38:54 rgb ++ * Lower the default mtu of virtual devices to 16260. ++ * ++ * Revision 1.80 1999/10/03 18:56:41 rgb ++ * Spinlock support for 2.3.xx. ++ * Don't forget to undo spinlocks on error! ++ * Check for valid eroute before copying the structure. ++ * ++ * Revision 1.79 1999/10/01 15:44:53 rgb ++ * Move spinlock header include to 2.1> scope. ++ * ++ * Revision 1.78 1999/10/01 00:02:43 rgb ++ * Added tdb structure locking. ++ * Added eroute structure locking. ++ * ++ * Revision 1.77 1999/09/30 02:52:29 rgb ++ * Add Marc Boucher's Copy-On-Write code (same as ipsec_rcv.c). ++ * ++ * Revision 1.76 1999/09/25 19:31:27 rgb ++ * Refine MSS hack to affect SYN, but not SYN+ACK packets. ++ * ++ * Revision 1.75 1999/09/24 22:52:38 rgb ++ * Fix two things broken in 2.0.38 by trying to fix network notifiers. ++ * ++ * Revision 1.74 1999/09/24 00:30:37 rgb ++ * Add test for changed source as well as destination to check for ++ * recursion. ++ * ++ * Revision 1.73 1999/09/23 20:52:24 rgb ++ * Add James Morris' MSS hack patch, disabled. ++ * ++ * Revision 1.72 1999/09/23 20:22:40 rgb ++ * Enable, tidy and fix network notifier code. ++ * ++ * Revision 1.71 1999/09/23 18:09:05 rgb ++ * Clean up 2.2.x fragmenting traces. ++ * Disable dev->type switching, forcing ARPHRD_TUNNEL. ++ * ++ * Revision 1.70 1999/09/22 14:14:24 rgb ++ * Add sanity checks for revectored calls to prevent calling a downed I/F. ++ * ++ * Revision 1.69 1999/09/21 15:00:57 rgb ++ * Add Marc Boucher's packet size check. ++ * Flesh out network device notifier code. ++ * ++ * Revision 1.68 1999/09/18 11:39:57 rgb ++ * Start to add (disabled) netdevice notifier code. ++ * ++ * Revision 1.67 1999/09/17 23:44:40 rgb ++ * Add a comment warning potential code hackers to stay away from mac.raw. ++ * ++ * Revision 1.66 1999/09/17 18:04:02 rgb ++ * Add fix for unpredictable hard_header_len for ISDN folks (thanks MB). ++ * Ditch TTL decrement in 2.2 (MB). ++ * ++ * Revision 1.65 1999/09/15 23:15:35 henry ++ * Marc Boucher's PPP fixes ++ * ++ * Revision 1.64 1999/09/07 13:40:53 rgb ++ * Ditch unreliable references to skb->mac.raw. ++ * ++ * Revision 1.63 1999/08/28 11:33:09 rgb ++ * Check for null skb->mac pointer. ++ * ++ * Revision 1.62 1999/08/28 02:02:30 rgb ++ * Add Marc Boucher's fix for properly dealing with skb->sk. ++ * ++ * Revision 1.61 1999/08/27 05:23:05 rgb ++ * Clean up skb->data/raw/nh/h manipulation. ++ * Add Marc Boucher's mods to aid tcpdump. ++ * Add sanity checks to skb->raw/nh/h pointer copies in skb_copy_expand. ++ * Re-order hard_header stripping -- might be able to remove it... ++ * ++ * Revision 1.60 1999/08/26 20:01:02 rgb ++ * Tidy up compiler directives and macros. ++ * Re-enable ICMP for tunnels where inner_dst != outer_dst. ++ * Remove unnecessary skb->dev = physdev assignment affecting 2.2.x. ++ * ++ * Revision 1.59 1999/08/25 15:44:41 rgb ++ * Clean up from 2.2.x instrumenting for compilation under 2.0.36. ++ * ++ * Revision 1.58 1999/08/25 15:00:54 rgb ++ * Add dst cache code for 2.2.xx. ++ * Add sanity check for skb packet header pointers. ++ * Add/modify debugging instrumentation to *_start_xmit, *_hard_header and ++ * *_rebuild_header. ++ * Add neigh_* cache code. ++ * Change dev->type back to ARPHRD_TUNNEL. ++ * ++ * Revision 1.57 1999/08/17 21:50:23 rgb ++ * Fixed minor debug output bugs. ++ * Regrouped error recovery exit code. ++ * Added compiler directives to remove unwanted code and symbols. ++ * Shut off ICMP messages: to be refined to only send ICMP to remote systems. ++ * Add debugging code for output function addresses. ++ * Fix minor bug in (possibly unused) header_cache_bind function. ++ * Add device neighbour caching code. ++ * Change dev->type from ARPHRD_TUNNEL to physdev->type. ++ * ++ * Revision 1.56 1999/08/03 17:22:56 rgb ++ * Debug output clarification using KERN_* macros. Other inactive changes ++ * added. ++ * ++ * Revision 1.55 1999/08/03 16:58:46 rgb ++ * Fix skb_copy_expand size bug. Was getting incorrect size. ++ * ++ * Revision 1.54 1999/07/14 19:32:38 rgb ++ * Fix oversize packet crash and ssh stalling in 2.2.x kernels. ++ * ++ * Revision 1.53 1999/06/10 15:44:02 rgb ++ * Minor reformatting and clean-up. ++ * ++ * Revision 1.52 1999/05/09 03:25:36 rgb ++ * Fix bug introduced by 2.2 quick-and-dirty patch. ++ * ++ * Revision 1.51 1999/05/08 21:24:59 rgb ++ * Add casting to silence the 2.2.x compile. ++ * ++ * Revision 1.50 1999/05/05 22:02:32 rgb ++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>. ++ * ++ * Revision 1.49 1999/04/29 15:18:52 rgb ++ * Change gettdb parameter to a pointer to reduce stack loading and ++ * facilitate parameter sanity checking. ++ * Fix undetected bug that might have tried to access a null pointer. ++ * Eliminate unnessessary usage of tdb_xform member to further switch ++ * away from the transform switch to the algorithm switch. ++ * Add return values to init and cleanup functions. ++ * ++ * Revision 1.48 1999/04/16 15:38:00 rgb ++ * Minor rearrangement of freeing code to avoid memory leaks with impossible or ++ * rare situations. ++ * ++ * Revision 1.47 1999/04/15 15:37:25 rgb ++ * Forward check changes from POST1_00 branch. ++ * ++ * Revision 1.32.2.4 1999/04/13 21:00:18 rgb ++ * Ditch 'things I wish I had known before...'. ++ * ++ * Revision 1.32.2.3 1999/04/13 20:34:38 rgb ++ * Free skb after fragmentation. ++ * Use stats more effectively. ++ * Add I/F to mtu notch-down reporting. ++ * ++ * Revision 1.32.2.2 1999/04/02 04:26:14 rgb ++ * Backcheck from HEAD, pre1.0. ++ * ++ * Revision 1.46 1999/04/11 00:29:00 henry ++ * GPL boilerplate ++ * ++ * Revision 1.45 1999/04/07 15:42:01 rgb ++ * Fix mtu/ping bug AGAIN! ++ * ++ * Revision 1.44 1999/04/06 04:54:27 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.43 1999/04/04 03:57:07 rgb ++ * ip_fragment() doesn't free the supplied skb. Freed. ++ * ++ * Revision 1.42 1999/04/01 23:27:15 rgb ++ * Preload size of virtual mtu. ++ * ++ * Revision 1.41 1999/04/01 09:31:23 rgb ++ * Invert meaning of ICMP PMTUD config option and clarify. ++ * Code clean-up. ++ * ++ * Revision 1.40 1999/04/01 04:37:17 rgb ++ * SSH stalling bug fix. ++ * ++ * Revision 1.39 1999/03/31 23:44:28 rgb ++ * Don't send ICMP on DF and frag_off. ++ * ++ * Revision 1.38 1999/03/31 15:20:10 rgb ++ * Quiet down debugging. ++ * ++ * Revision 1.37 1999/03/31 08:30:31 rgb ++ * Add switch to shut off ICMP PMTUD packets. ++ * ++ * Revision 1.36 1999/03/31 05:44:47 rgb ++ * Keep PMTU reduction private. ++ * ++ * Revision 1.35 1999/03/27 15:13:02 rgb ++ * PMTU/fragmentation bug fix. ++ * ++ * Revision 1.34 1999/03/17 21:19:26 rgb ++ * Fix kmalloc nonatomic bug. ++ * ++ * Revision 1.33 1999/03/17 15:38:42 rgb ++ * Code clean-up. ++ * ESP_NULL IV bug fix. ++ * ++ * Revision 1.32 1999/03/01 20:44:25 rgb ++ * Code clean-up. ++ * Memory leak bug fix. ++ * ++ * Revision 1.31 1999/02/27 00:02:09 rgb ++ * Tune to report the MTU reduction once, rather than after every recursion ++ * through the encapsulating code, preventing tcp stream stalling. ++ * ++ * Revision 1.30 1999/02/24 20:21:01 rgb ++ * Reformat debug printk's. ++ * Fix recursive encapsulation, dynamic MTU bugs and add debugging code. ++ * Clean-up. ++ * ++ * Revision 1.29 1999/02/22 17:08:14 rgb ++ * Fix recursive encapsulation code. ++ * ++ * Revision 1.28 1999/02/19 18:27:02 rgb ++ * Improve DF, fragmentation and PMTU behaviour and add dynamic MTU discovery. ++ * ++ * Revision 1.27 1999/02/17 16:51:37 rgb ++ * Clean out unused cruft. ++ * Temporarily tone down volume of debug output. ++ * Temporarily shut off fragment rejection. ++ * Disabled temporary failed recursive encapsulation loop. ++ * ++ * Revision 1.26 1999/02/12 21:21:26 rgb ++ * Move KLIPS_PRINT to ipsec_netlink.h for accessibility. ++ * ++ * Revision 1.25 1999/02/11 19:38:27 rgb ++ * More clean-up. ++ * Add sanity checking for skb_copy_expand() to prevent kernel panics on ++ * skb_put() values out of range. ++ * Fix head/tailroom calculation causing skb_put() out-of-range values. ++ * Fix return values to prevent 'nonatomic alloc_skb' warnings. ++ * Allocate new skb iff needed. ++ * Added more debug statements. ++ * Make headroom depend on structure, not hard-coded values. ++ * ++ * Revision 1.24 1999/02/10 23:20:33 rgb ++ * Shut up annoying 'statement has no effect' compiler warnings with ++ * debugging compiled out. ++ * ++ * Revision 1.23 1999/02/10 22:36:30 rgb ++ * Clean-up obsolete, unused and messy code. ++ * Converted most IPSEC_DEBUG statements to KLIPS_PRINT macros. ++ * Rename ipsec_tunnel_do_xmit to ipsec_tunnel_start_xmit and eliminated ++ * original ipsec_tunnel_start_xmit. ++ * Send all packet with different inner and outer destinations directly to ++ * the attached physical device, rather than back through ip_forward, ++ * preventing disappearing routes problems. ++ * Do sanity checking before investing too much CPU in allocating new ++ * structures. ++ * Fail on IP header options: We cannot process them yet. ++ * Add some helpful comments. ++ * Use virtual device for parameters instead of physical device. ++ * ++ * Revision 1.22 1999/02/10 03:03:02 rgb ++ * Duh. Fixed the TTL bug: forgot to update the checksum. ++ * ++ * Revision 1.21 1999/02/09 23:17:53 rgb ++ * Add structure members to ipsec_print_ip debug function. ++ * Temporarily fix TTL bug preventing tunnel mode from functioning. ++ * ++ * Revision 1.20 1999/02/09 00:14:25 rgb ++ * Add KLIPSPRINT macro. (Not used yet, though.) ++ * Delete old ip_tunnel code (BADCODE). ++ * Decrement TTL in outgoing packet. ++ * Set TTL on new IPIP_TUNNEL to default, not existing packet TTL. ++ * Delete ethernet only feature and fix hard-coded hard_header_len. ++ * ++ * Revision 1.19 1999/01/29 17:56:22 rgb ++ * 64-bit re-fix submitted by Peter Onion. ++ * ++ * Revision 1.18 1999/01/28 22:43:24 rgb ++ * Fixed bug in ipsec_print_ip that caused an OOPS, found by P.Onion. ++ * ++ * Revision 1.17 1999/01/26 02:08:16 rgb ++ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. ++ * Removed dead code. ++ * ++ * Revision 1.16 1999/01/22 06:25:26 rgb ++ * Cruft clean-out. ++ * Added algorithm switch code. ++ * 64-bit clean-up. ++ * Passthrough on IPIP protocol, spi 0x0 fix. ++ * Enhanced debugging. ++ * ++ * Revision 1.15 1998/12/01 13:22:04 rgb ++ * Added support for debug printing of version info. ++ * ++ * Revision 1.14 1998/11/30 13:22:55 rgb ++ * Rationalised all the klips kernel file headers. They are much shorter ++ * now and won't conflict under RH5.2. ++ * ++ * Revision 1.13 1998/11/17 21:13:52 rgb ++ * Put IKE port bypass debug output in user-switched debug statements. ++ * ++ * Revision 1.12 1998/11/13 13:20:25 rgb ++ * Fixed ntohs bug in udp/500 hole for IKE. ++ * ++ * Revision 1.11 1998/11/10 08:01:19 rgb ++ * Kill tcp/500 hole, keep udp/500 hole. ++ * ++ * Revision 1.10 1998/11/09 21:29:26 rgb ++ * If no eroute is found, discard packet and incr. tx_error. ++ * ++ * Revision 1.9 1998/10/31 06:50:00 rgb ++ * Add tcp/udp/500 bypass. ++ * Fixed up comments in #endif directives. ++ * ++ * Revision 1.8 1998/10/27 00:34:31 rgb ++ * Reformat debug output of IP headers. ++ * Newlines added before calls to ipsec_print_ip. ++ * ++ * Revision 1.7 1998/10/19 14:44:28 rgb ++ * Added inclusion of freeswan.h. ++ * sa_id structure implemented and used: now includes protocol. ++ * ++ * Revision 1.6 1998/10/09 04:31:35 rgb ++ * Added 'klips_debug' prefix to all klips printk debug statements. ++ * ++ * Revision 1.5 1998/08/28 03:09:51 rgb ++ * Prevent kernel log spam with default route through ipsec. ++ * ++ * Revision 1.4 1998/08/05 22:23:09 rgb ++ * Change setdev return code to ENXIO for a non-existant physical device. ++ * ++ * Revision 1.3 1998/07/29 20:41:11 rgb ++ * Add ipsec_tunnel_clear to clear all tunnel attachments. ++ * ++ * Revision 1.2 1998/06/25 20:00:33 rgb ++ * Clean up #endif comments. ++ * Rename dev_ipsec to dev_ipsec0 for consistency. ++ * Document ipsec device fields. ++ * Make ipsec_tunnel_probe visible from rest of kernel for static linking. ++ * Get debugging report for *every* ipsec device initialisation. ++ * Comment out redundant code. ++ * ++ * Revision 1.1 1998/06/18 21:27:50 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.8 1998/06/14 23:49:40 rgb ++ * Clarify version reporting on module loading. ++ * ++ * Revision 1.7 1998/05/27 23:19:20 rgb ++ * Added version reporting. ++ * ++ * Revision 1.6 1998/05/18 21:56:23 rgb ++ * Clean up for numerical consistency of output and cleaning up debug code. ++ * ++ * Revision 1.5 1998/05/12 02:44:23 rgb ++ * Clarifying 'no e-route to host' message. ++ * ++ * Revision 1.4 1998/04/30 15:34:35 rgb ++ * Enclosed most remaining debugging statements in #ifdef's to make it quieter. ++ * ++ * Revision 1.3 1998/04/21 21:28:54 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.2 1998/04/12 22:03:24 rgb ++ * Updated ESP-3DES-HMAC-MD5-96, ++ * ESP-DES-HMAC-MD5-96, ++ * AH-HMAC-MD5-96, ++ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository ++ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. ++ * ++ * Fixed eroute references in /proc/net/ipsec*. ++ * ++ * Started to patch module unloading memory leaks in ipsec_netlink and ++ * radij tree unloading. ++ * ++ * Revision 1.1 1998/04/09 03:06:12 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:04 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.5 1997/06/03 04:24:48 ji ++ * Added transport mode. ++ * Changed the way routing is done. ++ * Lots of bug fixes. ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * No changes. ++ * ++ * Revision 0.3 1996/11/20 14:39:04 ji ++ * Minor cleanups. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * Local Variables: ++ * c-style: linux ++ * End: ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_xform.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,351 @@ ++/* ++ * Common routines for IPSEC transformations. ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: ipsec_xform.c,v 1.63 2003/10/31 02:27:55 mcr Exp $ ++ */ ++ ++#include <linux/config.h> ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "freeswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#include <linux/random.h> /* get_random_bytes() */ ++#include <freeswan.h> ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++#endif ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include "freeswan/radij.h" ++#include "freeswan/ipsec_encap.h" ++#include "freeswan/ipsec_radij.h" ++#include "freeswan/ipsec_xform.h" ++#include "freeswan/ipsec_ipe4.h" ++#include "freeswan/ipsec_ah.h" ++#include "freeswan/ipsec_esp.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_xform = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++#ifdef SPINLOCK ++spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED; ++#else /* SPINLOCK */ ++spinlock_t tdb_lock; ++#endif /* SPINLOCK */ ++ ++/* ++ * $Log: ipsec_xform.c,v $ ++ * Revision 1.63 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.62.30.1 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.62 2002/05/14 02:34:21 rgb ++ * Delete stale code. ++ * ++ * Revision 1.61 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.60 2002/04/24 07:36:33 mcr ++ * Moved from ./klips/net/ipsec/ipsec_xform.c,v ++ * ++ * Revision 1.59 2002/03/29 15:01:36 rgb ++ * Delete decommissioned code. ++ * ++ * Revision 1.58 2002/01/29 17:17:57 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.57 2002/01/29 04:00:53 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.56 2001/11/27 05:17:22 mcr ++ * turn off the worst of the per-packet debugging. ++ * ++ * Revision 1.55 2001/11/26 09:23:50 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.54 2001/10/18 04:45:21 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/freeswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.53 2001/09/08 21:13:34 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * ++ * Revision 1.52 2001/06/14 19:35:11 rgb ++ * Update copyright date. ++ * ++ * Revision 1.51 2001/05/30 08:14:03 rgb ++ * Removed vestiges of esp-null transforms. ++ * ++ * Revision 1.50 2001/05/03 19:43:18 rgb ++ * Initialise error return variable. ++ * Update SENDERR macro. ++ * Fix sign of error return code for ipsec_tdbcleanup(). ++ * Use more appropriate return code for ipsec_tdbwipe(). ++ * ++ * Revision 1.49 2001/04/19 18:56:17 rgb ++ * Fixed tdb table locking comments. ++ * ++ * Revision 1.48 2001/02/27 22:24:55 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.47 2000/11/06 04:32:08 rgb ++ * Ditched spin_lock_irqsave in favour of spin_lock_bh. ++ * ++ * Revision 1.46 2000/09/20 16:21:57 rgb ++ * Cleaned up ident string alloc/free. ++ * ++ * Revision 1.45 2000/09/08 19:16:51 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * Removed all references to CONFIG_IPSEC_PFKEYv2. ++ * ++ * Revision 1.44 2000/08/30 05:29:04 rgb ++ * Compiler-define out no longer used tdb_init() in ipsec_xform.c. ++ * ++ * Revision 1.43 2000/08/18 21:30:41 rgb ++ * Purged all tdb_spi, tdb_proto and tdb_dst macros. They are unclear. ++ * ++ * Revision 1.42 2000/08/01 14:51:51 rgb ++ * Removed _all_ remaining traces of DES. ++ * ++ * Revision 1.41 2000/07/28 14:58:31 rgb ++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. ++ * ++ * Revision 1.40 2000/06/28 05:50:11 rgb ++ * Actually set iv_bits. ++ * ++ * Revision 1.39 2000/05/10 23:11:09 rgb ++ * Added netlink debugging output. ++ * Added a cast to quiet down the ntohl bug. ++ * ++ * Revision 1.38 2000/05/10 19:18:42 rgb ++ * Cast output of ntohl so that the broken prototype doesn't make our ++ * compile noisy. ++ * ++ * Revision 1.37 2000/03/16 14:04:59 rgb ++ * Hardwired CONFIG_IPSEC_PFKEYv2 on. ++ * ++ * Revision 1.36 2000/01/26 10:11:28 rgb ++ * Fixed spacing in error text causing run-in words. ++ * ++ * Revision 1.35 2000/01/21 06:17:16 rgb ++ * Tidied up compiler directive indentation for readability. ++ * Added ictx,octx vars for simplification.(kravietz) ++ * Added macros for HMAC padding magic numbers.(kravietz) ++ * Fixed missing key length reporting bug. ++ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in. ++ * ++ * Revision 1.34 1999/12/08 00:04:19 rgb ++ * Fixed SA direction overwriting bug for netlink users. ++ * ++ * Revision 1.33 1999/12/01 22:16:44 rgb ++ * Minor formatting changes in ESP MD5 initialisation. ++ * ++ * Revision 1.32 1999/11/25 09:06:36 rgb ++ * Fixed error return messages, should be returning negative numbers. ++ * Implemented SENDERR macro for propagating error codes. ++ * Added debug message and separate error code for algorithms not compiled ++ * in. ++ * ++ * Revision 1.31 1999/11/23 23:06:26 rgb ++ * Sort out pfkey and freeswan headers, putting them in a library path. ++ * ++ * Revision 1.30 1999/11/18 04:09:20 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * ++ * Revision 1.29 1999/11/17 15:53:40 rgb ++ * Changed all occurrences of #include "../../../lib/freeswan.h" ++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the ++ * klips/net/ipsec/Makefile. ++ * ++ * Revision 1.28 1999/10/18 20:04:01 rgb ++ * Clean-out unused cruft. ++ * ++ * Revision 1.27 1999/10/03 19:01:03 rgb ++ * Spinlock support for 2.3.xx and 2.0.xx kernels. ++ * ++ * Revision 1.26 1999/10/01 16:22:24 rgb ++ * Switch from assignment init. to functional init. of spinlocks. ++ * ++ * Revision 1.25 1999/10/01 15:44:54 rgb ++ * Move spinlock header include to 2.1> scope. ++ * ++ * Revision 1.24 1999/10/01 00:03:46 rgb ++ * Added tdb structure locking. ++ * Minor formatting changes. ++ * Add function to initialize tdb hash table. ++ * ++ * Revision 1.23 1999/05/25 22:42:12 rgb ++ * Add deltdbchain() debugging. ++ * ++ * Revision 1.22 1999/05/25 21:24:31 rgb ++ * Add debugging statements to deltdbchain(). ++ * ++ * Revision 1.21 1999/05/25 03:51:48 rgb ++ * Refix error return code. ++ * ++ * Revision 1.20 1999/05/25 03:34:07 rgb ++ * Fix error return for flush. ++ * ++ * Revision 1.19 1999/05/09 03:25:37 rgb ++ * Fix bug introduced by 2.2 quick-and-dirty patch. ++ * ++ * Revision 1.18 1999/05/05 22:02:32 rgb ++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>. ++ * ++ * Revision 1.17 1999/04/29 15:20:16 rgb ++ * Change gettdb parameter to a pointer to reduce stack loading and ++ * facilitate parameter sanity checking. ++ * Add sanity checking for null pointer arguments. ++ * Add debugging instrumentation. ++ * Add function deltdbchain() which will take care of unlinking, ++ * zeroing and deleting a chain of tdbs. ++ * Add a parameter to tdbcleanup to be able to delete a class of SAs. ++ * tdbwipe now actually zeroes the tdb as well as any of its pointed ++ * structures. ++ * ++ * Revision 1.16 1999/04/16 15:36:29 rgb ++ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing. ++ * ++ * Revision 1.15 1999/04/11 00:29:01 henry ++ * GPL boilerplate ++ * ++ * Revision 1.14 1999/04/06 04:54:28 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.13 1999/02/19 18:23:01 rgb ++ * Nix debug off compile warning. ++ * ++ * Revision 1.12 1999/02/17 16:52:16 rgb ++ * Consolidate satoa()s for space and speed efficiency. ++ * Convert DEBUG_IPSEC to KLIPS_PRINT ++ * Clean out unused cruft. ++ * Ditch NET_IPIP dependancy. ++ * Loop for 3des key setting. ++ * ++ * Revision 1.11 1999/01/26 02:09:05 rgb ++ * Remove ah/esp/IPIP switching on include files. ++ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. ++ * Removed dead code. ++ * Clean up debug code when switched off. ++ * Remove references to INET_GET_PROTOCOL. ++ * Added code exclusion macros to reduce code from unused algorithms. ++ * ++ * Revision 1.10 1999/01/22 06:28:55 rgb ++ * Cruft clean-out. ++ * Put random IV generation in kernel. ++ * Added algorithm switch code. ++ * Enhanced debugging. ++ * 64-bit clean-up. ++ * ++ * Revision 1.9 1998/11/30 13:22:55 rgb ++ * Rationalised all the klips kernel file headers. They are much shorter ++ * now and won't conflict under RH5.2. ++ * ++ * Revision 1.8 1998/11/25 04:59:06 rgb ++ * Add conditionals for no IPIP tunnel code. ++ * Delete commented out code. ++ * ++ * Revision 1.7 1998/10/31 06:50:41 rgb ++ * Convert xform ASCII names to no spaces. ++ * Fixed up comments in #endif directives. ++ * ++ * Revision 1.6 1998/10/19 14:44:28 rgb ++ * Added inclusion of freeswan.h. ++ * sa_id structure implemented and used: now includes protocol. ++ * ++ * Revision 1.5 1998/10/09 04:32:19 rgb ++ * Added 'klips_debug' prefix to all klips printk debug statements. ++ * ++ * Revision 1.4 1998/08/12 00:11:31 rgb ++ * Added new xform functions to the xform table. ++ * Fixed minor debug output spelling error. ++ * ++ * Revision 1.3 1998/07/09 17:45:31 rgb ++ * Clarify algorithm not available message. ++ * ++ * Revision 1.2 1998/06/23 03:00:51 rgb ++ * Check for presence of IPIP protocol if it is setup one way (we don't ++ * know what has been set up the other way and can only assume it will be ++ * symmetrical with the exception of keys). ++ * ++ * Revision 1.1 1998/06/18 21:27:51 henry ++ * move sources from klips/src to klips/net/ipsec, to keep stupid ++ * kernel-build scripts happier in the presence of symlinks ++ * ++ * Revision 1.3 1998/06/11 05:54:59 rgb ++ * Added transform version string pointer to xformsw initialisations. ++ * ++ * Revision 1.2 1998/04/21 21:28:57 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.1 1998/04/09 03:06:13 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:02 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.5 1997/06/03 04:24:48 ji ++ * Added ESP-3DES-MD5-96 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * Added new transforms. ++ * ++ * Revision 0.3 1996/11/20 14:39:04 ji ++ * Minor cleanups. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/ipsec_xmit.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1869 @@ ++/* ++ * IPSEC Transmit code. ++ * Copyright (C) 1996, 1997 John Ioannidis. ++ * Copyright (C) 1998-2003 Richard Guy Briggs. ++ * Copyright (C) 2004 Michael Richardson <mcr@xelerance.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++char ipsec_xmit_c_version[] = "RCSID $Id: ipsec_xmit.c,v 1.8 2004/04/06 02:49:26 mcr Exp $"; ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/config.h> /* for CONFIG_IP_FORWARD */ ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/tcp.h> /* struct tcphdr */ ++#include <linux/udp.h> /* struct udphdr */ ++#include <linux/skbuff.h> ++#include <openswan.h> ++#ifdef NET_21 ++# define MSS_HACK_ /* experimental */ ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# include <net/dst.h> ++# define proto_priv cb ++#endif /* NET_21 */ ++#include <asm/checksum.h> ++#include <net/icmp.h> /* icmp_send() */ ++#include <net/ip.h> ++#ifdef NETDEV_23 ++# include <linux/netfilter_ipv4.h> ++#endif /* NETDEV_23 */ ++ ++#include <linux/if_arp.h> ++#ifdef MSS_HACK ++# include <net/tcp.h> /* TCP options */ ++#endif /* MSS_HACK */ ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_life.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_eroute.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xmit.h" ++#include "openswan/ipsec_sa.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_ipe4.h" ++#include "openswan/ipsec_ah.h" ++#include "openswan/ipsec_esp.h" ++ ++#ifdef CONFIG_IPSEC_IPCOMP ++#include "openswan/ipcomp.h" ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_proto.h" ++#include "openswan/ipsec_alg.h" ++ ++ ++/* ++ * Stupid kernel API differences in APIs. Not only do some ++ * kernels not have ip_select_ident, but some have differing APIs, ++ * and SuSE has one with one parameter, but no way of checking to ++ * see what is really what. ++ */ ++ ++#ifdef SUSE_LINUX_2_4_19_IS_STUPID ++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph) ++#else ++ ++/* simplest case, nothing */ ++#if !defined(IP_SELECT_IDENT) ++#define KLIPS_IP_SELECT_IDENT(iph, skb) do { iph->id = htons(ip_id_count++); } while(0) ++#endif ++ ++/* kernels > 2.3.37-ish */ ++#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW) ++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst) ++#endif ++ ++/* kernels > 2.4.2 */ ++#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW) ++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL) ++#endif ++ ++#endif /* SUSE_LINUX_2_4_19_IS_STUPID */ ++ ++ ++static __u32 zeroes[64]; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int sysctl_ipsec_debug_verbose = 0; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++int ipsec_xmit_trap_count = 0; ++int ipsec_xmit_trap_sendcount = 0; ++ ++int sysctl_ipsec_icmp = 0; ++int sysctl_ipsec_tos = 0; ++ ++#ifdef CONFIG_IPSEC_DEBUG_ ++DEBUG_NO_STATIC void ++dmp(char *s, caddr_t bb, int len) ++{ ++ int i; ++ unsigned char *b = bb; ++ ++ if (debug_tunnel) { ++ printk(KERN_INFO "klips_debug:ipsec_tunnel_:dmp: " ++ "at %s, len=%d:", ++ s, ++ len); ++ for (i=0; i < len; i++) { ++ if(!(i%16)){ ++ printk("\nklips_debug: "); ++ } ++ printk(" %02x", *b++); ++ } ++ printk("\n"); ++ } ++} ++#else /* CONFIG_IPSEC_DEBUG */ ++#define dmp(_x, _y, _z) ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++#ifndef SKB_COPY_EXPAND ++/* ++ * This is mostly skbuff.c:skb_copy(). ++ */ ++struct sk_buff * ++skb_copy_expand(struct sk_buff *skb, int headroom, int tailroom, int priority) ++{ ++ struct sk_buff *n; ++ unsigned long offset; ++ ++ /* ++ * Do sanity checking ++ */ ++ if((headroom < 0) || (tailroom < 0) || ((headroom+tailroom) < 0)) { ++ printk(KERN_WARNING ++ "klips_error:skb_copy_expand: " ++ "Illegal negative head,tailroom %d,%d\n", ++ headroom, ++ tailroom); ++ return NULL; ++ } ++ /* ++ * Allocate the copy buffer ++ */ ++ ++#ifndef NET_21 ++ IS_SKB(skb); ++#endif /* !NET_21 */ ++ ++ ++ n=alloc_skb(skb->end - skb->head + headroom + tailroom, priority); ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:skb_copy_expand: " ++ "allocating %d bytes, head=0p%p data=0p%p tail=0p%p end=0p%p end-head=%d tail-data=%d\n", ++ skb->end - skb->head + headroom + tailroom, ++ skb->head, ++ skb->data, ++ skb->tail, ++ skb->end, ++ skb->end - skb->head, ++ skb->tail - skb->data); ++ ++ if(n==NULL) ++ return NULL; ++ ++ /* ++ * Shift between the two data areas in bytes ++ */ ++ ++ /* Set the data pointer */ ++ skb_reserve(n,skb->data-skb->head+headroom); ++ /* Set the tail pointer and length */ ++ if(skb_tailroom(n) < skb->len) { ++ printk(KERN_WARNING "klips_error:skb_copy_expand: " ++ "tried to skb_put %ld, %d available. This should never happen, please report.\n", ++ (unsigned long int)skb->len, ++ skb_tailroom(n)); ++ ipsec_kfree_skb(n); ++ return NULL; ++ } ++ skb_put(n,skb->len); ++ ++ offset=n->head + headroom - skb->head; ++ ++ /* Copy the bytes */ ++ memcpy(n->head + headroom, skb->head,skb->end-skb->head); ++#ifdef NET_21 ++ n->csum=skb->csum; ++ n->priority=skb->priority; ++ n->dst=dst_clone(skb->dst); ++ if(skb->nh.raw) ++ n->nh.raw=skb->nh.raw+offset; ++#ifndef NETDEV_23 ++ n->is_clone=0; ++#endif /* NETDEV_23 */ ++ atomic_set(&n->users, 1); ++ n->destructor = NULL; ++ n->security=skb->security; ++#else /* NET_21 */ ++ n->link3=NULL; ++ n->when=skb->when; ++ if(skb->ip_hdr) ++ n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset); ++ n->saddr=skb->saddr; ++ n->daddr=skb->daddr; ++ n->raddr=skb->raddr; ++ n->seq=skb->seq; ++ n->end_seq=skb->end_seq; ++ n->ack_seq=skb->ack_seq; ++ n->acked=skb->acked; ++ n->free=1; ++ n->arp=skb->arp; ++ n->tries=0; ++ n->lock=0; ++ n->users=0; ++#endif /* NET_21 */ ++ n->protocol=skb->protocol; ++ n->list=NULL; ++ n->sk=NULL; ++ n->dev=skb->dev; ++ if(skb->h.raw) ++ n->h.raw=skb->h.raw+offset; ++ if(skb->mac.raw) ++ n->mac.raw=skb->mac.raw+offset; ++ memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); ++#ifndef NETDEV_23 ++ n->used=skb->used; ++#endif /* !NETDEV_23 */ ++ n->pkt_type=skb->pkt_type; ++ n->stamp=skb->stamp; ++ ++#ifndef NET_21 ++ IS_SKB(n); ++#endif /* !NET_21 */ ++ return n; ++} ++#endif /* !SKB_COPY_EXPAND */ ++ ++#ifdef CONFIG_IPSEC_DEBUG ++void ++ipsec_print_ip(struct iphdr *ip) ++{ ++ char buf[ADDRTOA_BUF]; ++ ++ printk(KERN_INFO "klips_debug: IP:"); ++ printk(" ihl:%d", ip->ihl << 2); ++ printk(" ver:%d", ip->version); ++ printk(" tos:%d", ip->tos); ++ printk(" tlen:%d", ntohs(ip->tot_len)); ++ printk(" id:%d", ntohs(ip->id)); ++ printk(" %s%s%sfrag_off:%d", ++ ip->frag_off & __constant_htons(IP_CE) ? "CE " : "", ++ ip->frag_off & __constant_htons(IP_DF) ? "DF " : "", ++ ip->frag_off & __constant_htons(IP_MF) ? "MF " : "", ++ (ntohs(ip->frag_off) & IP_OFFSET) << 3); ++ printk(" ttl:%d", ip->ttl); ++ printk(" proto:%d", ip->protocol); ++ if(ip->protocol == IPPROTO_UDP) ++ printk(" (UDP)"); ++ if(ip->protocol == IPPROTO_TCP) ++ printk(" (TCP)"); ++ if(ip->protocol == IPPROTO_ICMP) ++ printk(" (ICMP)"); ++ printk(" chk:%d", ntohs(ip->check)); ++ addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf)); ++ printk(" saddr:%s", buf); ++ if(ip->protocol == IPPROTO_UDP) ++ printk(":%d", ++ ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); ++ if(ip->protocol == IPPROTO_TCP) ++ printk(":%d", ++ ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); ++ addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf)); ++ printk(" daddr:%s", buf); ++ if(ip->protocol == IPPROTO_UDP) ++ printk(":%d", ++ ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); ++ if(ip->protocol == IPPROTO_TCP) ++ printk(":%d", ++ ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); ++ if(ip->protocol == IPPROTO_ICMP) ++ printk(" type:code=%d:%d", ++ ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type, ++ ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code); ++ printk("\n"); ++ ++ if(sysctl_ipsec_debug_verbose) { ++ __u8 *c; ++ int i; ++ ++ c = ((__u8*)ip) + ip->ihl*4; ++ for(i = 0; i < ntohs(ip->tot_len) - ip->ihl*4; i++ /*, c++*/) { ++ if(!(i % 16)) { ++ printk(KERN_INFO ++ "klips_debug: @%03x:", ++ i); ++ } ++ printk(" %02x", /***/c[i]); ++ if(!((i + 1) % 16)) { ++ printk("\n"); ++ } ++ } ++ if(i % 16) { ++ printk("\n"); ++ } ++ } ++} ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++#ifdef MSS_HACK ++/* ++ * Issues: ++ * 1) Fragments arriving in the tunnel should probably be rejected. ++ * 2) How does this affect syncookies, mss_cache, dst cache ? ++ * 3) Path MTU discovery handling needs to be reviewed. For example, ++ * if we receive an ICMP 'packet too big' message from an intermediate ++ * router specifying it's next hop MTU, our stack may process this and ++ * adjust the MSS without taking our AH/ESP overheads into account. ++ */ ++ ++ ++/* ++ * Recaclulate checksum using differences between changed datum, ++ * borrowed from netfilter. ++ */ ++DEBUG_NO_STATIC u_int16_t ++ipsec_fast_csum(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) ++{ ++ u_int32_t diffs[] = { oldvalinv, newval }; ++ return csum_fold(csum_partial((char *)diffs, sizeof(diffs), ++ oldcheck^0xFFFF)); ++} ++ ++/* ++ * Determine effective MSS. ++ * ++ * Note that we assume that there is always an MSS option for our own ++ * SYN segments, which is mentioned in tcp_syn_build_options(), kernel 2.2.x. ++ * This could change, and we should probably parse TCP options instead. ++ * ++ */ ++DEBUG_NO_STATIC u_int8_t ++ipsec_adjust_mss(struct sk_buff *skb, struct tcphdr *tcph, u_int16_t mtu) ++{ ++ u_int16_t oldmss, newmss; ++ u_int32_t *mssp; ++ struct sock *sk = skb->sk; ++ ++ newmss = tcp_sync_mss(sk, mtu); ++ printk(KERN_INFO "klips: setting mss to %u\n", newmss); ++ mssp = (u_int32_t *)tcph + sizeof(struct tcphdr) / sizeof(u_int32_t); ++ oldmss = ntohl(*mssp) & 0x0000FFFF; ++ *mssp = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | newmss); ++ tcph->check = ipsec_fast_csum(htons(~oldmss), ++ htons(newmss), tcph->check); ++ return 1; ++} ++#endif /* MSS_HACK */ ++ ++/* ++ * Sanity checks ++ */ ++enum ipsec_xmit_value ++ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs) ++{ ++ ++ if (ixs->dev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_error:ipsec_xmit_sanity_check_dev: " ++ "No device associated with skb!\n" ); ++ return IPSEC_XMIT_NODEV; ++ } ++ ++ ixs->prv = ixs->dev->priv; ++ if (ixs->prv == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_error:ipsec_xmit_sanity_check_dev: " ++ "Device has no private structure!\n" ); ++ return IPSEC_XMIT_NOPRIVDEV; ++ } ++ ++ ixs->physdev = ixs->prv->dev; ++ if (ixs->physdev == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_error:ipsec_xmit_sanity_check_dev: " ++ "Device is not attached to physical device!\n" ); ++ return IPSEC_XMIT_NOPHYSDEV; ++ } ++ ++ ixs->physmtu = ixs->physdev->mtu; ++ ++ ixs->stats = (struct net_device_stats *) &(ixs->prv->mystats); ++ ++ return IPSEC_XMIT_OK; ++} ++ ++enum ipsec_xmit_value ++ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs) ++{ ++ /* ++ * Return if there is nothing to do. (Does this ever happen?) XXX ++ */ ++ if (ixs->skb == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_error:ipsec_xmit_sanity_check_skb: " ++ "Nothing to do!\n" ); ++ return IPSEC_XMIT_NOSKB; ++ } ++#ifdef NET_21 ++ /* if skb was cloned (most likely due to a packet sniffer such as ++ tcpdump being momentarily attached to the interface), make ++ a copy of our own to modify */ ++ if(skb_cloned(ixs->skb)) { ++ if ++#ifdef SKB_COW_NEW ++ (skb_cow(ixs->skb, skb_headroom(ixs->skb)) != 0) ++#else /* SKB_COW_NEW */ ++ ((ixs->skb = skb_cow(ixs->skb, skb_headroom(ixs->skb))) == NULL) ++#endif /* SKB_COW_NEW */ ++ { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_error:ipsec_xmit_sanity_check_skb: " ++ "skb_cow failed to allocate buffer, dropping.\n" ); ++ ixs->stats->tx_dropped++; ++ return IPSEC_XMIT_ERRSKBALLOC; ++ } ++ } ++#endif /* NET_21 */ ++ ++#ifdef NET_21 ++ ixs->iph = ixs->skb->nh.iph; ++#else /* NET_21 */ ++ ixs->iph = ixs->skb->ip_hdr; ++#endif /* NET_21 */ ++ ++ /* sanity check for IP version as we can't handle IPv6 right now */ ++ if (ixs->iph->version != 4) { ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_xmit_sanity_check_skb: " ++ "found IP Version %d but cannot process other IP versions than v4.\n", ++ ixs->iph->version); /* XXX */ ++ ixs->stats->tx_dropped++; ++ return IPSEC_XMIT_NOIPV6; ++ } ++ ++#if IPSEC_DISALLOW_IPOPTIONS ++ if ((ixs->iph->ihl << 2) != sizeof (struct iphdr)) { ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_xmit_sanity_check_skb: " ++ "cannot process IP header options yet. May be mal-formed packet.\n"); /* XXX */ ++ ixs->stats->tx_dropped++; ++ return IPSEC_XMIT_NOIPOPTIONS; ++ } ++#endif /* IPSEC_DISALLOW_IPOPTIONS */ ++ ++#ifndef NET_21 ++ if (ixs->iph->ttl <= 0) { ++ /* Tell the sender its packet died... */ ++ ICMP_SEND(ixs->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, ixs->physdev); ++ ++ KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xmit_sanity_check_skb: " ++ "TTL=0, too many hops!\n"); ++ ixs->stats->tx_dropped++; ++ return IPSEC_XMIT_TTLEXPIRED; ++ } ++#endif /* !NET_21 */ ++ ++ return IPSEC_XMIT_OK; ++} ++ ++enum ipsec_xmit_value ++ipsec_xmit_encap_once(struct ipsec_xmit_state *ixs) ++{ ++#ifdef CONFIG_IPSEC_ESP ++ struct esphdr *espp; ++#ifdef CONFIG_IPSEC_ENC_3DES ++ __u32 iv[ESP_IV_MAXSZ_INT]; ++#endif /* !CONFIG_IPSEC_ENC_3DES */ ++ unsigned char *idat, *pad; ++ int authlen = 0, padlen = 0, i; ++#endif /* !CONFIG_IPSEC_ESP */ ++#ifdef CONFIG_IPSEC_AH ++ struct iphdr ipo; ++ struct ahhdr *ahp; ++#endif /* CONFIG_IPSEC_AH */ ++#if defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) ++ union { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ MD5_CTX md5; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ SHA1_CTX sha1; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ } tctx; ++ __u8 hash[AH_AMAX]; ++#endif /* defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) */ ++ int headroom = 0, tailroom = 0, ilen = 0, len = 0; ++ unsigned char *dat; ++ int blocksize = 8; /* XXX: should be inside ixs --jjo */ ++#ifdef CONFIG_IPSEC_ALG ++ struct ipsec_alg_enc *ixt_e = NULL; ++ struct ipsec_alg_auth *ixt_a = NULL; ++#endif /* CONFIG_IPSEC_ALG */ ++ ++ ixs->iphlen = ixs->iph->ihl << 2; ++ ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen; ++ ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, SATOT_BUF); ++ KLIPS_PRINT(debug_tunnel & DB_TN_OXFS, ++ "klips_debug:ipsec_xmit_encap_once: " ++ "calling output for <%s%s%s>, SA:%s\n", ++ IPS_XFORM_NAME(ixs->ipsp), ++ ixs->sa_len ? ixs->sa_txt : " (error)"); ++ ++ switch(ixs->ipsp->ips_said.proto) { ++#ifdef CONFIG_IPSEC_AH ++ case IPPROTO_AH: ++ headroom += sizeof(struct ahhdr); ++ break; ++#endif /* CONFIG_IPSEC_AH */ ++#ifdef CONFIG_IPSEC_ESP ++ case IPPROTO_ESP: ++#ifdef CONFIG_IPSEC_ALG ++ if ((ixt_e=ixs->ipsp->ips_alg_enc)) { ++ blocksize = ixt_e->ixt_blocksize; ++ headroom += ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ixs->ipsp->ips_encalg) { ++#ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++ headroom += sizeof(struct esphdr); ++ break; ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_BADALG; ++ } ++#ifdef CONFIG_IPSEC_ALG ++ if ((ixt_a=ixs->ipsp->ips_alg_auth)) { ++ tailroom += AHHMAC_HASHLEN; ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ixs->ipsp->ips_authalg) { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ case AH_MD5: ++ authlen = AHHMAC_HASHLEN; ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ case AH_SHA: ++ authlen = AHHMAC_HASHLEN; ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ case AH_NONE: ++ break; ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_BADALG; ++ } ++#ifdef CONFIG_IPSEC_ALG ++ tailroom += blocksize != 1 ? ++ ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : ++ ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; ++#else ++ tailroom += ((8 - ((ixs->pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2; ++#endif /* CONFIG_IPSEC_ALG */ ++ tailroom += authlen; ++ break; ++#endif /* !CONFIG_IPSEC_ESP */ ++#ifdef CONFIG_IPSEC_IPIP ++ case IPPROTO_IPIP: ++ headroom += sizeof(struct iphdr); ++ ixs->iphlen = sizeof(struct iphdr); ++ break; ++#endif /* !CONFIG_IPSEC_IPIP */ ++#ifdef CONFIG_IPSEC_IPCOMP ++ case IPPROTO_COMP: ++ break; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_BADPROTO; ++ } ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_once: " ++ "pushing %d bytes, putting %d, proto %d.\n", ++ headroom, tailroom, ixs->ipsp->ips_said.proto); ++ if(skb_headroom(ixs->skb) < headroom) { ++ printk(KERN_WARNING ++ "klips_error:ipsec_xmit_encap_once: " ++ "tried to skb_push headroom=%d, %d available. This should never happen, please report.\n", ++ headroom, skb_headroom(ixs->skb)); ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_PUSHPULLERR; ++ } ++ dat = skb_push(ixs->skb, headroom); ++ ilen = ixs->skb->len - tailroom; ++ if(skb_tailroom(ixs->skb) < tailroom) { ++ printk(KERN_WARNING ++ "klips_error:ipsec_xmit_encap_once: " ++ "tried to skb_put %d, %d available. This should never happen, please report.\n", ++ tailroom, skb_tailroom(ixs->skb)); ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_PUSHPULLERR; ++ } ++ skb_put(ixs->skb, tailroom); ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_once: " ++ "head,tailroom: %d,%d before xform.\n", ++ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); ++ len = ixs->skb->len; ++ if(len > 0xfff0) { ++ printk(KERN_WARNING "klips_error:ipsec_xmit_encap_once: " ++ "tot_len (%d) > 65520. This should never happen, please report.\n", ++ len); ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_BADLEN; ++ } ++ memmove((void *)dat, (void *)(dat + headroom), ixs->iphlen); ++ ixs->iph = (struct iphdr *)dat; ++ ixs->iph->tot_len = htons(ixs->skb->len); ++ ++ switch(ixs->ipsp->ips_said.proto) { ++#ifdef CONFIG_IPSEC_ESP ++ case IPPROTO_ESP: ++ espp = (struct esphdr *)(dat + ixs->iphlen); ++ espp->esp_spi = ixs->ipsp->ips_said.spi; ++ espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); ++ ++#ifdef CONFIG_IPSEC_ALG ++ if (!ixt_e) ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ixs->ipsp->ips_encalg) { ++#if defined(CONFIG_IPSEC_ENC_3DES) ++#ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ iv[0] = *((__u32*)&(espp->esp_iv) ) = ++ ((__u32*)(ixs->ipsp->ips_iv))[0]; ++ iv[1] = *((__u32*)&(espp->esp_iv) + 1) = ++ ((__u32*)(ixs->ipsp->ips_iv))[1]; ++ break; ++#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_BADALG; ++ } ++ ++ idat = dat + ixs->iphlen + headroom; ++ ilen = len - (ixs->iphlen + headroom + authlen); ++ ++ /* Self-describing padding */ ++ pad = &dat[len - tailroom]; ++ padlen = tailroom - 2 - authlen; ++ for (i = 0; i < padlen; i++) { ++ pad[i] = i + 1; ++ } ++ dat[len - authlen - 2] = padlen; ++ ++ dat[len - authlen - 1] = ixs->iph->protocol; ++ ixs->iph->protocol = IPPROTO_ESP; ++ ++#ifdef CONFIG_IPSEC_ALG ++ /* Do all operations here: ++ * copy IV->ESP, encrypt, update ips IV ++ */ ++ if (ixt_e) { ++ int ret; ++ memcpy(espp->esp_iv, ++ ixs->ipsp->ips_iv, ++ ixt_e->ixt_ivlen/8); ++ ret=ipsec_alg_esp_encrypt(ixs->ipsp, ++ idat, ilen, espp->esp_iv, ++ IPSEC_ALG_ENCRYPT); ++ memcpy(ixs->ipsp->ips_iv, ++ idat + ilen - ixt_e->ixt_ivlen/8, ++ ixt_e->ixt_ivlen/8); ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ixs->ipsp->ips_encalg) { ++#ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++ des_ede3_cbc_encrypt((des_cblock *)idat, ++ (des_cblock *)idat, ++ ilen, ++ ((struct des_eks *)(ixs->ipsp->ips_key_e))[0].ks, ++ ((struct des_eks *)(ixs->ipsp->ips_key_e))[1].ks, ++ ((struct des_eks *)(ixs->ipsp->ips_key_e))[2].ks, ++ (des_cblock *)iv, 1); ++ break; ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_BADALG; ++ } ++ ++#ifdef CONFIG_IPSEC_ALG ++ if (!ixt_e) ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ixs->ipsp->ips_encalg) { ++#if defined(CONFIG_IPSEC_ENC_3DES) ++#ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ /* XXX update IV with the last 8 octets of the encryption */ ++#if KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK ++ ((__u32*)(ixs->ipsp->ips_iv))[0] = ++ ((__u32 *)(idat))[(ilen >> 2) - 2]; ++ ((__u32*)(ixs->ipsp->ips_iv))[1] = ++ ((__u32 *)(idat))[(ilen >> 2) - 1]; ++#else /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ ++ prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, EMT_ESPDES_IV_SZ); ++#endif /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ ++ break; ++#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_ESP_BADALG; ++ } ++ ++#ifdef CONFIG_IPSEC_ALG ++ if (ixt_a) { ++ ipsec_alg_sa_esp_hash(ixs->ipsp, ++ (caddr_t)espp, len - ixs->iphlen - authlen, ++ &(dat[len - authlen]), authlen); ++ ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ixs->ipsp->ips_authalg) { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ case AH_MD5: ++ dmp("espp", (char*)espp, len - ixs->iphlen - authlen); ++ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; ++ dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, (caddr_t)espp, len - ixs->iphlen - authlen); ++ dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Final(hash, &tctx.md5); ++ dmp("ictx hash", (char*)&hash, sizeof(hash)); ++ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; ++ dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, hash, AHMD596_ALEN); ++ dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Final(hash, &tctx.md5); ++ dmp("octx hash", (char*)&hash, sizeof(hash)); ++ memcpy(&(dat[len - authlen]), hash, authlen); ++ ++ /* paranoid */ ++ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); ++ memset((caddr_t)hash, 0, sizeof(*hash)); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ case AH_SHA: ++ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; ++ SHA1Update(&tctx.sha1, (caddr_t)espp, len - ixs->iphlen - authlen); ++ SHA1Final(hash, &tctx.sha1); ++ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; ++ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); ++ SHA1Final(hash, &tctx.sha1); ++ memcpy(&(dat[len - authlen]), hash, authlen); ++ ++ /* paranoid */ ++ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); ++ memset((caddr_t)hash, 0, sizeof(*hash)); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ case AH_NONE: ++ break; ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_AH_BADALG; ++ } ++#ifdef NET_21 ++ ixs->skb->h.raw = (unsigned char*)espp; ++#endif /* NET_21 */ ++ break; ++#endif /* !CONFIG_IPSEC_ESP */ ++#ifdef CONFIG_IPSEC_AH ++ case IPPROTO_AH: ++ ahp = (struct ahhdr *)(dat + ixs->iphlen); ++ ahp->ah_spi = ixs->ipsp->ips_said.spi; ++ ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); ++ ahp->ah_rv = 0; ++ ahp->ah_nh = ixs->iph->protocol; ++ ahp->ah_hl = (headroom >> 2) - sizeof(__u64)/sizeof(__u32); ++ ixs->iph->protocol = IPPROTO_AH; ++ dmp("ahp", (char*)ahp, sizeof(*ahp)); ++ ++ ipo = *ixs->iph; ++ ipo.tos = 0; ++ ipo.frag_off = 0; ++ ipo.ttl = 0; ++ ipo.check = 0; ++ dmp("ipo", (char*)&ipo, sizeof(ipo)); ++ ++ switch(ixs->ipsp->ips_authalg) { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ case AH_MD5: ++ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; ++ dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); ++ dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); ++ dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); ++ dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom); ++ dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Final(hash, &tctx.md5); ++ dmp("ictx hash", (char*)&hash, sizeof(hash)); ++ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; ++ dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Update(&tctx.md5, hash, AHMD596_ALEN); ++ dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); ++ MD5Final(hash, &tctx.md5); ++ dmp("octx hash", (char*)&hash, sizeof(hash)); ++ ++ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); ++ ++ /* paranoid */ ++ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); ++ memset((caddr_t)hash, 0, sizeof(*hash)); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ case AH_SHA: ++ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; ++ SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr)); ++ SHA1Update(&tctx.sha1, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); ++ SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); ++ SHA1Update(&tctx.sha1, dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom); ++ SHA1Final(hash, &tctx.sha1); ++ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; ++ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); ++ SHA1Final(hash, &tctx.sha1); ++ ++ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); ++ ++ /* paranoid */ ++ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); ++ memset((caddr_t)hash, 0, sizeof(*hash)); ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_AH_BADALG; ++ } ++#ifdef NET_21 ++ ixs->skb->h.raw = (unsigned char*)ahp; ++#endif /* NET_21 */ ++ break; ++#endif /* CONFIG_IPSEC_AH */ ++#ifdef CONFIG_IPSEC_IPIP ++ case IPPROTO_IPIP: ++ ixs->iph->version = 4; ++ switch(sysctl_ipsec_tos) { ++ case 0: ++#ifdef NET_21 ++ ixs->iph->tos = ixs->skb->nh.iph->tos; ++#else /* NET_21 */ ++ ixs->iph->tos = ixs->skb->ip_hdr->tos; ++#endif /* NET_21 */ ++ break; ++ case 1: ++ ixs->iph->tos = 0; ++ break; ++ default: ++ break; ++ } ++#ifdef NET_21 ++#ifdef NETDEV_23 ++ ixs->iph->ttl = sysctl_ip_default_ttl; ++#else /* NETDEV_23 */ ++ ixs->iph->ttl = ip_statistics.IpDefaultTTL; ++#endif /* NETDEV_23 */ ++#else /* NET_21 */ ++ ixs->iph->ttl = 64; /* ip_statistics.IpDefaultTTL; */ ++#endif /* NET_21 */ ++ ixs->iph->frag_off = 0; ++ ixs->iph->saddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr; ++ ixs->iph->daddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr; ++ ixs->iph->protocol = IPPROTO_IPIP; ++ ixs->iph->ihl = sizeof(struct iphdr) >> 2; ++ ++ KLIPS_IP_SELECT_IDENT(ixs->iph, ixs->skb); ++ ++ ixs->newdst = (__u32)ixs->iph->daddr; ++ ixs->newsrc = (__u32)ixs->iph->saddr; ++ ++#ifdef NET_21 ++ ixs->skb->h.ipiph = ixs->skb->nh.iph; ++#endif /* NET_21 */ ++ break; ++#endif /* !CONFIG_IPSEC_IPIP */ ++#ifdef CONFIG_IPSEC_IPCOMP ++ case IPPROTO_COMP: ++ { ++ unsigned int flags = 0; ++#ifdef CONFIG_IPSEC_DEBUG ++ unsigned int old_tot_len = ntohs(ixs->iph->tot_len); ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ixs->ipsp->ips_comp_ratio_dbytes += ntohs(ixs->iph->tot_len); ++ ++ ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags); ++ ++#ifdef NET_21 ++ ixs->iph = ixs->skb->nh.iph; ++#else /* NET_21 */ ++ ixs->iph = ixs->skb->ip_hdr; ++#endif /* NET_21 */ ++ ++ ixs->ipsp->ips_comp_ratio_cbytes += ntohs(ixs->iph->tot_len); ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if (debug_tunnel & DB_TN_CROUT) ++ { ++ if (old_tot_len > ntohs(ixs->iph->tot_len)) ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_once: " ++ "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n", ++ old_tot_len, ntohs(ixs->iph->tot_len), ++ ntohs(((struct ipcomphdr*)(((char*)ixs->iph) + ((ixs->iph->ihl) << 2)))->ipcomp_cpi), ++ ntohl(ixs->ipsp->ips_said.spi), ++ (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff)); ++ else ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_once: " ++ "packet did not compress (flags = %d).\n", ++ flags); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ } ++ break; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ default: ++ ixs->stats->tx_errors++; ++ return IPSEC_XMIT_BADPROTO; ++ } ++ ++#ifdef NET_21 ++ ixs->skb->nh.raw = ixs->skb->data; ++#else /* NET_21 */ ++ ixs->skb->ip_hdr = ixs->skb->h.iph = (struct iphdr *) ixs->skb->data; ++#endif /* NET_21 */ ++ ixs->iph->check = 0; ++ ixs->iph->check = ip_fast_csum((unsigned char *)ixs->iph, ixs->iph->ihl); ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_once: " ++ "after <%s%s%s>, SA:%s:\n", ++ IPS_XFORM_NAME(ixs->ipsp), ++ ixs->sa_len ? ixs->sa_txt : " (error)"); ++ KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); ++ ++ ixs->ipsp->ips_life.ipl_bytes.ipl_count += len; ++ ixs->ipsp->ips_life.ipl_bytes.ipl_last = len; ++ ++ if(!ixs->ipsp->ips_life.ipl_usetime.ipl_count) { ++ ixs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; ++ } ++ ixs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; ++ ixs->ipsp->ips_life.ipl_packets.ipl_count++; ++ ++ ixs->ipsp = ixs->ipsp->ips_onext; ++ ++ return IPSEC_XMIT_OK; ++} ++ ++/* ++ * If the IP packet (iph) is a carrying TCP/UDP, then set the encaps ++ * source and destination ports to those from the TCP/UDP header. ++ */ ++void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er) ++{ ++ struct udphdr *udp; ++ ++ switch (iph->protocol) { ++ case IPPROTO_UDP: ++ case IPPROTO_TCP: ++ /* ++ * The ports are at the same offsets in a TCP and UDP ++ * header so hack it ... ++ */ ++ udp = (struct udphdr*)(((char*)iph)+(iph->ihl<<2)); ++ er->sen_sport = udp->source; ++ er->sen_dport = udp->dest; ++ break; ++ default: ++ er->sen_sport = 0; ++ er->sen_dport = 0; ++ break; ++ } ++} ++ ++/* ++ * A TRAP eroute is installed and we want to replace it with a HOLD ++ * eroute. ++ */ ++static int create_hold_eroute(struct eroute *origtrap, ++ struct sk_buff * skb, struct iphdr * iph, ++ uint32_t eroute_pid) ++{ ++ struct eroute hold_eroute; ++ ip_said hold_said; ++ struct sk_buff *first, *last; ++ int error; ++ ++ first = last = NULL; ++ memset((caddr_t)&hold_eroute, 0, sizeof(hold_eroute)); ++ memset((caddr_t)&hold_said, 0, sizeof(hold_said)); ++ ++ hold_said.proto = IPPROTO_INT; ++ hold_said.spi = htonl(SPI_HOLD); ++ hold_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY; ++ ++ hold_eroute.er_eaddr.sen_len = sizeof(struct sockaddr_encap); ++ hold_eroute.er_emask.sen_len = sizeof(struct sockaddr_encap); ++ hold_eroute.er_eaddr.sen_family = AF_ENCAP; ++ hold_eroute.er_emask.sen_family = AF_ENCAP; ++ hold_eroute.er_eaddr.sen_type = SENT_IP4; ++ hold_eroute.er_emask.sen_type = 255; ++ ++ hold_eroute.er_eaddr.sen_ip_src.s_addr = iph->saddr; ++ hold_eroute.er_eaddr.sen_ip_dst.s_addr = iph->daddr; ++ hold_eroute.er_emask.sen_ip_src.s_addr = INADDR_BROADCAST; ++ hold_eroute.er_emask.sen_ip_dst.s_addr = INADDR_BROADCAST; ++ hold_eroute.er_emask.sen_sport = 0; ++ hold_eroute.er_emask.sen_dport = 0; ++ hold_eroute.er_pid = eroute_pid; ++ hold_eroute.er_count = 0; ++ hold_eroute.er_lasttime = jiffies/HZ; ++ ++ /* ++ * if it wasn't captured by a wildcard, then don't record it as ++ * a wildcard. ++ */ ++ if(origtrap->er_eaddr.sen_proto != 0) { ++ hold_eroute.er_eaddr.sen_proto = iph->protocol; ++ ++ if((iph->protocol == IPPROTO_TCP || ++ iph->protocol == IPPROTO_UDP) && ++ (origtrap->er_eaddr.sen_sport != 0 || ++ origtrap->er_eaddr.sen_dport != 0)) { ++ ++ if(origtrap->er_eaddr.sen_sport != 0) ++ hold_eroute.er_emask.sen_sport = ~0; ++ ++ if(origtrap->er_eaddr.sen_dport != 0) ++ hold_eroute.er_emask.sen_dport = ~0; ++ ++ ipsec_extract_ports(iph, &hold_eroute.er_eaddr); ++ } ++ } ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if (debug_pfkey) { ++ char buf1[64], buf2[64]; ++ subnettoa(hold_eroute.er_eaddr.sen_ip_src, ++ hold_eroute.er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); ++ subnettoa(hold_eroute.er_eaddr.sen_ip_dst, ++ hold_eroute.er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "calling breakeroute and makeroute for %s:%d->%s:%d %d HOLD eroute.\n", ++ buf1, ntohs(hold_eroute.er_eaddr.sen_sport), ++ buf2, ntohs(hold_eroute.er_eaddr.sen_dport), ++ hold_eroute.er_eaddr.sen_proto); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ if (ipsec_breakroute(&(hold_eroute.er_eaddr), &(hold_eroute.er_emask), ++ &first, &last)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "HOLD breakeroute found nothing.\n"); ++ } else { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "HOLD breakroute deleted %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u %u\n", ++ NIPQUAD(hold_eroute.er_eaddr.sen_ip_src), ++ ntohs(hold_eroute.er_eaddr.sen_sport), ++ NIPQUAD(hold_eroute.er_eaddr.sen_ip_dst), ++ ntohs(hold_eroute.er_eaddr.sen_dport), ++ hold_eroute.er_eaddr.sen_proto); ++ } ++ if (first != NULL) ++ kfree_skb(first); ++ if (last != NULL) ++ kfree_skb(last); ++ ++ error = ipsec_makeroute(&(hold_eroute.er_eaddr), ++ &(hold_eroute.er_emask), ++ hold_said, eroute_pid, skb, NULL, NULL); ++ if (error) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "HOLD makeroute returned %d, failed.\n", error); ++ } else { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "HOLD makeroute call successful.\n"); ++ } ++ return (error == 0); ++} ++ ++enum ipsec_xmit_value ++ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs) ++{ ++#ifdef CONFIG_IPSEC_ALG ++ struct ipsec_alg_enc *ixt_e = NULL; ++ struct ipsec_alg_auth *ixt_a = NULL; ++ int blocksize = 8; ++#endif /* CONFIG_IPSEC_ALG */ ++ enum ipsec_xmit_value bundle_stat = IPSEC_XMIT_OK; ++ ++ ixs->newdst = ixs->orgdst = ixs->iph->daddr; ++ ixs->newsrc = ixs->orgsrc = ixs->iph->saddr; ++ ixs->orgedst = ixs->outgoing_said.dst.u.v4.sin_addr.s_addr; ++ ixs->iphlen = ixs->iph->ihl << 2; ++ ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen; ++ ixs->max_headroom = ixs->max_tailroom = 0; ++ ++ if (ixs->outgoing_said.proto == IPPROTO_INT) { ++ switch (ntohl(ixs->outgoing_said.spi)) { ++ case SPI_DROP: ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "shunt SA of DROP or no eroute: dropping.\n"); ++ ixs->stats->tx_dropped++; ++ break; ++ ++ case SPI_REJECT: ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "shunt SA of REJECT: notifying and dropping.\n"); ++ ICMP_SEND(ixs->skb, ++ ICMP_DEST_UNREACH, ++ ICMP_PKT_FILTERED, ++ 0, ++ ixs->physdev); ++ ixs->stats->tx_dropped++; ++ break; ++ ++ case SPI_PASS: ++#ifdef NET_21 ++ ixs->pass = 1; ++#endif /* NET_21 */ ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "PASS: calling dev_queue_xmit\n"); ++ return IPSEC_XMIT_PASS; ++ goto cleanup; ++ ++ case SPI_HOLD: ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "shunt SA of HOLD: this does not make sense here, dropping.\n"); ++ ixs->stats->tx_dropped++; ++ break; ++ ++ case SPI_TRAP: ++ case SPI_TRAPSUBNET: ++ { ++ struct sockaddr_in src, dst; ++#ifdef CONFIG_IPSEC_DEBUG ++ char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF]; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ /* Signal all listening KMds with a PF_KEY ACQUIRE */ ++ ++ src.sin_family = AF_INET; ++ dst.sin_family = AF_INET; ++ src.sin_addr.s_addr = ixs->iph->saddr; ++ dst.sin_addr.s_addr = ixs->iph->daddr; ++ ++ ixs->ips.ips_transport_protocol = 0; ++ src.sin_port = 0; ++ dst.sin_port = 0; ++ { ++ int i; ++ for(i = 0; ++ i < sizeof(struct sockaddr_in) ++ - offsetof(struct sockaddr_in, sin_zero); ++ i++) { ++ src.sin_zero[i] = 0; ++ dst.sin_zero[i] = 0; ++ } ++ } ++ ++ if(ixs->eroute->er_eaddr.sen_proto != 0) { ++ ixs->ips.ips_transport_protocol = ixs->iph->protocol; ++ ++ if(ixs->eroute->er_eaddr.sen_sport != 0) { ++ src.sin_port = ++ (ixs->iph->protocol == IPPROTO_UDP ++ ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->source ++ : (ixs->iph->protocol == IPPROTO_TCP ++ ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->source ++ : 0)); ++ } ++ if(ixs->eroute->er_eaddr.sen_dport != 0) { ++ dst.sin_port = ++ (ixs->iph->protocol == IPPROTO_UDP ++ ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->dest ++ : (ixs->iph->protocol == IPPROTO_TCP ++ ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->dest ++ : 0)); ++ } ++ } ++ ++ ixs->ips.ips_addr_s = (struct sockaddr*)(&src); ++ ixs->ips.ips_addr_d = (struct sockaddr*)(&dst); ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n", ++ addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR", ++ ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_port), ++ addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR", ++ ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_port), ++ ixs->ips.ips_said.proto); ++ ++ /* increment count of total traps needed */ ++ ipsec_xmit_trap_count++; ++ ++ if (pfkey_acquire(&ixs->ips) == 0) { ++ ++ /* note that we succeeded */ ++ ipsec_xmit_trap_sendcount++; ++ ++ if (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)) { ++ /* ++ * The spinlock is to prevent any other ++ * process from accessing or deleting ++ * the eroute while we are using and ++ * updating it. ++ */ ++ spin_lock(&eroute_lock); ++ ixs->eroute = ipsec_findroute(&ixs->matcher); ++ if(ixs->eroute) { ++ ixs->eroute->er_said.spi = htonl(SPI_HOLD); ++ ixs->eroute->er_first = ixs->skb; ++ ixs->skb = NULL; ++ } ++ spin_unlock(&eroute_lock); ++ } else if (create_hold_eroute(ixs->eroute, ++ ixs->skb, ++ ixs->iph, ++ ixs->eroute_pid)) { ++ ixs->skb = NULL; ++ } ++ /* whether or not the above succeeded, we continue */ ++ ++ } ++ ixs->stats->tx_dropped++; ++ } ++ default: ++ /* XXX what do we do with an unknown shunt spi? */ ++ break; ++ } /* switch (ntohl(ixs->outgoing_said.spi)) */ ++ return IPSEC_XMIT_STOLEN; ++ } /* if (ixs->outgoing_said.proto == IPPROTO_INT) */ ++ ++ /* ++ The spinlock is to prevent any other process from ++ accessing or deleting the ipsec_sa hash table or any of the ++ ipsec_sa s while we are using and updating them. ++ ++ This is not optimal, but was relatively straightforward ++ at the time. A better way to do it has been planned for ++ more than a year, to lock the hash table and put reference ++ counts on each ipsec_sa instead. This is not likely to happen ++ in KLIPS1 unless a volunteer contributes it, but will be ++ designed into KLIPS2. ++ */ ++ spin_lock(&tdb_lock); ++ ++ ixs->ipsp = ipsec_sa_getbyid(&ixs->outgoing_said); ++ ixs->sa_len = satot(&ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); ++ ++ if (ixs->ipsp == NULL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "no ipsec_sa for SA%s: outgoing packet with no SA, dropped.\n", ++ ixs->sa_len ? ixs->sa_txt : " (error)"); ++ ixs->stats->tx_dropped++; ++ bundle_stat = IPSEC_XMIT_SAIDNOTFOUND; ++ goto cleanup; ++ } ++ ++ ipsec_sa_put(ixs->ipsp); /* incomplete */ ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "found ipsec_sa -- SA:<%s%s%s> %s\n", ++ IPS_XFORM_NAME(ixs->ipsp), ++ ixs->sa_len ? ixs->sa_txt : " (error)"); ++ ++ /* ++ * How much headroom do we need to be able to apply ++ * all the grouped transforms? ++ */ ++ ixs->ipsq = ixs->ipsp; /* save the head of the ipsec_sa chain */ ++ while (ixs->ipsp) { ++ ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); ++ if(ixs->sa_len == 0) { ++ strcpy(ixs->sa_txt, "(error)"); ++ } ++ ++ /* If it is in larval state, drop the packet, we cannot process yet. */ ++ if(ixs->ipsp->ips_state == SADB_SASTATE_LARVAL) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "ipsec_sa in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n", ++ IPS_XFORM_NAME(ixs->ipsp), ++ ixs->sa_len ? ixs->sa_txt : " (error)"); ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; ++ goto cleanup; ++ } ++ ++ if(ixs->ipsp->ips_state == SADB_SASTATE_DEAD) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "ipsec_sa in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n", ++ IPS_XFORM_NAME(ixs->ipsp), ++ ixs->sa_len ? ixs->sa_txt : " (error)"); ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; ++ goto cleanup; ++ } ++ ++ /* If the replay window counter == -1, expire SA, it will roll */ ++ if(ixs->ipsp->ips_replaywin && ixs->ipsp->ips_replaywin_lastseq == -1) { ++ pfkey_expire(ixs->ipsp, 1); ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n", ++ IPS_XFORM_NAME(ixs->ipsp), ++ ixs->sa_len ? ixs->sa_txt : " (error)"); ++ ipsec_sa_delchain(ixs->ipsp); ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_REPLAYROLLED; ++ goto cleanup; ++ } ++ ++ /* ++ * if this is the first time we are using this SA, mark start time, ++ * and offset hard/soft counters by "now" for later checking. ++ */ ++#if 0 ++ if(ixs->ipsp->ips_life.ipl_usetime.count == 0) { ++ ixs->ipsp->ips_life.ipl_usetime.count = jiffies; ++ ixs->ipsp->ips_life.ipl_usetime.hard += jiffies; ++ ixs->ipsp->ips_life.ipl_usetime.soft += jiffies; ++ } ++#endif ++ ++ ++ if(ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_bytes, "bytes", ixs->sa_txt, ++ ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || ++ ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_addtime, "addtime",ixs->sa_txt, ++ ipsec_life_timebased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || ++ ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_usetime, "usetime",ixs->sa_txt, ++ ipsec_life_timebased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || ++ ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_packets, "packets",ixs->sa_txt, ++ ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied) { ++ ++ ipsec_sa_delchain(ixs->ipsp); ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_LIFETIMEFAILED; ++ goto cleanup; ++ } ++ ++ ++ ixs->headroom = ixs->tailroom = 0; ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "calling room for <%s%s%s>, SA:%s\n", ++ IPS_XFORM_NAME(ixs->ipsp), ++ ixs->sa_len ? ixs->sa_txt : " (error)"); ++ switch(ixs->ipsp->ips_said.proto) { ++#ifdef CONFIG_IPSEC_AH ++ case IPPROTO_AH: ++ ixs->headroom += sizeof(struct ahhdr); ++ break; ++#endif /* CONFIG_IPSEC_AH */ ++#ifdef CONFIG_IPSEC_ESP ++ case IPPROTO_ESP: ++#ifdef CONFIG_IPSEC_ALG ++ if ((ixt_e=ixs->ipsp->ips_alg_enc)) { ++ blocksize = ixt_e->ixt_blocksize; ++ ixs->headroom += ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ixs->ipsp->ips_encalg) { ++#ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++ ixs->headroom += sizeof(struct esphdr); ++ break; ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ default: ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_ESP_BADALG; ++ goto cleanup; ++ } ++#ifdef CONFIG_IPSEC_ALG ++ if ((ixt_a=ixs->ipsp->ips_alg_auth)) { ++ ixs->tailroom += AHHMAC_HASHLEN; ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ixs->ipsp->ips_authalg) { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ case AH_MD5: ++ ixs->tailroom += AHHMAC_HASHLEN; ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ case AH_SHA: ++ ixs->tailroom += AHHMAC_HASHLEN; ++ break; ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ case AH_NONE: ++ break; ++ default: ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_AH_BADALG; ++ goto cleanup; ++ } ++#ifdef CONFIG_IPSEC_ALG ++ ixs->tailroom += blocksize != 1 ? ++ ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : ++ ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; ++#else ++ ixs->tailroom += ((8 - ((ixs->pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2; ++#endif /* CONFIG_IPSEC_ALG */ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if ((ixs->ipsp->ips_natt_type) && (!ixs->natt_type)) { ++ ixs->natt_type = ixs->ipsp->ips_natt_type; ++ ixs->natt_sport = ixs->ipsp->ips_natt_sport; ++ ixs->natt_dport = ixs->ipsp->ips_natt_dport; ++ switch (ixs->natt_type) { ++ case ESPINUDP_WITH_NON_IKE: ++ ixs->natt_head = sizeof(struct udphdr)+(2*sizeof(__u32)); ++ break; ++ ++ case ESPINUDP_WITH_NON_ESP: ++ ixs->natt_head = sizeof(struct udphdr); ++ break; ++ ++ default: ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT ++ , "klips_xmit: invalid nat-t type %d" ++ , ixs->natt_type); ++ bundle_stat = IPSEC_XMIT_ESPUDP_BADTYPE; ++ goto cleanup; ++ ++ break; ++ } ++ ixs->tailroom += ixs->natt_head; ++ } ++#endif ++ break; ++#endif /* !CONFIG_IPSEC_ESP */ ++#ifdef CONFIG_IPSEC_IPIP ++ case IPPROTO_IPIP: ++ ixs->headroom += sizeof(struct iphdr); ++ break; ++#endif /* !CONFIG_IPSEC_IPIP */ ++ case IPPROTO_COMP: ++#ifdef CONFIG_IPSEC_IPCOMP ++ /* ++ We can't predict how much the packet will ++ shrink without doing the actual compression. ++ We could do it here, if we were the first ++ encapsulation in the chain. That might save ++ us a skb_copy_expand, since we might fit ++ into the existing skb then. However, this ++ would be a bit unclean (and this hack has ++ bit us once), so we better not do it. After ++ all, the skb_copy_expand is cheap in ++ comparison to the actual compression. ++ At least we know the packet will not grow. ++ */ ++ break; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ default: ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_BADPROTO; ++ goto cleanup; ++ } ++ ixs->ipsp = ixs->ipsp->ips_onext; ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "Required head,tailroom: %d,%d\n", ++ ixs->headroom, ixs->tailroom); ++ ixs->max_headroom += ixs->headroom; ++ ixs->max_tailroom += ixs->tailroom; ++ ixs->pyldsz += (ixs->headroom + ixs->tailroom); ++ } ++ ixs->ipsp = ixs->ipsq; /* restore the head of the ipsec_sa chain */ ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n", ++ skb_headroom(ixs->skb), skb_tailroom(ixs->skb), ++ ixs->max_headroom, ixs->max_tailroom); ++ ++ ixs->tot_headroom += ixs->max_headroom; ++ ixs->tot_tailroom += ixs->max_tailroom; ++ ++ ixs->mtudiff = ixs->prv->mtu + ixs->tot_headroom + ixs->tot_tailroom - ixs->physmtu; ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n", ++ ixs->prv->mtu, ixs->physmtu, ++ ixs->tot_headroom, ixs->tot_tailroom, ixs->mtudiff, ntohs(ixs->iph->tot_len)); ++ if(ixs->mtudiff > 0) { ++ int newmtu = ixs->physmtu - (ixs->tot_headroom + ((ixs->tot_tailroom + 2) & ~7) + 5); ++ ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_info:ipsec_xmit_encap_bundle: " ++ "dev %s mtu of %d decreased by %d to %d\n", ++ ixs->dev->name, ++ ixs->prv->mtu, ++ ixs->prv->mtu - newmtu, ++ newmtu); ++ ixs->prv->mtu = newmtu; ++#ifdef NET_21 ++#if 0 ++ ixs->skb->dst->pmtu = ixs->prv->mtu; /* RGB */ ++#endif /* 0 */ ++#else /* NET_21 */ ++#if 0 ++ ixs->dev->mtu = ixs->prv->mtu; /* RGB */ ++#endif /* 0 */ ++#endif /* NET_21 */ ++ } ++ ++ /* ++ If the sender is doing PMTU discovery, and the ++ packet doesn't fit within ixs->prv->mtu, notify him ++ (unless it was an ICMP packet, or it was not the ++ zero-offset packet) and send it anyways. ++ ++ Note: buggy firewall configuration may prevent the ++ ICMP packet from getting back. ++ */ ++ if(sysctl_ipsec_icmp ++ && ixs->prv->mtu < ntohs(ixs->iph->tot_len) ++ && (ixs->iph->frag_off & __constant_htons(IP_DF)) ) { ++ int notify = ixs->iph->protocol != IPPROTO_ICMP ++ && (ixs->iph->frag_off & __constant_htons(IP_OFFSET)) == 0; ++ ++#ifdef IPSEC_obey_DF ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "fragmentation needed and DF set; %sdropping packet\n", ++ notify ? "sending ICMP and " : ""); ++ if (notify) ++ ICMP_SEND(ixs->skb, ++ ICMP_DEST_UNREACH, ++ ICMP_FRAG_NEEDED, ++ ixs->prv->mtu, ++ ixs->physdev); ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_CANNOTFRAG; ++ goto cleanup; ++#else /* IPSEC_obey_DF */ ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "fragmentation needed and DF set; %spassing packet\n", ++ notify ? "sending ICMP and " : ""); ++ if (notify) ++ ICMP_SEND(ixs->skb, ++ ICMP_DEST_UNREACH, ++ ICMP_FRAG_NEEDED, ++ ixs->prv->mtu, ++ ixs->physdev); ++#endif /* IPSEC_obey_DF */ ++ } ++ ++#ifdef MSS_HACK ++ /* ++ * If this is a transport mode TCP packet with ++ * SYN set, determine an effective MSS based on ++ * AH/ESP overheads determined above. ++ */ ++ if (ixs->iph->protocol == IPPROTO_TCP ++ && ixs->outgoing_said.proto != IPPROTO_IPIP) { ++ struct tcphdr *tcph = ixs->skb->h.th; ++ if (tcph->syn && !tcph->ack) { ++ if(!ipsec_adjust_mss(ixs->skb, tcph, ixs->prv->mtu)) { ++ printk(KERN_WARNING ++ "klips_warning:ipsec_xmit_encap_bundle: " ++ "ipsec_adjust_mss() failed\n"); ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_MSSERR; ++ goto cleanup; ++ } ++ } ++ } ++#endif /* MSS_HACK */ ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if ((ixs->natt_type) && (ixs->outgoing_said.proto != IPPROTO_IPIP)) { ++ /** ++ * NAT-Traversal and Transport Mode: ++ * we need to correct TCP/UDP checksum ++ * ++ * If we've got NAT-OA, we can fix checksum without recalculation. ++ * If we don't we can zero udp checksum. ++ */ ++ __u32 natt_oa = ixs->ipsp->ips_natt_oa ? ++ ((struct sockaddr_in*)(ixs->ipsp->ips_natt_oa))->sin_addr.s_addr : 0; ++ __u16 pkt_len = ixs->skb->tail - (unsigned char *)ixs->iph; ++ __u16 data_len = pkt_len - (ixs->iph->ihl << 2); ++ switch (ixs->iph->protocol) { ++ case IPPROTO_TCP: ++ if (data_len >= sizeof(struct tcphdr)) { ++ struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ixs->iph+ixs->iph->ihl); ++ if (natt_oa) { ++ __u32 buff[2] = { ~ixs->iph->daddr, natt_oa }; ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "NAT-T & TRANSPORT: " ++ "fix TCP checksum using NAT-OA\n"); ++ tcp->check = csum_fold( ++ csum_partial((unsigned char *)buff, sizeof(buff), ++ tcp->check^0xffff)); ++ } ++ else { ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "NAT-T & TRANSPORT: do not recalc TCP checksum\n"); ++ } ++ } ++ else { ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "NAT-T & TRANSPORT: can't fix TCP checksum\n"); ++ } ++ break; ++ case IPPROTO_UDP: ++ if (data_len >= sizeof(struct udphdr)) { ++ struct udphdr *udp = (struct udphdr *)((__u32 *)ixs->iph+ixs->iph->ihl); ++ if (udp->check == 0) { ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "NAT-T & TRANSPORT: UDP checksum already 0\n"); ++ } ++ else if (natt_oa) { ++ __u32 buff[2] = { ~ixs->iph->daddr, natt_oa }; ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "NAT-T & TRANSPORT: " ++ "fix UDP checksum using NAT-OA\n"); ++ udp->check = csum_fold( ++ csum_partial((unsigned char *)buff, sizeof(buff), ++ udp->check^0xffff)); ++ } ++ else { ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "NAT-T & TRANSPORT: zero UDP checksum\n"); ++ udp->check = 0; ++ } ++ } ++ else { ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "NAT-T & TRANSPORT: can't fix UDP checksum\n"); ++ } ++ break; ++ default: ++ KLIPS_PRINT(debug_tunnel, ++ "klips_debug:ipsec_tunnel_start_xmit: " ++ "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n"); ++ break; ++ } ++ } ++#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ ++ ++ if(!ixs->hard_header_stripped) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "allocating %d bytes for hardheader.\n", ++ ixs->hard_header_len); ++ if((ixs->saved_header = kmalloc(ixs->hard_header_len, GFP_ATOMIC)) == NULL) { ++ printk(KERN_WARNING "klips_debug:ipsec_xmit_encap_bundle: " ++ "Failed, tried to allocate %d bytes for temp hard_header.\n", ++ ixs->hard_header_len); ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_ERRMEMALLOC; ++ goto cleanup; ++ } ++ { ++ int i; ++ for (i = 0; i < ixs->hard_header_len; i++) { ++ ixs->saved_header[i] = ixs->skb->data[i]; ++ } ++ } ++ if(ixs->skb->len < ixs->hard_header_len) { ++ printk(KERN_WARNING "klips_error:ipsec_xmit_encap_bundle: " ++ "tried to skb_pull hhlen=%d, %d available. This should never happen, please report.\n", ++ ixs->hard_header_len, (int)(ixs->skb->len)); ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_ESP_PUSHPULLERR; ++ goto cleanup; ++ } ++ skb_pull(ixs->skb, ixs->hard_header_len); ++ ixs->hard_header_stripped = 1; ++ ++/* ixs->iph = (struct iphdr *) (ixs->skb->data); */ ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "head,tailroom: %d,%d after hard_header stripped.\n", ++ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); ++ KLIPS_IP_PRINT(debug_tunnel & DB_TN_CROUT, ixs->iph); ++ } else { ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "hard header already stripped.\n"); ++ } ++ ++ ixs->ll_headroom = (ixs->hard_header_len + 15) & ~15; ++ ++ if ((skb_headroom(ixs->skb) >= ixs->max_headroom + 2 * ixs->ll_headroom) && ++ (skb_tailroom(ixs->skb) >= ixs->max_tailroom) ++#ifndef NET_21 ++ && ixs->skb->free ++#endif /* !NET_21 */ ++ ) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "data fits in existing skb\n"); ++ } else { ++ struct sk_buff* tskb; ++ ++ if(!ixs->oskb) { ++ ixs->oskb = ixs->skb; ++ } ++ ++ tskb = skb_copy_expand(ixs->skb, ++ /* The need for 2 * link layer length here remains unexplained...RGB */ ++ ixs->max_headroom + 2 * ixs->ll_headroom, ++ ixs->max_tailroom, ++ GFP_ATOMIC); ++#ifdef NET_21 ++ if(tskb && ixs->skb->sk) { ++ skb_set_owner_w(tskb, ixs->skb->sk); ++ } ++#endif /* NET_21 */ ++ if(ixs->skb != ixs->oskb) { ++ ipsec_kfree_skb(ixs->skb); ++ } ++ ixs->skb = tskb; ++ if (!ixs->skb) { ++ printk(KERN_WARNING ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "Failed, tried to allocate %d head and %d tailroom\n", ++ ixs->max_headroom, ixs->max_tailroom); ++ ixs->stats->tx_errors++; ++ bundle_stat = IPSEC_XMIT_ERRSKBALLOC; ++ goto cleanup; ++ } ++ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, ++ "klips_debug:ipsec_xmit_encap_bundle: " ++ "head,tailroom: %d,%d after allocation\n", ++ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); ++ } ++ ++ /* ++ * Apply grouped transforms to packet ++ */ ++ while (ixs->ipsp) { ++ enum ipsec_xmit_value encap_stat = IPSEC_XMIT_OK; ++ ++ encap_stat = ipsec_xmit_encap_once(ixs); ++ if(encap_stat != IPSEC_XMIT_OK) { ++ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, ++ "klips_debug:ipsec_xmit_encap_bundle: encap_once failed: %d\n", ++ encap_stat); ++ ++ bundle_stat = IPSEC_XMIT_ENCAPFAIL; ++ goto cleanup; ++ } ++ } ++ /* end encapsulation loop here XXX */ ++ cleanup: ++ spin_unlock(&tdb_lock); ++ return bundle_stat; ++} ++ ++/* ++ * $Log: ipsec_xmit.c,v $ ++ * Revision 1.8 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.7 2004/02/03 03:13:41 mcr ++ * mark invalid encapsulation states. ++ * ++ * Revision 1.6.2.1 2003/12/22 15:25:52 jjo ++ * Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.6 2003/12/10 01:14:27 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.5 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.4.4.2 2003/10/29 01:37:39 mcr ++ * when creating %hold from %trap, only make the %hold as ++ * specific as the %trap was - so if the protocol and ports ++ * were wildcards, then the %hold will be too. ++ * ++ * Revision 1.4.4.1 2003/09/21 13:59:56 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.4 2003/06/20 02:28:10 mcr ++ * misstype of variable name, not detected by module build. ++ * ++ * Revision 1.3 2003/06/20 01:42:21 mcr ++ * added counters to measure how many ACQUIREs we send to pluto, ++ * and how many are successfully sent. ++ * ++ * Revision 1.2 2003/04/03 17:38:35 rgb ++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. ++ * Normalised coding style. ++ * Simplified logic and reduced duplication of code. ++ * ++ * Revision 1.1 2003/02/12 19:31:23 rgb ++ * Refactored from ipsec_tunnel.c ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/pfkey_v2.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,2126 @@ ++/* ++ * @(#) RFC2367 PF_KEYv2 Key management API domain socket I/F ++ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: pfkey_v2.c,v 1.81 2004/04/25 21:23:11 ken Exp $ ++ */ ++ ++/* ++ * Template from /usr/src/linux-2.0.36/net/unix/af_unix.c. ++ * Hints from /usr/src/linux-2.0.36/net/ipv4/udp.c. ++ */ ++ ++#define __NO_VERSION__ ++#include <linux/module.h> ++#include <linux/version.h> ++#include <linux/config.h> ++#include <linux/kernel.h> ++ ++#include "openswan/ipsec_param.h" ++ ++#include <linux/major.h> ++#include <linux/signal.h> ++#include <linux/sched.h> ++#include <linux/errno.h> ++#include <linux/string.h> ++#include <linux/stat.h> ++#include <linux/socket.h> ++#include <linux/un.h> ++#include <linux/fcntl.h> ++#include <linux/termios.h> ++#include <linux/socket.h> ++#include <linux/sockios.h> ++#include <linux/net.h> /* struct socket */ ++#include <linux/in.h> ++#include <linux/fs.h> ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <asm/segment.h> ++#include <linux/skbuff.h> ++#include <linux/netdevice.h> ++#include <net/sock.h> /* struct sock */ ++/* #include <net/tcp.h> */ ++#include <net/af_unix.h> ++#ifdef CONFIG_PROC_FS ++# include <linux/proc_fs.h> ++#endif /* CONFIG_PROC_FS */ ++ ++#include <linux/types.h> ++ ++#include <openswan.h> ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++#endif /* NET_21 */ ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_sa.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_proto.h" ++ ++#ifdef CONFIG_IPSEC_DEBUG ++int debug_pfkey = 0; ++extern int sysctl_ipsec_debug_verbose; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) ++ ++#ifndef SOCKOPS_WRAPPED ++#define SOCKOPS_WRAPPED(name) name ++#endif /* SOCKOPS_WRAPPED */ ++ ++extern struct proto_ops pfkey_ops; ++struct sock *pfkey_sock_list = NULL; ++struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1]; ++ ++struct socket_list *pfkey_open_sockets = NULL; ++struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1]; ++ ++int pfkey_msg_interp(struct sock *, struct sadb_msg *, struct sadb_msg **); ++ ++int ++pfkey_list_remove_socket(struct socket *socketp, struct socket_list **sockets) ++{ ++ struct socket_list *socket_listp,*prev; ++ ++ if(!socketp) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_remove_socket: " ++ "NULL socketp handed in, failed.\n"); ++ return -EINVAL; ++ } ++ ++ if(!sockets) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_remove_socket: " ++ "NULL sockets list handed in, failed.\n"); ++ return -EINVAL; ++ } ++ ++ socket_listp = *sockets; ++ prev = NULL; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_remove_socket: " ++ "removing sock=0p%p\n", ++ socketp); ++ ++ while(socket_listp != NULL) { ++ if(socket_listp->socketp == socketp) { ++ if(prev != NULL) { ++ prev->next = socket_listp->next; ++ } else { ++ *sockets = socket_listp->next; ++ } ++ ++ kfree((void*)socket_listp); ++ ++ break; ++ } ++ prev = socket_listp; ++ socket_listp = socket_listp->next; ++ } ++ ++ return 0; ++} ++ ++int ++pfkey_list_insert_socket(struct socket *socketp, struct socket_list **sockets) ++{ ++ struct socket_list *socket_listp; ++ ++ if(!socketp) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_insert_socket: " ++ "NULL socketp handed in, failed.\n"); ++ return -EINVAL; ++ } ++ ++ if(!sockets) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_insert_socket: " ++ "NULL sockets list handed in, failed.\n"); ++ return -EINVAL; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_insert_socket: " ++ "allocating %lu bytes for socketp=0p%p\n", ++ (unsigned long) sizeof(struct socket_list), ++ socketp); ++ ++ if((socket_listp = (struct socket_list *)kmalloc(sizeof(struct socket_list), GFP_KERNEL)) == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_insert_socket: " ++ "memory allocation error.\n"); ++ return -ENOMEM; ++ } ++ ++ socket_listp->socketp = socketp; ++ socket_listp->next = *sockets; ++ *sockets = socket_listp; ++ ++ return 0; ++} ++ ++int ++pfkey_list_remove_supported(struct supported *supported, struct supported_list **supported_list) ++{ ++ struct supported_list *supported_listp = *supported_list, *prev = NULL; ++ ++ if(!supported) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_remove_supported: " ++ "NULL supported handed in, failed.\n"); ++ return -EINVAL; ++ } ++ ++ if(!supported_list) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_remove_supported: " ++ "NULL supported_list handed in, failed.\n"); ++ return -EINVAL; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_remove_supported: " ++ "removing supported=0p%p\n", ++ supported); ++ ++ while(supported_listp != NULL) { ++ if(supported_listp->supportedp == supported) { ++ if(prev != NULL) { ++ prev->next = supported_listp->next; ++ } else { ++ *supported_list = supported_listp->next; ++ } ++ ++ kfree((void*)supported_listp); ++ ++ break; ++ } ++ prev = supported_listp; ++ supported_listp = supported_listp->next; ++ } ++ ++ return 0; ++} ++ ++int ++pfkey_list_insert_supported(struct supported *supported, struct supported_list **supported_list) ++{ ++ struct supported_list *supported_listp; ++ ++ if(!supported) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_insert_supported: " ++ "NULL supported handed in, failed.\n"); ++ return -EINVAL; ++ } ++ ++ if(!supported_list) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_insert_supported: " ++ "NULL supported_list handed in, failed.\n"); ++ return -EINVAL; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_insert_supported: " ++ "allocating %lu bytes for incoming, supported=0p%p, supported_list=0p%p\n", ++ (unsigned long) sizeof(struct supported_list), ++ supported, ++ supported_list); ++ ++ supported_listp = (struct supported_list *)kmalloc(sizeof(struct supported_list), GFP_KERNEL); ++ if(supported_listp == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_insert_supported: " ++ "memory allocation error.\n"); ++ return -ENOMEM; ++ } ++ ++ supported_listp->supportedp = supported; ++ supported_listp->next = *supported_list; ++ *supported_list = supported_listp; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_list_insert_supported: " ++ "outgoing, supported=0p%p, supported_list=0p%p\n", ++ supported, ++ supported_list); ++ ++ return 0; ++} ++ ++#ifndef NET_21 ++DEBUG_NO_STATIC void ++pfkey_state_change(struct sock *sk) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_state_change: .\n"); ++ if(!sk->dead) { ++ wake_up_interruptible(sk->sleep); ++ } ++} ++#endif /* !NET_21 */ ++ ++#ifndef NET_21 ++DEBUG_NO_STATIC void ++pfkey_data_ready(struct sock *sk, int len) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_data_ready: " ++ "sk=0p%p len=%d\n", ++ sk, ++ len); ++ if(!sk->dead) { ++ wake_up_interruptible(sk->sleep); ++ sock_wake_async(sk->socket, 1); ++ } ++} ++ ++DEBUG_NO_STATIC void ++pfkey_write_space(struct sock *sk) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_write_space: .\n"); ++ if(!sk->dead) { ++ wake_up_interruptible(sk->sleep); ++ sock_wake_async(sk->socket, 2); ++ } ++} ++#endif /* !NET_21 */ ++ ++DEBUG_NO_STATIC void ++pfkey_insert_socket(struct sock *sk) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_insert_socket: " ++ "sk=0p%p\n", ++ sk); ++ cli(); ++ sk->next=pfkey_sock_list; ++ pfkey_sock_list=sk; ++ sti(); ++} ++ ++DEBUG_NO_STATIC void ++pfkey_remove_socket(struct sock *sk) ++{ ++ struct sock **s; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_remove_socket: .\n"); ++ cli(); ++ s=&pfkey_sock_list; ++ ++ while(*s!=NULL) { ++ if(*s==sk) { ++ *s=sk->next; ++ sk->next=NULL; ++ sti(); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_remove_socket: " ++ "succeeded.\n"); ++ return; ++ } ++ s=&((*s)->next); ++ } ++ sti(); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_remove_socket: " ++ "not found.\n"); ++ return; ++} ++ ++DEBUG_NO_STATIC void ++pfkey_destroy_socket(struct sock *sk) ++{ ++ struct sk_buff *skb; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_destroy_socket: .\n"); ++ pfkey_remove_socket(sk); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_destroy_socket: " ++ "pfkey_remove_socket called.\n"); ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_destroy_socket: " ++ "sk(0p%p)->(&0p%p)receive_queue.{next=0p%p,prev=0p%p}.\n", ++ sk, ++ &(sk->receive_queue), ++ sk->receive_queue.next, ++ sk->receive_queue.prev); ++ while(sk && ((skb=skb_dequeue(&(sk->receive_queue)))!=NULL)) { ++#ifdef NET_21 ++#ifdef CONFIG_IPSEC_DEBUG ++ if(debug_pfkey && sysctl_ipsec_debug_verbose) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_destroy_socket: " ++ "skb=0p%p dequeued.\n", skb); ++ printk(KERN_INFO "klips_debug:pfkey_destroy_socket: " ++ "pfkey_skb contents:"); ++ printk(" next:0p%p", skb->next); ++ printk(" prev:0p%p", skb->prev); ++ printk(" list:0p%p", skb->list); ++ printk(" sk:0p%p", skb->sk); ++ printk(" stamp:%ld.%ld", skb->stamp.tv_sec, skb->stamp.tv_usec); ++ printk(" dev:0p%p", skb->dev); ++ if(skb->dev) { ++ if(skb->dev->name) { ++ printk(" dev->name:%s", skb->dev->name); ++ } else { ++ printk(" dev->name:NULL?"); ++ } ++ } else { ++ printk(" dev:NULL"); ++ } ++ printk(" h:0p%p", skb->h.raw); ++ printk(" nh:0p%p", skb->nh.raw); ++ printk(" mac:0p%p", skb->mac.raw); ++ printk(" dst:0p%p", skb->dst); ++ if(sysctl_ipsec_debug_verbose) { ++ int i; ++ ++ printk(" cb"); ++ for(i=0; i<48; i++) { ++ printk(":%2x", skb->cb[i]); ++ } ++ } ++ printk(" len:%d", skb->len); ++ printk(" csum:%d", skb->csum); ++#ifndef NETDEV_23 ++ printk(" used:%d", skb->used); ++ printk(" is_clone:%d", skb->is_clone); ++#endif /* NETDEV_23 */ ++ printk(" cloned:%d", skb->cloned); ++ printk(" pkt_type:%d", skb->pkt_type); ++ printk(" ip_summed:%d", skb->ip_summed); ++ printk(" priority:%d", skb->priority); ++ printk(" protocol:%d", skb->protocol); ++ printk(" security:%d", skb->security); ++ printk(" truesize:%d", skb->truesize); ++ printk(" head:0p%p", skb->head); ++ printk(" data:0p%p", skb->data); ++ printk(" tail:0p%p", skb->tail); ++ printk(" end:0p%p", skb->end); ++ if(sysctl_ipsec_debug_verbose) { ++ unsigned char* i; ++ printk(" data"); ++ for(i = skb->head; i < skb->end; i++) { ++ printk(":%2x", (unsigned char)(*(i))); ++ } ++ } ++ printk(" destructor:0p%p", skb->destructor); ++ printk("\n"); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++#endif /* NET_21 */ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_destroy_socket: " ++ "skb=0p%p freed.\n", ++ skb); ++ ipsec_kfree_skb(skb); ++ } ++ ++ sk->dead = 1; ++ sk_free(sk); ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_destroy_socket: destroyed.\n"); ++} ++ ++int ++pfkey_upmsg(struct socket *sock, struct sadb_msg *pfkey_msg) ++{ ++ int error = 0; ++ struct sk_buff * skb = NULL; ++ struct sock *sk; ++ ++ if(sock == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_upmsg: " ++ "NULL socket passed in.\n"); ++ return -EINVAL; ++ } ++ ++ if(pfkey_msg == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_upmsg: " ++ "NULL pfkey_msg passed in.\n"); ++ return -EINVAL; ++ } ++ ++#ifdef NET_21 ++ sk = sock->sk; ++#else /* NET_21 */ ++ sk = sock->data; ++#endif /* NET_21 */ ++ ++ if(sk == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_upmsg: " ++ "NULL sock passed in.\n"); ++ return -EINVAL; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_upmsg: " ++ "allocating %d bytes...\n", ++ (int)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)); ++ if(!(skb = alloc_skb(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, GFP_ATOMIC) )) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_upmsg: " ++ "no buffers left to send up a message.\n"); ++ return -ENOBUFS; ++ } ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_upmsg: " ++ "...allocated at 0p%p.\n", ++ skb); ++ ++ skb->dev = NULL; ++ ++ if(skb_tailroom(skb) < pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { ++ printk(KERN_WARNING "klips_error:pfkey_upmsg: " ++ "tried to skb_put %ld, %d available. This should never happen, please report.\n", ++ (unsigned long int)pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, ++ skb_tailroom(skb)); ++ ipsec_kfree_skb(skb); ++ return -ENOBUFS; ++ } ++ skb->h.raw = skb_put(skb, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); ++ memcpy(skb->h.raw, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); ++ ++#ifndef NET_21 ++ skb->free = 1; ++#endif /* !NET_21 */ ++ ++ if((error = sock_queue_rcv_skb(sk, skb)) < 0) { ++ skb->sk=NULL; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_upmsg: " ++ "error=%d calling sock_queue_rcv_skb with skb=0p%p.\n", ++ error, ++ skb); ++ ipsec_kfree_skb(skb); ++ return error; ++ } ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_create(struct socket *sock, int protocol) ++{ ++ struct sock *sk; ++ ++ if(sock == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_create: " ++ "socket NULL.\n"); ++ return -EINVAL; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_create: " ++ "sock=0p%p type:%d state:%d flags:%ld protocol:%d\n", ++ sock, ++ sock->type, ++ (unsigned int)(sock->state), ++ sock->flags, protocol); ++ ++ if(sock->type != SOCK_RAW) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_create: " ++ "only SOCK_RAW supported.\n"); ++ return -ESOCKTNOSUPPORT; ++ } ++ ++ if(protocol != PF_KEY_V2) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_create: " ++ "protocol not PF_KEY_V2.\n"); ++ return -EPROTONOSUPPORT; ++ } ++ ++ if((current->uid != 0)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_create: " ++ "must be root to open pfkey sockets.\n"); ++ return -EACCES; ++ } ++ ++#ifdef NET_21 ++ sock->state = SS_UNCONNECTED; ++#endif /* NET_21 */ ++ MOD_INC_USE_COUNT; ++#ifdef NET_21 ++ if((sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1)) == NULL) ++#else /* NET_21 */ ++ if((sk=(struct sock *)sk_alloc(GFP_KERNEL)) == NULL) ++#endif /* NET_21 */ ++ { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_create: " ++ "Out of memory trying to allocate.\n"); ++ MOD_DEC_USE_COUNT; ++ return -ENOMEM; ++ } ++ ++#ifndef NET_21 ++ memset(sk, 0, sizeof(*sk)); ++#endif /* !NET_21 */ ++ ++#ifdef NET_21 ++ sock_init_data(sock, sk); ++ ++ sk->destruct = NULL; ++ sk->reuse = 1; ++ sock->ops = &pfkey_ops; ++ ++ sk->zapped=0; ++ sk->family = PF_KEY; ++/* sk->num = protocol; */ ++ sk->protocol = protocol; ++ key_pid(sk) = current->pid; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_create: " ++ "sock->fasync_list=0p%p sk->sleep=0p%p.\n", ++ sock->fasync_list, ++ sk->sleep); ++#else /* NET_21 */ ++ sk->type=sock->type; ++ init_timer(&sk->timer); ++ skb_queue_head_init(&sk->write_queue); ++ skb_queue_head_init(&sk->receive_queue); ++ skb_queue_head_init(&sk->back_log); ++ sk->rcvbuf=SK_RMEM_MAX; ++ sk->sndbuf=SK_WMEM_MAX; ++ sk->allocation=GFP_KERNEL; ++ sk->state=TCP_CLOSE; ++ sk->priority=SOPRI_NORMAL; ++ sk->state_change=pfkey_state_change; ++ sk->data_ready=pfkey_data_ready; ++ sk->write_space=pfkey_write_space; ++ sk->error_report=pfkey_state_change; ++ sk->mtu=4096; ++ sk->socket=sock; ++ sock->data=(void *)sk; ++ sk->sleep=sock->wait; ++#endif /* NET_21 */ ++ ++ pfkey_insert_socket(sk); ++ pfkey_list_insert_socket(sock, &pfkey_open_sockets); ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_create: " ++ "Socket sock=0p%p sk=0p%p initialised.\n", sock, sk); ++ return 0; ++} ++ ++#ifndef NET_21 ++DEBUG_NO_STATIC int ++pfkey_dup(struct socket *newsock, struct socket *oldsock) ++{ ++ struct sock *sk; ++ ++ if(newsock==NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_dup: " ++ "No new socket attached.\n"); ++ return -EINVAL; ++ } ++ ++ if(oldsock==NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_dup: " ++ "No old socket attached.\n"); ++ return -EINVAL; ++ } ++ ++#ifdef NET_21 ++ sk=oldsock->sk; ++#else /* NET_21 */ ++ sk=oldsock->data; ++#endif /* NET_21 */ ++ ++ /* May not have data attached */ ++ if(sk==NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_dup: " ++ "No sock attached to old socket.\n"); ++ return -EINVAL; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_dup: .\n"); ++ ++ return pfkey_create(newsock, sk->protocol); ++} ++#endif /* !NET_21 */ ++ ++DEBUG_NO_STATIC int ++#ifdef NETDEV_23 ++pfkey_release(struct socket *sock) ++#else /* NETDEV_23 */ ++pfkey_release(struct socket *sock, struct socket *peersock) ++#endif /* NETDEV_23 */ ++{ ++ struct sock *sk; ++ int i; ++ ++ if(sock==NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_release: " ++ "No socket attached.\n"); ++ return 0; /* -EINVAL; */ ++ } ++ ++#ifdef NET_21 ++ sk=sock->sk; ++#else /* NET_21 */ ++ sk=sock->data; ++#endif /* NET_21 */ ++ ++ /* May not have data attached */ ++ if(sk==NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_release: " ++ "No sk attached to sock=0p%p.\n", sock); ++ return 0; /* -EINVAL; */ ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_release: " ++ "sock=0p%p sk=0p%p\n", sock, sk); ++ ++#ifdef NET_21 ++ if(!sk->dead) ++#endif /* NET_21 */ ++ if(sk->state_change) { ++ sk->state_change(sk); ++ } ++ ++#ifdef NET_21 ++ sock->sk = NULL; ++#else /* NET_21 */ ++ sock->data = NULL; ++#endif /* NET_21 */ ++ ++ /* Try to flush out this socket. Throw out buffers at least */ ++ pfkey_destroy_socket(sk); ++ pfkey_list_remove_socket(sock, &pfkey_open_sockets); ++ for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) { ++ pfkey_list_remove_socket(sock, &(pfkey_registered_sockets[i])); ++ } ++ ++ MOD_DEC_USE_COUNT; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_release: " ++ "succeeded.\n"); ++ ++ return 0; ++} ++ ++#ifndef NET_21 ++DEBUG_NO_STATIC int ++pfkey_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_bind: " ++ "operation not supported.\n"); ++ return -EINVAL; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_connect: " ++ "operation not supported.\n"); ++ return -EINVAL; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_socketpair(struct socket *a, struct socket *b) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_socketpair: " ++ "operation not supported.\n"); ++ return -EINVAL; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_accept(struct socket *sock, struct socket *newsock, int flags) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_aaccept: " ++ "operation not supported.\n"); ++ return -EINVAL; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, ++ int peer) ++{ ++ struct sockaddr *ska = (struct sockaddr*)uaddr; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_getname: .\n"); ++ ska->sa_family = PF_KEY; ++ *uaddr_len = sizeof(*ska); ++ return 0; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_select(struct socket *sock, int sel_type, select_table *wait) ++{ ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_select: " ++ ".sock=0p%p sk=0p%p sel_type=%d\n", ++ sock, ++ sock->data, ++ sel_type); ++ if(sock == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_select: " ++ "Null socket passed in.\n"); ++ return -EINVAL; ++ } ++ return datagram_select(sock->data, sel_type, wait); ++} ++ ++DEBUG_NO_STATIC int ++pfkey_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ioctl: " ++ "not supported.\n"); ++ return -EINVAL; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_listen(struct socket *sock, int backlog) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_listen: " ++ "not supported.\n"); ++ return -EINVAL; ++} ++#endif /* !NET_21 */ ++ ++DEBUG_NO_STATIC int ++pfkey_shutdown(struct socket *sock, int mode) ++{ ++ struct sock *sk; ++ ++ if(sock == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_shutdown: " ++ "NULL socket passed in.\n"); ++ return -EINVAL; ++ } ++ ++#ifdef NET_21 ++ sk=sock->sk; ++#else /* NET_21 */ ++ sk=sock->data; ++#endif /* NET_21 */ ++ ++ if(sk == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_shutdown: " ++ "No sock attached to socket.\n"); ++ return -EINVAL; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_shutdown: " ++ "mode=%x.\n", mode); ++ mode++; ++ ++ if(mode&SEND_SHUTDOWN) { ++ sk->shutdown|=SEND_SHUTDOWN; ++ sk->state_change(sk); ++ } ++ ++ if(mode&RCV_SHUTDOWN) { ++ sk->shutdown|=RCV_SHUTDOWN; ++ sk->state_change(sk); ++ } ++ return 0; ++} ++ ++#ifndef NET_21 ++DEBUG_NO_STATIC int ++pfkey_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) ++{ ++#ifndef NET_21 ++ struct sock *sk; ++ ++ if(sock == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_setsockopt: " ++ "Null socket passed in.\n"); ++ return -EINVAL; ++ } ++ ++ sk=sock->data; ++ ++ if(sk == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_setsockopt: " ++ "Null sock passed in.\n"); ++ return -EINVAL; ++ } ++#endif /* !NET_21 */ ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_setsockopt: .\n"); ++ if(level!=SOL_SOCKET) { ++ return -EOPNOTSUPP; ++ } ++#ifdef NET_21 ++ return sock_setsockopt(sock, level, optname, optval, optlen); ++#else /* NET_21 */ ++ return sock_setsockopt(sk, level, optname, optval, optlen); ++#endif /* NET_21 */ ++} ++ ++DEBUG_NO_STATIC int ++pfkey_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) ++{ ++#ifndef NET_21 ++ struct sock *sk; ++ ++ if(sock == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_setsockopt: " ++ "Null socket passed in.\n"); ++ return -EINVAL; ++ } ++ ++ sk=sock->data; ++ ++ if(sk == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_setsockopt: " ++ "Null sock passed in.\n"); ++ return -EINVAL; ++ } ++#endif /* !NET_21 */ ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_getsockopt: .\n"); ++ if(level!=SOL_SOCKET) { ++ return -EOPNOTSUPP; ++ } ++#ifdef NET_21 ++ return sock_getsockopt(sock, level, optname, optval, optlen); ++#else /* NET_21 */ ++ return sock_getsockopt(sk, level, optname, optval, optlen); ++#endif /* NET_21 */ ++} ++ ++DEBUG_NO_STATIC int ++pfkey_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) ++{ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_fcntl: " ++ "not supported.\n"); ++ return -EINVAL; ++} ++#endif /* !NET_21 */ ++ ++/* ++ * Send PF_KEY data down. ++ */ ++ ++DEBUG_NO_STATIC int ++#ifdef NET_21 ++pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) ++#else /* NET_21 */ ++pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags) ++#endif /* NET_21 */ ++{ ++ struct sock *sk; ++ int error = 0; ++ struct sadb_msg *pfkey_msg = NULL, *pfkey_reply = NULL; ++ ++ if(sock == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "Null socket passed in.\n"); ++ SENDERR(EINVAL); ++ } ++ ++#ifdef NET_21 ++ sk = sock->sk; ++#else /* NET_21 */ ++ sk = sock->data; ++#endif /* NET_21 */ ++ ++ if(sk == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "Null sock passed in.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(msg == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "Null msghdr passed in.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: .\n"); ++ if(sk->err) { ++ error = sock_error(sk); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "sk->err is non-zero, returns %d.\n", ++ error); ++ SENDERR(-error); ++ } ++ ++ if((current->uid != 0)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "must be root to send messages to pfkey sockets.\n"); ++ SENDERR(EACCES); ++ } ++ ++#ifdef NET_21 ++ if(msg->msg_control) ++#else /* NET_21 */ ++ if(flags || msg->msg_control) ++#endif /* NET_21 */ ++ { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "can't set flags or set msg_control.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(sk->shutdown & SEND_SHUTDOWN) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "shutdown.\n"); ++ send_sig(SIGPIPE, current, 0); ++ SENDERR(EPIPE); ++ } ++ ++ if(len < sizeof(struct sadb_msg)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "bogus msg len of %d, too small.\n", len); ++ SENDERR(EMSGSIZE); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "allocating %d bytes for downward message.\n", ++ len); ++ if((pfkey_msg = (struct sadb_msg*)kmalloc(len, GFP_KERNEL)) == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "memory allocation error.\n"); ++ SENDERR(ENOBUFS); ++ } ++ ++ memcpy_fromiovec((void *)pfkey_msg, msg->msg_iov, len); ++ ++ if(pfkey_msg->sadb_msg_version != PF_KEY_V2) { ++ KLIPS_PRINT(1 || debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "not PF_KEY_V2 msg, found %d, should be %d.\n", ++ pfkey_msg->sadb_msg_version, ++ PF_KEY_V2); ++ kfree((void*)pfkey_msg); ++ return -EINVAL; ++ } ++ ++ if(len != pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "bogus msg len of %d, not %d byte aligned.\n", ++ len, (int)IPSEC_PFKEYv2_ALIGN); ++ SENDERR(EMSGSIZE); ++ } ++ ++#if 0 ++ /* This check is questionable, since a downward message could be ++ the result of an ACQUIRE either from kernel (PID==0) or ++ userspace (some other PID). */ ++ /* check PID */ ++ if(pfkey_msg->sadb_msg_pid != current->pid) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "pid (%d) does not equal sending process pid (%d).\n", ++ pfkey_msg->sadb_msg_pid, current->pid); ++ SENDERR(EINVAL); ++ } ++#endif ++ ++ if(pfkey_msg->sadb_msg_reserved) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "reserved field must be zero, set to %d.\n", ++ pfkey_msg->sadb_msg_reserved); ++ SENDERR(EINVAL); ++ } ++ ++ if((pfkey_msg->sadb_msg_type > SADB_MAX) || (!pfkey_msg->sadb_msg_type)){ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "msg type too large or small:%d.\n", ++ pfkey_msg->sadb_msg_type); ++ SENDERR(EINVAL); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "msg sent for parsing.\n"); ++ ++ if((error = pfkey_msg_interp(sk, pfkey_msg, &pfkey_reply))) { ++ struct socket_list *pfkey_socketsp; ++ ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " ++ "pfkey_msg_parse returns %d.\n", ++ error); ++ ++ if((pfkey_reply = (struct sadb_msg*)kmalloc(sizeof(struct sadb_msg), GFP_KERNEL)) == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "memory allocation error.\n"); ++ SENDERR(ENOBUFS); ++ } ++ memcpy((void*)pfkey_reply, (void*)pfkey_msg, sizeof(struct sadb_msg)); ++ pfkey_reply->sadb_msg_errno = -error; ++ pfkey_reply->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; ++ ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ int error_upmsg = 0; ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " ++ "sending up error=%d message=0p%p to socket=0p%p.\n", ++ error, ++ pfkey_reply, ++ pfkey_socketsp->socketp); ++ if((error_upmsg = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " ++ "sending up error message to socket=0p%p failed with error=%d.\n", ++ pfkey_socketsp->socketp, ++ error_upmsg); ++ /* pfkey_msg_free(&pfkey_reply); */ ++ /* SENDERR(-error); */ ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " ++ "sending up error message to socket=0p%p succeeded.\n", ++ pfkey_socketsp->socketp); ++ } ++ ++ pfkey_msg_free(&pfkey_reply); ++ ++ SENDERR(-error); ++ } ++ ++ errlab: ++ if (pfkey_msg) { ++ kfree((void*)pfkey_msg); ++ } ++ ++ if(error) { ++ return error; ++ } else { ++ return len; ++ } ++} ++ ++/* ++ * Receive PF_KEY data up. ++ */ ++ ++DEBUG_NO_STATIC int ++#ifdef NET_21 ++pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm) ++#else /* NET_21 */ ++pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len) ++#endif /* NET_21 */ ++{ ++ struct sock *sk; ++#ifdef NET_21 ++ int noblock = flags & MSG_DONTWAIT; ++#endif /* NET_21 */ ++ struct sk_buff *skb; ++ int error; ++ ++ if(sock == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_recvmsg: " ++ "Null socket passed in.\n"); ++ return -EINVAL; ++ } ++ ++#ifdef NET_21 ++ sk = sock->sk; ++#else /* NET_21 */ ++ sk = sock->data; ++#endif /* NET_21 */ ++ ++ if(sk == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_recvmsg: " ++ "Null sock passed in for sock=0p%p.\n", sock); ++ return -EINVAL; ++ } ++ ++ if(msg == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_recvmsg: " ++ "Null msghdr passed in for sock=0p%p, sk=0p%p.\n", ++ sock, sk); ++ return -EINVAL; ++ } ++ ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_recvmsg: sock=0p%p sk=0p%p msg=0p%p size=%d.\n", ++ sock, sk, msg, size); ++ if(flags & ~MSG_PEEK) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "flags (%d) other than MSG_PEEK not supported.\n", ++ flags); ++ return -EOPNOTSUPP; ++ } ++ ++#ifdef NET_21 ++ msg->msg_namelen = 0; /* sizeof(*ska); */ ++#else /* NET_21 */ ++ if(addr_len) { ++ *addr_len = 0; /* sizeof(*ska); */ ++ } ++#endif /* NET_21 */ ++ ++ if(sk->err) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sendmsg: " ++ "sk->err=%d.\n", sk->err); ++ return sock_error(sk); ++ } ++ ++ if((skb = skb_recv_datagram(sk, flags, noblock, &error) ) == NULL) { ++ return error; ++ } ++ ++ if(size > skb->len) { ++ size = skb->len; ++ } ++#ifdef NET_21 ++ else if(size <skb->len) { ++ msg->msg_flags |= MSG_TRUNC; ++ } ++#endif /* NET_21 */ ++ ++ skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size); ++ sk->stamp=skb->stamp; ++ ++ skb_free_datagram(sk, skb); ++ return size; ++} ++ ++#ifdef NET_21 ++struct net_proto_family pfkey_family_ops = { ++ PF_KEY, ++ pfkey_create ++}; ++ ++struct proto_ops SOCKOPS_WRAPPED(pfkey_ops) = { ++#ifdef NETDEV_23 ++ family: PF_KEY, ++ release: pfkey_release, ++ bind: sock_no_bind, ++ connect: sock_no_connect, ++ socketpair: sock_no_socketpair, ++ accept: sock_no_accept, ++ getname: sock_no_getname, ++ poll: datagram_poll, ++ ioctl: sock_no_ioctl, ++ listen: sock_no_listen, ++ shutdown: pfkey_shutdown, ++ setsockopt: sock_no_setsockopt, ++ getsockopt: sock_no_getsockopt, ++ sendmsg: pfkey_sendmsg, ++ recvmsg: pfkey_recvmsg, ++ mmap: sock_no_mmap, ++#else /* NETDEV_23 */ ++ PF_KEY, ++ sock_no_dup, ++ pfkey_release, ++ sock_no_bind, ++ sock_no_connect, ++ sock_no_socketpair, ++ sock_no_accept, ++ sock_no_getname, ++ datagram_poll, ++ sock_no_ioctl, ++ sock_no_listen, ++ pfkey_shutdown, ++ sock_no_setsockopt, ++ sock_no_getsockopt, ++ sock_no_fcntl, ++ pfkey_sendmsg, ++ pfkey_recvmsg ++#endif /* NETDEV_23 */ ++}; ++ ++#ifdef NETDEV_23 ++#include <linux/smp_lock.h> ++SOCKOPS_WRAP(pfkey, PF_KEY); ++#endif /* NETDEV_23 */ ++ ++#else /* NET_21 */ ++struct proto_ops pfkey_proto_ops = { ++ PF_KEY, ++ pfkey_create, ++ pfkey_dup, ++ pfkey_release, ++ pfkey_bind, ++ pfkey_connect, ++ pfkey_socketpair, ++ pfkey_accept, ++ pfkey_getname, ++ pfkey_select, ++ pfkey_ioctl, ++ pfkey_listen, ++ pfkey_shutdown, ++ pfkey_setsockopt, ++ pfkey_getsockopt, ++ pfkey_fcntl, ++ pfkey_sendmsg, ++ pfkey_recvmsg ++}; ++#endif /* NET_21 */ ++ ++#ifdef CONFIG_PROC_FS ++#ifndef PROC_FS_2325 ++DEBUG_NO_STATIC ++#endif /* PROC_FS_2325 */ ++int ++pfkey_get_info(char *buffer, char **start, off_t offset, int length ++#ifndef PROC_NO_DUMMY ++, int dummy ++#endif /* !PROC_NO_DUMMY */ ++) ++{ ++ const int max_content = length > 0? length-1 : 0; ++ off_t begin=0; ++ int len=0; ++ struct sock *sk=pfkey_sock_list; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if(!sysctl_ipsec_debug_verbose) { ++#endif /* CONFIG_IPSEC_DEBUG */ ++ len+= snprintf(buffer,length, ++ " sock pid socket next prev e n p sndbf Flags Type St\n"); ++#ifdef CONFIG_IPSEC_DEBUG ++ } else { ++ len+= snprintf(buffer,length, ++ " sock pid d sleep socket next prev e r z n p sndbf stamp Flags Type St\n"); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ while(sk!=NULL) { ++#ifdef CONFIG_IPSEC_DEBUG ++ if(!sysctl_ipsec_debug_verbose) { ++#endif /* CONFIG_IPSEC_DEBUG */ ++ len += ipsec_snprintf(buffer+len, length-len, ++ "%8p %5d %8p %8p %8p %d %d %d %5d %08lX %8X %2X\n", ++ sk, ++ key_pid(sk), ++ sk->socket, ++ sk->next, ++ sk->prev, ++ sk->err, ++ sk->num, ++ sk->protocol, ++ sk->sndbuf, ++ sk->socket->flags, ++ sk->socket->type, ++ sk->socket->state); ++#ifdef CONFIG_IPSEC_DEBUG ++ } else { ++ len += ipsec_snprintf(buffer+len, length-len, ++ "%8p %5d %d %8p %8p %8p %8p %d %d %d %d %d %5d %d.%06d %08lX %8X %2X\n", ++ sk, ++ key_pid(sk), ++ sk->dead, ++ sk->sleep, ++ sk->socket, ++ sk->next, ++ sk->prev, ++ sk->err, ++ sk->reuse, ++ sk->zapped, ++ sk->num, ++ sk->protocol, ++ sk->sndbuf, ++ (unsigned int)sk->stamp.tv_sec, ++ (unsigned int)sk->stamp.tv_usec, ++ sk->socket->flags, ++ sk->socket->type, ++ sk->socket->state); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ if (len >= max_content) { ++ /* we've done all that can fit -- stop loop */ ++ len = max_content; /* truncate crap */ ++ break; ++ } else { ++ ++ const off_t pos = begin + len; /* file position of end of what we've generated */ ++ ++ if (pos <= offset) { ++ /* all is before first interesting character: ++ * discard, but note where we are. ++ */ ++ len = 0; ++ begin = pos; ++ } ++ } ++ sk=sk->next; ++ ++ } ++ ++ *start = buffer + (offset - begin); /* Start of wanted data */ ++ return len - (offset - begin); ++ ++} ++ ++#ifndef PROC_FS_2325 ++DEBUG_NO_STATIC ++#endif /* PROC_FS_2325 */ ++int ++pfkey_supported_get_info(char *buffer, char **start, off_t offset, int length ++#ifndef PROC_NO_DUMMY ++, int dummy ++#endif /* !PROC_NO_DUMMY */ ++) ++{ ++ const int max_content = length > 0? length-1 : 0; ++ off_t begin=0; ++ int len=0; ++ int satype; ++ struct supported_list *pfkey_supported_p; ++ ++ len += ipsec_snprintf(buffer, length, ++ "satype exttype alg_id ivlen minbits maxbits\n"); ++ ++ for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) { ++ pfkey_supported_p = pfkey_supported_list[satype]; ++ while(pfkey_supported_p) { ++ len += ipsec_snprintf(buffer+len, length-len, ++ " %2d %2d %2d %3d %3d %3d\n", ++ satype, ++ pfkey_supported_p->supportedp->supported_alg_exttype, ++ pfkey_supported_p->supportedp->supported_alg_id, ++ pfkey_supported_p->supportedp->supported_alg_ivlen, ++ pfkey_supported_p->supportedp->supported_alg_minbits, ++ pfkey_supported_p->supportedp->supported_alg_maxbits); ++ ++ if (len >= max_content) { ++ /* we've done all that can fit -- stop loop */ ++ len = max_content; /* truncate crap */ ++ break; ++ } else { ++ const off_t pos = begin + len; /* file position of end of what we've generated */ ++ ++ if (pos <= offset) { ++ /* all is before first interesting character: ++ * discard, but note where we are. ++ */ ++ len = 0; ++ begin = pos; ++ } ++ } ++ ++ pfkey_supported_p = pfkey_supported_p->next; ++ } ++ } ++ ++ *start = buffer + (offset - begin); /* Start of wanted data */ ++ return len - (offset - begin); ++ ++} ++ ++#ifndef PROC_FS_2325 ++DEBUG_NO_STATIC ++#endif /* PROC_FS_2325 */ ++int ++pfkey_registered_get_info(char *buffer, char **start, off_t offset, int length ++#ifndef PROC_NO_DUMMY ++, int dummy ++#endif /* !PROC_NO_DUMMY */ ++) ++{ ++ const int max_content = length > 0? length-1 : 0; ++ off_t begin=0; ++ int len=0; ++ int satype; ++ struct socket_list *pfkey_sockets; ++ ++ len += ipsec_snprintf(buffer, length, ++ "satype socket pid sk\n"); ++ ++ for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) { ++ pfkey_sockets = pfkey_registered_sockets[satype]; ++ while(pfkey_sockets) { ++#ifdef NET_21 ++ len += ipsec_snprintf(buffer+len, length-len, ++ " %2d %8p %5d %8p\n", ++ satype, ++ pfkey_sockets->socketp, ++ key_pid(pfkey_sockets->socketp->sk), ++ pfkey_sockets->socketp->sk); ++#else /* NET_21 */ ++ len += ipsec_snprintf(buffer+len, length-len, ++ " %2d %8p N/A %8p\n", ++ satype, ++ pfkey_sockets->socketp, ++#if 0 ++ key_pid((pfkey_sockets->socketp)->data), ++#endif ++ (pfkey_sockets->socketp)->data); ++#endif /* NET_21 */ ++ ++ if (len >= max_content) { ++ /* we've done all that can fit -- stop loop (could stop two) */ ++ len = max_content; /* truncate crap */ ++ break; ++ } else { ++ const off_t pos = begin + len; /* file position of end of what we've generated */ ++ ++ if (pos <= offset) { ++ /* all is before first interesting character: ++ * discard, but note where we are. ++ */ ++ len = 0; ++ begin = pos; ++ } ++ } ++ ++ ++ pfkey_sockets = pfkey_sockets->next; ++ } ++ } ++ *start = buffer + (offset - begin); /* Start of wanted data */ ++ return len - (offset - begin); ++} ++ ++#ifndef PROC_FS_2325 ++struct proc_dir_entry proc_net_pfkey = ++{ ++ 0, ++ 6, "pf_key", ++ S_IFREG | S_IRUGO, 1, 0, 0, ++ 0, &proc_net_inode_operations, ++ pfkey_get_info ++}; ++struct proc_dir_entry proc_net_pfkey_supported = ++{ ++ 0, ++ 16, "pf_key_supported", ++ S_IFREG | S_IRUGO, 1, 0, 0, ++ 0, &proc_net_inode_operations, ++ pfkey_supported_get_info ++}; ++struct proc_dir_entry proc_net_pfkey_registered = ++{ ++ 0, ++ 17, "pf_key_registered", ++ S_IFREG | S_IRUGO, 1, 0, 0, ++ 0, &proc_net_inode_operations, ++ pfkey_registered_get_info ++}; ++#endif /* !PROC_FS_2325 */ ++#endif /* CONFIG_PROC_FS */ ++ ++DEBUG_NO_STATIC int ++supported_add_all(int satype, struct supported supported[], int size) ++{ ++ int i; ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:init_pfkey: " ++ "sizeof(supported_init_<satype=%d>)[%d]/sizeof(struct supported)[%d]=%d.\n", ++ satype, ++ size, ++ (int)sizeof(struct supported), ++ (int)(size/sizeof(struct supported))); ++ ++ for(i = 0; i < size / sizeof(struct supported); i++) { ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:init_pfkey: " ++ "i=%d inserting satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", ++ i, ++ satype, ++ supported[i].supported_alg_exttype, ++ supported[i].supported_alg_id, ++ supported[i].supported_alg_ivlen, ++ supported[i].supported_alg_minbits, ++ supported[i].supported_alg_maxbits); ++ ++ error |= pfkey_list_insert_supported(&(supported[i]), ++ &(pfkey_supported_list[satype])); ++ } ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++supported_remove_all(int satype) ++{ ++ int error = 0; ++ struct supported*supportedp; ++ ++ while(pfkey_supported_list[satype]) { ++ supportedp = pfkey_supported_list[satype]->supportedp; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:init_pfkey: " ++ "removing satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", ++ satype, ++ supportedp->supported_alg_exttype, ++ supportedp->supported_alg_id, ++ supportedp->supported_alg_ivlen, ++ supportedp->supported_alg_minbits, ++ supportedp->supported_alg_maxbits); ++ ++ error |= pfkey_list_remove_supported(supportedp, ++ &(pfkey_supported_list[satype])); ++ } ++ return error; ++} ++ ++int ++pfkey_init(void) ++{ ++ int error = 0; ++ int i; ++ ++ static struct supported supported_init_ah[] = { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128}, ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160} ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ }; ++ static struct supported supported_init_esp[] = { ++#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128}, ++#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160}, ++#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++#ifdef CONFIG_IPSEC_ENC_3DES ++ {SADB_EXT_SUPPORTED_ENCRYPT, SADB_EALG_3DESCBC, 64, 168, 168}, ++#endif /* CONFIG_IPSEC_ENC_3DES */ ++ }; ++ static struct supported supported_init_ipip[] = { ++ {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv4, 0, 32, 32} ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv4, 0, 128, 32} ++ , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv6, 0, 32, 128} ++ , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv6, 0, 128, 128} ++#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ ++ }; ++#ifdef CONFIG_IPSEC_IPCOMP ++ static struct supported supported_init_ipcomp[] = { ++ {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_CALG_DEFLATE, 0, 1, 1} ++ }; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#if 0 ++ printk(KERN_INFO ++ "klips_info:pfkey_init: " ++ "FreeS/WAN: initialising PF_KEYv2 domain sockets.\n"); ++#endif ++ ++ for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) { ++ pfkey_registered_sockets[i] = NULL; ++ pfkey_supported_list[i] = NULL; ++ } ++ ++ error |= supported_add_all(SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah)); ++ error |= supported_add_all(SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp)); ++#ifdef CONFIG_IPSEC_IPCOMP ++ error |= supported_add_all(SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp)); ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ error |= supported_add_all(SADB_X_SATYPE_IPIP, supported_init_ipip, sizeof(supported_init_ipip)); ++ ++#ifdef NET_21 ++ error |= sock_register(&pfkey_family_ops); ++#else /* NET_21 */ ++ error |= sock_register(pfkey_proto_ops.family, &pfkey_proto_ops); ++#endif /* NET_21 */ ++ ++#ifdef CONFIG_PROC_FS ++# ifndef PROC_FS_2325 ++# ifdef PROC_FS_21 ++ error |= proc_register(proc_net, &proc_net_pfkey); ++ error |= proc_register(proc_net, &proc_net_pfkey_supported); ++ error |= proc_register(proc_net, &proc_net_pfkey_registered); ++# else /* PROC_FS_21 */ ++ error |= proc_register_dynamic(&proc_net, &proc_net_pfkey); ++ error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_supported); ++ error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_registered); ++# endif /* PROC_FS_21 */ ++# else /* !PROC_FS_2325 */ ++ proc_net_create ("pf_key", 0, pfkey_get_info); ++ proc_net_create ("pf_key_supported", 0, pfkey_supported_get_info); ++ proc_net_create ("pf_key_registered", 0, pfkey_registered_get_info); ++# endif /* !PROC_FS_2325 */ ++#endif /* CONFIG_PROC_FS */ ++ ++ return error; ++} ++ ++int ++pfkey_cleanup(void) ++{ ++ int error = 0; ++ ++ printk(KERN_INFO "klips_info:pfkey_cleanup: " ++ "shutting down PF_KEY domain sockets.\n"); ++#ifdef NET_21 ++ error |= sock_unregister(PF_KEY); ++#else /* NET_21 */ ++ error |= sock_unregister(pfkey_proto_ops.family); ++#endif /* NET_21 */ ++ ++ error |= supported_remove_all(SADB_SATYPE_AH); ++ error |= supported_remove_all(SADB_SATYPE_ESP); ++#ifdef CONFIG_IPSEC_IPCOMP ++ error |= supported_remove_all(SADB_X_SATYPE_COMP); ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ error |= supported_remove_all(SADB_X_SATYPE_IPIP); ++ ++#ifdef CONFIG_PROC_FS ++# ifndef PROC_FS_2325 ++ if (proc_net_unregister(proc_net_pfkey.low_ino) != 0) ++ printk("klips_debug:pfkey_cleanup: " ++ "cannot unregister /proc/net/pf_key\n"); ++ if (proc_net_unregister(proc_net_pfkey_supported.low_ino) != 0) ++ printk("klips_debug:pfkey_cleanup: " ++ "cannot unregister /proc/net/pf_key_supported\n"); ++ if (proc_net_unregister(proc_net_pfkey_registered.low_ino) != 0) ++ printk("klips_debug:pfkey_cleanup: " ++ "cannot unregister /proc/net/pf_key_registered\n"); ++# else /* !PROC_FS_2325 */ ++ proc_net_remove ("pf_key"); ++ proc_net_remove ("pf_key_supported"); ++ proc_net_remove ("pf_key_registered"); ++# endif /* !PROC_FS_2325 */ ++#endif /* CONFIG_PROC_FS */ ++ ++ /* other module unloading cleanup happens here */ ++ return error; ++} ++ ++#ifdef MODULE ++#if 0 ++int ++init_module(void) ++{ ++ pfkey_init(); ++ return 0; ++} ++ ++void ++cleanup_module(void) ++{ ++ pfkey_cleanup(); ++} ++#endif /* 0 */ ++#else /* MODULE */ ++void ++pfkey_proto_init(struct net_proto *pro) ++{ ++ pfkey_init(); ++} ++#endif /* MODULE */ ++ ++/* ++ * $Log: pfkey_v2.c,v $ ++ * Revision 1.81 2004/04/25 21:23:11 ken ++ * Pull in dhr's changes from FreeS/WAN 2.06 ++ * ++ * Revision 1.80 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.79.4.1 2003/12/22 15:25:52 jjo ++ * . Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.79 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.78.4.1 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.78 2003/04/03 17:38:09 rgb ++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. ++ * ++ * Revision 1.77 2002/10/17 16:49:36 mcr ++ * sock->ops should reference the unwrapped options so that ++ * we get hacked in locking on SMP systems. ++ * ++ * Revision 1.76 2002/10/12 23:11:53 dhr ++ * ++ * [KenB + DHR] more 64-bit cleanup ++ * ++ * Revision 1.75 2002/09/20 05:01:57 rgb ++ * Added memory allocation debugging. ++ * ++ * Revision 1.74 2002/09/19 02:42:50 mcr ++ * do not define the pfkey_ops function for now. ++ * ++ * Revision 1.73 2002/09/17 17:29:23 mcr ++ * #if 0 out some dead code - pfkey_ops is never used as written. ++ * ++ * Revision 1.72 2002/07/24 18:44:54 rgb ++ * Type fiddling to tame ia64 compiler. ++ * ++ * Revision 1.71 2002/05/23 07:14:11 rgb ++ * Cleaned up %p variants to 0p%p for test suite cleanup. ++ * ++ * Revision 1.70 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.69 2002/04/24 07:36:33 mcr ++ * Moved from ./klips/net/ipsec/pfkey_v2.c,v ++ * ++ * Revision 1.68 2002/03/08 01:15:17 mcr ++ * put some internal structure only debug messages behind ++ * && sysctl_ipsec_debug_verbose. ++ * ++ * Revision 1.67 2002/01/29 17:17:57 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.66 2002/01/29 04:00:54 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.65 2002/01/29 02:13:18 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.64 2001/11/26 09:23:51 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.61.2.1 2001/09/25 02:28:44 mcr ++ * cleaned up includes. ++ * ++ * Revision 1.63 2001/11/12 19:38:00 rgb ++ * Continue trying other sockets even if one fails and return only original ++ * error. ++ * ++ * Revision 1.62 2001/10/18 04:45:22 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/freeswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.61 2001/09/20 15:32:59 rgb ++ * Min/max cleanup. ++ * ++ * Revision 1.60 2001/06/14 19:35:12 rgb ++ * Update copyright date. ++ * ++ * Revision 1.59 2001/06/13 15:35:48 rgb ++ * Fixed #endif comments. ++ * ++ * Revision 1.58 2001/05/04 16:37:24 rgb ++ * Remove erroneous checking of return codes for proc_net_* in 2.4. ++ * ++ * Revision 1.57 2001/05/03 19:43:36 rgb ++ * Initialise error return variable. ++ * Check error return codes in startup and shutdown. ++ * Standardise on SENDERR() macro. ++ * ++ * Revision 1.56 2001/04/21 23:05:07 rgb ++ * Define out skb->used for 2.4 kernels. ++ * ++ * Revision 1.55 2001/02/28 05:03:28 rgb ++ * Clean up and rationalise startup messages. ++ * ++ * Revision 1.54 2001/02/27 22:24:55 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.53 2001/02/27 06:48:18 rgb ++ * Fixed pfkey socket unregister log message to reflect type and function. ++ * ++ * Revision 1.52 2001/02/26 22:34:38 rgb ++ * Fix error return code that was getting overwritten by the error return ++ * code of an upmsg. ++ * ++ * Revision 1.51 2001/01/30 23:42:47 rgb ++ * Allow pfkey msgs from pid other than user context required for ACQUIRE ++ * and subsequent ADD or UDATE. ++ * ++ * Revision 1.50 2001/01/23 20:22:59 rgb ++ * 2.4 fix to remove removed is_clone member. ++ * ++ * Revision 1.49 2000/11/06 04:33:47 rgb ++ * Changed non-exported functions to DEBUG_NO_STATIC. ++ * ++ * Revision 1.48 2000/09/29 19:47:41 rgb ++ * Update copyright. ++ * ++ * Revision 1.47 2000/09/22 04:23:04 rgb ++ * Added more debugging to pfkey_upmsg() call from pfkey_sendmsg() error. ++ * ++ * Revision 1.46 2000/09/21 04:20:44 rgb ++ * Fixed array size off-by-one error. (Thanks Svenning!) ++ * ++ * Revision 1.45 2000/09/20 04:01:26 rgb ++ * Changed static functions to DEBUG_NO_STATIC for revealing function names ++ * in oopsen. ++ * ++ * Revision 1.44 2000/09/19 00:33:17 rgb ++ * 2.0 fixes. ++ * ++ * Revision 1.43 2000/09/16 01:28:13 rgb ++ * Fixed use of 0 in p format warning. ++ * ++ * Revision 1.42 2000/09/16 01:09:41 rgb ++ * Fixed debug format warning for pointers that was expecting ints. ++ * ++ * Revision 1.41 2000/09/13 15:54:00 rgb ++ * Rewrote pfkey_get_info(), added pfkey_{supported,registered}_get_info(). ++ * Moved supported algos add and remove to functions. ++ * ++ * Revision 1.40 2000/09/12 18:49:28 rgb ++ * Added IPIP tunnel and IPCOMP register support. ++ * ++ * Revision 1.39 2000/09/12 03:23:49 rgb ++ * Converted #if0 debugs to sysctl. ++ * Removed debug_pfkey initialisations that prevented no_debug loading or ++ * linking. ++ * ++ * Revision 1.38 2000/09/09 06:38:02 rgb ++ * Return positive errno in pfkey_reply error message. ++ * ++ * Revision 1.37 2000/09/08 19:19:09 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * Clean-up of long-unused crud... ++ * Create pfkey error message on on failure. ++ * Give pfkey_list_{insert,remove}_{socket,supported}() some error ++ * checking. ++ * ++ * Revision 1.36 2000/09/01 18:49:38 rgb ++ * Reap experimental NET_21_ bits. ++ * Turned registered sockets list into an array of one list per satype. ++ * Remove references to deprecated sklist_{insert,remove}_socket. ++ * Removed leaking socket debugging code. ++ * Removed duplicate pfkey_insert_socket in pfkey_create. ++ * Removed all references to pfkey msg->msg_name, since it is not used for ++ * pfkey. ++ * Added a supported algorithms array lists, one per satype and registered ++ * existing algorithms. ++ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to ++ * list. ++ * Only send pfkey_expire() messages to sockets registered for that satype. ++ * ++ * Revision 1.35 2000/08/24 17:03:00 rgb ++ * Corrected message size error return code for PF_KEYv2. ++ * Removed downward error prohibition. ++ * ++ * Revision 1.34 2000/08/21 16:32:26 rgb ++ * Re-formatted for cosmetic consistency and readability. ++ * ++ * Revision 1.33 2000/08/20 21:38:24 rgb ++ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil) ++ * Extended the upward message initiation of pfkey_sendmsg(). (Momchil) ++ * ++ * Revision 1.32 2000/07/28 14:58:31 rgb ++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. ++ * ++ * Revision 1.31 2000/05/16 03:04:00 rgb ++ * Updates for 2.3.99pre8 from MB. ++ * ++ * Revision 1.30 2000/05/10 19:22:21 rgb ++ * Use sklist private functions for 2.3.xx compatibility. ++ * ++ * Revision 1.29 2000/03/22 16:17:03 rgb ++ * Fixed SOCKOPS_WRAPPED macro for SMP (MB). ++ * ++ * Revision 1.28 2000/02/21 19:30:45 rgb ++ * Removed references to pkt_bridged for 2.3.47 compatibility. ++ * ++ * Revision 1.27 2000/02/14 21:07:00 rgb ++ * Fixed /proc/net/pf-key legend spacing. ++ * ++ * Revision 1.26 2000/01/22 03:46:59 rgb ++ * Fixed pfkey error return mechanism so that we are able to free the ++ * local copy of the pfkey_msg, plugging a memory leak and silencing ++ * the bad object free complaints. ++ * ++ * Revision 1.25 2000/01/21 06:19:44 rgb ++ * Moved pfkey_list_remove_socket() calls to before MOD_USE_DEC_COUNT. ++ * Added debugging to pfkey_upmsg. ++ * ++ * Revision 1.24 2000/01/10 16:38:23 rgb ++ * MB fixups for 2.3.x. ++ * ++ * Revision 1.23 1999/12/09 23:22:16 rgb ++ * Added more instrumentation for debugging 2.0 socket ++ * selection/reading. ++ * Removed erroneous 2.0 wait==NULL check bug in select. ++ * ++ * Revision 1.22 1999/12/08 20:32:16 rgb ++ * Tidied up 2.0.xx support, after major pfkey work, eliminating ++ * msg->msg_name twiddling in the process, since it is not defined ++ * for PF_KEYv2. ++ * ++ * Revision 1.21 1999/12/01 22:17:19 rgb ++ * Set skb->dev to zero on new skb in case it is a reused skb. ++ * Added check for skb_put overflow and freeing to avoid upmsg on error. ++ * Added check for wrong pfkey version and freeing to avoid upmsg on ++ * error. ++ * Shut off content dumping in pfkey_destroy. ++ * Added debugging message for size of buffer allocated for upmsg. ++ * ++ * Revision 1.20 1999/11/27 12:11:00 rgb ++ * Minor clean-up, enabling quiet operation of pfkey if desired. ++ * ++ * Revision 1.19 1999/11/25 19:04:21 rgb ++ * Update proc_fs code for pfkey to use dynamic registration. ++ * ++ * Revision 1.18 1999/11/25 09:07:17 rgb ++ * Implemented SENDERR macro for propagating error codes. ++ * Fixed error return code bug. ++ * ++ * Revision 1.17 1999/11/23 23:07:20 rgb ++ * Change name of pfkey_msg_parser to pfkey_msg_interp since it no longer ++ * parses. (PJO) ++ * Sort out pfkey and freeswan headers, putting them in a library path. ++ * ++ * Revision 1.16 1999/11/20 22:00:22 rgb ++ * Moved socketlist type declarations and prototypes for shared use. ++ * Renamed reformatted and generically extended for use by other socket ++ * lists pfkey_{del,add}_open_socket to pfkey_list_{remove,insert}_socket. ++ * ++ * Revision 1.15 1999/11/18 04:15:09 rgb ++ * Make pfkey_data_ready temporarily available for 2.2.x testing. ++ * Clean up pfkey_destroy_socket() debugging statements. ++ * Add Peter Onion's code to send messages up to all listening sockets. ++ * Changed all occurrences of #include "../../../lib/freeswan.h" ++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the ++ * klips/net/ipsec/Makefile. ++ * Replaced all kernel version macros to shorter, readable form. ++ * Added CONFIG_PROC_FS compiler directives in case it is shut off. ++ * ++ * Revision 1.14 1999/11/17 16:01:00 rgb ++ * Make pfkey_data_ready temporarily available for 2.2.x testing. ++ * Clean up pfkey_destroy_socket() debugging statements. ++ * Add Peter Onion's code to send messages up to all listening sockets. ++ * Changed #include "../../../lib/freeswan.h" to #include <freeswan.h> ++ * which works due to -Ilibfreeswan in the klips/net/ipsec/Makefile. ++ * ++ * Revision 1.13 1999/10/27 19:59:51 rgb ++ * Removed af_unix comments that are no longer relevant. ++ * Added debug prink statements. ++ * Added to the /proc output in pfkey_get_info. ++ * Made most functions non-static to enable oops tracing. ++ * Re-enable skb dequeueing and freeing. ++ * Fix skb_alloc() and skb_put() size bug in pfkey_upmsg(). ++ * ++ * Revision 1.12 1999/10/26 17:05:42 rgb ++ * Complete re-ordering based on proto_ops structure order. ++ * Separated out proto_ops structures for 2.0.x and 2.2.x for clarity. ++ * Simplification to use built-in socket ops where possible for 2.2.x. ++ * Add shorter macros for compiler directives to visually clean-up. ++ * Add lots of sk skb dequeueing debugging statements. ++ * Added to the /proc output in pfkey_get_info. ++ * ++ * Revision 1.11 1999/09/30 02:55:10 rgb ++ * Bogus skb detection. ++ * Fix incorrect /proc/net/ipsec-eroute printk message. ++ * ++ * Revision 1.10 1999/09/21 15:22:13 rgb ++ * Temporary fix while I figure out the right way to destroy sockets. ++ * ++ * Revision 1.9 1999/07/08 19:19:44 rgb ++ * Fix pointer format warning. ++ * Fix missing member error under 2.0.xx kernels. ++ * ++ * Revision 1.8 1999/06/13 07:24:04 rgb ++ * Add more debugging. ++ * ++ * Revision 1.7 1999/06/10 05:24:17 rgb ++ * Clarified compiler directives. ++ * Renamed variables to reduce confusion. ++ * Used sklist_*_socket() kernel functions to simplify 2.2.x socket support. ++ * Added lots of sanity checking. ++ * ++ * Revision 1.6 1999/06/03 18:59:50 rgb ++ * More updates to 2.2.x socket support. Almost works, oops at end of call. ++ * ++ * Revision 1.5 1999/05/25 22:44:05 rgb ++ * Start fixing 2.2 sockets. ++ * ++ * Revision 1.4 1999/04/29 15:21:34 rgb ++ * Move log to the end of the file. ++ * Eliminate min/max redefinition in #include <net/tcp.h>. ++ * Correct path for pfkey #includes ++ * Standardise an error return method. ++ * Add debugging instrumentation. ++ * Move message type checking to pfkey_msg_parse(). ++ * Add check for errno incorrectly set. ++ * Add check for valid PID. ++ * Add check for reserved illegally set. ++ * Add check for message out of bounds. ++ * ++ * Revision 1.3 1999/04/15 17:58:07 rgb ++ * Add RCSID labels. ++ * ++ * Revision 1.2 1999/04/15 15:37:26 rgb ++ * Forward check changes from POST1_00 branch. ++ * ++ * Revision 1.1.2.2 1999/04/13 20:37:12 rgb ++ * Header Title correction. ++ * ++ * Revision 1.1.2.1 1999/03/26 20:58:55 rgb ++ * Add pfkeyv2 support to KLIPS. ++ * ++ * ++ * RFC 2367 ++ * PF_KEY_v2 Key Management API ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/pfkey_v2_ext_process.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,922 @@ ++/* ++ * @(#) RFC2367 PF_KEYv2 Key management API message parser ++ * Copyright (C) 1998-2003 Richard Guy Briggs. ++ * Copyright (C) 2004 Michael Richardson <mcr@xelerance.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: pfkey_v2_ext_process.c,v 1.15 2004/04/06 02:49:26 mcr Exp $ ++ */ ++ ++/* ++ * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. ++ */ ++ ++char pfkey_v2_ext_process_c_version[] = "$Id: pfkey_v2_ext_process.c,v 1.15 2004/04/06 02:49:26 mcr Exp $"; ++ ++#include <linux/config.h> ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++ ++#include <openswan.h> ++ ++#include <crypto/des.h> ++ ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define ip_chk_addr inet_addr_type ++# define IS_MYADDR RTN_LOCAL ++#endif ++#include <asm/checksum.h> ++#include <net/ip.h> ++#ifdef NETLINK_SOCK ++# include <linux/netlink.h> ++#else ++# include <net/netlink.h> ++#endif ++ ++#include <linux/random.h> /* get_random_bytes() */ ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_ah.h" ++#include "openswan/ipsec_esp.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_rcv.h" ++#include "openswan/ipcomp.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_proto.h" ++#include "openswan/ipsec_alg.h" ++ ++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) ++ ++int ++pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext; ++ int error = 0; ++ struct ipsec_sa* ipsp; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sa_process: .\n"); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sa_process: " ++ "extr or extr->ips is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_ext->sadb_ext_type) { ++ case SADB_EXT_SA: ++ ipsp = extr->ips; ++ break; ++ case SADB_X_EXT_SA2: ++ if(extr->ips2 == NULL) { ++ extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ ++ } ++ if(extr->ips2 == NULL) { ++ SENDERR(-error); ++ } ++ ipsp = extr->ips2; ++ break; ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sa_process: " ++ "invalid exttype=%d.\n", ++ pfkey_ext->sadb_ext_type); ++ SENDERR(EINVAL); ++ } ++ ++ ipsp->ips_said.spi = pfkey_sa->sadb_sa_spi; ++ ipsp->ips_replaywin = pfkey_sa->sadb_sa_replay; ++ ipsp->ips_state = pfkey_sa->sadb_sa_state; ++ ipsp->ips_flags = pfkey_sa->sadb_sa_flags; ++ ipsp->ips_replaywin_lastseq = ipsp->ips_replaywin_bitmap = 0; ++ ipsp->ips_ref_rel = pfkey_sa->sadb_x_sa_ref; ++ ++ switch(ipsp->ips_said.proto) { ++ case IPPROTO_AH: ++ ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; ++ ipsp->ips_encalg = SADB_EALG_NONE; ++ break; ++ case IPPROTO_ESP: ++ ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; ++ ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; ++#ifdef CONFIG_IPSEC_ALG ++ ipsec_alg_sa_init(ipsp); ++#endif /* CONFIG_IPSEC_ALG */ ++ break; ++ case IPPROTO_IPIP: ++ ipsp->ips_authalg = AH_NONE; ++ ipsp->ips_encalg = ESP_NONE; ++ break; ++#ifdef CONFIG_IPSEC_IPCOMP ++ case IPPROTO_COMP: ++ ipsp->ips_authalg = AH_NONE; ++ ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; ++ break; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ case IPPROTO_INT: ++ ipsp->ips_authalg = AH_NONE; ++ ipsp->ips_encalg = ESP_NONE; ++ break; ++ case 0: ++ break; ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sa_process: " ++ "unknown proto=%d.\n", ++ ipsp->ips_said.proto); ++ SENDERR(EINVAL); ++ } ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_lifetime_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_lifetime_process: .\n"); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_lifetime_process: " ++ "extr or extr->ips is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_lifetime->sadb_lifetime_exttype) { ++ case SADB_EXT_LIFETIME_CURRENT: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_lifetime_process: " ++ "lifetime_current not supported yet.\n"); ++ SENDERR(EINVAL); ++ break; ++ case SADB_EXT_LIFETIME_HARD: ++ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_allocations, ++ pfkey_lifetime->sadb_lifetime_allocations); ++ ++ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_bytes, ++ pfkey_lifetime->sadb_lifetime_bytes); ++ ++ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_addtime, ++ pfkey_lifetime->sadb_lifetime_addtime); ++ ++ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_usetime, ++ pfkey_lifetime->sadb_lifetime_usetime); ++ ++ break; ++ ++ case SADB_EXT_LIFETIME_SOFT: ++ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_allocations, ++ pfkey_lifetime->sadb_lifetime_allocations); ++ ++ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_bytes, ++ pfkey_lifetime->sadb_lifetime_bytes); ++ ++ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_addtime, ++ pfkey_lifetime->sadb_lifetime_addtime); ++ ++ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_usetime, ++ pfkey_lifetime->sadb_lifetime_usetime); ++ ++ break; ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_lifetime_process: " ++ "invalid exttype=%d.\n", ++ pfkey_ext->sadb_ext_type); ++ SENDERR(EINVAL); ++ } ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ int saddr_len = 0; ++ char ipaddr_txt[ADDRTOA_BUF]; ++ unsigned char **sap; ++ unsigned short * portp = 0; ++ struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; ++ struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); ++ struct ipsec_sa* ipsp; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process:\n"); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "extr or extr->ips is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ switch(s->sa_family) { ++ case AF_INET: ++ saddr_len = sizeof(struct sockaddr_in); ++ addrtoa(((struct sockaddr_in*)s)->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt)); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found address family=%d, AF_INET, %s.\n", ++ s->sa_family, ++ ipaddr_txt); ++ break; ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ case AF_INET6: ++ saddr_len = sizeof(struct sockaddr_in6); ++ break; ++#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "s->sa_family=%d not supported.\n", ++ s->sa_family); ++ SENDERR(EPFNOSUPPORT); ++ } ++ ++ switch(pfkey_address->sadb_address_exttype) { ++ case SADB_EXT_ADDRESS_SRC: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found src address.\n"); ++ sap = (unsigned char **)&(extr->ips->ips_addr_s); ++ extr->ips->ips_addr_s_size = saddr_len; ++ break; ++ case SADB_EXT_ADDRESS_DST: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found dst address.\n"); ++ sap = (unsigned char **)&(extr->ips->ips_addr_d); ++ extr->ips->ips_addr_d_size = saddr_len; ++ break; ++ case SADB_EXT_ADDRESS_PROXY: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found proxy address.\n"); ++ sap = (unsigned char **)&(extr->ips->ips_addr_p); ++ extr->ips->ips_addr_p_size = saddr_len; ++ break; ++ case SADB_X_EXT_ADDRESS_DST2: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found 2nd dst address.\n"); ++ if(extr->ips2 == NULL) { ++ extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ ++ } ++ if(extr->ips2 == NULL) { ++ SENDERR(-error); ++ } ++ sap = (unsigned char **)&(extr->ips2->ips_addr_d); ++ extr->ips2->ips_addr_d_size = saddr_len; ++ break; ++ case SADB_X_EXT_ADDRESS_SRC_FLOW: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found src flow address.\n"); ++ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { ++ SENDERR(ENOMEM); ++ } ++ sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_src); ++ portp = &(extr->eroute->er_eaddr.sen_sport); ++ break; ++ case SADB_X_EXT_ADDRESS_DST_FLOW: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found dst flow address.\n"); ++ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { ++ SENDERR(ENOMEM); ++ } ++ sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_dst); ++ portp = &(extr->eroute->er_eaddr.sen_dport); ++ break; ++ case SADB_X_EXT_ADDRESS_SRC_MASK: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found src mask address.\n"); ++ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { ++ SENDERR(ENOMEM); ++ } ++ sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_src); ++ portp = &(extr->eroute->er_emask.sen_sport); ++ break; ++ case SADB_X_EXT_ADDRESS_DST_MASK: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found dst mask address.\n"); ++ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { ++ SENDERR(ENOMEM); ++ } ++ sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_dst); ++ portp = &(extr->eroute->er_emask.sen_dport); ++ break; ++#ifdef NAT_TRAVERSAL ++ case SADB_X_EXT_NAT_T_OA: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "found NAT-OA address.\n"); ++ sap = (unsigned char **)&(extr->ips->ips_natt_oa); ++ extr->ips->ips_natt_oa_size = saddr_len; ++ break; ++#endif ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "unrecognised ext_type=%d.\n", ++ pfkey_address->sadb_address_exttype); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_address->sadb_address_exttype) { ++ case SADB_EXT_ADDRESS_SRC: ++ case SADB_EXT_ADDRESS_DST: ++ case SADB_EXT_ADDRESS_PROXY: ++ case SADB_X_EXT_ADDRESS_DST2: ++#ifdef NAT_TRAVERSAL ++ case SADB_X_EXT_NAT_T_OA: ++#endif ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "allocating %d bytes for saddr.\n", ++ saddr_len); ++ if(!(*sap = kmalloc(saddr_len, GFP_KERNEL))) { ++ SENDERR(ENOMEM); ++ } ++ memcpy(*sap, s, saddr_len); ++ break; ++ default: ++ if(s->sa_family != AF_INET) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "s->sa_family=%d not supported.\n", ++ s->sa_family); ++ SENDERR(EPFNOSUPPORT); ++ } ++ (unsigned long)(*sap) = ((struct sockaddr_in*)s)->sin_addr.s_addr; ++ if (portp != 0) ++ *portp = ((struct sockaddr_in*)s)->sin_port; ++#ifdef CONFIG_IPSEC_DEBUG ++ if(extr->eroute) { ++ char buf1[64], buf2[64]; ++ if (debug_pfkey) { ++ subnettoa(extr->eroute->er_eaddr.sen_ip_src, ++ extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); ++ subnettoa(extr->eroute->er_eaddr.sen_ip_dst, ++ extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_parse: " ++ "extr->eroute set to %s:%d->%s:%d\n", ++ buf1, ++ ntohs(extr->eroute->er_eaddr.sen_sport), ++ buf2, ++ ntohs(extr->eroute->er_eaddr.sen_dport)); ++ } ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ } ++ ++ ipsp = extr->ips; ++ switch(pfkey_address->sadb_address_exttype) { ++ case SADB_X_EXT_ADDRESS_DST2: ++ ipsp = extr->ips2; ++ case SADB_EXT_ADDRESS_DST: ++ if(s->sa_family == AF_INET) { ++ ipsp->ips_said.dst.u.v4.sin_addr.s_addr = ((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr.s_addr; ++ ipsp->ips_said.dst.u.v4.sin_family = AF_INET; ++ addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, ++ 0, ++ ipaddr_txt, ++ sizeof(ipaddr_txt)); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "ips_said.dst set to %s.\n", ++ ipaddr_txt); ++ } else { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: " ++ "uh, ips_said.dst doesn't do address family=%d yet, said will be invalid.\n", ++ s->sa_family); ++ } ++ default: ++ break; ++ } ++ ++ /* XXX check if port!=0 */ ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_address_process: successful.\n"); ++ errlab: ++ return error; ++} ++ ++int ++pfkey_key_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_key_process: .\n"); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_key_process: " ++ "extr or extr->ips is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_key->sadb_key_exttype) { ++ case SADB_EXT_KEY_AUTH: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_key_process: " ++ "allocating %d bytes for authkey.\n", ++ DIVUP(pfkey_key->sadb_key_bits, 8)); ++ if(!(extr->ips->ips_key_a = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_key_process: " ++ "memory allocation error.\n"); ++ SENDERR(ENOMEM); ++ } ++ extr->ips->ips_key_bits_a = pfkey_key->sadb_key_bits; ++ extr->ips->ips_key_a_size = DIVUP(pfkey_key->sadb_key_bits, 8); ++ memcpy(extr->ips->ips_key_a, ++ (char*)pfkey_key + sizeof(struct sadb_key), ++ extr->ips->ips_key_a_size); ++ break; ++ case SADB_EXT_KEY_ENCRYPT: /* Key(s) */ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_key_process: " ++ "allocating %d bytes for enckey.\n", ++ DIVUP(pfkey_key->sadb_key_bits, 8)); ++ if(!(extr->ips->ips_key_e = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_key_process: " ++ "memory allocation error.\n"); ++ SENDERR(ENOMEM); ++ } ++ extr->ips->ips_key_bits_e = pfkey_key->sadb_key_bits; ++ extr->ips->ips_key_e_size = DIVUP(pfkey_key->sadb_key_bits, 8); ++ memcpy(extr->ips->ips_key_e, ++ (char*)pfkey_key + sizeof(struct sadb_key), ++ extr->ips->ips_key_e_size); ++ break; ++ default: ++ SENDERR(EINVAL); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_key_process: " ++ "success.\n"); ++errlab: ++ return error; ++} ++ ++int ++pfkey_ident_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext; ++ int data_len; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ident_process: .\n"); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ident_process: " ++ "extr or extr->ips is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_ident->sadb_ident_exttype) { ++ case SADB_EXT_IDENTITY_SRC: ++ data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); ++ ++ extr->ips->ips_ident_s.type = pfkey_ident->sadb_ident_type; ++ extr->ips->ips_ident_s.id = pfkey_ident->sadb_ident_id; ++ extr->ips->ips_ident_s.len = pfkey_ident->sadb_ident_len; ++ if(data_len) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ident_process: " ++ "allocating %d bytes for ident_s.\n", ++ data_len); ++ if(!(extr->ips->ips_ident_s.data ++ = kmalloc(data_len, GFP_KERNEL))) { ++ SENDERR(ENOMEM); ++ } ++ memcpy(extr->ips->ips_ident_s.data, ++ (char*)pfkey_ident + sizeof(struct sadb_ident), ++ data_len); ++ } else { ++ extr->ips->ips_ident_s.data = NULL; ++ } ++ break; ++ case SADB_EXT_IDENTITY_DST: /* Identity(ies) */ ++ data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); ++ ++ extr->ips->ips_ident_d.type = pfkey_ident->sadb_ident_type; ++ extr->ips->ips_ident_d.id = pfkey_ident->sadb_ident_id; ++ extr->ips->ips_ident_d.len = pfkey_ident->sadb_ident_len; ++ if(data_len) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ident_process: " ++ "allocating %d bytes for ident_d.\n", ++ data_len); ++ if(!(extr->ips->ips_ident_d.data ++ = kmalloc(data_len, GFP_KERNEL))) { ++ SENDERR(ENOMEM); ++ } ++ memcpy(extr->ips->ips_ident_d.data, ++ (char*)pfkey_ident + sizeof(struct sadb_ident), ++ data_len); ++ } else { ++ extr->ips->ips_ident_d.data = NULL; ++ } ++ break; ++ default: ++ SENDERR(EINVAL); ++ } ++errlab: ++ return error; ++} ++ ++int ++pfkey_sens_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_sens_process: " ++ "Sorry, I can't process exttype=%d yet.\n", ++ pfkey_ext->sadb_ext_type); ++ SENDERR(EINVAL); /* don't process these yet */ ++ errlab: ++ return error; ++} ++ ++int ++pfkey_prop_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_prop_process: " ++ "Sorry, I can't process exttype=%d yet.\n", ++ pfkey_ext->sadb_ext_type); ++ SENDERR(EINVAL); /* don't process these yet */ ++ ++ errlab: ++ return error; ++} ++ ++int ++pfkey_supported_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_supported_process: " ++ "Sorry, I can't process exttype=%d yet.\n", ++ pfkey_ext->sadb_ext_type); ++ SENDERR(EINVAL); /* don't process these yet */ ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_spirange_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_spirange_process: .\n"); ++/* errlab: */ ++ return error; ++} ++ ++int ++pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_kmprivate_process: " ++ "Sorry, I can't process exttype=%d yet.\n", ++ pfkey_ext->sadb_ext_type); ++ SENDERR(EINVAL); /* don't process these yet */ ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_satype_process: .\n"); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_satype_process: " ++ "extr or extr->ips is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(extr->ips2 == NULL) { ++ extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ ++ } ++ if(extr->ips2 == NULL) { ++ SENDERR(-error); ++ } ++ if(!(extr->ips2->ips_said.proto = satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_satype_process: " ++ "proto lookup from satype=%d failed.\n", ++ pfkey_x_satype->sadb_x_satype_satype); ++ SENDERR(EINVAL); ++ } ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_satype_process: " ++ "protocol==%d decoded from satype==%d(%s).\n", ++ extr->ips2->ips_said.proto, ++ pfkey_x_satype->sadb_x_satype_satype, ++ satype2name(pfkey_x_satype->sadb_x_satype_satype)); ++ ++errlab: ++ return error; ++} ++ ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++int ++pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)pfkey_ext; ++ ++ if(!pfkey_x_nat_t_type) { ++ printk("klips_debug:pfkey_x_nat_t_type_process: " ++ "null pointer passed in\n"); ++ SENDERR(EINVAL); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_nat_t_type_process: %d.\n", ++ pfkey_x_nat_t_type->sadb_x_nat_t_type_type); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_nat_t_type_process: " ++ "extr or extr->ips is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_x_nat_t_type->sadb_x_nat_t_type_type) { ++ case ESPINUDP_WITH_NON_IKE: /* with Non-IKE (older version) */ ++ case ESPINUDP_WITH_NON_ESP: /* with Non-ESP */ ++ ++ extr->ips->ips_natt_type = pfkey_x_nat_t_type->sadb_x_nat_t_type_type; ++ break; ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_nat_t_type_process: " ++ "unknown type %d.\n", ++ pfkey_x_nat_t_type->sadb_x_nat_t_type_type); ++ SENDERR(EINVAL); ++ break; ++ } ++ ++errlab: ++ return error; ++} ++ ++int ++pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)pfkey_ext; ++ ++ if(!pfkey_x_nat_t_port) { ++ printk("klips_debug:pfkey_x_nat_t_port_process: " ++ "null pointer passed in\n"); ++ SENDERR(EINVAL); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_nat_t_port_process: %d/%d.\n", ++ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype, ++ pfkey_x_nat_t_port->sadb_x_nat_t_port_port); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_nat_t_type_process: " ++ "extr or extr->ips is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype) { ++ case SADB_X_EXT_NAT_T_SPORT: ++ extr->ips->ips_natt_sport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; ++ break; ++ case SADB_X_EXT_NAT_T_DPORT: ++ extr->ips->ips_natt_dport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; ++ break; ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_nat_t_port_process: " ++ "unknown exttype %d.\n", ++ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype); ++ SENDERR(EINVAL); ++ break; ++ } ++ ++errlab: ++ return error; ++} ++#endif ++ ++int ++pfkey_x_debug_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext; ++ ++ if(!pfkey_x_debug) { ++ printk("klips_debug:pfkey_x_debug_process: " ++ "null pointer passed in\n"); ++ SENDERR(EINVAL); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_debug_process: .\n"); ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if(pfkey_x_debug->sadb_x_debug_netlink >> ++ (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 - 1)) { ++ pfkey_x_debug->sadb_x_debug_netlink &= ++ ~(1 << (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 -1)); ++ debug_tunnel |= pfkey_x_debug->sadb_x_debug_tunnel; ++ debug_netlink |= pfkey_x_debug->sadb_x_debug_netlink; ++ debug_xform |= pfkey_x_debug->sadb_x_debug_xform; ++ debug_eroute |= pfkey_x_debug->sadb_x_debug_eroute; ++ debug_spi |= pfkey_x_debug->sadb_x_debug_spi; ++ debug_radij |= pfkey_x_debug->sadb_x_debug_radij; ++ debug_esp |= pfkey_x_debug->sadb_x_debug_esp; ++ debug_ah |= pfkey_x_debug->sadb_x_debug_ah; ++ debug_rcv |= pfkey_x_debug->sadb_x_debug_rcv; ++ debug_pfkey |= pfkey_x_debug->sadb_x_debug_pfkey; ++#ifdef CONFIG_IPSEC_IPCOMP ++ sysctl_ipsec_debug_ipcomp |= pfkey_x_debug->sadb_x_debug_ipcomp; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ sysctl_ipsec_debug_verbose |= pfkey_x_debug->sadb_x_debug_verbose; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_debug_process: " ++ "set\n"); ++ } else { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_debug_process: " ++ "unset\n"); ++ debug_tunnel &= pfkey_x_debug->sadb_x_debug_tunnel; ++ debug_netlink &= pfkey_x_debug->sadb_x_debug_netlink; ++ debug_xform &= pfkey_x_debug->sadb_x_debug_xform; ++ debug_eroute &= pfkey_x_debug->sadb_x_debug_eroute; ++ debug_spi &= pfkey_x_debug->sadb_x_debug_spi; ++ debug_radij &= pfkey_x_debug->sadb_x_debug_radij; ++ debug_esp &= pfkey_x_debug->sadb_x_debug_esp; ++ debug_ah &= pfkey_x_debug->sadb_x_debug_ah; ++ debug_rcv &= pfkey_x_debug->sadb_x_debug_rcv; ++ debug_pfkey &= pfkey_x_debug->sadb_x_debug_pfkey; ++#ifdef CONFIG_IPSEC_IPCOMP ++ sysctl_ipsec_debug_ipcomp &= pfkey_x_debug->sadb_x_debug_ipcomp; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ sysctl_ipsec_debug_verbose &= pfkey_x_debug->sadb_x_debug_verbose; ++ } ++#else /* CONFIG_IPSEC_DEBUG */ ++ printk("klips_debug:pfkey_x_debug_process: " ++ "debugging not enabled\n"); ++ SENDERR(EINVAL); ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++errlab: ++ return error; ++} ++ ++/* ++ * $Log: pfkey_v2_ext_process.c,v $ ++ * Revision 1.15 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.14 2004/02/03 03:13:59 mcr ++ * no longer #ifdef out NON_ESP mode. That was a mistake. ++ * ++ * Revision 1.13 2003/12/15 18:13:12 mcr ++ * when compiling with NAT traversal, don't assume that the ++ * kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP ++ * is set. ++ * ++ * Revision 1.12.2.1 2003/12/22 15:25:52 jjo ++ * Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.12 2003/12/10 01:14:27 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.11 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.10.4.2 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.10.4.1 2003/09/21 13:59:56 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.10 2003/02/06 01:51:41 rgb ++ * Removed no longer relevant comment ++ * ++ * Revision 1.9 2003/01/30 02:32:44 rgb ++ * ++ * Transmit error code through to caller from callee for better diagnosis of problems. ++ * ++ * Revision 1.8 2002/12/13 22:42:22 mcr ++ * restored sa_ref code ++ * ++ * Revision 1.7 2002/12/13 22:40:48 mcr ++ * temporarily removed sadb_x_sa_ref reference for 2.xx ++ * ++ * Revision 1.6 2002/10/05 05:02:58 dhr ++ * ++ * C labels go on statements ++ * ++ * Revision 1.5 2002/09/20 15:41:08 rgb ++ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). ++ * Added sadb_x_sa_ref to struct sadb_sa. ++ * ++ * Revision 1.4 2002/09/20 05:02:02 rgb ++ * Added memory allocation debugging. ++ * ++ * Revision 1.3 2002/07/24 18:44:54 rgb ++ * Type fiddling to tame ia64 compiler. ++ * ++ * Revision 1.2 2002/05/27 18:55:03 rgb ++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. ++ * ++ * Revision 1.1 2002/05/14 02:33:51 rgb ++ * Moved all the extension processing functions to pfkey_v2_ext_process.c. ++ * ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/pfkey_v2_parser.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,4018 @@ ++/* ++ * @(#) RFC2367 PF_KEYv2 Key management API message parser ++ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs <rgb@freeswan.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: pfkey_v2_parser.c,v 1.123 2004/04/06 02:49:26 mcr Exp $ ++ */ ++ ++/* ++ * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. ++ */ ++ ++char pfkey_v2_parser_c_version[] = "$Id: pfkey_v2_parser.c,v 1.123 2004/04/06 02:49:26 mcr Exp $"; ++ ++#include <linux/config.h> ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++ ++#include <openswan.h> ++ ++#include <crypto/des.h> ++ ++#ifdef SPINLOCK ++# ifdef SPINLOCK_23 ++# include <linux/spinlock.h> /* *lock* */ ++# else /* SPINLOCK_23 */ ++# include <asm/spinlock.h> /* *lock* */ ++# endif /* SPINLOCK_23 */ ++#endif /* SPINLOCK */ ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++# define ip_chk_addr inet_addr_type ++# define IS_MYADDR RTN_LOCAL ++#endif ++#include <asm/checksum.h> ++#include <net/ip.h> ++#ifdef NETLINK_SOCK ++# include <linux/netlink.h> ++#else ++# include <net/netlink.h> ++#endif ++ ++#include <linux/random.h> /* get_random_bytes() */ ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_sa.h" ++ ++#include "openswan/ipsec_radij.h" ++#include "openswan/ipsec_xform.h" ++#include "openswan/ipsec_ah.h" ++#include "openswan/ipsec_esp.h" ++#include "openswan/ipsec_tunnel.h" ++#include "openswan/ipsec_rcv.h" ++#include "openswan/ipcomp.h" ++ ++#include <pfkeyv2.h> ++#include <pfkey.h> ++ ++#include "openswan/ipsec_proto.h" ++#include "openswan/ipsec_alg.h" ++ ++ ++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) ++ ++struct sklist_t { ++ struct socket *sk; ++ struct sklist_t* next; ++} pfkey_sklist_head, *pfkey_sklist, *pfkey_sklist_prev; ++ ++__u32 pfkey_msg_seq = 0; ++ ++ ++#if 0 ++#define DUMP_SAID dump_said(&extr->ips->ips_said, __LINE__) ++#define DUMP_SAID2 dump_said(&extr.ips->ips_said, __LINE__) ++static void dump_said(ip_said *s, int line) ++{ ++ char msa[SATOT_BUF]; ++ size_t msa_len; ++ ++ msa_len = satot(s, 0, msa, sizeof(msa)); ++ ++ printk("line: %d msa: %s\n", line, msa); ++} ++#endif ++ ++ ++int ++pfkey_alloc_eroute(struct eroute** eroute) ++{ ++ int error = 0; ++ if(*eroute) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_alloc_eroute: " ++ "eroute struct already allocated\n"); ++ SENDERR(EEXIST); ++ } ++ ++ if((*eroute = kmalloc(sizeof(**eroute), GFP_ATOMIC) ) == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_alloc_eroute: " ++ "memory allocation error\n"); ++ SENDERR(ENOMEM); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_alloc_eroute: " ++ "allocating %lu bytes for an eroute at 0p%p\n", ++ (unsigned long) sizeof(**eroute), *eroute); ++ ++ memset((caddr_t)*eroute, 0, sizeof(**eroute)); ++ (*eroute)->er_eaddr.sen_len = ++ (*eroute)->er_emask.sen_len = sizeof(struct sockaddr_encap); ++ (*eroute)->er_eaddr.sen_family = ++ (*eroute)->er_emask.sen_family = AF_ENCAP; ++ (*eroute)->er_eaddr.sen_type = SENT_IP4; ++ (*eroute)->er_emask.sen_type = 255; ++ (*eroute)->er_pid = 0; ++ (*eroute)->er_count = 0; ++ (*eroute)->er_lasttime = jiffies/HZ; ++ ++ errlab: ++ return(error); ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_protocol_process(struct sadb_ext *pfkey_ext, ++ struct pfkey_extracted_data *extr) ++{ ++ int error = 0; ++ struct sadb_protocol * p = (struct sadb_protocol *)pfkey_ext; ++ ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: %p\n", extr); ++ ++ if (extr == 0) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_protocol_process:" ++ "extr is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ if (extr->eroute == 0) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_protocol_process:" ++ "extr->eroute is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ extr->eroute->er_eaddr.sen_proto = p->sadb_protocol_proto; ++ extr->eroute->er_emask.sen_proto = p->sadb_protocol_proto ? ~0:0; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_protocol_process: protocol = %d.\n", ++ p->sadb_protocol_proto); ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_ipsec_sa_init(struct ipsec_sa *ipsp, struct sadb_ext **extensions) ++{ ++ int i; ++ int error = 0; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ char ipaddr_txt[ADDRTOA_BUF]; ++ char ipaddr2_txt[ADDRTOA_BUF]; ++#if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1) ++ unsigned char kb[AHMD596_BLKLEN]; ++#endif ++#ifdef CONFIG_IPSEC_ALG ++ struct ipsec_alg_enc *ixt_e = NULL; ++ struct ipsec_alg_auth *ixt_a = NULL; ++#endif /* CONFIG_IPSEC_ALG */ ++ ++ if(ipsp == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "ipsp is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ sa_len = satot(&ipsp->ips_said, 0, sa, sizeof(sa)); ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "(pfkey defined) called for SA:%s\n", ++ sa_len ? sa : " (error)"); ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "calling init routine of %s%s%s\n", ++ IPS_XFORM_NAME(ipsp)); ++ ++ switch(ipsp->ips_said.proto) { ++ ++#ifdef CONFIG_IPSEC_IPIP ++ case IPPROTO_IPIP: { ++ addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr, ++ 0, ++ ipaddr_txt, sizeof(ipaddr_txt)); ++ addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, ++ 0, ++ ipaddr2_txt, sizeof(ipaddr_txt)); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", ++ ipaddr_txt, ++ ipaddr2_txt); ++ } ++ break; ++#endif /* !CONFIG_IPSEC_IPIP */ ++#ifdef CONFIG_IPSEC_AH ++ case IPPROTO_AH: ++ switch(ipsp->ips_authalg) { ++# ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ case AH_MD5: { ++ unsigned char *akp; ++ unsigned int aks; ++ MD5_CTX *ictx; ++ MD5_CTX *octx; ++ ++ if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ++ ipsp->ips_key_bits_a, AHMD596_KLEN * 8); ++ SENDERR(EINVAL); ++ } ++ ++# if KLIPS_DIVULGE_HMAC_KEY ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); ++# endif /* KLIPS_DIVULGE_HMAC_KEY */ ++ ++ ipsp->ips_auth_bits = AHMD596_ALEN * 8; ++ ++ /* save the pointer to the key material */ ++ akp = ipsp->ips_key_a; ++ aks = ipsp->ips_key_a_size; ++ ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "allocating %lu bytes for md5_ctx.\n", ++ (unsigned long) sizeof(struct md5_ctx)); ++ if((ipsp->ips_key_a = (caddr_t) ++ kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ++ ipsp->ips_key_a = akp; ++ SENDERR(ENOMEM); ++ } ++ ipsp->ips_key_a_size = sizeof(struct md5_ctx); ++ ++ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { ++ kb[i] = akp[i] ^ HMAC_IPAD; ++ } ++ for (; i < AHMD596_BLKLEN; i++) { ++ kb[i] = HMAC_IPAD; ++ } ++ ++ ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); ++ MD5Init(ictx); ++ MD5Update(ictx, kb, AHMD596_BLKLEN); ++ ++ for (i = 0; i < AHMD596_BLKLEN; i++) { ++ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); ++ } ++ ++ octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); ++ MD5Init(octx); ++ MD5Update(octx, kb, AHMD596_BLKLEN); ++ ++# if KLIPS_DIVULGE_HMAC_KEY ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ++ ((__u32*)ictx)[0], ++ ((__u32*)ictx)[1], ++ ((__u32*)ictx)[2], ++ ((__u32*)ictx)[3], ++ ((__u32*)octx)[0], ++ ((__u32*)octx)[1], ++ ((__u32*)octx)[2], ++ ((__u32*)octx)[3] ); ++# endif /* KLIPS_DIVULGE_HMAC_KEY */ ++ ++ /* zero key buffer -- paranoid */ ++ memset(akp, 0, aks); ++ kfree(akp); ++ } ++ break; ++# endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++# ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ case AH_SHA: { ++ unsigned char *akp; ++ unsigned int aks; ++ SHA1_CTX *ictx; ++ SHA1_CTX *octx; ++ ++ if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ++ ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); ++ SENDERR(EINVAL); ++ } ++ ++# if KLIPS_DIVULGE_HMAC_KEY ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); ++# endif /* KLIPS_DIVULGE_HMAC_KEY */ ++ ++ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; ++ ++ /* save the pointer to the key material */ ++ akp = ipsp->ips_key_a; ++ aks = ipsp->ips_key_a_size; ++ ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "allocating %lu bytes for sha1_ctx.\n", ++ (unsigned long) sizeof(struct sha1_ctx)); ++ if((ipsp->ips_key_a = (caddr_t) ++ kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ++ ipsp->ips_key_a = akp; ++ SENDERR(ENOMEM); ++ } ++ ipsp->ips_key_a_size = sizeof(struct sha1_ctx); ++ ++ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { ++ kb[i] = akp[i] ^ HMAC_IPAD; ++ } ++ for (; i < AHMD596_BLKLEN; i++) { ++ kb[i] = HMAC_IPAD; ++ } ++ ++ ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); ++ SHA1Init(ictx); ++ SHA1Update(ictx, kb, AHSHA196_BLKLEN); ++ ++ for (i = 0; i < AHSHA196_BLKLEN; i++) { ++ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); ++ } ++ ++ octx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->octx); ++ SHA1Init(octx); ++ SHA1Update(octx, kb, AHSHA196_BLKLEN); ++ ++# if KLIPS_DIVULGE_HMAC_KEY ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ++ ((__u32*)ictx)[0], ++ ((__u32*)ictx)[1], ++ ((__u32*)ictx)[2], ++ ((__u32*)ictx)[3], ++ ((__u32*)octx)[0], ++ ((__u32*)octx)[1], ++ ((__u32*)octx)[2], ++ ((__u32*)octx)[3] ); ++# endif /* KLIPS_DIVULGE_HMAC_KEY */ ++ /* zero key buffer -- paranoid */ ++ memset(akp, 0, aks); ++ kfree(akp); ++ } ++ break; ++# endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "authalg=%d support not available in the kernel", ++ ipsp->ips_authalg); ++ SENDERR(EINVAL); ++ } ++ break; ++#endif /* CONFIG_IPSEC_AH */ ++#ifdef CONFIG_IPSEC_ESP ++ case IPPROTO_ESP: { ++#if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1) ++ unsigned char *akp; ++ unsigned int aks; ++#endif ++#if defined (CONFIG_IPSEC_ENC_3DES) ++ unsigned char *ekp; ++ unsigned int eks; ++#endif ++ ++ ipsp->ips_iv_size = 0; ++#ifdef CONFIG_IPSEC_ALG ++ if ((ixt_e=ipsp->ips_alg_enc)) { ++ ipsp->ips_iv_size = ixt_e->ixt_ivlen/8; ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ipsp->ips_encalg) { ++# ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++# endif /* CONFIG_IPSEC_ENC_3DES */ ++# if defined(CONFIG_IPSEC_ENC_3DES) ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "allocating %u bytes for iv.\n", ++ EMT_ESPDES_IV_SZ); ++ if((ipsp->ips_iv = (caddr_t) ++ kmalloc((ipsp->ips_iv_size = EMT_ESPDES_IV_SZ), GFP_ATOMIC)) == NULL) { ++ SENDERR(ENOMEM); ++ } ++ prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, EMT_ESPDES_IV_SZ); ++ ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; ++ ipsp->ips_iv_size = EMT_ESPDES_IV_SZ; ++ break; ++# endif /* defined(CONFIG_IPSEC_ENC_3DES) */ ++ case ESP_NONE: ++ break; ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "encalg=%d support not available in the kernel", ++ ipsp->ips_encalg); ++ SENDERR(EINVAL); ++ } ++ ++ /* Create IV */ ++ if (ipsp->ips_iv_size) { ++ if((ipsp->ips_iv = (caddr_t) ++ kmalloc(ipsp->ips_iv_size, GFP_ATOMIC)) == NULL) { ++ SENDERR(ENOMEM); ++ } ++ prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, ipsp->ips_iv_size); ++ ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; ++ } ++ ++#ifdef CONFIG_IPSEC_ALG ++ if (ixt_e) { ++ if ((error=ipsec_alg_enc_key_create(ipsp)) < 0) ++ SENDERR(-error); ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ switch(ipsp->ips_encalg) { ++# ifdef CONFIG_IPSEC_ENC_3DES ++ case ESP_3DES: ++ if(ipsp->ips_key_bits_e != (EMT_ESP3DES_KEY_SZ * 8)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "incorrect encryption key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ++ ipsp->ips_key_bits_e, EMT_ESP3DES_KEY_SZ * 8); ++ SENDERR(EINVAL); ++ } ++ ++ /* save encryption key pointer */ ++ ekp = ipsp->ips_key_e; ++ eks = ipsp->ips_key_e_size; ++ ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "allocating %lu bytes for 3des.\n", ++ (unsigned long) (3 * sizeof(struct des_eks))); ++ if((ipsp->ips_key_e = (caddr_t) ++ kmalloc(3 * sizeof(struct des_eks), GFP_ATOMIC)) == NULL) { ++ ipsp->ips_key_e = ekp; ++ SENDERR(ENOMEM); ++ } ++ ipsp->ips_key_e_size = 3 * sizeof(struct des_eks); ++ ++ for(i = 0; i < 3; i++) { ++#if KLIPS_DIVULGE_CYPHER_KEY ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "3des key %d/3 is 0x%08x%08x\n", ++ i + 1, ++ ntohl(*((__u32 *)ekp + i * 2)), ++ ntohl(*((__u32 *)ekp + i * 2 + 1))); ++# endif ++#if KLIPS_FIXES_DES_PARITY ++ /* force parity */ ++ des_set_odd_parity((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i)); ++#endif ++ error = des_set_key((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i), ++ ((struct des_eks *)(ipsp->ips_key_e))[i].ks); ++ if (error == -1) ++ printk("klips_debug:pfkey_ipsec_sa_init: " ++ "parity error in des key %d/3\n", ++ i + 1); ++ else if (error == -2) ++ printk("klips_debug:pfkey_ipsec_sa_init: " ++ "illegal weak des key %d/3\n", i + 1); ++ if (error) { ++ memset(ekp, 0, eks); ++ kfree(ekp); ++ SENDERR(EINVAL); ++ } ++ } ++ ++ /* paranoid */ ++ memset(ekp, 0, eks); ++ kfree(ekp); ++ break; ++# endif /* CONFIG_IPSEC_ENC_3DES */ ++ case ESP_NONE: ++ break; ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "encalg=%d support not available in the kernel", ++ ipsp->ips_encalg); ++ SENDERR(EINVAL); ++ } ++ ++#ifdef CONFIG_IPSEC_ALG ++ if ((ixt_a=ipsp->ips_alg_auth)) { ++ if ((error=ipsec_alg_auth_key_create(ipsp)) < 0) ++ SENDERR(-error); ++ } else ++#endif /* CONFIG_IPSEC_ALG */ ++ ++ switch(ipsp->ips_authalg) { ++# ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 ++ case AH_MD5: { ++ MD5_CTX *ictx; ++ MD5_CTX *octx; ++ ++ if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ++ ipsp->ips_key_bits_a, ++ AHMD596_KLEN * 8); ++ SENDERR(EINVAL); ++ } ++ ++# if KLIPS_DIVULGE_HMAC_KEY ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ++ ntohl(*(((__u32 *)(ipsp->ips_key_a))+0)), ++ ntohl(*(((__u32 *)(ipsp->ips_key_a))+1)), ++ ntohl(*(((__u32 *)(ipsp->ips_key_a))+2)), ++ ntohl(*(((__u32 *)(ipsp->ips_key_a))+3))); ++# endif /* KLIPS_DIVULGE_HMAC_KEY */ ++ ipsp->ips_auth_bits = AHMD596_ALEN * 8; ++ ++ /* save the pointer to the key material */ ++ akp = ipsp->ips_key_a; ++ aks = ipsp->ips_key_a_size; ++ ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "allocating %lu bytes for md5_ctx.\n", ++ (unsigned long) sizeof(struct md5_ctx)); ++ if((ipsp->ips_key_a = (caddr_t) ++ kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ++ ipsp->ips_key_a = akp; ++ SENDERR(ENOMEM); ++ } ++ ipsp->ips_key_a_size = sizeof(struct md5_ctx); ++ ++ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { ++ kb[i] = akp[i] ^ HMAC_IPAD; ++ } ++ for (; i < AHMD596_BLKLEN; i++) { ++ kb[i] = HMAC_IPAD; ++ } ++ ++ ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); ++ MD5Init(ictx); ++ MD5Update(ictx, kb, AHMD596_BLKLEN); ++ ++ for (i = 0; i < AHMD596_BLKLEN; i++) { ++ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); ++ } ++ ++ octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); ++ MD5Init(octx); ++ MD5Update(octx, kb, AHMD596_BLKLEN); ++ ++# if KLIPS_DIVULGE_HMAC_KEY ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ++ ((__u32*)ictx)[0], ++ ((__u32*)ictx)[1], ++ ((__u32*)ictx)[2], ++ ((__u32*)ictx)[3], ++ ((__u32*)octx)[0], ++ ((__u32*)octx)[1], ++ ((__u32*)octx)[2], ++ ((__u32*)octx)[3] ); ++# endif /* KLIPS_DIVULGE_HMAC_KEY */ ++ /* paranoid */ ++ memset(akp, 0, aks); ++ kfree(akp); ++ break; ++ } ++# endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ ++# ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 ++ case AH_SHA: { ++ SHA1_CTX *ictx; ++ SHA1_CTX *octx; ++ ++ if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ++ ipsp->ips_key_bits_a, ++ AHSHA196_KLEN * 8); ++ SENDERR(EINVAL); ++ } ++ ++# if KLIPS_DIVULGE_HMAC_KEY ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ++ ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); ++# endif /* KLIPS_DIVULGE_HMAC_KEY */ ++ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; ++ ++ /* save the pointer to the key material */ ++ akp = ipsp->ips_key_a; ++ aks = ipsp->ips_key_a_size; ++ ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "allocating %lu bytes for sha1_ctx.\n", ++ (unsigned long) sizeof(struct sha1_ctx)); ++ if((ipsp->ips_key_a = (caddr_t) ++ kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ++ ipsp->ips_key_a = akp; ++ SENDERR(ENOMEM); ++ } ++ ipsp->ips_key_a_size = sizeof(struct sha1_ctx); ++ ++ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { ++ kb[i] = akp[i] ^ HMAC_IPAD; ++ } ++ for (; i < AHMD596_BLKLEN; i++) { ++ kb[i] = HMAC_IPAD; ++ } ++ ++ ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); ++ SHA1Init(ictx); ++ SHA1Update(ictx, kb, AHSHA196_BLKLEN); ++ ++ for (i = 0; i < AHSHA196_BLKLEN; i++) { ++ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); ++ } ++ ++ octx = &((struct sha1_ctx*)(ipsp->ips_key_a))->octx; ++ SHA1Init(octx); ++ SHA1Update(octx, kb, AHSHA196_BLKLEN); ++ ++# if KLIPS_DIVULGE_HMAC_KEY ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ++ ((__u32*)ictx)[0], ++ ((__u32*)ictx)[1], ++ ((__u32*)ictx)[2], ++ ((__u32*)ictx)[3], ++ ((__u32*)octx)[0], ++ ((__u32*)octx)[1], ++ ((__u32*)octx)[2], ++ ((__u32*)octx)[3] ); ++# endif /* KLIPS_DIVULGE_HMAC_KEY */ ++ memset(akp, 0, aks); ++ kfree(akp); ++ break; ++ } ++# endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ ++ case AH_NONE: ++ break; ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "authalg=%d support not available in the kernel.\n", ++ ipsp->ips_authalg); ++ SENDERR(EINVAL); ++ } ++ } ++ break; ++#endif /* !CONFIG_IPSEC_ESP */ ++#ifdef CONFIG_IPSEC_IPCOMP ++ case IPPROTO_COMP: ++ ipsp->ips_comp_adapt_tries = 0; ++ ipsp->ips_comp_adapt_skip = 0; ++ ipsp->ips_comp_ratio_cbytes = 0; ++ ipsp->ips_comp_ratio_dbytes = 0; ++ break; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ default: ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_ipsec_sa_init: " ++ "proto=%d unknown.\n", ++ ipsp->ips_said.proto); ++ SENDERR(EINVAL); ++ } ++ ++ errlab: ++ return(error); ++} ++ ++ ++int ++pfkey_safe_build(int error, struct sadb_ext *extensions[SADB_MAX+1]) ++{ ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build: " ++ "error=%d\n", ++ error); ++ if (!error) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" ++ "success.\n"); ++ return 1; ++ } else { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" ++ "caught error %d\n", ++ error); ++ pfkey_extensions_free(extensions); ++ return 0; ++ } ++} ++ ++ ++DEBUG_NO_STATIC int ++pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ipsec_spi_t minspi = htonl(256), maxspi = htonl(-1L); ++ int found_avail = 0; ++ struct ipsec_sa *ipsq; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_reply = NULL; ++ struct socket_list *pfkey_socketsp; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_getspi_parse: .\n"); ++ ++ pfkey_extensions_init(extensions_reply); ++ ++ if(extr == NULL || extr->ips == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_getspi_parse: " ++ "error, extr or extr->ipsec_sa pointer NULL\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(extensions[SADB_EXT_SPIRANGE]) { ++ minspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_min; ++ maxspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_max; ++ } ++ ++ if(maxspi == minspi) { ++ extr->ips->ips_said.spi = maxspi; ++ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); ++ if(ipsq != NULL) { ++ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); ++ ipsec_sa_put(ipsq); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_getspi_parse: " ++ "EMT_GETSPI found an old ipsec_sa for SA: %s, delete it first.\n", ++ sa_len ? sa : " (error)"); ++ SENDERR(EEXIST); ++ } else { ++ found_avail = 1; ++ } ++ } else { ++ int i = 0; ++ __u32 rand_val; ++ __u32 spi_diff; ++ while( ( i < (spi_diff = (ntohl(maxspi) - ntohl(minspi)))) && !found_avail ) { ++ prng_bytes(&ipsec_prng, (char *) &(rand_val), ++ ( (spi_diff < (2^8)) ? 1 : ++ ( (spi_diff < (2^16)) ? 2 : ++ ( (spi_diff < (2^24)) ? 3 : ++ 4 ) ) ) ); ++ extr->ips->ips_said.spi = htonl(ntohl(minspi) + ++ (rand_val % ++ (spi_diff + 1))); ++ i++; ++ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); ++ if(ipsq == NULL) { ++ found_avail = 1; ++ } else { ++ ipsec_sa_put(ipsq); ++ } ++ } ++ } ++ ++ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); ++ ++ if (!found_avail) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_getspi_parse: " ++ "found an old ipsec_sa for SA: %s, delete it first.\n", ++ sa_len ? sa : " (error)"); ++ SENDERR(EEXIST); ++ } ++ ++ if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) { ++ extr->ips->ips_flags |= EMT_INBOUND; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_getspi_parse: " ++ "existing ipsec_sa not found (this is good) for SA: %s, %s-bound, allocating.\n", ++ sa_len ? sa : " (error)", ++ extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); ++ ++ /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ ++ extr->ips->ips_rcvif = NULL; ++ extr->ips->ips_life.ipl_addtime.ipl_count = jiffies/HZ; ++ ++ extr->ips->ips_state = SADB_SASTATE_LARVAL; ++ ++ if(!extr->ips->ips_life.ipl_allocations.ipl_count) { ++ extr->ips->ips_life.ipl_allocations.ipl_count += 1; ++ } ++ ++ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], ++ SADB_GETSPI, ++ satype, ++ 0, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], ++ SADB_EXT_SA, ++ extr->ips->ips_said.spi, ++ 0, ++ SADB_SASTATE_LARVAL, ++ 0, ++ 0, ++ 0, ++ extr->ips->ips_ref), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_s), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_d), ++ extensions_reply) )) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " ++ "failed to build the getspi reply message extensions\n"); ++ goto errlab; ++ } ++ ++ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " ++ "failed to build the getspi reply message\n"); ++ SENDERR(-error); ++ } ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " ++ "sending up getspi reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " ++ "sending up getspi reply message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++ if((error = ipsec_sa_add(extr->ips))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " ++ "failed to add the larval SA=%s with error=%d.\n", ++ sa_len ? sa : " (error)", ++ error); ++ SENDERR(-error); ++ } ++ extr->ips = NULL; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_getspi_parse: " ++ "successful for SA: %s\n", ++ sa_len ? sa : " (error)"); ++ ++ errlab: ++ if (pfkey_reply) { ++ pfkey_msg_free(&pfkey_reply); ++ } ++ pfkey_extensions_free(extensions_reply); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct ipsec_sa* ipsq; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_reply = NULL; ++ struct socket_list *pfkey_socketsp; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ struct ipsec_sa *nat_t_ips_saved = NULL; ++#endif ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse: .\n"); ++ ++ pfkey_extensions_init(extensions_reply); ++ ++ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse: " ++ "error, sa_state=%d must be MATURE=%d\n", ++ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, ++ SADB_SASTATE_MATURE); ++ SENDERR(EINVAL); ++ } ++ ++ if(extr == NULL || extr->ips == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse: " ++ "error, extr or extr->ips pointer NULL\n"); ++ SENDERR(EINVAL); ++ } ++ ++ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); ++ ++ spin_lock_bh(&tdb_lock); ++ ++ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); ++ if (ipsq == NULL) { ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse: " ++ "reserved ipsec_sa for SA: %s not found. Call SADB_GETSPI first or call SADB_ADD instead.\n", ++ sa_len ? sa : " (error)"); ++ SENDERR(ENOENT); ++ } ++ ++ if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) { ++ extr->ips->ips_flags |= EMT_INBOUND; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse: " ++ "existing ipsec_sa found (this is good) for SA: %s, %s-bound, updating.\n", ++ sa_len ? sa : " (error)", ++ extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if (extr->ips->ips_natt_sport || extr->ips->ips_natt_dport) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse: only updating NAT-T ports " ++ "(%u:%u -> %u:%u)\n", ++ ipsq->ips_natt_sport, ipsq->ips_natt_dport, ++ extr->ips->ips_natt_sport, extr->ips->ips_natt_dport); ++ ++ if (extr->ips->ips_natt_sport) { ++ ipsq->ips_natt_sport = extr->ips->ips_natt_sport; ++ if (ipsq->ips_addr_s->sa_family == AF_INET) { ++ ((struct sockaddr_in *)(ipsq->ips_addr_s))->sin_port = htons(extr->ips->ips_natt_sport); ++ } ++ } ++ ++ if (extr->ips->ips_natt_dport) { ++ ipsq->ips_natt_dport = extr->ips->ips_natt_dport; ++ if (ipsq->ips_addr_d->sa_family == AF_INET) { ++ ((struct sockaddr_in *)(ipsq->ips_addr_d))->sin_port = htons(extr->ips->ips_natt_dport); ++ } ++ } ++ ++ nat_t_ips_saved = extr->ips; ++ extr->ips = ipsq; ++ } ++ else { ++#endif ++ ++ /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ ++ extr->ips->ips_rcvif = NULL; ++ if ((error = pfkey_ipsec_sa_init(extr->ips, extensions))) { ++ ipsec_sa_put(ipsq); ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse: " ++ "not successful for SA: %s, deleting.\n", ++ sa_len ? sa : " (error)"); ++ SENDERR(-error); ++ } ++ ++ extr->ips->ips_life.ipl_addtime.ipl_count = ipsq->ips_life.ipl_addtime.ipl_count; ++ ipsec_sa_put(ipsq); ++ if((error = ipsec_sa_delchain(ipsq))) { ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse: " ++ "error=%d, trouble deleting intermediate ipsec_sa for SA=%s.\n", ++ error, ++ sa_len ? sa : " (error)"); ++ SENDERR(-error); ++ } ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ } ++#endif ++ ++ spin_unlock_bh(&tdb_lock); ++ ++ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], ++ SADB_UPDATE, ++ satype, ++ 0, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], ++ SADB_EXT_SA, ++ extr->ips->ips_said.spi, ++ extr->ips->ips_replaywin, ++ extr->ips->ips_state, ++ extr->ips->ips_authalg, ++ extr->ips->ips_encalg, ++ extr->ips->ips_flags, ++ extr->ips->ips_ref), ++ extensions_reply) ++ /* The 3 lifetime extentions should only be sent if non-zero. */ ++ && (extensions[SADB_EXT_LIFETIME_HARD] ++ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], ++ SADB_EXT_LIFETIME_HARD, ++ extr->ips->ips_life.ipl_allocations.ipl_hard, ++ extr->ips->ips_life.ipl_bytes.ipl_hard, ++ extr->ips->ips_life.ipl_addtime.ipl_hard, ++ extr->ips->ips_life.ipl_usetime.ipl_hard, ++ extr->ips->ips_life.ipl_packets.ipl_hard), ++ extensions_reply) : 1) ++ && (extensions[SADB_EXT_LIFETIME_SOFT] ++ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], ++ SADB_EXT_LIFETIME_SOFT, ++ extr->ips->ips_life.ipl_allocations.ipl_count, ++ extr->ips->ips_life.ipl_bytes.ipl_count, ++ extr->ips->ips_life.ipl_addtime.ipl_count, ++ extr->ips->ips_life.ipl_usetime.ipl_count, ++ extr->ips->ips_life.ipl_packets.ipl_count), ++ extensions_reply) : 1) ++ && (extr->ips->ips_life.ipl_allocations.ipl_count ++ || extr->ips->ips_life.ipl_bytes.ipl_count ++ || extr->ips->ips_life.ipl_addtime.ipl_count ++ || extr->ips->ips_life.ipl_usetime.ipl_count ++ || extr->ips->ips_life.ipl_packets.ipl_count ++ ++ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT], ++ SADB_EXT_LIFETIME_CURRENT, ++ extr->ips->ips_life.ipl_allocations.ipl_count, ++ extr->ips->ips_life.ipl_bytes.ipl_count, ++ extr->ips->ips_life.ipl_addtime.ipl_count, ++ extr->ips->ips_life.ipl_usetime.ipl_count, ++ extr->ips->ips_life.ipl_packets.ipl_count), ++ extensions_reply) : 1) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_s), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_d), ++ extensions_reply) ++ && (extr->ips->ips_ident_s.data ++ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], ++ SADB_EXT_IDENTITY_SRC, ++ extr->ips->ips_ident_s.type, ++ extr->ips->ips_ident_s.id, ++ extr->ips->ips_ident_s.len, ++ extr->ips->ips_ident_s.data), ++ extensions_reply) : 1) ++ && (extr->ips->ips_ident_d.data ++ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], ++ SADB_EXT_IDENTITY_DST, ++ extr->ips->ips_ident_d.type, ++ extr->ips->ips_ident_d.id, ++ extr->ips->ips_ident_d.len, ++ extr->ips->ips_ident_d.data), ++ extensions_reply) : 1) ++#if 0 ++ /* FIXME: This won't work yet because I have not finished ++ it. */ ++ && (extr->ips->ips_sens_ ++ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], ++ extr->ips->ips_sens_dpd, ++ extr->ips->ips_sens_sens_level, ++ extr->ips->ips_sens_sens_len, ++ extr->ips->ips_sens_sens_bitmap, ++ extr->ips->ips_sens_integ_level, ++ extr->ips->ips_sens_integ_len, ++ extr->ips->ips_sens_integ_bitmap), ++ extensions_reply) : 1) ++#endif ++ )) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " ++ "failed to build the update reply message extensions\n"); ++ SENDERR(-error); ++ } ++ ++ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " ++ "failed to build the update reply message\n"); ++ SENDERR(-error); ++ } ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " ++ "sending up update reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " ++ "sending up update reply message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ if (nat_t_ips_saved) { ++ /** ++ * As we _really_ update existing SA, we keep tdbq and need to delete ++ * parsed ips (nat_t_ips_saved, was extr->ips). ++ * ++ * goto errlab with extr->ips = nat_t_ips_saved will free it. ++ */ ++ ++ extr->ips = nat_t_ips_saved; ++ ++ error = 0; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse (NAT-T ports): " ++ "successful for SA: %s\n", ++ sa_len ? sa : " (error)"); ++ ++ goto errlab; ++ } ++#endif ++ ++ if((error = ipsec_sa_add(extr->ips))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " ++ "failed to update the mature SA=%s with error=%d.\n", ++ sa_len ? sa : " (error)", ++ error); ++ SENDERR(-error); ++ } ++ extr->ips = NULL; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_update_parse: " ++ "successful for SA: %s\n", ++ sa_len ? sa : " (error)"); ++ ++ errlab: ++ if (pfkey_reply) { ++ pfkey_msg_free(&pfkey_reply); ++ } ++ pfkey_extensions_free(extensions_reply); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_add_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct ipsec_sa* ipsq; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_reply = NULL; ++ struct socket_list *pfkey_socketsp; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_add_parse: .\n"); ++ ++ pfkey_extensions_init(extensions_reply); ++ ++ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_add_parse: " ++ "error, sa_state=%d must be MATURE=%d\n", ++ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, ++ SADB_SASTATE_MATURE); ++ SENDERR(EINVAL); ++ } ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_add_parse: " ++ "extr or extr->ips pointer NULL\n"); ++ SENDERR(EINVAL); ++ } ++ ++ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); ++ ++ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); ++ if(ipsq != NULL) { ++ ipsec_sa_put(ipsq); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_add_parse: " ++ "found an old ipsec_sa for SA%s, delete it first.\n", ++ sa_len ? sa : " (error)"); ++ SENDERR(EEXIST); ++ } ++ ++ if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) { ++ extr->ips->ips_flags |= EMT_INBOUND; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_add_parse: " ++ "existing ipsec_sa not found (this is good) for SA%s, %s-bound, allocating.\n", ++ sa_len ? sa : " (error)", ++ extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); ++ ++ /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ ++ extr->ips->ips_rcvif = NULL; ++ ++ if ((error = pfkey_ipsec_sa_init(extr->ips, extensions))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_add_parse: " ++ "not successful for SA: %s, deleting.\n", ++ sa_len ? sa : " (error)"); ++ SENDERR(-error); ++ } ++ ++ extr->ips->ips_life.ipl_addtime.ipl_count = jiffies / HZ; ++ if(!extr->ips->ips_life.ipl_allocations.ipl_count) { ++ extr->ips->ips_life.ipl_allocations.ipl_count += 1; ++ } ++ ++ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], ++ SADB_ADD, ++ satype, ++ 0, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], ++ SADB_EXT_SA, ++ extr->ips->ips_said.spi, ++ extr->ips->ips_replaywin, ++ extr->ips->ips_state, ++ extr->ips->ips_authalg, ++ extr->ips->ips_encalg, ++ extr->ips->ips_flags, ++ extr->ips->ips_ref), ++ extensions_reply) ++ /* The 3 lifetime extentions should only be sent if non-zero. */ ++ && (extensions[SADB_EXT_LIFETIME_HARD] ++ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], ++ SADB_EXT_LIFETIME_HARD, ++ extr->ips->ips_life.ipl_allocations.ipl_hard, ++ extr->ips->ips_life.ipl_bytes.ipl_hard, ++ extr->ips->ips_life.ipl_addtime.ipl_hard, ++ extr->ips->ips_life.ipl_usetime.ipl_hard, ++ extr->ips->ips_life.ipl_packets.ipl_hard), ++ extensions_reply) : 1) ++ && (extensions[SADB_EXT_LIFETIME_SOFT] ++ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], ++ SADB_EXT_LIFETIME_SOFT, ++ extr->ips->ips_life.ipl_allocations.ipl_soft, ++ extr->ips->ips_life.ipl_bytes.ipl_soft, ++ extr->ips->ips_life.ipl_addtime.ipl_soft, ++ extr->ips->ips_life.ipl_usetime.ipl_soft, ++ extr->ips->ips_life.ipl_packets.ipl_soft), ++ extensions_reply) : 1) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_s), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_d), ++ extensions_reply) ++ && (extr->ips->ips_ident_s.data ++ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], ++ SADB_EXT_IDENTITY_SRC, ++ extr->ips->ips_ident_s.type, ++ extr->ips->ips_ident_s.id, ++ extr->ips->ips_ident_s.len, ++ extr->ips->ips_ident_s.data), ++ extensions_reply) : 1) ++ && (extr->ips->ips_ident_d.data ++ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], ++ SADB_EXT_IDENTITY_DST, ++ extr->ips->ips_ident_d.type, ++ extr->ips->ips_ident_d.id, ++ extr->ips->ips_ident_d.len, ++ extr->ips->ips_ident_d.data), ++ extensions_reply) : 1) ++#if 0 ++ /* FIXME: This won't work yet because I have not finished ++ it. */ ++ && (extr->ips->ips_sens_ ++ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], ++ extr->ips->ips_sens_dpd, ++ extr->ips->ips_sens_sens_level, ++ extr->ips->ips_sens_sens_len, ++ extr->ips->ips_sens_sens_bitmap, ++ extr->ips->ips_sens_integ_level, ++ extr->ips->ips_sens_integ_len, ++ extr->ips->ips_sens_integ_bitmap), ++ extensions_reply) : 1) ++#endif ++ )) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " ++ "failed to build the add reply message extensions\n"); ++ SENDERR(-error); ++ } ++ ++ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " ++ "failed to build the add reply message\n"); ++ SENDERR(-error); ++ } ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " ++ "sending up add reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " ++ "sending up add reply message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++ if((error = ipsec_sa_add(extr->ips))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " ++ "failed to add the mature SA=%s with error=%d.\n", ++ sa_len ? sa : " (error)", ++ error); ++ SENDERR(-error); ++ } ++ extr->ips = NULL; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_add_parse: " ++ "successful for SA: %s\n", ++ sa_len ? sa : " (error)"); ++ ++ errlab: ++ if (pfkey_reply) { ++ pfkey_msg_free(&pfkey_reply); ++ } ++ pfkey_extensions_free(extensions_reply); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ struct ipsec_sa *ipsp; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ int error = 0; ++ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_reply = NULL; ++ struct socket_list *pfkey_socketsp; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_delete_parse: .\n"); ++ ++ pfkey_extensions_init(extensions_reply); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_delete_parse: " ++ "extr or extr->ips pointer NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); ++ ++ spin_lock_bh(&tdb_lock); ++ ++ ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said)); ++ if (ipsp == NULL) { ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_delete_parse: " ++ "ipsec_sa not found for SA:%s, could not delete.\n", ++ sa_len ? sa : " (error)"); ++ SENDERR(ESRCH); ++ } ++ ++ ipsec_sa_put(ipsp); ++ if((error = ipsec_sa_delchain(ipsp))) { ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_delete_parse: " ++ "error=%d returned trying to delete ipsec_sa for SA:%s.\n", ++ error, ++ sa_len ? sa : " (error)"); ++ SENDERR(-error); ++ } ++ spin_unlock_bh(&tdb_lock); ++ ++ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], ++ SADB_DELETE, ++ satype, ++ 0, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], ++ SADB_EXT_SA, ++ extr->ips->ips_said.spi, ++ 0, ++ 0, ++ 0, ++ 0, ++ 0, ++ extr->ips->ips_ref), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_s), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_d), ++ extensions_reply) ++ )) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " ++ "failed to build the delete reply message extensions\n"); ++ SENDERR(-error); ++ } ++ ++ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " ++ "failed to build the delete reply message\n"); ++ SENDERR(-error); ++ } ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " ++ "sending up delete reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " ++ "sending up delete reply message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++ errlab: ++ if (pfkey_reply) { ++ pfkey_msg_free(&pfkey_reply); ++ } ++ pfkey_extensions_free(extensions_reply); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_get_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct ipsec_sa *ipsp; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_reply = NULL; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_get_parse: .\n"); ++ ++ pfkey_extensions_init(extensions_reply); ++ ++ if(!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_get_parse: " ++ "extr or extr->ips pointer NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); ++ ++ spin_lock_bh(&tdb_lock); ++ ++ ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said)); ++ if (ipsp == NULL) { ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " ++ "ipsec_sa not found for SA=%s, could not get.\n", ++ sa_len ? sa : " (error)"); ++ SENDERR(ESRCH); ++ } ++ ++ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], ++ SADB_GET, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype, ++ 0, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], ++ SADB_EXT_SA, ++ extr->ips->ips_said.spi, ++ extr->ips->ips_replaywin, ++ extr->ips->ips_state, ++ extr->ips->ips_authalg, ++ extr->ips->ips_encalg, ++ extr->ips->ips_flags, ++ extr->ips->ips_ref), ++ extensions_reply) ++ /* The 3 lifetime extentions should only be sent if non-zero. */ ++ && (ipsp->ips_life.ipl_allocations.ipl_count ++ || ipsp->ips_life.ipl_bytes.ipl_count ++ || ipsp->ips_life.ipl_addtime.ipl_count ++ || ipsp->ips_life.ipl_usetime.ipl_count ++ || ipsp->ips_life.ipl_packets.ipl_count ++ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT], ++ SADB_EXT_LIFETIME_CURRENT, ++ ipsp->ips_life.ipl_allocations.ipl_count, ++ ipsp->ips_life.ipl_bytes.ipl_count, ++ ipsp->ips_life.ipl_addtime.ipl_count, ++ ipsp->ips_life.ipl_usetime.ipl_count, ++ ipsp->ips_life.ipl_packets.ipl_count), ++ extensions_reply) : 1) ++ && (ipsp->ips_life.ipl_allocations.ipl_hard ++ || ipsp->ips_life.ipl_bytes.ipl_hard ++ || ipsp->ips_life.ipl_addtime.ipl_hard ++ || ipsp->ips_life.ipl_usetime.ipl_hard ++ || ipsp->ips_life.ipl_packets.ipl_hard ++ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], ++ SADB_EXT_LIFETIME_HARD, ++ ipsp->ips_life.ipl_allocations.ipl_hard, ++ ipsp->ips_life.ipl_bytes.ipl_hard, ++ ipsp->ips_life.ipl_addtime.ipl_hard, ++ ipsp->ips_life.ipl_usetime.ipl_hard, ++ ipsp->ips_life.ipl_packets.ipl_hard), ++ extensions_reply) : 1) ++ && (ipsp->ips_life.ipl_allocations.ipl_soft ++ || ipsp->ips_life.ipl_bytes.ipl_soft ++ || ipsp->ips_life.ipl_addtime.ipl_soft ++ || ipsp->ips_life.ipl_usetime.ipl_soft ++ || ipsp->ips_life.ipl_packets.ipl_soft ++ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], ++ SADB_EXT_LIFETIME_SOFT, ++ ipsp->ips_life.ipl_allocations.ipl_soft, ++ ipsp->ips_life.ipl_bytes.ipl_soft, ++ ipsp->ips_life.ipl_addtime.ipl_soft, ++ ipsp->ips_life.ipl_usetime.ipl_soft, ++ ipsp->ips_life.ipl_packets.ipl_soft), ++ extensions_reply) : 1) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_s), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_d), ++ extensions_reply) ++ && (extr->ips->ips_addr_p ++ ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_PROXY], ++ SADB_EXT_ADDRESS_PROXY, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_p), ++ extensions_reply) : 1) ++#if 0 ++ /* FIXME: This won't work yet because the keys are not ++ stored directly in the ipsec_sa. They are stored as ++ contexts. */ ++ && (extr->ips->ips_key_a_size ++ ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_AUTH], ++ SADB_EXT_KEY_AUTH, ++ extr->ips->ips_key_a_size * 8, ++ extr->ips->ips_key_a), ++ extensions_reply) : 1) ++ /* FIXME: This won't work yet because the keys are not ++ stored directly in the ipsec_sa. They are stored as ++ key schedules. */ ++ && (extr->ips->ips_key_e_size ++ ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_ENCRYPT], ++ SADB_EXT_KEY_ENCRYPT, ++ extr->ips->ips_key_e_size * 8, ++ extr->ips->ips_key_e), ++ extensions_reply) : 1) ++#endif ++ && (extr->ips->ips_ident_s.data ++ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], ++ SADB_EXT_IDENTITY_SRC, ++ extr->ips->ips_ident_s.type, ++ extr->ips->ips_ident_s.id, ++ extr->ips->ips_ident_s.len, ++ extr->ips->ips_ident_s.data), ++ extensions_reply) : 1) ++ && (extr->ips->ips_ident_d.data ++ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], ++ SADB_EXT_IDENTITY_DST, ++ extr->ips->ips_ident_d.type, ++ extr->ips->ips_ident_d.id, ++ extr->ips->ips_ident_d.len, ++ extr->ips->ips_ident_d.data), ++ extensions_reply) : 1) ++#if 0 ++ /* FIXME: This won't work yet because I have not finished ++ it. */ ++ && (extr->ips->ips_sens_ ++ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], ++ extr->ips->ips_sens_dpd, ++ extr->ips->ips_sens_sens_level, ++ extr->ips->ips_sens_sens_len, ++ extr->ips->ips_sens_sens_bitmap, ++ extr->ips->ips_sens_integ_level, ++ extr->ips->ips_sens_integ_len, ++ extr->ips->ips_sens_integ_bitmap), ++ extensions_reply) : 1) ++#endif ++ )) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " ++ "failed to build the get reply message extensions\n"); ++ ipsec_sa_put(ipsp); ++ spin_unlock_bh(&tdb_lock); ++ SENDERR(-error); ++ } ++ ++ ipsec_sa_put(ipsp); ++ spin_unlock_bh(&tdb_lock); ++ ++ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " ++ "failed to build the get reply message\n"); ++ SENDERR(-error); ++ } ++ ++ if((error = pfkey_upmsg(sk->socket, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " ++ "failed to send the get reply message\n"); ++ SENDERR(-error); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " ++ "succeeded in sending get reply message.\n"); ++ ++ errlab: ++ if (pfkey_reply) { ++ pfkey_msg_free(&pfkey_reply); ++ } ++ pfkey_extensions_free(extensions_reply); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_acquire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct socket_list *pfkey_socketsp; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_acquire_parse: .\n"); ++ ++ /* XXX I don't know if we want an upper bound, since userspace may ++ want to register itself for an satype > SADB_SATYPE_MAX. */ ++ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_acquire_parse: " ++ "SATYPE=%d invalid.\n", ++ satype); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(pfkey_registered_sockets[satype])) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " ++ "no sockets registered for SAtype=%d(%s).\n", ++ satype, ++ satype2name(satype)); ++ SENDERR(EPROTONOSUPPORT); ++ } ++ ++ for(pfkey_socketsp = pfkey_registered_sockets[satype]; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " ++ "sending up acquire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " ++ "sending up acquire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_register_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_parse: .\n"); ++ ++ /* XXX I don't know if we want an upper bound, since userspace may ++ want to register itself for an satype > SADB_SATYPE_MAX. */ ++ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_parse: " ++ "SATYPE=%d invalid.\n", ++ satype); ++ SENDERR(EINVAL); ++ } ++ ++ if(!pfkey_list_insert_socket(sk->socket, ++ &(pfkey_registered_sockets[satype]))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_parse: " ++ "SATYPE=%02d(%s) successfully registered by KMd (pid=%d).\n", ++ satype, ++ satype2name(satype), ++ key_pid(sk)); ++ }; ++ ++ /* send up register msg with supported SATYPE algos */ ++ ++ error=pfkey_register_reply(satype, (struct sadb_msg*)extensions[SADB_EXT_RESERVED]); ++ errlab: ++ return error; ++} ++ ++int ++pfkey_register_reply(int satype, struct sadb_msg *sadb_msg) ++{ ++ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_reply = NULL; ++ struct socket_list *pfkey_socketsp; ++ struct supported_list *pfkey_supported_listp; ++ unsigned int alg_num_a = 0, alg_num_e = 0; ++ struct sadb_alg *alg_a = NULL, *alg_e = NULL, *alg_ap = NULL, *alg_ep = NULL; ++ int error = 0; ++ ++ pfkey_extensions_init(extensions_reply); ++ ++ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " ++ "SAtype=%d unspecified or unknown.\n", ++ satype); ++ SENDERR(EINVAL); ++ } ++ if(!(pfkey_registered_sockets[satype])) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " ++ "no sockets registered for SAtype=%d(%s).\n", ++ satype, ++ satype2name(satype)); ++ SENDERR(EPROTONOSUPPORT); ++ } ++ /* send up register msg with supported SATYPE algos */ ++ pfkey_supported_listp = pfkey_supported_list[satype]; ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_reply: " ++ "pfkey_supported_list[%d]=0p%p\n", ++ satype, ++ pfkey_supported_list[satype]); ++ while(pfkey_supported_listp) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_reply: " ++ "checking supported=0p%p\n", ++ pfkey_supported_listp); ++ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_reply: " ++ "adding auth alg.\n"); ++ alg_num_a++; ++ } ++ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_reply: " ++ "adding encrypt alg.\n"); ++ alg_num_e++; ++ } ++ pfkey_supported_listp = pfkey_supported_listp->next; ++ } ++ ++ if(alg_num_a) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_reply: " ++ "allocating %lu bytes for auth algs.\n", ++ (unsigned long) (alg_num_a * sizeof(struct sadb_alg))); ++ if((alg_a = kmalloc(alg_num_a * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_reply: " ++ "auth alg memory allocation error\n"); ++ SENDERR(ENOMEM); ++ } ++ alg_ap = alg_a; ++ } ++ ++ if(alg_num_e) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_reply: " ++ "allocating %lu bytes for enc algs.\n", ++ (unsigned long) (alg_num_e * sizeof(struct sadb_alg))); ++ if((alg_e = kmalloc(alg_num_e * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_reply: " ++ "enc alg memory allocation error\n"); ++ SENDERR(ENOMEM); ++ } ++ alg_ep = alg_e; ++ } ++ ++ pfkey_supported_listp = pfkey_supported_list[satype]; ++ while(pfkey_supported_listp) { ++ if(alg_num_a) { ++ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) { ++ alg_ap->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id; ++ alg_ap->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen; ++ alg_ap->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits; ++ alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits; ++ alg_ap->sadb_alg_reserved = 0; ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_register_reply: " ++ "adding auth=0p%p\n", ++ alg_ap); ++ alg_ap++; ++ } ++ } ++ if(alg_num_e) { ++ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) { ++ alg_ep->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id; ++ alg_ep->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen; ++ alg_ep->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits; ++ alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits; ++ alg_ep->sadb_alg_reserved = 0; ++ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, ++ "klips_debug:pfkey_register_reply: " ++ "adding encrypt=0p%p\n", ++ alg_ep); ++ alg_ep++; ++ } ++ } ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_register_reply: " ++ "found satype=%d(%s) exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_supported_listp->supportedp->supported_alg_exttype, ++ pfkey_supported_listp->supportedp->supported_alg_id, ++ pfkey_supported_listp->supportedp->supported_alg_ivlen, ++ pfkey_supported_listp->supportedp->supported_alg_minbits, ++ pfkey_supported_listp->supportedp->supported_alg_maxbits); ++ pfkey_supported_listp = pfkey_supported_listp->next; ++ } ++ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], ++ SADB_REGISTER, ++ satype, ++ 0, ++ sadb_msg? sadb_msg->sadb_msg_seq : ++pfkey_msg_seq, ++ sadb_msg? sadb_msg->sadb_msg_pid: current->pid), ++ extensions_reply) && ++ (alg_num_a ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_AUTH], ++ SADB_EXT_SUPPORTED_AUTH, ++ alg_num_a, ++ alg_a), ++ extensions_reply) : 1) && ++ (alg_num_e ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_ENCRYPT], ++ SADB_EXT_SUPPORTED_ENCRYPT, ++ alg_num_e, ++ alg_e), ++ extensions_reply) : 1))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " ++ "failed to build the register message extensions_reply\n"); ++ SENDERR(-error); ++ } ++ ++ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " ++ "failed to build the register message\n"); ++ SENDERR(-error); ++ } ++ /* this should go to all registered sockets for that satype only */ ++ for(pfkey_socketsp = pfkey_registered_sockets[satype]; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " ++ "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " ++ "sending up register message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++ errlab: ++ if(alg_a) { ++ kfree(alg_a); ++ } ++ if(alg_e) { ++ kfree(alg_e); ++ } ++ if (pfkey_reply) { ++ pfkey_msg_free(&pfkey_reply); ++ } ++ pfkey_extensions_free(extensions_reply); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_expire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct socket_list *pfkey_socketsp; ++#ifdef CONFIG_IPSEC_DEBUG ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_expire_parse: .\n"); ++ ++ if(pfkey_open_sockets) { ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " ++ "sending up expire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " ++ "sending up expire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ } ++ ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_flush_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ struct socket_list *pfkey_socketsp; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++ uint8_t proto = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_flush_parse: " ++ "flushing type %d SAs\n", ++ satype); ++ ++ if(satype && !(proto = satype2proto(satype))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_flush_parse: " ++ "satype %d lookup failed.\n", ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); ++ SENDERR(EINVAL); ++ } ++ ++ if ((error = ipsec_sadb_cleanup(proto))) { ++ SENDERR(-error); ++ } ++ ++ if(pfkey_open_sockets) { ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " ++ "sending up flush reply message for satype=%d(%s) (proto=%d) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ proto, ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " ++ "sending up flush reply message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ } ++ ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_dump_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_dump_parse: .\n"); ++ ++ SENDERR(ENOSYS); ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_promisc_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_promisc_parse: .\n"); ++ ++ SENDERR(ENOSYS); ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_pchange_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_pchange_parse: .\n"); ++ ++ SENDERR(ENOSYS); ++ errlab: ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ struct ipsec_sa *ips1p, *ips2p, *ipsp; ++ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_reply = NULL; ++ struct socket_list *pfkey_socketsp; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++ char sa1[SATOT_BUF], sa2[SATOT_BUF]; ++ size_t sa_len1, sa_len2 = 0; ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_grpsa_parse: .\n"); ++ ++ pfkey_extensions_init(extensions_reply); ++ ++ if(extr == NULL || extr->ips == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_grpsa_parse: " ++ "extr or extr->ips is NULL, fatal.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ sa_len1 = satot(&extr->ips->ips_said, 0, sa1, sizeof(sa1)); ++ if(extr->ips2 != NULL) { ++ sa_len2 = satot(&extr->ips2->ips_said, 0, sa2, sizeof(sa2)); ++ } ++ ++ spin_lock_bh(&tdb_lock); ++ ++ ips1p = ipsec_sa_getbyid(&(extr->ips->ips_said)); ++ if(ips1p == NULL) { ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_grpsa_parse: " ++ "reserved ipsec_sa for SA1: %s not found. Call SADB_ADD/UPDATE first.\n", ++ sa_len1 ? sa1 : " (error)"); ++ SENDERR(ENOENT); ++ } ++ if(extr->ips2) { /* GRPSA */ ++ ips2p = ipsec_sa_getbyid(&(extr->ips2->ips_said)); ++ if(ips2p == NULL) { ++ ipsec_sa_put(ips1p); ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_grpsa_parse: " ++ "reserved ipsec_sa for SA2: %s not found. Call SADB_ADD/UPDATE first.\n", ++ sa_len2 ? sa2 : " (error)"); ++ SENDERR(ENOENT); ++ } ++ ++ /* Is either one already linked? */ ++ if(ips1p->ips_onext) { ++ ipsec_sa_put(ips1p); ++ ipsec_sa_put(ips2p); ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_grpsa_parse: " ++ "ipsec_sa for SA: %s is already linked.\n", ++ sa_len1 ? sa1 : " (error)"); ++ SENDERR(EEXIST); ++ } ++ if(ips2p->ips_inext) { ++ ipsec_sa_put(ips1p); ++ ipsec_sa_put(ips2p); ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_grpsa_parse: " ++ "ipsec_sa for SA: %s is already linked.\n", ++ sa_len2 ? sa2 : " (error)"); ++ SENDERR(EEXIST); ++ } ++ ++ /* Is extr->ips already linked to extr->ips2? */ ++ ipsp = ips2p; ++ while(ipsp) { ++ if(ipsp == ips1p) { ++ ipsec_sa_put(ips1p); ++ ipsec_sa_put(ips2p); ++ spin_unlock_bh(&tdb_lock); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_grpsa_parse: " ++ "ipsec_sa for SA: %s is already linked to %s.\n", ++ sa_len1 ? sa1 : " (error)", ++ sa_len2 ? sa2 : " (error)"); ++ SENDERR(EEXIST); ++ } ++ ipsp = ipsp->ips_onext; ++ } ++ ++ /* link 'em */ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_grpsa_parse: " ++ "linking ipsec_sa SA: %s with %s.\n", ++ sa_len1 ? sa1 : " (error)", ++ sa_len2 ? sa2 : " (error)"); ++ ips1p->ips_onext = ips2p; ++ ips2p->ips_inext = ips1p; ++ } else { /* UNGRPSA */ ++ ipsec_sa_put(ips1p); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_grpsa_parse: " ++ "unlinking ipsec_sa SA: %s.\n", ++ sa_len1 ? sa1 : " (error)"); ++ while(ips1p->ips_onext) { ++ ips1p = ips1p->ips_onext; ++ } ++ while(ips1p->ips_inext) { ++ ipsp = ips1p; ++ ips1p = ips1p->ips_inext; ++ ipsec_sa_put(ips1p); ++ ipsp->ips_inext = NULL; ++ ipsec_sa_put(ipsp); ++ ips1p->ips_onext = NULL; ++ } ++ } ++ ++ spin_unlock_bh(&tdb_lock); ++ ++ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], ++ SADB_X_GRPSA, ++ satype, ++ 0, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], ++ SADB_EXT_SA, ++ extr->ips->ips_said.spi, ++ extr->ips->ips_replaywin, ++ extr->ips->ips_state, ++ extr->ips->ips_authalg, ++ extr->ips->ips_encalg, ++ extr->ips->ips_flags, ++ extr->ips->ips_ref), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_d), ++ extensions_reply) ++ && (extr->ips2 ++ ? (pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply[SADB_X_EXT_SATYPE2], ++ ((struct sadb_x_satype*)extensions[SADB_X_EXT_SATYPE2])->sadb_x_satype_satype ++ /* proto2satype(extr->ips2->ips_said.proto) */), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_X_EXT_SA2], ++ SADB_X_EXT_SA2, ++ extr->ips2->ips_said.spi, ++ extr->ips2->ips_replaywin, ++ extr->ips2->ips_state, ++ extr->ips2->ips_authalg, ++ extr->ips2->ips_encalg, ++ extr->ips2->ips_flags, ++ extr->ips2->ips_ref), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST2], ++ SADB_X_EXT_ADDRESS_DST2, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips2->ips_addr_d), ++ extensions_reply) ) : 1 ) ++ )) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " ++ "failed to build the x_grpsa reply message extensions\n"); ++ SENDERR(-error); ++ } ++ ++ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " ++ "failed to build the x_grpsa reply message\n"); ++ SENDERR(-error); ++ } ++ ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " ++ "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " ++ "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " ++ "succeeded in sending x_grpsa reply message.\n"); ++ ++ errlab: ++ if (pfkey_reply) { ++ pfkey_msg_free(&pfkey_reply); ++ } ++ pfkey_extensions_free(extensions_reply); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++#ifdef CONFIG_IPSEC_DEBUG ++ char buf1[64], buf2[64]; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_reply = NULL; ++ struct socket_list *pfkey_socketsp; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++ ip_address srcflow, dstflow, srcmask, dstmask; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: .\n"); ++ ++ pfkey_extensions_init(extensions_reply); ++ ++ memset((caddr_t)&srcflow, 0, sizeof(srcflow)); ++ memset((caddr_t)&dstflow, 0, sizeof(dstflow)); ++ memset((caddr_t)&srcmask, 0, sizeof(srcmask)); ++ memset((caddr_t)&dstmask, 0, sizeof(dstmask)); ++ ++ if(!extr || !(extr->ips) || !(extr->eroute)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "missing extr, ipsec_sa or eroute data.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ srcflow.u.v4.sin_family = AF_INET; ++ dstflow.u.v4.sin_family = AF_INET; ++ srcmask.u.v4.sin_family = AF_INET; ++ dstmask.u.v4.sin_family = AF_INET; ++ srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; ++ dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; ++ srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; ++ dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if (debug_pfkey) { ++ subnettoa(extr->eroute->er_eaddr.sen_ip_src, ++ extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); ++ subnettoa(extr->eroute->er_eaddr.sen_ip_dst, ++ extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "calling breakeroute and/or makeroute for %s->%s\n", ++ buf1, buf2); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ if(extr->ips->ips_flags & SADB_X_SAFLAGS_INFLOW) { ++/* if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) */ ++ struct ipsec_sa *ipsp, *ipsq; ++ char sa[SATOT_BUF]; ++ size_t sa_len; ++ ++ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); ++ if(ipsq == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "ipsec_sa not found, cannot set incoming policy.\n"); ++ SENDERR(ENOENT); ++ } ++ ++ ipsp = ipsq; ++ while(ipsp && ipsp->ips_said.proto != IPPROTO_IPIP) { ++ ipsp = ipsp->ips_inext; ++ } ++ ++ if(ipsp == NULL) { ++ ipsec_sa_put(ipsq); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "SA chain does not have an IPIP SA, cannot set incoming policy.\n"); ++ SENDERR(ENOENT); ++ } ++ ++ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); ++ ++ ipsp->ips_flags |= SADB_X_SAFLAGS_INFLOW; ++ ipsp->ips_flow_s = srcflow; ++ ipsp->ips_flow_d = dstflow; ++ ipsp->ips_mask_s = srcmask; ++ ipsp->ips_mask_d = dstmask; ++ ++ ipsec_sa_put(ipsq); ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "inbound eroute, setting incoming policy information in IPIP ipsec_sa for SA: %s.\n", ++ sa_len ? sa : " (error)"); ++ } else { ++ struct sk_buff *first = NULL, *last = NULL; ++ ++ if(extr->ips->ips_flags & SADB_X_SAFLAGS_REPLACEFLOW) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "REPLACEFLOW flag set, calling breakeroute.\n"); ++ if ((error = ipsec_breakroute(&(extr->eroute->er_eaddr), ++ &(extr->eroute->er_emask), ++ &first, &last))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "breakeroute returned %d. first=0p%p, last=0p%p\n", ++ error, ++ first, ++ last); ++ if(first != NULL) { ++ ipsec_kfree_skb(first); ++ } ++ if(last != NULL) { ++ ipsec_kfree_skb(last); ++ } ++ SENDERR(-error); ++ } ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "calling makeroute.\n"); ++ ++ if ((error = ipsec_makeroute(&(extr->eroute->er_eaddr), ++ &(extr->eroute->er_emask), ++ extr->ips->ips_said, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid, ++ NULL, ++ &(extr->ips->ips_ident_s), ++ &(extr->ips->ips_ident_d)))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "makeroute returned %d.\n", error); ++ SENDERR(-error); ++ } ++ if(first != NULL) { ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "first=0p%p HOLD packet re-injected.\n", ++ first); ++ DEV_QUEUE_XMIT(first, first->dev, SOPRI_NORMAL); ++ } ++ if(last != NULL) { ++ KLIPS_PRINT(debug_eroute, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "last=0p%p HOLD packet re-injected.\n", ++ last); ++ DEV_QUEUE_XMIT(last, last->dev, SOPRI_NORMAL); ++ } ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "makeroute call successful.\n"); ++ ++ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], ++ SADB_X_ADDFLOW, ++ satype, ++ 0, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], ++ SADB_EXT_SA, ++ extr->ips->ips_said.spi, ++ extr->ips->ips_replaywin, ++ extr->ips->ips_state, ++ extr->ips->ips_authalg, ++ extr->ips->ips_encalg, ++ extr->ips->ips_flags, ++ extr->ips->ips_ref), ++ extensions_reply) ++ && (extensions[SADB_EXT_ADDRESS_SRC] ++ ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_s), ++ extensions_reply) : 1) ++ && (extensions[SADB_EXT_ADDRESS_DST] ++ ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ extr->ips->ips_addr_d), ++ extensions_reply) : 1) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW], ++ SADB_X_EXT_ADDRESS_SRC_FLOW, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ (struct sockaddr*)&srcflow), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW], ++ SADB_X_EXT_ADDRESS_DST_FLOW, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ (struct sockaddr*)&dstflow), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK], ++ SADB_X_EXT_ADDRESS_SRC_MASK, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ (struct sockaddr*)&srcmask), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK], ++ SADB_X_EXT_ADDRESS_DST_MASK, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ (struct sockaddr*)&dstmask), ++ extensions_reply) ++ )) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " ++ "failed to build the x_addflow reply message extensions\n"); ++ SENDERR(-error); ++ } ++ ++ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " ++ "failed to build the x_addflow reply message\n"); ++ SENDERR(-error); ++ } ++ ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " ++ "sending up x_addflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " ++ "sending up x_addflow reply message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ extr->ips->ips_said.proto, ++ pfkey_socketsp->socketp); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_addflow_parse: " ++ "extr->ips cleaned up and freed.\n"); ++ ++ errlab: ++ if (pfkey_reply) { ++ pfkey_msg_free(&pfkey_reply); ++ } ++ pfkey_extensions_free(extensions_reply); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_delflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++#ifdef CONFIG_IPSEC_DEBUG ++ char buf1[64], buf2[64]; ++#endif /* CONFIG_IPSEC_DEBUG */ ++ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_reply = NULL; ++ struct socket_list *pfkey_socketsp; ++ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ++ ip_address srcflow, dstflow, srcmask, dstmask; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_delflow_parse: .\n"); ++ ++ pfkey_extensions_init(extensions_reply); ++ ++ memset((caddr_t)&srcflow, 0, sizeof(srcflow)); ++ memset((caddr_t)&dstflow, 0, sizeof(dstflow)); ++ memset((caddr_t)&srcmask, 0, sizeof(srcmask)); ++ memset((caddr_t)&dstmask, 0, sizeof(dstmask)); ++ ++ if(!extr || !(extr->ips)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_delflow_parse: " ++ "extr, or extr->ips is NULL, fatal\n"); ++ SENDERR(EINVAL); ++ } ++ ++ if(extr->ips->ips_flags & SADB_X_SAFLAGS_CLEARFLOW) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_delflow_parse: " ++ "CLEARFLOW flag set, calling cleareroutes.\n"); ++ if ((error = ipsec_cleareroutes())) ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_delflow_parse: " ++ "cleareroutes returned %d.\n", error); ++ SENDERR(-error); ++ } else { ++ struct sk_buff *first = NULL, *last = NULL; ++ ++ if(!(extr->eroute)) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_delflow_parse: " ++ "extr->eroute is NULL, fatal.\n"); ++ SENDERR(EINVAL); ++ } ++ ++ srcflow.u.v4.sin_family = AF_INET; ++ dstflow.u.v4.sin_family = AF_INET; ++ srcmask.u.v4.sin_family = AF_INET; ++ dstmask.u.v4.sin_family = AF_INET; ++ srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; ++ dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; ++ srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; ++ dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; ++ ++#ifdef CONFIG_IPSEC_DEBUG ++ if (debug_pfkey) { ++ subnettoa(extr->eroute->er_eaddr.sen_ip_src, ++ extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); ++ subnettoa(extr->eroute->er_eaddr.sen_ip_dst, ++ extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_delflow_parse: " ++ "calling breakeroute for %s->%s\n", ++ buf1, buf2); ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ error = ipsec_breakroute(&(extr->eroute->er_eaddr), ++ &(extr->eroute->er_emask), ++ &first, &last); ++ if(error) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_delflow_parse: " ++ "breakeroute returned %d. first=0p%p, last=0p%p\n", ++ error, ++ first, ++ last); ++ } ++ if(first != NULL) { ++ ipsec_kfree_skb(first); ++ } ++ if(last != NULL) { ++ ipsec_kfree_skb(last); ++ } ++ if(error) { ++ SENDERR(-error); ++ } ++ } ++ ++ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], ++ SADB_X_DELFLOW, ++ satype, ++ 0, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ++ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], ++ SADB_EXT_SA, ++ extr->ips->ips_said.spi, ++ extr->ips->ips_replaywin, ++ extr->ips->ips_state, ++ extr->ips->ips_authalg, ++ extr->ips->ips_encalg, ++ extr->ips->ips_flags, ++ extr->ips->ips_ref), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW], ++ SADB_X_EXT_ADDRESS_SRC_FLOW, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ (struct sockaddr*)&srcflow), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW], ++ SADB_X_EXT_ADDRESS_DST_FLOW, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ (struct sockaddr*)&dstflow), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK], ++ SADB_X_EXT_ADDRESS_SRC_MASK, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ (struct sockaddr*)&srcmask), ++ extensions_reply) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK], ++ SADB_X_EXT_ADDRESS_DST_MASK, ++ 0, /*extr->ips->ips_said.proto,*/ ++ 0, ++ (struct sockaddr*)&dstmask), ++ extensions_reply) ++ )) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " ++ "failed to build the x_delflow reply message extensions\n"); ++ SENDERR(-error); ++ } ++ ++ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " ++ "failed to build the x_delflow reply message\n"); ++ SENDERR(-error); ++ } ++ ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " ++ "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " ++ "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_delflow_parse: " ++ "extr->ips cleaned up and freed.\n"); ++ ++ errlab: ++ if (pfkey_reply) { ++ pfkey_msg_free(&pfkey_reply); ++ } ++ pfkey_extensions_free(extensions_reply); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_msg_debug_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ int error = 0; ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_x_msg_debug_parse: .\n"); ++ ++/* errlab:*/ ++ return error; ++} ++ ++/* pfkey_expire expects the ipsec_sa table to be locked before being called. */ ++int ++pfkey_expire(struct ipsec_sa *ipsp, int hard) ++{ ++ struct sadb_ext *extensions[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_msg = NULL; ++ struct socket_list *pfkey_socketsp; ++ int error = 0; ++ uint8_t satype; ++ ++ pfkey_extensions_init(extensions); ++ ++ if(!(satype = proto2satype(ipsp->ips_said.proto))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_expire: " ++ "satype lookup for protocol %d lookup failed.\n", ++ ipsp->ips_said.proto); ++ SENDERR(EINVAL); ++ } ++ ++ if(!pfkey_open_sockets) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " ++ "no sockets listening.\n"); ++ SENDERR(EPROTONOSUPPORT); ++ } ++ ++ if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], ++ SADB_EXPIRE, ++ satype, ++ 0, ++ ++pfkey_msg_seq, ++ 0), ++ extensions) ++ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions[SADB_EXT_SA], ++ SADB_EXT_SA, ++ ipsp->ips_said.spi, ++ ipsp->ips_replaywin, ++ ipsp->ips_state, ++ ipsp->ips_authalg, ++ ipsp->ips_encalg, ++ ipsp->ips_flags, ++ ipsp->ips_ref), ++ extensions) ++ && pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_CURRENT], ++ SADB_EXT_LIFETIME_CURRENT, ++ ipsp->ips_life.ipl_allocations.ipl_count, ++ ipsp->ips_life.ipl_bytes.ipl_count, ++ ipsp->ips_life.ipl_addtime.ipl_count, ++ ipsp->ips_life.ipl_usetime.ipl_count, ++ ipsp->ips_life.ipl_packets.ipl_count), ++ extensions) ++ && (hard ? ++ pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_HARD], ++ SADB_EXT_LIFETIME_HARD, ++ ipsp->ips_life.ipl_allocations.ipl_hard, ++ ipsp->ips_life.ipl_bytes.ipl_hard, ++ ipsp->ips_life.ipl_addtime.ipl_hard, ++ ipsp->ips_life.ipl_usetime.ipl_hard, ++ ipsp->ips_life.ipl_packets.ipl_hard), ++ extensions) ++ : pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_SOFT], ++ SADB_EXT_LIFETIME_SOFT, ++ ipsp->ips_life.ipl_allocations.ipl_soft, ++ ipsp->ips_life.ipl_bytes.ipl_soft, ++ ipsp->ips_life.ipl_addtime.ipl_soft, ++ ipsp->ips_life.ipl_usetime.ipl_soft, ++ ipsp->ips_life.ipl_packets.ipl_soft), ++ extensions)) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ++ 0, /* ipsp->ips_said.proto, */ ++ 0, ++ ipsp->ips_addr_s), ++ extensions) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ 0, /* ipsp->ips_said.proto, */ ++ 0, ++ ipsp->ips_addr_d), ++ extensions))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " ++ "failed to build the expire message extensions\n"); ++ spin_unlock(&tdb_lock); ++ goto errlab; ++ } ++ ++ if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " ++ "failed to build the expire message\n"); ++ SENDERR(-error); ++ } ++ ++ for(pfkey_socketsp = pfkey_open_sockets; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " ++ "sending up expire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " ++ "sending up expire message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ ipsp->ips_said.proto, ++ pfkey_socketsp->socketp); ++ } ++ ++ errlab: ++ if (pfkey_msg) { ++ pfkey_msg_free(&pfkey_msg); ++ } ++ pfkey_extensions_free(extensions); ++ return error; ++} ++ ++int ++pfkey_acquire(struct ipsec_sa *ipsp) ++{ ++ struct sadb_ext *extensions[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_msg = NULL; ++ struct socket_list *pfkey_socketsp; ++ int error = 0; ++ struct sadb_comb comb[] = { ++ /* auth; encrypt; flags; */ ++ /* auth_minbits; auth_maxbits; encrypt_minbits; encrypt_maxbits; */ ++ /* reserved; soft_allocations; hard_allocations; soft_bytes; hard_bytes; */ ++ /* soft_addtime; hard_addtime; soft_usetime; hard_usetime; */ ++ /* soft_packets; hard_packets; */ ++ { SADB_AALG_MD5HMAC, SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, ++ 128, 128, 168, 168, ++ 0, 0, 0, 0, 0, ++ 57600, 86400, 57600, 86400, ++ 0, 0 }, ++ { SADB_AALG_SHA1HMAC, SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, ++ 160, 160, 168, 168, ++ 0, 0, 0, 0, 0, ++ 57600, 86400, 57600, 86400, ++ 0, 0 } ++ }; ++ ++ /* XXX This should not be hard-coded. It should be taken from the spdb */ ++ uint8_t satype = SADB_SATYPE_ESP; ++ ++ pfkey_extensions_init(extensions); ++ ++ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " ++ "SAtype=%d unspecified or unknown.\n", ++ satype); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(pfkey_registered_sockets[satype])) { ++ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " ++ "no sockets registered for SAtype=%d(%s).\n", ++ satype, ++ satype2name(satype)); ++ SENDERR(EPROTONOSUPPORT); ++ } ++ ++ if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], ++ SADB_ACQUIRE, ++ satype, ++ 0, ++ ++pfkey_msg_seq, ++ 0), ++ extensions) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ++ ipsp->ips_transport_protocol, ++ 0, ++ ipsp->ips_addr_s), ++ extensions) ++ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ ipsp->ips_transport_protocol, ++ 0, ++ ipsp->ips_addr_d), ++ extensions) ++#if 0 ++ && (ipsp->ips_addr_p ++ ? pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_PROXY], ++ SADB_EXT_ADDRESS_PROXY, ++ ipsp->ips_transport_protocol, ++ 0, ++ ipsp->ips_addr_p), ++ extensions) : 1) ++#endif ++ && (ipsp->ips_ident_s.type != SADB_IDENTTYPE_RESERVED ++ ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_SRC], ++ SADB_EXT_IDENTITY_SRC, ++ ipsp->ips_ident_s.type, ++ ipsp->ips_ident_s.id, ++ ipsp->ips_ident_s.len, ++ ipsp->ips_ident_s.data), ++ extensions) : 1) ++ ++ && (ipsp->ips_ident_d.type != SADB_IDENTTYPE_RESERVED ++ ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_DST], ++ SADB_EXT_IDENTITY_DST, ++ ipsp->ips_ident_d.type, ++ ipsp->ips_ident_d.id, ++ ipsp->ips_ident_d.len, ++ ipsp->ips_ident_d.data), ++ extensions) : 1) ++#if 0 ++ /* FIXME: This won't work yet because I have not finished ++ it. */ ++ && (ipsp->ips_sens_ ++ ? pfkey_safe_build(error = pfkey_sens_build(&extensions[SADB_EXT_SENSITIVITY], ++ ipsp->ips_sens_dpd, ++ ipsp->ips_sens_sens_level, ++ ipsp->ips_sens_sens_len, ++ ipsp->ips_sens_sens_bitmap, ++ ipsp->ips_sens_integ_level, ++ ipsp->ips_sens_integ_len, ++ ipsp->ips_sens_integ_bitmap), ++ extensions) : 1) ++#endif ++ && pfkey_safe_build(error = pfkey_prop_build(&extensions[SADB_EXT_PROPOSAL], ++ 64, /* replay */ ++ sizeof(comb)/sizeof(struct sadb_comb), ++ &(comb[0])), ++ extensions) ++ )) { ++ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " ++ "failed to build the acquire message extensions\n"); ++ SENDERR(-error); ++ } ++ ++ if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { ++ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " ++ "failed to build the acquire message\n"); ++ SENDERR(-error); ++ } ++ ++#if KLIPS_PFKEY_ACQUIRE_LOSSAGE > 0 ++ if(sysctl_ipsec_regress_pfkey_lossage) { ++ return(0); ++ } ++#endif ++ ++ /* this should go to all registered sockets for that satype only */ ++ for(pfkey_socketsp = pfkey_registered_sockets[satype]; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { ++ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " ++ "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " ++ "sending up acquire message for satype=%d(%s) to socket=0p%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++ errlab: ++ if (pfkey_msg) { ++ pfkey_msg_free(&pfkey_msg); ++ } ++ pfkey_extensions_free(extensions); ++ return error; ++} ++ ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++int ++pfkey_nat_t_new_mapping(struct ipsec_sa *ipsp, struct sockaddr *ipaddr, ++ __u16 sport) ++{ ++ struct sadb_ext *extensions[SADB_EXT_MAX+1]; ++ struct sadb_msg *pfkey_msg = NULL; ++ struct socket_list *pfkey_socketsp; ++ int error = 0; ++ uint8_t satype = (ipsp->ips_said.proto==IPPROTO_ESP) ? SADB_SATYPE_ESP : 0; ++ ++ /* Construct SADB_X_NAT_T_NEW_MAPPING message */ ++ ++ pfkey_extensions_init(extensions); ++ ++ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " ++ "SAtype=%d unspecified or unknown.\n", ++ satype); ++ SENDERR(EINVAL); ++ } ++ ++ if(!(pfkey_registered_sockets[satype])) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " ++ "no sockets registered for SAtype=%d(%s).\n", ++ satype, ++ satype2name(satype)); ++ SENDERR(EPROTONOSUPPORT); ++ } ++ ++ if (!(pfkey_safe_build ++ (error = pfkey_msg_hdr_build(&extensions[0], SADB_X_NAT_T_NEW_MAPPING, ++ satype, 0, ++pfkey_msg_seq, 0), extensions) ++ /* SA */ ++ && pfkey_safe_build ++ (error = pfkey_sa_build(&extensions[SADB_EXT_SA], ++ SADB_EXT_SA, ipsp->ips_said.spi, 0, 0, 0, 0, 0), extensions) ++ /* ADDRESS_SRC = old addr */ ++ && pfkey_safe_build ++ (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ipsp->ips_said.proto, 0, ipsp->ips_addr_s), ++ extensions) ++ /* NAT_T_SPORT = old port */ ++ && pfkey_safe_build ++ (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_SPORT], ++ SADB_X_EXT_NAT_T_SPORT, ipsp->ips_natt_sport), extensions) ++ /* ADDRESS_DST = new addr */ ++ && pfkey_safe_build ++ (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ipsp->ips_said.proto, 0, ipaddr), extensions) ++ /* NAT_T_DPORT = new port */ ++ && pfkey_safe_build ++ (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_DPORT], ++ SADB_X_EXT_NAT_T_DPORT, sport), extensions) ++ )) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " ++ "failed to build the nat_t_new_mapping message extensions\n"); ++ SENDERR(-error); ++ } ++ ++ if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " ++ "failed to build the nat_t_new_mapping message\n"); ++ SENDERR(-error); ++ } ++ ++ /* this should go to all registered sockets for that satype only */ ++ for(pfkey_socketsp = pfkey_registered_sockets[satype]; ++ pfkey_socketsp; ++ pfkey_socketsp = pfkey_socketsp->next) { ++ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " ++ "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p failed with error=%d.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp, ++ error); ++ SENDERR(-error); ++ } ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " ++ "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p succeeded.\n", ++ satype, ++ satype2name(satype), ++ pfkey_socketsp->socketp); ++ } ++ ++ errlab: ++ if (pfkey_msg) { ++ pfkey_msg_free(&pfkey_msg); ++ } ++ pfkey_extensions_free(extensions); ++ return error; ++} ++ ++DEBUG_NO_STATIC int ++pfkey_x_nat_t_new_mapping_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) ++{ ++ /* SADB_X_NAT_T_NEW_MAPPING not used in kernel */ ++ return -EINVAL; ++} ++#endif ++ ++DEBUG_NO_STATIC int (*ext_processors[SADB_EXT_MAX+1])(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) = ++{ ++ NULL, /* pfkey_msg_process, */ ++ pfkey_sa_process, ++ pfkey_lifetime_process, ++ pfkey_lifetime_process, ++ pfkey_lifetime_process, ++ pfkey_address_process, ++ pfkey_address_process, ++ pfkey_address_process, ++ pfkey_key_process, ++ pfkey_key_process, ++ pfkey_ident_process, ++ pfkey_ident_process, ++ pfkey_sens_process, ++ pfkey_prop_process, ++ pfkey_supported_process, ++ pfkey_supported_process, ++ pfkey_spirange_process, ++ pfkey_x_kmprivate_process, ++ pfkey_x_satype_process, ++ pfkey_sa_process, ++ pfkey_address_process, ++ pfkey_address_process, ++ pfkey_address_process, ++ pfkey_address_process, ++ pfkey_address_process, ++ pfkey_x_debug_process, ++ pfkey_x_protocol_process ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ , ++ pfkey_x_nat_t_type_process, ++ pfkey_x_nat_t_port_process, ++ pfkey_x_nat_t_port_process, ++ pfkey_address_process ++#endif ++}; ++ ++ ++DEBUG_NO_STATIC int (*msg_parsers[SADB_MAX +1])(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr) ++ = ++{ ++ NULL, /* RESERVED */ ++ pfkey_getspi_parse, ++ pfkey_update_parse, ++ pfkey_add_parse, ++ pfkey_delete_parse, ++ pfkey_get_parse, ++ pfkey_acquire_parse, ++ pfkey_register_parse, ++ pfkey_expire_parse, ++ pfkey_flush_parse, ++ pfkey_dump_parse, ++ pfkey_x_promisc_parse, ++ pfkey_x_pchange_parse, ++ pfkey_x_grpsa_parse, ++ pfkey_x_addflow_parse, ++ pfkey_x_delflow_parse, ++ pfkey_x_msg_debug_parse ++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL ++ , pfkey_x_nat_t_new_mapping_parse ++#endif ++}; ++ ++int ++pfkey_build_reply(struct sadb_msg *pfkey_msg, struct pfkey_extracted_data *extr, ++ struct sadb_msg **pfkey_reply) ++{ ++ struct sadb_ext *extensions[SADB_EXT_MAX+1]; ++ int error = 0; ++ int msg_type = pfkey_msg->sadb_msg_type; ++ int seq = pfkey_msg->sadb_msg_seq; ++ ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " ++ "building reply with type: %d\n", ++ msg_type); ++ pfkey_extensions_init(extensions); ++ if (!extr || !extr->ips) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " ++ "bad ipsec_sa passed\n"); ++ return EINVAL; ++ } ++ error = pfkey_safe_build(pfkey_msg_hdr_build(&extensions[0], ++ msg_type, ++ proto2satype(extr->ips->ips_said.proto), ++ 0, ++ seq, ++ pfkey_msg->sadb_msg_pid), ++ extensions) && ++ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & ++ 1 << SADB_EXT_SA) ++ || pfkey_safe_build(pfkey_sa_ref_build(&extensions[SADB_EXT_SA], ++ SADB_EXT_SA, ++ extr->ips->ips_said.spi, ++ extr->ips->ips_replaywin, ++ extr->ips->ips_state, ++ extr->ips->ips_authalg, ++ extr->ips->ips_encalg, ++ extr->ips->ips_flags, ++ extr->ips->ips_ref), ++ extensions)) && ++ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & ++ 1 << SADB_EXT_LIFETIME_CURRENT) ++ || pfkey_safe_build(pfkey_lifetime_build(&extensions ++ [SADB_EXT_LIFETIME_CURRENT], ++ SADB_EXT_LIFETIME_CURRENT, ++ extr->ips->ips_life.ipl_allocations.ipl_count, ++ extr->ips->ips_life.ipl_bytes.ipl_count, ++ extr->ips->ips_life.ipl_addtime.ipl_count, ++ extr->ips->ips_life.ipl_usetime.ipl_count, ++ extr->ips->ips_life.ipl_packets.ipl_count), ++ extensions)) && ++ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & ++ 1 << SADB_EXT_ADDRESS_SRC) ++ || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], ++ SADB_EXT_ADDRESS_SRC, ++ extr->ips->ips_said.proto, ++ 0, ++ extr->ips->ips_addr_s), ++ extensions)) && ++ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & ++ 1 << SADB_EXT_ADDRESS_DST) ++ || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], ++ SADB_EXT_ADDRESS_DST, ++ extr->ips->ips_said.proto, ++ 0, ++ extr->ips->ips_addr_d), ++ extensions)); ++ ++ if (error == 0) { ++ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " ++ "building extensions failed\n"); ++ return EINVAL; ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_build_reply: " ++ "built extensions, proceed to build the message\n"); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_build_reply: " ++ "extensions[1]=0p%p\n", ++ extensions[1]); ++ error = pfkey_msg_build(pfkey_reply, extensions, EXT_BITS_OUT); ++ pfkey_extensions_free(extensions); ++ ++ return error; ++} ++ ++int ++pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg, ++ struct sadb_msg **pfkey_reply) ++{ ++ int error = 0; ++ int i; ++ struct sadb_ext *extensions[SADB_EXT_MAX+1]; ++ struct pfkey_extracted_data extr = {NULL, NULL, NULL}; ++ ++ pfkey_extensions_init(extensions); ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "parsing message ver=%d, type=%d, errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", ++ pfkey_msg->sadb_msg_version, ++ pfkey_msg->sadb_msg_type, ++ pfkey_msg->sadb_msg_errno, ++ pfkey_msg->sadb_msg_satype, ++ satype2name(pfkey_msg->sadb_msg_satype), ++ pfkey_msg->sadb_msg_len, ++ pfkey_msg->sadb_msg_reserved, ++ pfkey_msg->sadb_msg_seq, ++ pfkey_msg->sadb_msg_pid); ++ ++ extr.ips = ipsec_sa_alloc(&error); /* pass in error var by pointer */ ++ if(extr.ips == NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "memory allocation error.\n"); ++ SENDERR(-error); ++ } ++ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "allocated extr->ips=0p%p.\n", ++ extr.ips); ++ ++ if(pfkey_msg->sadb_msg_satype > SADB_SATYPE_MAX) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "satype %d > max %d\n", ++ pfkey_msg->sadb_msg_satype, ++ SADB_SATYPE_MAX); ++ SENDERR(EINVAL); ++ } ++ ++ switch(pfkey_msg->sadb_msg_type) { ++ case SADB_GETSPI: ++ case SADB_UPDATE: ++ case SADB_ADD: ++ case SADB_DELETE: ++ case SADB_X_GRPSA: ++ case SADB_X_ADDFLOW: ++ ++ if(!(extr.ips->ips_said.proto = satype2proto(pfkey_msg->sadb_msg_satype))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "satype %d lookup failed.\n", ++ pfkey_msg->sadb_msg_satype); ++ SENDERR(EINVAL); ++ } else { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "satype %d lookups to proto=%d.\n", ++ pfkey_msg->sadb_msg_satype, ++ extr.ips->ips_said.proto); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ /* The NULL below causes the default extension parsers to be used */ ++ /* Parse the extensions */ ++ if((error = pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_IN))) ++ { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "message parsing failed with error %d.\n", ++ error); ++ SENDERR(-error); ++ } ++ ++ /* Process the extensions */ ++ for(i=1; i <= SADB_EXT_MAX;i++) { ++ if(extensions[i] != NULL) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "processing ext %d 0p%p with processor 0p%p.\n", ++ i, extensions[i], ext_processors[i]); ++ if((error = ext_processors[i](extensions[i], &extr))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "extension processing for type %d failed with error %d.\n", ++ i, ++ error); ++ SENDERR(-error); ++ } ++ ++ } ++ ++ } ++ ++ /* Parse the message types */ ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "parsing message type %d(%s) with msg_parser 0p%p.\n", ++ pfkey_msg->sadb_msg_type, ++ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), ++ msg_parsers[pfkey_msg->sadb_msg_type]); ++ if((error = msg_parsers[pfkey_msg->sadb_msg_type](sk, extensions, &extr))) { ++ KLIPS_PRINT(debug_pfkey, ++ "klips_debug:pfkey_msg_interp: " ++ "message parsing failed with error %d.\n", ++ error); ++ SENDERR(-error); ++ } ++ ++#if 0 ++ error = pfkey_build_reply(pfkey_msg, &extr, pfkey_reply); ++ if (error) { ++ *pfkey_reply = NULL; ++ } ++#endif ++ errlab: ++ if(extr.ips != NULL) { ++ ipsec_sa_wipe(extr.ips); ++ } ++ if(extr.ips2 != NULL) { ++ ipsec_sa_wipe(extr.ips2); ++ } ++ if (extr.eroute != NULL) { ++ kfree(extr.eroute); ++ } ++ return(error); ++} ++ ++/* ++ * $Log: pfkey_v2_parser.c,v $ ++ * Revision 1.123 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.122.2.2 2004/04/05 04:30:46 mcr ++ * patches for alg-branch to compile/work with 2.x openswan ++ * ++ * Revision 1.122.2.1 2003/12/22 15:25:52 jjo ++ * . Merged algo-0.8.1-rc11-test1 into alg-branch ++ * ++ * Revision 1.122 2003/12/10 01:14:27 mcr ++ * NAT-traversal patches to KLIPS. ++ * ++ * Revision 1.121 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.120.4.2 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.120.4.1 2003/09/21 13:59:56 mcr ++ * pre-liminary X.509 patch - does not yet pass tests. ++ * ++ * Revision 1.120 2003/04/03 17:38:09 rgb ++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. ++ * ++ * Revision 1.119 2003/02/06 01:52:37 rgb ++ * Removed no longer relevant comment ++ * ++ * Revision 1.118 2003/01/30 02:32:44 rgb ++ * ++ * Transmit error code through to caller from callee for better diagnosis of problems. ++ * ++ * Revision 1.117 2003/01/16 18:48:13 rgb ++ * ++ * Fixed sign bug in error return from an sa allocation call in ++ * pfkey_msg_interp. ++ * ++ * Revision 1.116 2002/10/17 16:38:01 rgb ++ * Change pfkey_alloc_eroute() to never static since its consumers ++ * have been moved outside the file. ++ * ++ * Revision 1.115 2002/10/12 23:11:53 dhr ++ * ++ * [KenB + DHR] more 64-bit cleanup ++ * ++ * Revision 1.114 2002/10/05 05:02:58 dhr ++ * ++ * C labels go on statements ++ * ++ * Revision 1.113 2002/09/30 19:11:22 rgb ++ * Turn on debugging for upgoing acquire messages to test for reliability. ++ * ++ * Revision 1.112 2002/09/20 15:41:16 rgb ++ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). ++ * Added sadb_x_sa_ref to struct sadb_sa. ++ * Added ref parameter to pfkey_sa_build(). ++ * ++ * Revision 1.111 2002/09/20 05:02:08 rgb ++ * Added memory allocation debugging. ++ * Convert to switch to divulge hmac keys for debugging. ++ * Added text labels to elucidate numeric values presented. ++ * ++ * Revision 1.110 2002/08/03 18:03:05 mcr ++ * loop that checks for SPI's to have been already linked ++ * fails to actually step to next pointer, but continuously ++ * resets to head of list. Wrong pointer used. ++ * test east-icmp-02 revealed this. ++ * ++ * Revision 1.109 2002/07/26 08:48:31 rgb ++ * Added SA ref table code. ++ * ++ * Revision 1.108 2002/05/27 18:55:03 rgb ++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. ++ * ++ * Revision 1.107 2002/05/23 07:16:08 rgb ++ * Added ipsec_sa_put() for releasing an ipsec_sa refcount. ++ * Pointer clean-up. ++ * Added refcount code. ++ * ++ * Revision 1.106 2002/05/14 02:34:13 rgb ++ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion ++ * with "put" usage in the kernel. ++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, ++ * ipsec_sa or ipsec_sa. ++ * Moved all the extension parsing functions to pfkey_v2_ext_process.c. ++ * ++ * Revision 1.105 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.104 2002/04/24 07:36:34 mcr ++ * Moved from ./klips/net/ipsec/pfkey_v2_parser.c,v ++ * ++ * Revision 1.103 2002/04/20 00:12:25 rgb ++ * Added esp IV CBC attack fix, disabled. ++ * ++ * Revision 1.102 2002/03/08 01:15:17 mcr ++ * put some internal structure only debug messages behind ++ * && sysctl_ipsec_debug_verbose. ++ * ++ * Revision 1.101 2002/01/29 17:17:57 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.100 2002/01/29 04:00:54 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.99 2002/01/29 02:13:19 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.98 2002/01/12 02:57:57 mcr ++ * first regression test causes acquire messages to be lost ++ * 100% of the time. This is to help testing of pluto. ++ * ++ * Revision 1.97 2001/11/26 09:23:52 rgb ++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. ++ * ++ * Revision 1.93.2.4 2001/10/23 04:20:27 mcr ++ * parity was forced on wrong structure! prototypes help here. ++ * ++ * Revision 1.93.2.3 2001/10/22 21:14:59 mcr ++ * include des.h, removed phony prototypes and fixed calling ++ * conventions to match real prototypes. ++ * ++ * Revision 1.93.2.2 2001/10/15 05:39:03 mcr ++ * %08lx is not the right format for u32. Use %08x. 64-bit safe? ha. ++ * ++ * Revision 1.93.2.1 2001/09/25 02:30:14 mcr ++ * struct tdb -> struct ipsec_sa. ++ * use new lifetime structure. common format routines for debug. ++ * ++ * Revision 1.96 2001/11/06 20:47:54 rgb ++ * Fixed user context call to ipsec_dev_start_xmit() bug. Call ++ * dev_queue_xmit() instead. ++ * ++ * Revision 1.95 2001/11/06 19:47:46 rgb ++ * Added packet parameter to lifetime and comb structures. ++ * ++ * Revision 1.94 2001/10/18 04:45:23 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/freeswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.93 2001/09/20 15:32:59 rgb ++ * Min/max cleanup. ++ * ++ * Revision 1.92 2001/09/19 16:35:48 rgb ++ * PF_KEY ident fix for getspi from NetCelo (puttdb duplication). ++ * ++ * Revision 1.91 2001/09/15 16:24:06 rgb ++ * Re-inject first and last HOLD packet when an eroute REPLACE is done. ++ * ++ * Revision 1.90 2001/09/14 16:58:38 rgb ++ * Added support for storing the first and last packets through a HOLD. ++ * ++ * Revision 1.89 2001/09/08 21:14:07 rgb ++ * Added pfkey ident extension support for ISAKMPd. (NetCelo) ++ * Better state coherency (error management) between pf_key and IKE daemon. ++ * (NetCelo) ++ * ++ * Revision 1.88 2001/08/27 19:42:44 rgb ++ * Fix memory leak of encrypt and auth structs in pfkey register. ++ * ++ * Revision 1.87 2001/07/06 19:50:46 rgb ++ * Removed unused debugging code. ++ * Added inbound policy checking code for IPIP SAs. ++ * ++ * Revision 1.86 2001/06/20 06:26:04 rgb ++ * Changed missing SA errors from EEXIST to ENOENT and added debug output ++ * for already linked SAs. ++ * ++ * Revision 1.85 2001/06/15 04:57:02 rgb ++ * Remove single error return condition check and check for all errors in ++ * the case of a replace eroute delete operation. This means that ++ * applications must expect to be deleting something before replacing it ++ * and if nothing is found, complain. ++ * ++ * Revision 1.84 2001/06/14 19:35:12 rgb ++ * Update copyright date. ++ * ++ * Revision 1.83 2001/06/12 00:03:19 rgb ++ * Silence debug set/unset under normal conditions. ++ * ++ * Revision 1.82 2001/05/30 08:14:04 rgb ++ * Removed vestiges of esp-null transforms. ++ * ++ * Revision 1.81 2001/05/27 06:12:12 rgb ++ * Added structures for pid, packet count and last access time to eroute. ++ * Added packet count to beginning of /proc/net/ipsec_eroute. ++ * ++ * Revision 1.80 2001/05/03 19:43:59 rgb ++ * Check error return codes for all build function calls. ++ * Standardise on SENDERR() macro. ++ * ++ * Revision 1.79 2001/04/20 21:09:16 rgb ++ * Cleaned up fixed tdbwipes. ++ * Free pfkey_reply and clean up extensions_reply for grpsa, addflow and ++ * delflow (Per Cederqvist) plugging memleaks. ++ * ++ * Revision 1.78 2001/04/19 19:02:39 rgb ++ * Fixed extr.tdb freeing, stealing it for getspi, update and add. ++ * Refined a couple of spinlocks, fixed the one in update. ++ * ++ * Revision 1.77 2001/04/18 20:26:16 rgb ++ * Wipe/free eroute and both tdbs from extr at end of pfkey_msg_interp() ++ * instead of inside each message type parser. This fixes two memleaks. ++ * ++ * Revision 1.76 2001/04/17 23:51:18 rgb ++ * Quiet down pfkey_x_debug_process(). ++ * ++ * Revision 1.75 2001/03/29 01:55:05 rgb ++ * Fixed pfkey key init memleak. ++ * Fixed pfkey encryption key debug output. ++ * ++ * Revision 1.74 2001/03/27 05:29:14 rgb ++ * Debug output cleanup/silencing. ++ * ++ * Revision 1.73 2001/02/28 05:03:28 rgb ++ * Clean up and rationalise startup messages. ++ * ++ * Revision 1.72 2001/02/27 22:24:56 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.71 2001/02/27 06:59:30 rgb ++ * Added satype2name() conversions most places satype is debug printed. ++ * ++ * Revision 1.70 2001/02/26 22:37:08 rgb ++ * Fixed 'unknown proto' INT bug in new code. ++ * Added satype to protocol debugging instrumentation. ++ * ++ * Revision 1.69 2001/02/26 19:57:51 rgb ++ * Re-formatted debug output (split lines, consistent spacing). ++ * Fixed as yet undetected FLUSH bug which called ipsec_tdbcleanup() ++ * with an satype instead of proto. ++ * Checked for satype consistency and fixed minor bugs. ++ * Fixed undetected ungrpspi bug that tried to upmsg a second tdb. ++ * Check for satype sanity in pfkey_expire(). ++ * Added satype sanity check to addflow. ++ * ++ * Revision 1.68 2001/02/12 23:14:40 rgb ++ * Remove double spin lock in pfkey_expire(). ++ * ++ * Revision 1.67 2001/01/31 19:23:40 rgb ++ * Fixed double-unlock bug introduced by grpsa upmsg (found by Lars Heete). ++ * ++ * Revision 1.66 2001/01/29 22:20:04 rgb ++ * Fix minor add upmsg lifetime bug. ++ * ++ * Revision 1.65 2001/01/24 06:12:33 rgb ++ * Fixed address extension compile bugs just introduced. ++ * ++ * Revision 1.64 2001/01/24 00:31:15 rgb ++ * Added upmsg for addflow/delflow. ++ * ++ * Revision 1.63 2001/01/23 22:02:55 rgb ++ * Added upmsg to x_grpsa. ++ * Fixed lifetimes extentions to add/update/get upmsg. ++ * ++ * Revision 1.62 2000/11/30 21:47:51 rgb ++ * Fix error return bug after returning from pfkey_tdb_init(). ++ * ++ * Revision 1.61 2000/11/17 18:10:29 rgb ++ * Fixed bugs mostly relating to spirange, to treat all spi variables as ++ * network byte order since this is the way PF_KEYv2 stored spis. ++ * ++ * Revision 1.60 2000/11/06 04:34:53 rgb ++ * Changed non-exported functions to DEBUG_NO_STATIC. ++ * Add Svenning's adaptive content compression. ++ * Ditched spin_lock_irqsave in favour of spin_lock/_bh. ++ * Fixed double unlock bug (Svenning). ++ * Fixed pfkey_msg uninitialized bug in pfkey_{expire,acquire}(). ++ * Fixed incorrect extension type (prop) in pfkey)acquire(). ++ * ++ * Revision 1.59 2000/10/11 15:25:12 rgb ++ * Fixed IPCOMP disabled compile bug. ++ * ++ * Revision 1.58 2000/10/11 14:54:03 rgb ++ * Fixed pfkey_acquire() satype to SADB_SATYPE_ESP and removed pfkey ++ * protocol violations of setting pfkey_address_build() protocol parameter ++ * to non-zero except in the case of pfkey_acquire(). ++ * ++ * Revision 1.57 2000/10/10 20:10:18 rgb ++ * Added support for debug_ipcomp and debug_verbose to klipsdebug. ++ * ++ * Revision 1.56 2000/10/06 20:24:36 rgb ++ * Fixes to pfkey_acquire to initialize extensions[] and use correct ++ * ipproto. ++ * ++ * Revision 1.55 2000/10/03 03:20:57 rgb ++ * Added brackets to get a?b:c scope right for pfkey_register reply. ++ * ++ * Revision 1.54 2000/09/29 19:49:30 rgb ++ * As-yet-unused-bits cleanup. ++ * ++ * Revision 1.53 2000/09/28 00:35:45 rgb ++ * Padded SATYPE printout in pfkey_register for vertical alignment. ++ * ++ * Revision 1.52 2000/09/20 16:21:58 rgb ++ * Cleaned up ident string alloc/free. ++ * ++ * Revision 1.51 2000/09/20 04:04:20 rgb ++ * Changed static functions to DEBUG_NO_STATIC to reveal function names in ++ * oopsen. ++ * ++ * Revision 1.50 2000/09/16 01:10:53 rgb ++ * Fixed unused var warning with debug off. ++ * ++ * Revision 1.49 2000/09/15 11:37:02 rgb ++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk> ++ * IPCOMP zlib deflate code. ++ * ++ * Revision 1.48 2000/09/15 04:57:57 rgb ++ * Cleaned up existing IPCOMP code before svenning addition. ++ * Initialize pfkey_reply and extensions_reply in case of early error in ++ * message parsing functions (thanks Kai!). ++ * ++ * Revision 1.47 2000/09/13 08:02:56 rgb ++ * Added KMd registration notification. ++ * ++ * Revision 1.46 2000/09/12 22:35:36 rgb ++ * Restructured to remove unused extensions from CLEARFLOW messages. ++ * ++ * Revision 1.45 2000/09/12 03:24:23 rgb ++ * Converted #if0 debugs to sysctl. ++ * ++ * Revision 1.44 2000/09/09 06:38:39 rgb ++ * Correct SADB message type for update, add and delete. ++ * ++ * Revision 1.43 2000/09/08 19:19:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * Removed all references to CONFIG_IPSEC_PFKEYv2. ++ * Put in sanity checks in most msg type parsers to catch invalid satypes ++ * and empty socket lists. ++ * Moved spin-locks in pfkey_get_parse() to simplify. ++ * Added pfkey_acquire(). ++ * Added upwards messages to update, add, delete, acquire_parse, ++ * expire_parse and flush. ++ * Fix pfkey_prop_build() parameter to be only single indirection. ++ * Changed all replies to use pfkey_reply. ++ * Check return code on puttdb() and deltdbchain() in getspi, update, ++ * add, delete. ++ * Fixed up all pfkey replies to open and registered sockets. ++ * ++ * Revision 1.42 2000/09/01 18:50:26 rgb ++ * Added a supported algorithms array lists, one per satype and registered ++ * existing algorithms. ++ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to ++ * list. ++ * Only send pfkey_expire() messages to sockets registered for that satype. ++ * Added reply to pfkey_getspi_parse(). ++ * Added reply to pfkey_get_parse(). ++ * Fixed debug output label bug in pfkey_lifetime_process(). ++ * Cleaned up pfkey_sa_process a little. ++ * Moved pfkey_safe_build() above message type parsers to make it available ++ * for creating replies. ++ * Added comments for future work in pfkey_acquire_parse(). ++ * Fleshed out guts of pfkey_register_parse(). ++ * ++ * Revision 1.41 2000/08/24 16:58:11 rgb ++ * Fixed key debugging variables. ++ * Fixed error return code for a failed search. ++ * Changed order of pfkey_get operations. ++ * ++ * Revision 1.40 2000/08/21 16:32:27 rgb ++ * Re-formatted for cosmetic consistency and readability. ++ * ++ * Revision 1.39 2000/08/20 21:38:57 rgb ++ * Bugfixes to as-yet-unused pfkey_update_parse() and ++ * pfkey_register_parse(). (Momchil) ++ * Added functions pfkey_safe_build(), pfkey_expire() and ++ * pfkey_build_reply(). (Momchil) ++ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil) ++ * ++ * Revision 1.38 2000/08/18 21:30:41 rgb ++ * Purged all tdb_spi, tdb_proto and tdb_dst macros. They are unclear. ++ * ++ * Revision 1.37 2000/08/18 18:18:02 rgb ++ * Cosmetic and descriptive changes made to debug test. ++ * getspi and update fixes from Momchil. ++ * ++ * Revision 1.36 2000/08/15 15:41:55 rgb ++ * Fixed the (as yet unused and untested) pfkey_getspi() routine. ++ * ++ * Revision 1.35 2000/08/01 14:51:52 rgb ++ * Removed _all_ remaining traces of DES. ++ * ++ * Revision 1.34 2000/07/28 14:58:32 rgb ++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. ++ * ++ * Revision 1.33 2000/06/28 05:50:11 rgb ++ * Actually set iv_bits. ++ * ++ * Revision 1.32 2000/05/30 18:36:56 rgb ++ * Fix AH auth hash setup bug. This breaks interop with previous PF_KEY ++ * FreeS/WAN, but fixes interop with other implementations. ++ * ++ * Revision 1.31 2000/03/16 14:05:48 rgb ++ * Fixed brace scope preventing non-debug compile. ++ * Added null parameter check for pfkey_x_debug(). ++ * ++ * Revision 1.30 2000/01/22 23:21:13 rgb ++ * Use new function satype2proto(). ++ * ++ * Revision 1.29 2000/01/22 08:40:21 rgb ++ * Invert condition to known value to avoid AF_INET6 in 2.0.36. ++ * ++ * Revision 1.28 2000/01/22 07:58:57 rgb ++ * Fixed REPLACEFLOW bug, missing braces around KLIPS_PRINT *and* SENDERR. ++ * ++ * Revision 1.27 2000/01/22 03:48:01 rgb ++ * Added extr pointer component debugging. ++ * ++ * Revision 1.26 2000/01/21 09:41:25 rgb ++ * Changed a (void*) to (char*) cast to do proper pointer math. ++ * Don't call tdbwipe if tdb2 is NULL. ++ * ++ * Revision 1.25 2000/01/21 06:21:01 rgb ++ * Added address cases for eroute flows. ++ * Tidied up compiler directive indentation for readability. ++ * Added ictx,octx vars for simplification. ++ * Added macros for HMAC padding magic numbers. ++ * Converted from double tdb arguments to one structure (extr) ++ * containing pointers to all temporary information structures ++ * and checking for valid arguments to all ext processors and ++ * msg type parsers. ++ * Added spiungrp'ing. ++ * Added klipsdebug switching capability. ++ * Removed sa_process() check for zero protocol. ++ * Added address case for DST2 for grouping. ++ * Added/changed minor debugging instrumentation. ++ * Fixed spigrp for single said, ungrouping case. ++ * Added code to parse addflow and delflow messages. ++ * Removed redundant statements duplicating tdbwipe() functionality ++ * and causing double kfrees. ++ * Permit addflow to have a protocol of 0. ++ * ++ * Revision 1.24 1999/12/09 23:23:00 rgb ++ * Added check to pfkey_sa_process() to do eroutes. ++ * Converted to DIVUP() macro. ++ * Converted if() to switch() in pfkey_register_parse(). ++ * Use new pfkey_extensions_init() instead of memset(). ++ * ++ * Revision 1.23 1999/12/01 22:18:13 rgb ++ * Preset minspi and maxspi values in case and spirange extension is not ++ * included and check for the presence of an spirange extension before ++ * using it. Initialise tdb_sastate to LARVAL. ++ * Fixed debugging output typo. ++ * Fixed authentication context initialisation bugs (4 places). ++ * ++ * Revision 1.22 1999/11/27 11:53:08 rgb ++ * Moved pfkey_msg_parse prototype to pfkey.h ++ * Moved exts_permitted/required prototype to pfkey.h. ++ * Moved sadb_satype2proto protocol lookup table to lib/pfkey_v2_parse.c. ++ * Deleted SADB_X_EXT_SA2 code from pfkey_sa_process() since it will never ++ * be called. ++ * Moved protocol/algorithm checks to lib/pfkey_v2_parse.c ++ * Debugging error messages added. ++ * Enable lifetime_current checking. ++ * Remove illegal requirement for SA extension to be present in an ++ * originating GETSPI call. ++ * Re-instate requirement for UPDATE or ADD message to be MATURE. ++ * Add argument to pfkey_msg_parse() for direction. ++ * Fixed IPIP dst address bug and purged redundant, leaky code. ++ * ++ * Revision 1.21 1999/11/24 05:24:20 rgb ++ * hanged 'void*extensions' to 'struct sadb_ext*extensions'. ++ * Fixed indention. ++ * Ditched redundant replay check. ++ * Fixed debug message text from 'parse' to 'process'. ++ * Added more debug output. ++ * Forgot to zero extensions array causing bug, fixed. ++ * ++ * Revision 1.20 1999/11/23 23:08:13 rgb ++ * Move all common parsing code to lib/pfkey_v2_parse.c and rename ++ * remaining bits to *_process. (PJO) ++ * Add macros for dealing with alignment and rounding up more opaquely. ++ * Use provided macro ADDRTOA_BUF instead of hardcoded value. ++ * Sort out pfkey and freeswan headers, putting them in a library path. ++ * Corrected a couple of bugs in as-yet-inactive code. ++ * ++ * Revision 1.19 1999/11/20 22:01:10 rgb ++ * Add more descriptive error messages for non-zero reserved fields. ++ * Add more descriptive error message for spirange parsing. ++ * Start on supported extension parsing. ++ * Start on register and get message parsing. ++ * ++ * Revision 1.18 1999/11/18 04:09:20 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * ++ * Revision 1.17 1999/11/17 15:53:41 rgb ++ * Changed all occurrences of #include "../../../lib/freeswan.h" ++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the ++ * klips/net/ipsec/Makefile. ++ * ++ * Revision 1.16 1999/10/26 16:57:43 rgb ++ * Add shorter macros for compiler directives to visually clean-up. ++ * Give ipv6 code meaningful compiler directive. ++ * Add comments to other #if 0 debug code. ++ * Remove unused *_bh_atomic() calls. ++ * Fix mis-placed spinlock. ++ * ++ * Revision 1.15 1999/10/16 18:27:10 rgb ++ * Clean-up unused cruft. ++ * Fix-up lifetime_allocations_c and lifetime_addtime_c initialisations. ++ * ++ * Revision 1.14 1999/10/08 18:37:34 rgb ++ * Fix end-of-line spacing to sate whining PHMs. ++ * ++ * Revision 1.13 1999/10/03 18:49:12 rgb ++ * Spinlock fixes for 2.0.xx and 2.3.xx. ++ * ++ * Revision 1.12 1999/10/01 15:44:54 rgb ++ * Move spinlock header include to 2.1> scope. ++ * ++ * Revision 1.11 1999/10/01 00:05:45 rgb ++ * Added tdb structure locking. ++ * Use 'jiffies' instead of do_get_timeofday(). ++ * Fix lifetime assignments. ++ * ++ * Revision 1.10 1999/09/21 15:24:45 rgb ++ * Rework spirange code to save entropy and prevent endless loops. ++ * ++ * Revision 1.9 1999/09/16 12:10:21 rgb ++ * Minor fixes to random spi selection for correctness and entropy conservation. ++ * ++ * Revision 1.8 1999/05/25 22:54:46 rgb ++ * Fix comparison that should be an assignment in an if. ++ * ++ * Revision 1.7 1999/05/09 03:25:37 rgb ++ * Fix bug introduced by 2.2 quick-and-dirty patch. ++ * ++ * Revision 1.6 1999/05/08 21:32:30 rgb ++ * Fix error return reporting. ++ * ++ * Revision 1.5 1999/05/05 22:02:33 rgb ++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>. ++ * ++ * Revision 1.4 1999/04/29 15:22:40 rgb ++ * Standardise an error return method. ++ * Add debugging instrumentation. ++ * Add check for existence of macros min/max. ++ * Add extensions permitted/required in/out filters. ++ * Add satype-to-protocol table. ++ * Add a second tdb pointer to each parser to accomodate GRPSA. ++ * Move AH & no_algo_set to GETSPI, UPDATE and ADD. ++ * Add OOO window check. ++ * Add support for IPPROTO_IPIP and hooks for IPPROTO_COMP. ++ * Add timestamp to lifetime parse. ++ * Fix address structure length checking bug. ++ * Fix address structure allocation bug (forgot to kmalloc!). ++ * Add checks for extension lengths. ++ * Add checks for extension reserved illegal values. ++ * Add check for spirange legal values. ++ * Add an extension type for parsing a second satype, SA and ++ * DST_ADDRESS. ++ * Make changes to tdb_init() template to get pfkey_tdb_init(), ++ * eliminating any mention of xformsw. ++ * Implement getspi, update and grpsa (not tested). ++ * Add stubs for as yet unimplemented message types. ++ * Add table of message parsers to substitute for msg_parse switch. ++ * ++ * Revision 1.3 1999/04/15 17:58:07 rgb ++ * Add RCSID labels. ++ * ++ * Revision 1.2 1999/04/15 15:37:26 rgb ++ * Forward check changes from POST1_00 branch. ++ * ++ * Revision 1.1.2.1 1999/03/26 20:58:56 rgb ++ * Add pfkeyv2 support to KLIPS. ++ * ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/radij.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,1225 @@ ++char radij_c_version[] = "RCSID $Id: radij.c,v 1.46 2004/04/06 02:49:26 mcr Exp $"; ++ ++/* ++ * This file is defived from ${SRC}/sys/net/radix.c of BSD 4.4lite ++ * ++ * Variable and procedure names have been modified so that they don't ++ * conflict with the original BSD code, as a small number of modifications ++ * have been introduced and we may want to reuse this code in BSD. ++ * ++ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek ++ * chi or a German ch sound (as `doch', not as in `milch'), or even a ++ * spanish j as in Juan. It is not as far back in the throat like ++ * the corresponding Hebrew sound, nor is it a soft breath like the English h. ++ * It has nothing to do with the Dutch ij sound. ++ * ++ * Here is the appropriate copyright notice: ++ */ ++ ++/* ++ * Copyright (c) 1988, 1989, 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. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the University of ++ * California, Berkeley and its contributors. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)radix.c 8.2 (Berkeley) 1/4/94 ++ */ ++ ++/* ++ * Routines to build and maintain radix trees for routing lookups. ++ */ ++ ++#include <linux/config.h> ++#include <linux/version.h> ++#include <linux/kernel.h> /* printk() */ ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef MALLOC_SLAB ++# include <linux/slab.h> /* kmalloc() */ ++#else /* MALLOC_SLAB */ ++# include <linux/malloc.h> /* kmalloc() */ ++#endif /* MALLOC_SLAB */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/interrupt.h> /* mark_bh */ ++ ++#include <linux/netdevice.h> /* struct device, and other headers */ ++#include <linux/etherdevice.h> /* eth_type_trans */ ++#include <linux/ip.h> /* struct iphdr */ ++#include <linux/skbuff.h> ++#ifdef NET_21 ++# include <asm/uaccess.h> ++# include <linux/in6.h> ++#endif /* NET_21 */ ++#include <asm/checksum.h> ++#include <net/ip.h> ++ ++#include <openswan.h> ++ ++#include "openswan/radij.h" ++#include "openswan/ipsec_encap.h" ++#include "openswan/ipsec_radij.h" ++ ++int maj_keylen; ++struct radij_mask *rj_mkfreelist; ++struct radij_node_head *mask_rjhead; ++static int gotOddMasks; ++static char *maskedKey; ++static char *rj_zeroes, *rj_ones; ++ ++#define rj_masktop (mask_rjhead->rnh_treetop) ++#ifdef Bcmp ++# undef Bcmp ++#endif /* Bcmp */ ++#define Bcmp(a, b, l) (l == 0 ? 0 : memcmp((caddr_t)(b), (caddr_t)(a), (size_t)l)) ++/* ++ * The data structure for the keys is a radix tree with one way ++ * branching removed. The index rj_b at an internal node n represents a bit ++ * position to be tested. The tree is arranged so that all descendants ++ * of a node n have keys whose bits all agree up to position rj_b - 1. ++ * (We say the index of n is rj_b.) ++ * ++ * There is at least one descendant which has a one bit at position rj_b, ++ * and at least one with a zero there. ++ * ++ * A route is determined by a pair of key and mask. We require that the ++ * bit-wise logical and of the key and mask to be the key. ++ * We define the index of a route to associated with the mask to be ++ * the first bit number in the mask where 0 occurs (with bit number 0 ++ * representing the highest order bit). ++ * ++ * We say a mask is normal if every bit is 0, past the index of the mask. ++ * If a node n has a descendant (k, m) with index(m) == index(n) == rj_b, ++ * and m is a normal mask, then the route applies to every descendant of n. ++ * If the index(m) < rj_b, this implies the trailing last few bits of k ++ * before bit b are all 0, (and hence consequently true of every descendant ++ * of n), so the route applies to all descendants of the node as well. ++ * ++ * The present version of the code makes no use of normal routes, ++ * but similar logic shows that a non-normal mask m such that ++ * index(m) <= index(n) could potentially apply to many children of n. ++ * Thus, for each non-host route, we attach its mask to a list at an internal ++ * node as high in the tree as we can go. ++ */ ++ ++struct radij_node * ++rj_search(v_arg, head) ++ void *v_arg; ++ struct radij_node *head; ++{ ++ register struct radij_node *x; ++ register caddr_t v; ++ ++ for (x = head, v = v_arg; x->rj_b >= 0;) { ++ if (x->rj_bmask & v[x->rj_off]) ++ x = x->rj_r; ++ else ++ x = x->rj_l; ++ } ++ return (x); ++}; ++ ++struct radij_node * ++rj_search_m(v_arg, head, m_arg) ++ struct radij_node *head; ++ void *v_arg, *m_arg; ++{ ++ register struct radij_node *x; ++ register caddr_t v = v_arg, m = m_arg; ++ ++ for (x = head; x->rj_b >= 0;) { ++ if ((x->rj_bmask & m[x->rj_off]) && ++ (x->rj_bmask & v[x->rj_off])) ++ x = x->rj_r; ++ else ++ x = x->rj_l; ++ } ++ return x; ++}; ++ ++int ++rj_refines(m_arg, n_arg) ++ void *m_arg, *n_arg; ++{ ++ register caddr_t m = m_arg, n = n_arg; ++ register caddr_t lim, lim2 = lim = n + *(u_char *)n; ++ int longer = (*(u_char *)n++) - (int)(*(u_char *)m++); ++ int masks_are_equal = 1; ++ ++ if (longer > 0) ++ lim -= longer; ++ while (n < lim) { ++ if (*n & ~(*m)) ++ return 0; ++ if (*n++ != *m++) ++ masks_are_equal = 0; ++ ++ } ++ while (n < lim2) ++ if (*n++) ++ return 0; ++ if (masks_are_equal && (longer < 0)) ++ for (lim2 = m - longer; m < lim2; ) ++ if (*m++) ++ return 1; ++ return (!masks_are_equal); ++} ++ ++ ++struct radij_node * ++rj_match(v_arg, head) ++ void *v_arg; ++ struct radij_node_head *head; ++{ ++ caddr_t v = v_arg; ++ register struct radij_node *t = head->rnh_treetop, *x; ++ register caddr_t cp = v, cp2, cp3; ++ caddr_t cplim, mstart; ++ struct radij_node *saved_t, *top = t; ++ int off = t->rj_off, vlen = *(u_char *)cp, matched_off; ++ ++ /* ++ * Open code rj_search(v, top) to avoid overhead of extra ++ * subroutine call. ++ */ ++ for (; t->rj_b >= 0; ) { ++ if (t->rj_bmask & cp[t->rj_off]) ++ t = t->rj_r; ++ else ++ t = t->rj_l; ++ } ++ /* ++ * See if we match exactly as a host destination ++ */ ++ KLIPS_PRINT(debug_radij, ++ "klips_debug:rj_match: " ++ "* See if we match exactly as a host destination\n"); ++ ++ cp += off; cp2 = t->rj_key + off; cplim = v + vlen; ++ for (; cp < cplim; cp++, cp2++) ++ if (*cp != *cp2) ++ goto on1; ++ /* ++ * This extra grot is in case we are explicitly asked ++ * to look up the default. Ugh! ++ */ ++ if ((t->rj_flags & RJF_ROOT) && t->rj_dupedkey) ++ t = t->rj_dupedkey; ++ return t; ++on1: ++ matched_off = cp - v; ++ saved_t = t; ++ KLIPS_PRINT(debug_radij, ++ "klips_debug:rj_match: " ++ "** try to match a leaf, t=0p%p\n", t); ++ do { ++ if (t->rj_mask) { ++ /* ++ * Even if we don't match exactly as a hosts; ++ * we may match if the leaf we wound up at is ++ * a route to a net. ++ */ ++ cp3 = matched_off + t->rj_mask; ++ cp2 = matched_off + t->rj_key; ++ for (; cp < cplim; cp++) ++ if ((*cp2++ ^ *cp) & *cp3++) ++ break; ++ if (cp == cplim) ++ return t; ++ cp = matched_off + v; ++ } ++ } while ((t = t->rj_dupedkey)); ++ t = saved_t; ++ /* start searching up the tree */ ++ KLIPS_PRINT(debug_radij, ++ "klips_debug:rj_match: " ++ "*** start searching up the tree, t=0p%p\n", ++ t); ++ do { ++ register struct radij_mask *m; ++ ++ t = t->rj_p; ++ KLIPS_PRINT(debug_radij, ++ "klips_debug:rj_match: " ++ "**** t=0p%p\n", ++ t); ++ if ((m = t->rj_mklist)) { ++ /* ++ * After doing measurements here, it may ++ * turn out to be faster to open code ++ * rj_search_m here instead of always ++ * copying and masking. ++ */ ++ /* off = min(t->rj_off, matched_off); */ ++ off = t->rj_off; ++ if (matched_off < off) ++ off = matched_off; ++ mstart = maskedKey + off; ++ do { ++ cp2 = mstart; ++ cp3 = m->rm_mask + off; ++ KLIPS_PRINT(debug_radij, ++ "klips_debug:rj_match: " ++ "***** cp2=0p%p cp3=0p%p\n", ++ cp2, cp3); ++ for (cp = v + off; cp < cplim;) ++ *cp2++ = *cp++ & *cp3++; ++ x = rj_search(maskedKey, t); ++ while (x && x->rj_mask != m->rm_mask) ++ x = x->rj_dupedkey; ++ if (x && ++ (Bcmp(mstart, x->rj_key + off, ++ vlen - off) == 0)) ++ return x; ++ } while ((m = m->rm_mklist)); ++ } ++ } while (t != top); ++ KLIPS_PRINT(debug_radij, ++ "klips_debug:rj_match: " ++ "***** not found.\n"); ++ return 0; ++}; ++ ++#ifdef RJ_DEBUG ++int rj_nodenum; ++struct radij_node *rj_clist; ++int rj_saveinfo; ++DEBUG_NO_STATIC void traverse(struct radij_node *); ++#ifdef RJ_DEBUG2 ++int rj_debug = 1; ++#else ++int rj_debug = 0; ++#endif /* RJ_DEBUG2 */ ++#endif /* RJ_DEBUG */ ++ ++struct radij_node * ++rj_newpair(v, b, nodes) ++ void *v; ++ int b; ++ struct radij_node nodes[2]; ++{ ++ register struct radij_node *tt = nodes, *t = tt + 1; ++ t->rj_b = b; t->rj_bmask = 0x80 >> (b & 7); ++ t->rj_l = tt; t->rj_off = b >> 3; ++ tt->rj_b = -1; tt->rj_key = (caddr_t)v; tt->rj_p = t; ++ tt->rj_flags = t->rj_flags = RJF_ACTIVE; ++#ifdef RJ_DEBUG ++ tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++; ++ tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt; ++#endif /* RJ_DEBUG */ ++ return t; ++} ++ ++struct radij_node * ++rj_insert(v_arg, head, dupentry, nodes) ++ void *v_arg; ++ struct radij_node_head *head; ++ int *dupentry; ++ struct radij_node nodes[2]; ++{ ++ caddr_t v = v_arg; ++ struct radij_node *top = head->rnh_treetop; ++ int head_off = top->rj_off, vlen = (int)*((u_char *)v); ++ register struct radij_node *t = rj_search(v_arg, top); ++ register caddr_t cp = v + head_off; ++ register int b; ++ struct radij_node *tt; ++ /* ++ *find first bit at which v and t->rj_key differ ++ */ ++ { ++ register caddr_t cp2 = t->rj_key + head_off; ++ register int cmp_res; ++ caddr_t cplim = v + vlen; ++ ++ while (cp < cplim) ++ if (*cp2++ != *cp++) ++ goto on1; ++ *dupentry = 1; ++ return t; ++on1: ++ *dupentry = 0; ++ cmp_res = (cp[-1] ^ cp2[-1]) & 0xff; ++ for (b = (cp - v) << 3; cmp_res; b--) ++ cmp_res >>= 1; ++ } ++ { ++ register struct radij_node *p, *x = top; ++ cp = v; ++ do { ++ p = x; ++ if (cp[x->rj_off] & x->rj_bmask) ++ x = x->rj_r; ++ else x = x->rj_l; ++ } while (b > (unsigned) x->rj_b); /* x->rj_b < b && x->rj_b >= 0 */ ++#ifdef RJ_DEBUG ++ if (rj_debug) ++ printk("klips_debug:rj_insert: Going In:\n"), traverse(p); ++#endif /* RJ_DEBUG */ ++ t = rj_newpair(v_arg, b, nodes); tt = t->rj_l; ++ if ((cp[p->rj_off] & p->rj_bmask) == 0) ++ p->rj_l = t; ++ else ++ p->rj_r = t; ++ x->rj_p = t; t->rj_p = p; /* frees x, p as temp vars below */ ++ if ((cp[t->rj_off] & t->rj_bmask) == 0) { ++ t->rj_r = x; ++ } else { ++ t->rj_r = tt; t->rj_l = x; ++ } ++#ifdef RJ_DEBUG ++ if (rj_debug) ++ printk("klips_debug:rj_insert: Coming out:\n"), traverse(p); ++#endif /* RJ_DEBUG */ ++ } ++ return (tt); ++} ++ ++struct radij_node * ++rj_addmask(n_arg, search, skip) ++ int search, skip; ++ void *n_arg; ++{ ++ caddr_t netmask = (caddr_t)n_arg; ++ register struct radij_node *x; ++ register caddr_t cp, cplim; ++ register int b, mlen, j; ++ int maskduplicated; ++ ++ mlen = *(u_char *)netmask; ++ if (search) { ++ x = rj_search(netmask, rj_masktop); ++ mlen = *(u_char *)netmask; ++ if (Bcmp(netmask, x->rj_key, mlen) == 0) ++ return (x); ++ } ++ R_Malloc(x, struct radij_node *, maj_keylen + 2 * sizeof (*x)); ++ if (x == 0) ++ return (0); ++ Bzero(x, maj_keylen + 2 * sizeof (*x)); ++ cp = (caddr_t)(x + 2); ++ Bcopy(netmask, cp, mlen); ++ netmask = cp; ++ x = rj_insert(netmask, mask_rjhead, &maskduplicated, x); ++ /* ++ * Calculate index of mask. ++ */ ++ cplim = netmask + mlen; ++ for (cp = netmask + skip; cp < cplim; cp++) ++ if (*(u_char *)cp != 0xff) ++ break; ++ b = (cp - netmask) << 3; ++ if (cp != cplim) { ++ if (*cp != 0) { ++ gotOddMasks = 1; ++ for (j = 0x80; j; b++, j >>= 1) ++ if ((j & *cp) == 0) ++ break; ++ } ++ } ++ x->rj_b = -1 - b; ++ return (x); ++} ++ ++#if 0 ++struct radij_node * ++#endif ++int ++rj_addroute(v_arg, n_arg, head, treenodes) ++ void *v_arg, *n_arg; ++ struct radij_node_head *head; ++ struct radij_node treenodes[2]; ++{ ++ caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; ++ register struct radij_node *t, *x=NULL, *tt; ++ struct radij_node *saved_tt, *top = head->rnh_treetop; ++ short b = 0, b_leaf; ++ int mlen, keyduplicated; ++ caddr_t cplim; ++ struct radij_mask *m, **mp; ++ ++ /* ++ * In dealing with non-contiguous masks, there may be ++ * many different routes which have the same mask. ++ * We will find it useful to have a unique pointer to ++ * the mask to speed avoiding duplicate references at ++ * nodes and possibly save time in calculating indices. ++ */ ++ if (netmask) { ++ x = rj_search(netmask, rj_masktop); ++ mlen = *(u_char *)netmask; ++ if (Bcmp(netmask, x->rj_key, mlen) != 0) { ++ x = rj_addmask(netmask, 0, top->rj_off); ++ if (x == 0) ++ return -ENOMEM; /* (0) rgb */ ++ } ++ netmask = x->rj_key; ++ b = -1 - x->rj_b; ++ } ++ /* ++ * Deal with duplicated keys: attach node to previous instance ++ */ ++ saved_tt = tt = rj_insert(v, head, &keyduplicated, treenodes); ++#ifdef RJ_DEBUG ++ printk("addkey: duplicated: %d\n", keyduplicated); ++#endif ++ if (keyduplicated) { ++ do { ++ if (tt->rj_mask == netmask) ++ return -EEXIST; /* -ENXIO; (0) rgb */ ++ t = tt; ++ if (netmask == 0 || ++ (tt->rj_mask && rj_refines(netmask, tt->rj_mask))) ++ break; ++ } while ((tt = tt->rj_dupedkey)); ++ /* ++ * If the mask is not duplicated, we wouldn't ++ * find it among possible duplicate key entries ++ * anyway, so the above test doesn't hurt. ++ * ++ * We sort the masks for a duplicated key the same way as ++ * in a masklist -- most specific to least specific. ++ * This may require the unfortunate nuisance of relocating ++ * the head of the list. ++ */ ++ if (tt && t == saved_tt) { ++ struct radij_node *xx = x; ++ /* link in at head of list */ ++ (tt = treenodes)->rj_dupedkey = t; ++ tt->rj_flags = t->rj_flags; ++ tt->rj_p = x = t->rj_p; ++ if (x->rj_l == t) x->rj_l = tt; else x->rj_r = tt; ++ saved_tt = tt; x = xx; ++ } else { ++ (tt = treenodes)->rj_dupedkey = t->rj_dupedkey; ++ t->rj_dupedkey = tt; ++ } ++#ifdef RJ_DEBUG ++ t=tt+1; tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++; ++ tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt; ++#endif /* RJ_DEBUG */ ++ t = saved_tt; ++ tt->rj_key = (caddr_t) v; ++ tt->rj_b = -1; ++ tt->rj_flags = t->rj_flags & ~RJF_ROOT; ++ } ++ /* ++ * Put mask in tree. ++ */ ++ if (netmask) { ++ tt->rj_mask = netmask; ++ tt->rj_b = x->rj_b; ++ } ++ t = saved_tt->rj_p; ++ b_leaf = -1 - t->rj_b; ++ if (t->rj_r == saved_tt) x = t->rj_l; else x = t->rj_r; ++ /* Promote general routes from below */ ++ if (x->rj_b < 0) { ++ if (x->rj_mask && (x->rj_b >= b_leaf) && x->rj_mklist == 0) { ++ MKGet(m); ++ if (m) { ++ Bzero(m, sizeof *m); ++ m->rm_b = x->rj_b; ++ m->rm_mask = x->rj_mask; ++ x->rj_mklist = t->rj_mklist = m; ++ } ++ } ++ } else if (x->rj_mklist) { ++ /* ++ * Skip over masks whose index is > that of new node ++ */ ++ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) ++ if (m->rm_b >= b_leaf) ++ break; ++ t->rj_mklist = m; *mp = 0; ++ } ++ /* Add new route to highest possible ancestor's list */ ++ if ((netmask == 0) || (b > t->rj_b )) { ++#ifdef RJ_DEBUG ++ printk("klips:radij.c: netmask = %p or b(%d)>t->rjb(%d)\n", netmask, b, t->rj_b); ++#endif ++ return 0; /* tt rgb */ /* can't lift at all */ ++ } ++ b_leaf = tt->rj_b; ++ do { ++ x = t; ++ t = t->rj_p; ++ } while (b <= t->rj_b && x != top); ++ /* ++ * Search through routes associated with node to ++ * insert new route according to index. ++ * For nodes of equal index, place more specific ++ * masks first. ++ */ ++ cplim = netmask + mlen; ++ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) { ++ if (m->rm_b < b_leaf) ++ continue; ++ if (m->rm_b > b_leaf) ++ break; ++ if (m->rm_mask == netmask) { ++ m->rm_refs++; ++ tt->rj_mklist = m; ++#ifdef RJ_DEBUG ++ printk("klips:radij.c: m->rm_mask %p == netmask\n", netmask); ++#endif ++ return 0; /* tt rgb */ ++ } ++ if (rj_refines(netmask, m->rm_mask)) ++ break; ++ } ++ MKGet(m); ++ if (m == 0) { ++ printk("klips_debug:rj_addroute: " ++ "Mask for route not entered\n"); ++ return 0; /* (tt) rgb */ ++ } ++ Bzero(m, sizeof *m); ++ m->rm_b = b_leaf; ++ m->rm_mask = netmask; ++ m->rm_mklist = *mp; ++ *mp = m; ++ tt->rj_mklist = m; ++#ifdef RJ_DEBUG ++ printk("klips:radij.c: addroute done\n"); ++#endif ++ return 0; /* tt rgb */ ++} ++ ++int ++rj_delete(v_arg, netmask_arg, head, node) ++ void *v_arg, *netmask_arg; ++ struct radij_node_head *head; ++ struct radij_node **node; ++{ ++ register struct radij_node *t, *p, *x, *tt; ++ struct radij_mask *m, *saved_m, **mp; ++ struct radij_node *dupedkey, *saved_tt, *top; ++ caddr_t v, netmask; ++ int b, head_off, vlen; ++ ++ v = v_arg; ++ netmask = netmask_arg; ++ x = head->rnh_treetop; ++ tt = rj_search(v, x); ++ head_off = x->rj_off; ++ vlen = *(u_char *)v; ++ saved_tt = tt; ++ top = x; ++ if (tt == 0 || ++ Bcmp(v + head_off, tt->rj_key + head_off, vlen - head_off)) ++ return -EFAULT; /* (0) rgb */ ++ /* ++ * Delete our route from mask lists. ++ */ ++ if ((dupedkey = tt->rj_dupedkey)) { ++ if (netmask) ++ netmask = rj_search(netmask, rj_masktop)->rj_key; ++ while (tt->rj_mask != netmask) ++ if ((tt = tt->rj_dupedkey) == 0) ++ return -ENOENT; /* -ENXIO; (0) rgb */ ++ } ++ if (tt->rj_mask == 0 || (saved_m = m = tt->rj_mklist) == 0) ++ goto on1; ++ if (m->rm_mask != tt->rj_mask) { ++ printk("klips_debug:rj_delete: " ++ "inconsistent annotation\n"); ++ goto on1; ++ } ++ if (--m->rm_refs >= 0) ++ goto on1; ++ b = -1 - tt->rj_b; ++ t = saved_tt->rj_p; ++ if (b > t->rj_b) ++ goto on1; /* Wasn't lifted at all */ ++ do { ++ x = t; ++ t = t->rj_p; ++ } while (b <= t->rj_b && x != top); ++ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) ++ if (m == saved_m) { ++ *mp = m->rm_mklist; ++ MKFree(m); ++ break; ++ } ++ if (m == 0) ++ printk("klips_debug:rj_delete: " ++ "couldn't find our annotation\n"); ++on1: ++ /* ++ * Eliminate us from tree ++ */ ++ if (tt->rj_flags & RJF_ROOT) ++ return -EFAULT; /* (0) rgb */ ++#ifdef RJ_DEBUG ++ /* Get us out of the creation list */ ++ for (t = rj_clist; t && t->rj_ybro != tt; t = t->rj_ybro) {} ++ if (t) t->rj_ybro = tt->rj_ybro; ++#endif /* RJ_DEBUG */ ++ t = tt->rj_p; ++ if (dupedkey) { ++ if (tt == saved_tt) { ++ x = dupedkey; x->rj_p = t; ++ if (t->rj_l == tt) t->rj_l = x; else t->rj_r = x; ++ } else { ++ for (x = p = saved_tt; p && p->rj_dupedkey != tt;) ++ p = p->rj_dupedkey; ++ if (p) p->rj_dupedkey = tt->rj_dupedkey; ++ else printk("klips_debug:rj_delete: " ++ "couldn't find node that we started with\n"); ++ } ++ t = tt + 1; ++ if (t->rj_flags & RJF_ACTIVE) { ++#ifndef RJ_DEBUG ++ *++x = *t; p = t->rj_p; ++#else ++ b = t->rj_info; *++x = *t; t->rj_info = b; p = t->rj_p; ++#endif /* RJ_DEBUG */ ++ if (p->rj_l == t) p->rj_l = x; else p->rj_r = x; ++ x->rj_l->rj_p = x; x->rj_r->rj_p = x; ++ } ++ goto out; ++ } ++ if (t->rj_l == tt) x = t->rj_r; else x = t->rj_l; ++ p = t->rj_p; ++ if (p->rj_r == t) p->rj_r = x; else p->rj_l = x; ++ x->rj_p = p; ++ /* ++ * Demote routes attached to us. ++ */ ++ if (t->rj_mklist) { ++ if (x->rj_b >= 0) { ++ for (mp = &x->rj_mklist; (m = *mp);) ++ mp = &m->rm_mklist; ++ *mp = t->rj_mklist; ++ } else { ++ for (m = t->rj_mklist; m;) { ++ struct radij_mask *mm = m->rm_mklist; ++ if (m == x->rj_mklist && (--(m->rm_refs) < 0)) { ++ x->rj_mklist = 0; ++ MKFree(m); ++ } else ++ printk("klips_debug:rj_delete: " ++ "Orphaned Mask 0p%p at 0p%p\n", m, x); ++ m = mm; ++ } ++ } ++ } ++ /* ++ * We may be holding an active internal node in the tree. ++ */ ++ x = tt + 1; ++ if (t != x) { ++#ifndef RJ_DEBUG ++ *t = *x; ++#else ++ b = t->rj_info; *t = *x; t->rj_info = b; ++#endif /* RJ_DEBUG */ ++ t->rj_l->rj_p = t; t->rj_r->rj_p = t; ++ p = x->rj_p; ++ if (p->rj_l == x) p->rj_l = t; else p->rj_r = t; ++ } ++out: ++ tt->rj_flags &= ~RJF_ACTIVE; ++ tt[1].rj_flags &= ~RJF_ACTIVE; ++ *node = tt; ++ return 0; /* (tt) rgb */ ++} ++ ++int ++rj_walktree(h, f, w) ++ struct radij_node_head *h; ++ register int (*f)(struct radij_node *,void *); ++ void *w; ++{ ++ int error; ++ struct radij_node *base, *next; ++ register struct radij_node *rn; ++ ++ if(!h || !f /* || !w */) { ++ return -ENODATA; ++ } ++ ++ rn = h->rnh_treetop; ++ /* ++ * This gets complicated because we may delete the node ++ * while applying the function f to it, so we need to calculate ++ * the successor node in advance. ++ */ ++ /* First time through node, go left */ ++ while (rn->rj_b >= 0) ++ rn = rn->rj_l; ++ for (;;) { ++#ifdef CONFIG_IPSEC_DEBUG ++ if(debug_radij) { ++ printk("klips_debug:rj_walktree: " ++ "for: rn=0p%p rj_b=%d rj_flags=%x", ++ rn, ++ rn->rj_b, ++ rn->rj_flags); ++ rn->rj_b >= 0 ? ++ printk(" node off=%x\n", ++ rn->rj_off) : ++ printk(" leaf key = %08x->%08x\n", ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)) ++ ; ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ base = rn; ++ /* If at right child go back up, otherwise, go right */ ++ while (rn->rj_p->rj_r == rn && (rn->rj_flags & RJF_ROOT) == 0) ++ rn = rn->rj_p; ++ /* Find the next *leaf* since next node might vanish, too */ ++ for (rn = rn->rj_p->rj_r; rn->rj_b >= 0;) ++ rn = rn->rj_l; ++ next = rn; ++#ifdef CONFIG_IPSEC_DEBUG ++ if(debug_radij) { ++ printk("klips_debug:rj_walktree: " ++ "processing leaves, rn=0p%p rj_b=%d rj_flags=%x", ++ rn, ++ rn->rj_b, ++ rn->rj_flags); ++ rn->rj_b >= 0 ? ++ printk(" node off=%x\n", ++ rn->rj_off) : ++ printk(" leaf key = %08x->%08x\n", ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)) ++ ; ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ /* Process leaves */ ++ while ((rn = base)) { ++ base = rn->rj_dupedkey; ++#ifdef CONFIG_IPSEC_DEBUG ++ if(debug_radij) { ++ printk("klips_debug:rj_walktree: " ++ "while: base=0p%p rn=0p%p rj_b=%d rj_flags=%x", ++ base, ++ rn, ++ rn->rj_b, ++ rn->rj_flags); ++ rn->rj_b >= 0 ? ++ printk(" node off=%x\n", ++ rn->rj_off) : ++ printk(" leaf key = %08x->%08x\n", ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)) ++ ; ++ } ++#endif /* CONFIG_IPSEC_DEBUG */ ++ if (!(rn->rj_flags & RJF_ROOT) && (error = (*f)(rn, w))) ++ return (-error); ++ } ++ rn = next; ++ if (rn->rj_flags & RJF_ROOT) ++ return (0); ++ } ++ /* NOTREACHED */ ++} ++ ++int ++rj_inithead(head, off) ++ void **head; ++ int off; ++{ ++ register struct radij_node_head *rnh; ++ register struct radij_node *t, *tt, *ttt; ++ if (*head) ++ return (1); ++ R_Malloc(rnh, struct radij_node_head *, sizeof (*rnh)); ++ if (rnh == NULL) ++ return (0); ++ Bzero(rnh, sizeof (*rnh)); ++ *head = rnh; ++ t = rj_newpair(rj_zeroes, off, rnh->rnh_nodes); ++ ttt = rnh->rnh_nodes + 2; ++ t->rj_r = ttt; ++ t->rj_p = t; ++ tt = t->rj_l; ++ tt->rj_flags = t->rj_flags = RJF_ROOT | RJF_ACTIVE; ++ tt->rj_b = -1 - off; ++ *ttt = *tt; ++ ttt->rj_key = rj_ones; ++ rnh->rnh_addaddr = rj_addroute; ++ rnh->rnh_deladdr = rj_delete; ++ rnh->rnh_matchaddr = rj_match; ++ rnh->rnh_walktree = rj_walktree; ++ rnh->rnh_treetop = t; ++ return (1); ++} ++ ++void ++rj_init() ++{ ++ char *cp, *cplim; ++ ++ if (maj_keylen == 0) { ++ printk("klips_debug:rj_init: " ++ "radij functions require maj_keylen be set\n"); ++ return; ++ } ++ R_Malloc(rj_zeroes, char *, 3 * maj_keylen); ++ if (rj_zeroes == NULL) ++ panic("rj_init"); ++ Bzero(rj_zeroes, 3 * maj_keylen); ++ rj_ones = cp = rj_zeroes + maj_keylen; ++ maskedKey = cplim = rj_ones + maj_keylen; ++ while (cp < cplim) ++ *cp++ = -1; ++ if (rj_inithead((void **)&mask_rjhead, 0) == 0) ++ panic("rj_init 2"); ++} ++ ++void ++rj_preorder(struct radij_node *rn, int l) ++{ ++ int i; ++ ++ if (rn == NULL){ ++ printk("klips_debug:rj_preorder: " ++ "NULL pointer\n"); ++ return; ++ } ++ ++ if (rn->rj_b >= 0){ ++ rj_preorder(rn->rj_l, l+1); ++ rj_preorder(rn->rj_r, l+1); ++ printk("klips_debug:"); ++ for (i=0; i<l; i++) ++ printk("*"); ++ printk(" off = %d\n", ++ rn->rj_off); ++ } else { ++ printk("klips_debug:"); ++ for (i=0; i<l; i++) ++ printk("@"); ++ printk(" flags = %x", ++ (u_int)rn->rj_flags); ++ if (rn->rj_flags & RJF_ACTIVE) { ++ printk(" @key=0p%p", ++ rn->rj_key); ++ printk(" key = %08x->%08x", ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)); ++ printk(" @mask=0p%p", ++ rn->rj_mask); ++ if (rn->rj_mask) ++ printk(" mask = %08x->%08x", ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_src.s_addr), ++ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_dst.s_addr)); ++ if (rn->rj_dupedkey) ++ printk(" dupedkey = 0p%p", ++ rn->rj_dupedkey); ++ } ++ printk("\n"); ++ } ++} ++ ++#ifdef RJ_DEBUG ++DEBUG_NO_STATIC void traverse(struct radij_node *p) ++{ ++ rj_preorder(p, 0); ++} ++#endif /* RJ_DEBUG */ ++ ++void ++rj_dumptrees(void) ++{ ++ rj_preorder(rnh->rnh_treetop, 0); ++} ++ ++void ++rj_free_mkfreelist(void) ++{ ++ struct radij_mask *mknp, *mknp2; ++ ++ mknp = rj_mkfreelist; ++ while(mknp) ++ { ++ mknp2 = mknp; ++ mknp = mknp->rm_mklist; ++ kfree(mknp2); ++ } ++} ++ ++int ++radijcleartree(void) ++{ ++ return rj_walktree(rnh, ipsec_rj_walker_delete, NULL); ++} ++ ++int ++radijcleanup(void) ++{ ++ int error = 0; ++ ++ error = radijcleartree(); ++ ++ rj_free_mkfreelist(); ++ ++/* rj_walktree(mask_rjhead, ipsec_rj_walker_delete, NULL); */ ++ if(mask_rjhead) { ++ kfree(mask_rjhead); ++ } ++ ++ if(rj_zeroes) { ++ kfree(rj_zeroes); ++ } ++ ++ if(rnh) { ++ kfree(rnh); ++ } ++ ++ return error; ++} ++ ++/* ++ * $Log: radij.c,v $ ++ * Revision 1.46 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.45 2003/10/31 02:27:55 mcr ++ * pulled up port-selector patches and sa_id elimination. ++ * ++ * Revision 1.44.30.1 2003/10/29 01:30:41 mcr ++ * elimited "struct sa_id". ++ * ++ * Revision 1.44 2002/07/24 18:44:54 rgb ++ * Type fiddling to tame ia64 compiler. ++ * ++ * Revision 1.43 2002/05/23 07:14:11 rgb ++ * Cleaned up %p variants to 0p%p for test suite cleanup. ++ * ++ * Revision 1.42 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.41 2002/04/24 07:36:35 mcr ++ * Moved from ./klips/net/ipsec/radij.c,v ++ * ++ * Revision 1.40 2002/01/29 17:17:58 mcr ++ * moved include of ipsec_param.h to after include of linux/kernel.h ++ * otherwise, it seems that some option that is set in ipsec_param.h ++ * screws up something subtle in the include path to kernel.h, and ++ * it complains on the snprintf() prototype. ++ * ++ * Revision 1.39 2002/01/29 04:00:55 mcr ++ * more excise of kversions.h header. ++ * ++ * Revision 1.38 2002/01/29 02:13:19 mcr ++ * introduction of ipsec_kversion.h means that include of ++ * ipsec_param.h must preceed any decisions about what files to ++ * include to deal with differences in kernel source. ++ * ++ * Revision 1.37 2001/10/18 04:45:23 rgb ++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, ++ * lib/freeswan.h version macros moved to lib/kversions.h. ++ * Other compiler directive cleanups. ++ * ++ * Revision 1.36 2001/08/22 13:43:51 henry ++ * eliminate the single use of min() to avoid problems with Linus changing it ++ * ++ * Revision 1.35 2001/06/15 04:57:29 rgb ++ * Clarified error return codes. ++ * Changed mask add already exists to EEXIST. ++ * Changed mask delete did not exist to ENOENT. ++ * ++ * Revision 1.34 2001/05/03 19:44:26 rgb ++ * Fix sign of error return codes for rj_addroute(). ++ * ++ * Revision 1.33 2001/02/27 22:24:56 rgb ++ * Re-formatting debug output (line-splitting, joining, 1arg/line). ++ * Check for satoa() return codes. ++ * ++ * Revision 1.32 2001/02/27 06:23:15 rgb ++ * Debug line splitting. ++ * ++ * Revision 1.31 2000/11/06 04:35:21 rgb ++ * Clear table *before* releasing other items in radijcleanup. ++ * ++ * Revision 1.30 2000/09/20 04:07:40 rgb ++ * Changed static functions to DEBUG_NO_STATIC to reveal function names in ++ * oopsen. ++ * ++ * Revision 1.29 2000/09/12 03:25:02 rgb ++ * Moved radij_c_version printing to ipsec_version_get_info(). ++ * ++ * Revision 1.28 2000/09/08 19:12:56 rgb ++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. ++ * ++ * Revision 1.27 2000/07/28 14:58:32 rgb ++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. ++ * ++ * Revision 1.26 2000/05/10 23:11:37 rgb ++ * Comment out most of the startup version information. ++ * ++ * Revision 1.25 2000/01/21 06:21:47 rgb ++ * Change return codes to negative on error. ++ * ++ * Revision 1.24 1999/11/18 04:09:20 rgb ++ * Replaced all kernel version macros to shorter, readable form. ++ * ++ * Revision 1.23 1999/11/17 15:53:41 rgb ++ * Changed all occurrences of #include "../../../lib/freeswan.h" ++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the ++ * klips/net/ipsec/Makefile. ++ * ++ * Revision 1.22 1999/10/15 22:17:28 rgb ++ * Modify radijcleanup() to call radijcleartree(). ++ * ++ * Revision 1.21 1999/10/08 18:37:34 rgb ++ * Fix end-of-line spacing to sate whining PHMs. ++ * ++ * Revision 1.20 1999/10/01 15:44:54 rgb ++ * Move spinlock header include to 2.1> scope. ++ * ++ * Revision 1.19 1999/10/01 08:35:52 rgb ++ * Add spinlock include to shut up compiler for 2.0.38. ++ * ++ * Revision 1.18 1999/09/23 18:02:52 rgb ++ * De-alarm the search failure message so it doesn't sound so grave. ++ * ++ * Revision 1.17 1999/05/25 21:26:01 rgb ++ * Fix rj_walktree() sanity checking bug. ++ * ++ * Revision 1.16 1999/05/09 03:25:38 rgb ++ * Fix bug introduced by 2.2 quick-and-dirty patch. ++ * ++ * Revision 1.15 1999/05/05 22:02:33 rgb ++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>. ++ * ++ * Revision 1.14 1999/04/29 15:24:15 rgb ++ * Add sanity checking for null pointer arguments. ++ * Standardise an error return method. ++ * ++ * Revision 1.13 1999/04/11 00:29:02 henry ++ * GPL boilerplate ++ * ++ * Revision 1.12 1999/04/06 04:54:28 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ * Revision 1.11 1999/02/17 16:52:53 rgb ++ * Convert DEBUG_IPSEC to KLIPS_PRINT ++ * Clean out unused cruft. ++ * ++ * Revision 1.10 1999/01/22 06:30:05 rgb ++ * Cruft clean-out. ++ * 64-bit clean-up. ++ * ++ * Revision 1.9 1998/12/01 13:22:04 rgb ++ * Added support for debug printing of version info. ++ * ++ * Revision 1.8 1998/11/30 13:22:55 rgb ++ * Rationalised all the klips kernel file headers. They are much shorter ++ * now and won't conflict under RH5.2. ++ * ++ * Revision 1.7 1998/10/25 02:43:26 rgb ++ * Change return type on rj_addroute and rj_delete and add and argument ++ * to the latter to be able to transmit more infomation about errors. ++ * ++ * Revision 1.6 1998/10/19 14:30:06 rgb ++ * Added inclusion of freeswan.h. ++ * ++ * Revision 1.5 1998/10/09 04:33:27 rgb ++ * Added 'klips_debug' prefix to all klips printk debug statements. ++ * Fixed output formatting slightly. ++ * ++ * Revision 1.4 1998/07/28 00:06:59 rgb ++ * Add debug detail to tree traversing. ++ * ++ * Revision 1.3 1998/07/14 18:07:58 rgb ++ * Add a routine to clear the eroute tree. ++ * ++ * Revision 1.2 1998/06/25 20:03:22 rgb ++ * Cleanup #endif comments. Debug output for rj_init. ++ * ++ * Revision 1.1 1998/06/18 21:30:22 henry ++ * move sources from klips/src to klips/net/ipsec to keep stupid kernel ++ * build scripts happier about symlinks ++ * ++ * Revision 1.8 1998/05/25 20:34:15 rgb ++ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. ++ * ++ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and ++ * add ipsec_rj_walker_delete. ++ * ++ * Recover memory for eroute table on unload of module. ++ * ++ * Revision 1.7 1998/05/21 12:58:58 rgb ++ * Moved 'extern' definitions to ipsec_radij.h to support /proc 3k limit fix. ++ * ++ * Revision 1.6 1998/04/23 20:57:29 rgb ++ * Cleaned up compiler warnings for unused debugging functions. ++ * ++ * Revision 1.5 1998/04/22 16:51:38 rgb ++ * Tidy up radij debug code from recent rash of modifications to debug code. ++ * ++ * Revision 1.4 1998/04/21 21:28:56 rgb ++ * Rearrange debug switches to change on the fly debug output from user ++ * space. Only kernel changes checked in at this time. radij.c was also ++ * changed to temporarily remove buggy debugging code in rj_delete causing ++ * an OOPS and hence, netlink device open errors. ++ * ++ * Revision 1.3 1998/04/14 17:30:37 rgb ++ * Fix up compiling errors for radij tree memory reclamation. ++ * ++ * Revision 1.2 1998/04/12 22:03:25 rgb ++ * Updated ESP-3DES-HMAC-MD5-96, ++ * ESP-DES-HMAC-MD5-96, ++ * AH-HMAC-MD5-96, ++ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository ++ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. ++ * ++ * Fixed eroute references in /proc/net/ipsec*. ++ * ++ * Started to patch module unloading memory leaks in ipsec_netlink and ++ * radij tree unloading. ++ * ++ * Revision 1.1 1998/04/09 03:06:15 henry ++ * sources moved up from linux/net/ipsec ++ * ++ * Revision 1.1.1.1 1998/04/08 05:35:03 henry ++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 ++ * ++ * Revision 0.4 1997/01/15 01:28:15 ji ++ * No changes. ++ * ++ * Revision 0.3 1996/11/20 14:39:04 ji ++ * Minor cleanups. ++ * Rationalized debugging code. ++ * ++ * Revision 0.2 1996/11/02 00:18:33 ji ++ * First limited release. ++ * ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/sysctl_net_ipsec.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,196 @@ ++/* ++ * sysctl interface to net IPSEC subsystem. ++ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * RCSID $Id: sysctl_net_ipsec.c,v 1.16 2004/04/06 02:49:26 mcr Exp $ ++ */ ++ ++/* -*- linux-c -*- ++ * ++ * Initiated April 3, 1998, Richard Guy Briggs <rgb@conscoop.ottawa.on.ca> ++ */ ++ ++#include <linux/mm.h> ++#include <linux/sysctl.h> ++ ++#include "openswan/ipsec_param.h" ++ ++#ifdef CONFIG_SYSCTL ++ ++#define NET_IPSEC 2112 /* Random number */ ++#ifdef CONFIG_IPSEC_DEBUG ++extern int debug_ah; ++extern int debug_esp; ++extern int debug_tunnel; ++extern int debug_eroute; ++extern int debug_spi; ++extern int debug_radij; ++extern int debug_netlink; ++extern int debug_xform; ++extern int debug_rcv; ++extern int debug_pfkey; ++extern int sysctl_ipsec_debug_verbose; ++#ifdef CONFIG_IPSEC_IPCOMP ++extern int sysctl_ipsec_debug_ipcomp; ++#endif /* CONFIG_IPSEC_IPCOMP */ ++#endif /* CONFIG_IPSEC_DEBUG */ ++ ++extern int sysctl_ipsec_icmp; ++extern int sysctl_ipsec_inbound_policy_check; ++extern int sysctl_ipsec_tos; ++int sysctl_ipsec_regress_pfkey_lossage; ++ ++enum { ++#ifdef CONFIG_IPSEC_DEBUG ++ NET_IPSEC_DEBUG_AH=1, ++ NET_IPSEC_DEBUG_ESP=2, ++ NET_IPSEC_DEBUG_TUNNEL=3, ++ NET_IPSEC_DEBUG_EROUTE=4, ++ NET_IPSEC_DEBUG_SPI=5, ++ NET_IPSEC_DEBUG_RADIJ=6, ++ NET_IPSEC_DEBUG_NETLINK=7, ++ NET_IPSEC_DEBUG_XFORM=8, ++ NET_IPSEC_DEBUG_RCV=9, ++ NET_IPSEC_DEBUG_PFKEY=10, ++ NET_IPSEC_DEBUG_VERBOSE=11, ++ NET_IPSEC_DEBUG_IPCOMP=12, ++#endif /* CONFIG_IPSEC_DEBUG */ ++ NET_IPSEC_ICMP=13, ++ NET_IPSEC_INBOUND_POLICY_CHECK=14, ++ NET_IPSEC_TOS=15, ++ NET_IPSEC_REGRESS_PFKEY_LOSSAGE=16, ++}; ++ ++static ctl_table ipsec_table[] = { ++#ifdef CONFIG_IPSEC_DEBUG ++ { NET_IPSEC_DEBUG_AH, "debug_ah", &debug_ah, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_ESP, "debug_esp", &debug_esp, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_TUNNEL, "debug_tunnel", &debug_tunnel, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_EROUTE, "debug_eroute", &debug_eroute, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_SPI, "debug_spi", &debug_spi, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_RADIJ, "debug_radij", &debug_radij, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_NETLINK, "debug_netlink", &debug_netlink, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_XFORM, "debug_xform", &debug_xform, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_RCV, "debug_rcv", &debug_rcv, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_PFKEY, "debug_pfkey", &debug_pfkey, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_DEBUG_VERBOSE, "debug_verbose",&sysctl_ipsec_debug_verbose, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++#ifdef CONFIG_IPSEC_IPCOMP ++ { NET_IPSEC_DEBUG_IPCOMP, "debug_ipcomp", &sysctl_ipsec_debug_ipcomp, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++#endif /* CONFIG_IPSEC_IPCOMP */ ++ ++#ifdef CONFIG_IPSEC_REGRESS ++ { NET_IPSEC_REGRESS_PFKEY_LOSSAGE, "pfkey_lossage", ++ &sysctl_ipsec_regress_pfkey_lossage, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++#endif /* CONFIG_IPSEC_REGRESS */ ++ ++#endif /* CONFIG_IPSEC_DEBUG */ ++ { NET_IPSEC_ICMP, "icmp", &sysctl_ipsec_icmp, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_INBOUND_POLICY_CHECK, "inbound_policy_check", &sysctl_ipsec_inbound_policy_check, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ { NET_IPSEC_TOS, "tos", &sysctl_ipsec_tos, ++ sizeof(int), 0644, NULL, &proc_dointvec}, ++ {0} ++}; ++ ++static ctl_table ipsec_net_table[] = { ++ { NET_IPSEC, "ipsec", NULL, 0, 0555, ipsec_table }, ++ { 0 } ++}; ++ ++static ctl_table ipsec_root_table[] = { ++ { CTL_NET, "net", NULL, 0, 0555, ipsec_net_table }, ++ { 0 } ++}; ++ ++static struct ctl_table_header *ipsec_table_header; ++ ++int ipsec_sysctl_register(void) ++{ ++ ipsec_table_header = register_sysctl_table(ipsec_root_table, 0); ++ if (!ipsec_table_header) { ++ return -ENOMEM; ++ } ++ return 0; ++} ++ ++void ipsec_sysctl_unregister(void) ++{ ++ unregister_sysctl_table(ipsec_table_header); ++} ++ ++#endif /* CONFIG_SYSCTL */ ++ ++/* ++ * $Log: sysctl_net_ipsec.c,v $ ++ * Revision 1.16 2004/04/06 02:49:26 mcr ++ * pullup of algo code from alg-branch. ++ * ++ * Revision 1.15 2002/04/24 07:55:32 mcr ++ * #include patches and Makefiles for post-reorg compilation. ++ * ++ * Revision 1.14 2002/04/24 07:36:35 mcr ++ * Moved from ./klips/net/ipsec/sysctl_net_ipsec.c,v ++ * ++ * Revision 1.13 2002/01/12 02:58:32 mcr ++ * first regression test causes acquire messages to be lost ++ * 100% of the time. This is to help testing of pluto. ++ * ++ * Revision 1.12 2001/06/14 19:35:13 rgb ++ * Update copyright date. ++ * ++ * Revision 1.11 2001/02/26 19:58:13 rgb ++ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs. ++ * ++ * Revision 1.10 2000/09/16 01:50:15 rgb ++ * Protect sysctl_ipsec_debug_ipcomp with compiler defines too so that the ++ * linker won't blame rj_delete() for missing symbols. ;-> Damn statics... ++ * ++ * Revision 1.9 2000/09/15 23:17:51 rgb ++ * Moved stuff around to compile with debug off. ++ * ++ * Revision 1.8 2000/09/15 11:37:02 rgb ++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk> ++ * IPCOMP zlib deflate code. ++ * ++ * Revision 1.7 2000/09/15 07:37:15 rgb ++ * Munged silly log comment that was causing a warning. ++ * ++ * Revision 1.6 2000/09/15 04:58:23 rgb ++ * Added tos runtime switch. ++ * Removed 'sysctl_ipsec_' prefix from /proc/sys/net/ipsec/ filenames. ++ * ++ * Revision 1.5 2000/09/12 03:25:28 rgb ++ * Filled in and implemented sysctl. ++ * ++ * Revision 1.4 1999/04/11 00:29:03 henry ++ * GPL boilerplate ++ * ++ * Revision 1.3 1999/04/06 04:54:29 rgb ++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes ++ * patch shell fixes. ++ * ++ */ +--- /dev/null Tue Mar 11 13:02:56 2003 ++++ linux/net/ipsec/version.c Mon Feb 9 13:51:03 2004 +@@ -0,0 +1,44 @@ ++/* ++ * return IPsec version information ++ * Copyright (C) 2001 Henry Spencer. ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Library General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public ++ * License for more details. ++ * ++ * RCSID $Id: version.in.c,v 1.2 2004/04/14 05:09:46 ken Exp $ ++ */ ++ ++#ifdef __KERNEL__ ++#include <linux/netdevice.h> ++#endif ++ ++#include "openswan.h" ++ ++#define V "cvs2002Mar12_01:19:03" /* substituted in by Makefile */ ++static const char openswan_number[] = V; ++static const char openswan_string[] = "Openswan " V; ++ ++/* ++ - ipsec_version_code - return IPsec version number/code, as string ++ */ ++const char * ++ipsec_version_code() ++{ ++ return openswan_number; ++} ++ ++/* ++ - ipsec_version_string - return full version string ++ */ ++const char * ++ipsec_version_string() ++{ ++ return openswan_string; ++} +RCSID $Id: af_inet.c.fs2_4.patch,v 1.6 2002/04/24 07:36:36 mcr Exp $ +--- linux-old/net/ipv4/af_inet.c.preipsec Wed Apr 26 15:13:17 2000 ++++ linux/net/ipv4/af_inet.c Fri Jun 30 15:01:27 2000 +@@ -1019,6 +1019,17 @@ + ip_mr_init(); + #endif + ++#if defined(CONFIG_IPSEC) ++ { ++ extern /* void */ int ipsec_init(void); ++ /* ++ * Initialise AF_INET ESP and AH protocol support including ++ * e-routing and SA tables ++ */ ++ ipsec_init(); ++ } ++#endif /* CONFIG_IPSEC */ ++ + /* + * Create all the /proc entries. + */ +--- /dev/null Fri May 10 13:59:54 2002 ++++ linux/net/ipsec/Makefile.ver Sun Jul 28 22:10:40 2002 +@@ -0,0 +1 @@ ++IPSECVERSION=cvs2002Mar12_01:19:03 +make[1]: Leaving directory `/data/mtx/oe/tmp/work/openswan-2.2.0-r0/openswan-2.2.0' |