diff -c -w -r -N linux-2.6.16-ng-natt/arch/x86_64/defconfig linux-2.6.16-ng-natt-klips/arch/x86_64/defconfig *** linux-2.6.16-ng-natt/arch/x86_64/defconfig 2006-03-20 00:53:29.000000000 -0500 --- linux-2.6.16-ng-natt-klips/arch/x86_64/defconfig 2008-06-01 17:37:12.000000000 -0400 *************** *** 1348,1350 **** --- 1348,1497 ---- # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set + + # + # RCSID $Id: defconfig,v 1.30 2005/09/15 02:31:12 paul Exp $ + # + + # + # Libreswan 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_KLIPS=m + + # To do tunnel mode IPSec, this must be enabled. + CONFIG_KLIPS_IPIP=y + + # To enable authentication, say 'y'. (Highly recommended) + CONFIG_KLIPS_AH=y + + # Authentication algorithm(s): + CONFIG_KLIPS_AUTH_HMAC_MD5=y + CONFIG_KLIPS_AUTH_HMAC_SHA1=y + + # To enable encryption, say 'y'. (Highly recommended) + CONFIG_KLIPS_ESP=y + + # modular algo extensions (and new ALGOs) + CONFIG_KLIPS_ALG=y + + # Encryption algorithm(s): + CONFIG_KLIPS_ENC_3DES=y + CONFIG_KLIPS_ENC_AES=y + + # Use CryptoAPI for ALG? - by default, no. + CONFIG_KLIPS_ENC_CRYPTOAPI=n + + # IP Compression: new, probably still has minor bugs. + CONFIG_KLIPS_IPCOMP=n + + # To enable userspace-switchable KLIPS debugging, say 'y'. + CONFIG_KLIPS_DEBUG=y + + # + # + # $Log: defconfig,v $ + # Revision 1.30 2005/09/15 02:31:12 paul + # Changed a FreeS/WAN occurance to Libreswan + # + # Revision 1.29 2005/08/24 22:10:05 mcr + # do not list NAT_TRAVERSAL as a default for KLIPS, + # let it live in the packaging "MODULE_DEF_CONFIG" files. + # + # Revision 1.28 2005/05/11 03:15:42 mcr + # adjusted makefiles to sanely build modules properly. + # + # Revision 1.27 2005/03/20 03:00:05 mcr + # default configuration should enable NAT_TRAVERSAL. + # + # Revision 1.26 2004/07/10 19:11:18 mcr + # CONFIG_IPSEC -> CONFIG_KLIPS. + # + # 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 libreswan + # + # 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 + # 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. + # + # diff -c -w -r -N linux-2.6.16-ng-natt/arch/x86_64/defconfig.orig linux-2.6.16-ng-natt-klips/arch/x86_64/defconfig.orig *** linux-2.6.16-ng-natt/arch/x86_64/defconfig.orig 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/arch/x86_64/defconfig.orig 2006-03-20 00:53:29.000000000 -0500 *************** *** 0 **** --- 1,1350 ---- + # + # Automatically generated make config: don't edit + # Linux kernel version: 2.6.16-rc3-git9 + # Sat Feb 18 00:27:03 2006 + # + CONFIG_X86_64=y + CONFIG_64BIT=y + CONFIG_X86=y + CONFIG_SEMAPHORE_SLEEPERS=y + CONFIG_MMU=y + CONFIG_RWSEM_GENERIC_SPINLOCK=y + CONFIG_GENERIC_CALIBRATE_DELAY=y + CONFIG_X86_CMPXCHG=y + CONFIG_EARLY_PRINTK=y + CONFIG_GENERIC_ISA_DMA=y + CONFIG_GENERIC_IOMAP=y + CONFIG_ARCH_MAY_HAVE_PC_FDC=y + CONFIG_DMI=y + + # + # Code maturity level options + # + CONFIG_EXPERIMENTAL=y + CONFIG_LOCK_KERNEL=y + CONFIG_INIT_ENV_ARG_LIMIT=32 + + # + # General setup + # + CONFIG_LOCALVERSION="" + CONFIG_LOCALVERSION_AUTO=y + CONFIG_SWAP=y + CONFIG_SYSVIPC=y + CONFIG_POSIX_MQUEUE=y + # CONFIG_BSD_PROCESS_ACCT is not set + CONFIG_SYSCTL=y + # CONFIG_AUDIT is not set + CONFIG_IKCONFIG=y + CONFIG_IKCONFIG_PROC=y + # CONFIG_CPUSETS is not set + CONFIG_INITRAMFS_SOURCE="" + CONFIG_UID16=y + CONFIG_VM86=y + CONFIG_CC_OPTIMIZE_FOR_SIZE=y + # CONFIG_EMBEDDED is not set + CONFIG_KALLSYMS=y + CONFIG_KALLSYMS_ALL=y + # CONFIG_KALLSYMS_EXTRA_PASS is not set + CONFIG_HOTPLUG=y + CONFIG_PRINTK=y + CONFIG_BUG=y + CONFIG_ELF_CORE=y + CONFIG_BASE_FULL=y + CONFIG_FUTEX=y + CONFIG_EPOLL=y + CONFIG_SHMEM=y + CONFIG_CC_ALIGN_FUNCTIONS=0 + CONFIG_CC_ALIGN_LABELS=0 + CONFIG_CC_ALIGN_LOOPS=0 + CONFIG_CC_ALIGN_JUMPS=0 + CONFIG_SLAB=y + # CONFIG_TINY_SHMEM is not set + CONFIG_BASE_SMALL=0 + # CONFIG_SLOB is not set + + # + # Loadable module support + # + CONFIG_MODULES=y + CONFIG_MODULE_UNLOAD=y + CONFIG_MODULE_FORCE_UNLOAD=y + CONFIG_OBSOLETE_MODPARM=y + # CONFIG_MODVERSIONS is not set + # CONFIG_MODULE_SRCVERSION_ALL is not set + # CONFIG_KMOD is not set + CONFIG_STOP_MACHINE=y + + # + # Block layer + # + CONFIG_LBD=y + + # + # IO Schedulers + # + CONFIG_IOSCHED_NOOP=y + # CONFIG_IOSCHED_AS is not set + CONFIG_IOSCHED_DEADLINE=y + CONFIG_IOSCHED_CFQ=y + # CONFIG_DEFAULT_AS is not set + # CONFIG_DEFAULT_DEADLINE is not set + CONFIG_DEFAULT_CFQ=y + # CONFIG_DEFAULT_NOOP is not set + CONFIG_DEFAULT_IOSCHED="cfq" + + # + # Processor type and features + # + CONFIG_X86_PC=y + # CONFIG_X86_VSMP is not set + # CONFIG_MK8 is not set + # CONFIG_MPSC is not set + CONFIG_GENERIC_CPU=y + CONFIG_X86_L1_CACHE_BYTES=128 + CONFIG_X86_L1_CACHE_SHIFT=7 + CONFIG_X86_TSC=y + CONFIG_X86_GOOD_APIC=y + # CONFIG_MICROCODE is not set + CONFIG_X86_MSR=y + CONFIG_X86_CPUID=y + CONFIG_X86_HT=y + CONFIG_X86_IO_APIC=y + CONFIG_X86_LOCAL_APIC=y + CONFIG_MTRR=y + CONFIG_SMP=y + CONFIG_SCHED_SMT=y + # CONFIG_PREEMPT_NONE is not set + CONFIG_PREEMPT_VOLUNTARY=y + # CONFIG_PREEMPT is not set + CONFIG_PREEMPT_BKL=y + CONFIG_NUMA=y + CONFIG_K8_NUMA=y + CONFIG_X86_64_ACPI_NUMA=y + CONFIG_NUMA_EMU=y + CONFIG_ARCH_DISCONTIGMEM_ENABLE=y + CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y + CONFIG_ARCH_SPARSEMEM_ENABLE=y + CONFIG_SELECT_MEMORY_MODEL=y + # CONFIG_FLATMEM_MANUAL is not set + CONFIG_DISCONTIGMEM_MANUAL=y + # CONFIG_SPARSEMEM_MANUAL is not set + CONFIG_DISCONTIGMEM=y + CONFIG_FLAT_NODE_MEM_MAP=y + CONFIG_NEED_MULTIPLE_NODES=y + # CONFIG_SPARSEMEM_STATIC is not set + CONFIG_SPLIT_PTLOCK_CPUS=4 + CONFIG_MIGRATION=y + CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y + CONFIG_NR_CPUS=32 + CONFIG_HOTPLUG_CPU=y + CONFIG_HPET_TIMER=y + CONFIG_X86_PM_TIMER=y + CONFIG_HPET_EMULATE_RTC=y + CONFIG_GART_IOMMU=y + CONFIG_SWIOTLB=y + CONFIG_X86_MCE=y + CONFIG_X86_MCE_INTEL=y + CONFIG_X86_MCE_AMD=y + # CONFIG_KEXEC is not set + # CONFIG_CRASH_DUMP is not set + CONFIG_PHYSICAL_START=0x100000 + CONFIG_SECCOMP=y + # CONFIG_HZ_100 is not set + CONFIG_HZ_250=y + # CONFIG_HZ_1000 is not set + CONFIG_HZ=250 + CONFIG_GENERIC_HARDIRQS=y + CONFIG_GENERIC_IRQ_PROBE=y + CONFIG_ISA_DMA_API=y + CONFIG_GENERIC_PENDING_IRQ=y + + # + # Power management options + # + CONFIG_PM=y + # CONFIG_PM_LEGACY is not set + # CONFIG_PM_DEBUG is not set + CONFIG_SOFTWARE_SUSPEND=y + CONFIG_PM_STD_PARTITION="" + CONFIG_SUSPEND_SMP=y + + # + # ACPI (Advanced Configuration and Power Interface) Support + # + CONFIG_ACPI=y + CONFIG_ACPI_SLEEP=y + CONFIG_ACPI_SLEEP_PROC_FS=y + CONFIG_ACPI_SLEEP_PROC_SLEEP=y + CONFIG_ACPI_AC=y + CONFIG_ACPI_BATTERY=y + CONFIG_ACPI_BUTTON=y + # CONFIG_ACPI_VIDEO is not set + # CONFIG_ACPI_HOTKEY is not set + CONFIG_ACPI_FAN=y + CONFIG_ACPI_PROCESSOR=y + CONFIG_ACPI_HOTPLUG_CPU=y + CONFIG_ACPI_THERMAL=y + CONFIG_ACPI_NUMA=y + # CONFIG_ACPI_ASUS is not set + # CONFIG_ACPI_IBM is not set + CONFIG_ACPI_TOSHIBA=y + CONFIG_ACPI_BLACKLIST_YEAR=2001 + # CONFIG_ACPI_DEBUG is not set + CONFIG_ACPI_EC=y + CONFIG_ACPI_POWER=y + CONFIG_ACPI_SYSTEM=y + CONFIG_ACPI_CONTAINER=y + + # + # CPU Frequency scaling + # + CONFIG_CPU_FREQ=y + CONFIG_CPU_FREQ_TABLE=y + # CONFIG_CPU_FREQ_DEBUG is not set + CONFIG_CPU_FREQ_STAT=y + # CONFIG_CPU_FREQ_STAT_DETAILS is not set + CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y + # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set + CONFIG_CPU_FREQ_GOV_PERFORMANCE=y + # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set + CONFIG_CPU_FREQ_GOV_USERSPACE=y + CONFIG_CPU_FREQ_GOV_ONDEMAND=y + # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set + + # + # CPUFreq processor drivers + # + CONFIG_X86_POWERNOW_K8=y + CONFIG_X86_POWERNOW_K8_ACPI=y + # CONFIG_X86_SPEEDSTEP_CENTRINO is not set + CONFIG_X86_ACPI_CPUFREQ=y + + # + # shared options + # + CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y + # CONFIG_X86_SPEEDSTEP_LIB is not set + + # + # Bus options (PCI etc.) + # + CONFIG_PCI=y + CONFIG_PCI_DIRECT=y + CONFIG_PCI_MMCONFIG=y + CONFIG_UNORDERED_IO=y + CONFIG_PCIEPORTBUS=y + CONFIG_PCI_MSI=y + # CONFIG_PCI_LEGACY_PROC is not set + # CONFIG_PCI_DEBUG is not set + + # + # PCCARD (PCMCIA/CardBus) support + # + # CONFIG_PCCARD is not set + + # + # PCI Hotplug Support + # + # CONFIG_HOTPLUG_PCI is not set + + # + # Executable file formats / Emulations + # + CONFIG_BINFMT_ELF=y + # CONFIG_BINFMT_MISC is not set + CONFIG_IA32_EMULATION=y + CONFIG_IA32_AOUT=y + CONFIG_COMPAT=y + CONFIG_SYSVIPC_COMPAT=y + + # + # Networking + # + CONFIG_NET=y + + # + # Networking options + # + # CONFIG_NETDEBUG is not set + CONFIG_PACKET=y + # CONFIG_PACKET_MMAP is not set + CONFIG_UNIX=y + # CONFIG_NET_KEY is not set + CONFIG_INET=y + CONFIG_IP_MULTICAST=y + # CONFIG_IP_ADVANCED_ROUTER is not set + CONFIG_IP_FIB_HASH=y + CONFIG_IP_PNP=y + CONFIG_IP_PNP_DHCP=y + # CONFIG_IP_PNP_BOOTP is not set + # CONFIG_IP_PNP_RARP is not set + # CONFIG_NET_IPIP is not set + # CONFIG_NET_IPGRE is not set + # CONFIG_IP_MROUTE is not set + # CONFIG_ARPD is not set + # CONFIG_SYN_COOKIES is not set + # CONFIG_INET_AH is not set + # CONFIG_INET_ESP is not set + # CONFIG_INET_IPCOMP is not set + # CONFIG_INET_TUNNEL is not set + CONFIG_INET_DIAG=y + CONFIG_INET_TCP_DIAG=y + # CONFIG_TCP_CONG_ADVANCED is not set + CONFIG_TCP_CONG_BIC=y + CONFIG_IPV6=y + # CONFIG_IPV6_PRIVACY is not set + # CONFIG_INET6_AH is not set + # CONFIG_INET6_ESP is not set + # CONFIG_INET6_IPCOMP is not set + # CONFIG_INET6_TUNNEL is not set + # CONFIG_IPV6_TUNNEL is not set + # CONFIG_NETFILTER is not set + + # + # DCCP Configuration (EXPERIMENTAL) + # + # CONFIG_IP_DCCP is not set + + # + # SCTP Configuration (EXPERIMENTAL) + # + # CONFIG_IP_SCTP is not set + + # + # TIPC Configuration (EXPERIMENTAL) + # + # CONFIG_TIPC is not set + # CONFIG_ATM is not set + # CONFIG_BRIDGE is not set + # CONFIG_VLAN_8021Q is not set + # CONFIG_DECNET is not set + # CONFIG_LLC2 is not set + # CONFIG_IPX is not set + # CONFIG_ATALK is not set + # CONFIG_X25 is not set + # CONFIG_LAPB is not set + # CONFIG_NET_DIVERT is not set + # CONFIG_ECONET is not set + # CONFIG_WAN_ROUTER is not set + + # + # QoS and/or fair queueing + # + # CONFIG_NET_SCHED is not set + + # + # Network testing + # + # CONFIG_NET_PKTGEN is not set + # CONFIG_HAMRADIO is not set + # CONFIG_IRDA is not set + # CONFIG_BT is not set + # CONFIG_IEEE80211 is not set + + # + # Device Drivers + # + + # + # Generic Driver Options + # + CONFIG_STANDALONE=y + CONFIG_PREVENT_FIRMWARE_BUILD=y + CONFIG_FW_LOADER=y + # CONFIG_DEBUG_DRIVER is not set + + # + # Connector - unified userspace <-> kernelspace linker + # + # CONFIG_CONNECTOR is not set + + # + # Memory Technology Devices (MTD) + # + # CONFIG_MTD is not set + + # + # Parallel port support + # + # CONFIG_PARPORT is not set + + # + # Plug and Play support + # + # CONFIG_PNP is not set + + # + # Block devices + # + CONFIG_BLK_DEV_FD=y + # CONFIG_BLK_CPQ_DA is not set + # CONFIG_BLK_CPQ_CISS_DA is not set + # CONFIG_BLK_DEV_DAC960 is not set + # CONFIG_BLK_DEV_UMEM is not set + # CONFIG_BLK_DEV_COW_COMMON is not set + CONFIG_BLK_DEV_LOOP=y + # CONFIG_BLK_DEV_CRYPTOLOOP is not set + # CONFIG_BLK_DEV_NBD is not set + # CONFIG_BLK_DEV_SX8 is not set + # CONFIG_BLK_DEV_UB is not set + CONFIG_BLK_DEV_RAM=y + CONFIG_BLK_DEV_RAM_COUNT=16 + CONFIG_BLK_DEV_RAM_SIZE=4096 + CONFIG_BLK_DEV_INITRD=y + # CONFIG_CDROM_PKTCDVD is not set + # CONFIG_ATA_OVER_ETH is not set + + # + # ATA/ATAPI/MFM/RLL support + # + CONFIG_IDE=y + CONFIG_BLK_DEV_IDE=y + + # + # Please see Documentation/ide.txt for help/info on IDE drives + # + # CONFIG_BLK_DEV_IDE_SATA is not set + # CONFIG_BLK_DEV_HD_IDE is not set + CONFIG_BLK_DEV_IDEDISK=y + CONFIG_IDEDISK_MULTI_MODE=y + CONFIG_BLK_DEV_IDECD=y + # CONFIG_BLK_DEV_IDETAPE is not set + # CONFIG_BLK_DEV_IDEFLOPPY is not set + # CONFIG_BLK_DEV_IDESCSI is not set + # CONFIG_IDE_TASK_IOCTL is not set + + # + # IDE chipset support/bugfixes + # + CONFIG_IDE_GENERIC=y + # CONFIG_BLK_DEV_CMD640 is not set + CONFIG_BLK_DEV_IDEPCI=y + # CONFIG_IDEPCI_SHARE_IRQ is not set + # CONFIG_BLK_DEV_OFFBOARD is not set + # CONFIG_BLK_DEV_GENERIC is not set + # CONFIG_BLK_DEV_OPTI621 is not set + # CONFIG_BLK_DEV_RZ1000 is not set + CONFIG_BLK_DEV_IDEDMA_PCI=y + # CONFIG_BLK_DEV_IDEDMA_FORCED is not set + CONFIG_IDEDMA_PCI_AUTO=y + # CONFIG_IDEDMA_ONLYDISK is not set + # CONFIG_BLK_DEV_AEC62XX is not set + # CONFIG_BLK_DEV_ALI15X3 is not set + CONFIG_BLK_DEV_AMD74XX=y + CONFIG_BLK_DEV_ATIIXP=y + # CONFIG_BLK_DEV_CMD64X is not set + # CONFIG_BLK_DEV_TRIFLEX is not set + # CONFIG_BLK_DEV_CY82C693 is not set + # CONFIG_BLK_DEV_CS5520 is not set + # CONFIG_BLK_DEV_CS5530 is not set + # CONFIG_BLK_DEV_HPT34X is not set + # CONFIG_BLK_DEV_HPT366 is not set + # CONFIG_BLK_DEV_SC1200 is not set + CONFIG_BLK_DEV_PIIX=y + # CONFIG_BLK_DEV_IT821X is not set + # CONFIG_BLK_DEV_NS87415 is not set + # CONFIG_BLK_DEV_PDC202XX_OLD is not set + CONFIG_BLK_DEV_PDC202XX_NEW=y + # CONFIG_BLK_DEV_SVWKS is not set + # CONFIG_BLK_DEV_SIIMAGE is not set + # CONFIG_BLK_DEV_SIS5513 is not set + # CONFIG_BLK_DEV_SLC90E66 is not set + # CONFIG_BLK_DEV_TRM290 is not set + # CONFIG_BLK_DEV_VIA82CXXX is not set + # CONFIG_IDE_ARM is not set + CONFIG_BLK_DEV_IDEDMA=y + # CONFIG_IDEDMA_IVB is not set + CONFIG_IDEDMA_AUTO=y + # CONFIG_BLK_DEV_HD is not set + + # + # SCSI device support + # + # CONFIG_RAID_ATTRS is not set + CONFIG_SCSI=y + # CONFIG_SCSI_PROC_FS is not set + + # + # SCSI support type (disk, tape, CD-ROM) + # + CONFIG_BLK_DEV_SD=y + # CONFIG_CHR_DEV_ST is not set + # CONFIG_CHR_DEV_OSST is not set + # CONFIG_BLK_DEV_SR is not set + # CONFIG_CHR_DEV_SG is not set + # CONFIG_CHR_DEV_SCH is not set + + # + # Some SCSI devices (e.g. CD jukebox) support multiple LUNs + # + # CONFIG_SCSI_MULTI_LUN is not set + CONFIG_SCSI_CONSTANTS=y + # CONFIG_SCSI_LOGGING is not set + + # + # SCSI Transport Attributes + # + CONFIG_SCSI_SPI_ATTRS=y + CONFIG_SCSI_FC_ATTRS=y + # CONFIG_SCSI_ISCSI_ATTRS is not set + # CONFIG_SCSI_SAS_ATTRS is not set + + # + # SCSI low-level drivers + # + # CONFIG_ISCSI_TCP is not set + # CONFIG_BLK_DEV_3W_XXXX_RAID is not set + # CONFIG_SCSI_3W_9XXX is not set + # CONFIG_SCSI_ACARD is not set + # CONFIG_SCSI_AACRAID is not set + # CONFIG_SCSI_AIC7XXX is not set + # CONFIG_SCSI_AIC7XXX_OLD is not set + CONFIG_SCSI_AIC79XX=y + CONFIG_AIC79XX_CMDS_PER_DEVICE=32 + CONFIG_AIC79XX_RESET_DELAY_MS=4000 + # CONFIG_AIC79XX_ENABLE_RD_STRM is not set + # CONFIG_AIC79XX_DEBUG_ENABLE is not set + CONFIG_AIC79XX_DEBUG_MASK=0 + # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set + CONFIG_MEGARAID_NEWGEN=y + CONFIG_MEGARAID_MM=y + CONFIG_MEGARAID_MAILBOX=y + # CONFIG_MEGARAID_LEGACY is not set + CONFIG_MEGARAID_SAS=y + CONFIG_SCSI_SATA=y + CONFIG_SCSI_SATA_AHCI=y + # CONFIG_SCSI_SATA_SVW is not set + CONFIG_SCSI_ATA_PIIX=y + # CONFIG_SCSI_SATA_MV is not set + CONFIG_SCSI_SATA_NV=y + # CONFIG_SCSI_PDC_ADMA is not set + # CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + CONFIG_SCSI_SATA_SIL=y + # CONFIG_SCSI_SATA_SIL24 is not set + # CONFIG_SCSI_SATA_SIS is not set + # CONFIG_SCSI_SATA_ULI is not set + CONFIG_SCSI_SATA_VIA=y + # CONFIG_SCSI_SATA_VITESSE is not set + CONFIG_SCSI_SATA_INTEL_COMBINED=y + # CONFIG_SCSI_BUSLOGIC is not set + # CONFIG_SCSI_DMX3191D is not set + # CONFIG_SCSI_EATA is not set + # CONFIG_SCSI_FUTURE_DOMAIN is not set + # CONFIG_SCSI_GDTH is not set + # CONFIG_SCSI_IPS is not set + # CONFIG_SCSI_INITIO is not set + # CONFIG_SCSI_INIA100 is not set + # CONFIG_SCSI_SYM53C8XX_2 is not set + # CONFIG_SCSI_IPR is not set + # CONFIG_SCSI_QLOGIC_FC is not set + # CONFIG_SCSI_QLOGIC_1280 is not set + # CONFIG_SCSI_QLA_FC is not set + # CONFIG_SCSI_LPFC is not set + # CONFIG_SCSI_DC395x is not set + # CONFIG_SCSI_DC390T is not set + # CONFIG_SCSI_DEBUG is not set + + # + # Multi-device support (RAID and LVM) + # + CONFIG_MD=y + # CONFIG_BLK_DEV_MD is not set + CONFIG_BLK_DEV_DM=y + # CONFIG_DM_CRYPT is not set + # CONFIG_DM_SNAPSHOT is not set + # CONFIG_DM_MIRROR is not set + # CONFIG_DM_ZERO is not set + # CONFIG_DM_MULTIPATH is not set + + # + # Fusion MPT device support + # + CONFIG_FUSION=y + CONFIG_FUSION_SPI=y + # CONFIG_FUSION_FC is not set + # CONFIG_FUSION_SAS is not set + CONFIG_FUSION_MAX_SGE=128 + # CONFIG_FUSION_CTL is not set + + # + # IEEE 1394 (FireWire) support + # + CONFIG_IEEE1394=y + + # + # Subsystem Options + # + # CONFIG_IEEE1394_VERBOSEDEBUG is not set + # CONFIG_IEEE1394_OUI_DB is not set + # CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set + # CONFIG_IEEE1394_EXPORT_FULL_API is not set + + # + # Device Drivers + # + + # + # Texas Instruments PCILynx requires I2C + # + CONFIG_IEEE1394_OHCI1394=y + + # + # Protocol Drivers + # + # CONFIG_IEEE1394_VIDEO1394 is not set + # CONFIG_IEEE1394_SBP2 is not set + # CONFIG_IEEE1394_ETH1394 is not set + # CONFIG_IEEE1394_DV1394 is not set + CONFIG_IEEE1394_RAWIO=y + + # + # I2O device support + # + # CONFIG_I2O is not set + + # + # Network device support + # + CONFIG_NETDEVICES=y + # CONFIG_DUMMY is not set + # CONFIG_BONDING is not set + # CONFIG_EQUALIZER is not set + CONFIG_TUN=y + + # + # ARCnet devices + # + # CONFIG_ARCNET is not set + + # + # PHY device support + # + # CONFIG_PHYLIB is not set + + # + # Ethernet (10 or 100Mbit) + # + CONFIG_NET_ETHERNET=y + CONFIG_MII=y + # CONFIG_HAPPYMEAL is not set + # CONFIG_SUNGEM is not set + # CONFIG_CASSINI is not set + CONFIG_NET_VENDOR_3COM=y + CONFIG_VORTEX=y + # CONFIG_TYPHOON is not set + + # + # Tulip family network device support + # + # CONFIG_NET_TULIP is not set + # CONFIG_HP100 is not set + CONFIG_NET_PCI=y + # CONFIG_PCNET32 is not set + # CONFIG_AMD8111_ETH is not set + # CONFIG_ADAPTEC_STARFIRE is not set + # CONFIG_B44 is not set + CONFIG_FORCEDETH=y + # CONFIG_DGRS is not set + # CONFIG_EEPRO100 is not set + CONFIG_E100=y + # CONFIG_FEALNX is not set + # CONFIG_NATSEMI is not set + # CONFIG_NE2K_PCI is not set + CONFIG_8139CP=y + CONFIG_8139TOO=y + # CONFIG_8139TOO_PIO is not set + # CONFIG_8139TOO_TUNE_TWISTER is not set + # CONFIG_8139TOO_8129 is not set + # CONFIG_8139_OLD_RX_RESET is not set + # CONFIG_SIS900 is not set + # CONFIG_EPIC100 is not set + # CONFIG_SUNDANCE is not set + # CONFIG_VIA_RHINE is not set + + # + # Ethernet (1000 Mbit) + # + # CONFIG_ACENIC is not set + # CONFIG_DL2K is not set + CONFIG_E1000=y + # CONFIG_E1000_NAPI is not set + # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set + # CONFIG_NS83820 is not set + # CONFIG_HAMACHI is not set + # CONFIG_YELLOWFIN is not set + # CONFIG_R8169 is not set + # CONFIG_SIS190 is not set + # CONFIG_SKGE is not set + # CONFIG_SKY2 is not set + # CONFIG_SK98LIN is not set + # CONFIG_VIA_VELOCITY is not set + CONFIG_TIGON3=y + # CONFIG_BNX2 is not set + + # + # Ethernet (10000 Mbit) + # + # CONFIG_CHELSIO_T1 is not set + # CONFIG_IXGB is not set + CONFIG_S2IO=m + # CONFIG_S2IO_NAPI is not set + + # + # Token Ring devices + # + # CONFIG_TR is not set + + # + # Wireless LAN (non-hamradio) + # + # CONFIG_NET_RADIO is not set + + # + # Wan interfaces + # + # CONFIG_WAN is not set + # CONFIG_FDDI is not set + # CONFIG_HIPPI is not set + # CONFIG_PPP is not set + # CONFIG_SLIP is not set + # CONFIG_NET_FC is not set + # CONFIG_SHAPER is not set + CONFIG_NETCONSOLE=y + CONFIG_NETPOLL=y + # CONFIG_NETPOLL_RX is not set + # CONFIG_NETPOLL_TRAP is not set + CONFIG_NET_POLL_CONTROLLER=y + + # + # ISDN subsystem + # + # CONFIG_ISDN is not set + + # + # Telephony Support + # + # CONFIG_PHONE is not set + + # + # Input device support + # + CONFIG_INPUT=y + + # + # Userland interfaces + # + CONFIG_INPUT_MOUSEDEV=y + CONFIG_INPUT_MOUSEDEV_PSAUX=y + CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 + CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 + # CONFIG_INPUT_JOYDEV is not set + # CONFIG_INPUT_TSDEV is not set + CONFIG_INPUT_EVDEV=y + # CONFIG_INPUT_EVBUG is not set + + # + # Input Device Drivers + # + CONFIG_INPUT_KEYBOARD=y + CONFIG_KEYBOARD_ATKBD=y + # CONFIG_KEYBOARD_SUNKBD is not set + # CONFIG_KEYBOARD_LKKBD is not set + # CONFIG_KEYBOARD_XTKBD is not set + # CONFIG_KEYBOARD_NEWTON is not set + CONFIG_INPUT_MOUSE=y + CONFIG_MOUSE_PS2=y + # CONFIG_MOUSE_SERIAL is not set + # CONFIG_MOUSE_VSXXXAA is not set + # CONFIG_INPUT_JOYSTICK is not set + # CONFIG_INPUT_TOUCHSCREEN is not set + # CONFIG_INPUT_MISC is not set + + # + # Hardware I/O ports + # + CONFIG_SERIO=y + CONFIG_SERIO_I8042=y + # CONFIG_SERIO_SERPORT is not set + # CONFIG_SERIO_CT82C710 is not set + # CONFIG_SERIO_PCIPS2 is not set + CONFIG_SERIO_LIBPS2=y + # CONFIG_SERIO_RAW is not set + # CONFIG_GAMEPORT is not set + + # + # Character devices + # + CONFIG_VT=y + CONFIG_VT_CONSOLE=y + CONFIG_HW_CONSOLE=y + # CONFIG_SERIAL_NONSTANDARD is not set + + # + # Serial drivers + # + CONFIG_SERIAL_8250=y + CONFIG_SERIAL_8250_CONSOLE=y + # CONFIG_SERIAL_8250_ACPI is not set + CONFIG_SERIAL_8250_NR_UARTS=4 + CONFIG_SERIAL_8250_RUNTIME_UARTS=4 + # CONFIG_SERIAL_8250_EXTENDED is not set + + # + # Non-8250 serial port support + # + CONFIG_SERIAL_CORE=y + CONFIG_SERIAL_CORE_CONSOLE=y + # CONFIG_SERIAL_JSM is not set + CONFIG_UNIX98_PTYS=y + CONFIG_LEGACY_PTYS=y + CONFIG_LEGACY_PTY_COUNT=256 + + # + # IPMI + # + # CONFIG_IPMI_HANDLER is not set + + # + # Watchdog Cards + # + CONFIG_WATCHDOG=y + # CONFIG_WATCHDOG_NOWAYOUT is not set + + # + # Watchdog Device Drivers + # + CONFIG_SOFT_WATCHDOG=y + # CONFIG_ACQUIRE_WDT is not set + # CONFIG_ADVANTECH_WDT is not set + # CONFIG_ALIM1535_WDT is not set + # CONFIG_ALIM7101_WDT is not set + # CONFIG_SC520_WDT is not set + # CONFIG_EUROTECH_WDT is not set + # CONFIG_IB700_WDT is not set + # CONFIG_IBMASR is not set + # CONFIG_WAFER_WDT is not set + # CONFIG_I6300ESB_WDT is not set + # CONFIG_I8XX_TCO is not set + # CONFIG_SC1200_WDT is not set + # CONFIG_60XX_WDT is not set + # CONFIG_SBC8360_WDT is not set + # CONFIG_CPU5_WDT is not set + # CONFIG_W83627HF_WDT is not set + # CONFIG_W83877F_WDT is not set + # CONFIG_W83977F_WDT is not set + # CONFIG_MACHZ_WDT is not set + # CONFIG_SBC_EPX_C3_WATCHDOG is not set + + # + # PCI-based Watchdog Cards + # + # CONFIG_PCIPCWATCHDOG is not set + # CONFIG_WDTPCI is not set + + # + # USB-based Watchdog Cards + # + # CONFIG_USBPCWATCHDOG is not set + CONFIG_HW_RANDOM=y + # CONFIG_NVRAM is not set + CONFIG_RTC=y + # CONFIG_DTLK is not set + # CONFIG_R3964 is not set + # CONFIG_APPLICOM is not set + + # + # Ftape, the floppy tape device driver + # + CONFIG_AGP=y + CONFIG_AGP_AMD64=y + CONFIG_AGP_INTEL=y + # CONFIG_DRM is not set + # CONFIG_MWAVE is not set + CONFIG_RAW_DRIVER=y + CONFIG_MAX_RAW_DEVS=256 + CONFIG_HPET=y + # CONFIG_HPET_RTC_IRQ is not set + CONFIG_HPET_MMAP=y + # CONFIG_HANGCHECK_TIMER is not set + + # + # TPM devices + # + # CONFIG_TCG_TPM is not set + # CONFIG_TELCLOCK is not set + + # + # I2C support + # + # CONFIG_I2C is not set + + # + # SPI support + # + # CONFIG_SPI is not set + # CONFIG_SPI_MASTER is not set + + # + # Dallas's 1-wire bus + # + # CONFIG_W1 is not set + + # + # Hardware Monitoring support + # + CONFIG_HWMON=y + # CONFIG_HWMON_VID is not set + # CONFIG_SENSORS_F71805F is not set + # CONFIG_SENSORS_HDAPS is not set + # CONFIG_HWMON_DEBUG_CHIP is not set + + # + # Misc devices + # + # CONFIG_IBM_ASM is not set + + # + # Multimedia Capabilities Port drivers + # + + # + # Multimedia devices + # + # CONFIG_VIDEO_DEV is not set + + # + # Digital Video Broadcasting Devices + # + # CONFIG_DVB is not set + + # + # Graphics support + # + # CONFIG_FB is not set + CONFIG_VIDEO_SELECT=y + + # + # Console display driver support + # + CONFIG_VGA_CONSOLE=y + CONFIG_DUMMY_CONSOLE=y + + # + # Sound + # + CONFIG_SOUND=y + + # + # Advanced Linux Sound Architecture + # + # CONFIG_SND is not set + + # + # Open Sound System + # + CONFIG_SOUND_PRIME=y + CONFIG_OBSOLETE_OSS_DRIVER=y + # CONFIG_SOUND_BT878 is not set + # CONFIG_SOUND_CMPCI is not set + # CONFIG_SOUND_EMU10K1 is not set + # CONFIG_SOUND_FUSION is not set + # CONFIG_SOUND_CS4281 is not set + # CONFIG_SOUND_ES1370 is not set + # CONFIG_SOUND_ES1371 is not set + # CONFIG_SOUND_ESSSOLO1 is not set + # CONFIG_SOUND_MAESTRO is not set + # CONFIG_SOUND_MAESTRO3 is not set + CONFIG_SOUND_ICH=y + # CONFIG_SOUND_SONICVIBES is not set + # CONFIG_SOUND_TRIDENT is not set + # CONFIG_SOUND_MSNDCLAS is not set + # CONFIG_SOUND_MSNDPIN is not set + # CONFIG_SOUND_VIA82CXXX is not set + # CONFIG_SOUND_OSS is not set + # CONFIG_SOUND_ALI5455 is not set + # CONFIG_SOUND_FORTE is not set + # CONFIG_SOUND_RME96XX is not set + # CONFIG_SOUND_AD1980 is not set + + # + # USB support + # + CONFIG_USB_ARCH_HAS_HCD=y + CONFIG_USB_ARCH_HAS_OHCI=y + CONFIG_USB=y + # CONFIG_USB_DEBUG is not set + + # + # Miscellaneous USB options + # + CONFIG_USB_DEVICEFS=y + # CONFIG_USB_BANDWIDTH is not set + # CONFIG_USB_DYNAMIC_MINORS is not set + # CONFIG_USB_SUSPEND is not set + # CONFIG_USB_OTG is not set + + # + # USB Host Controller Drivers + # + CONFIG_USB_EHCI_HCD=y + # CONFIG_USB_EHCI_SPLIT_ISO is not set + # CONFIG_USB_EHCI_ROOT_HUB_TT is not set + # CONFIG_USB_ISP116X_HCD is not set + CONFIG_USB_OHCI_HCD=y + # CONFIG_USB_OHCI_BIG_ENDIAN is not set + CONFIG_USB_OHCI_LITTLE_ENDIAN=y + CONFIG_USB_UHCI_HCD=y + # CONFIG_USB_SL811_HCD is not set + + # + # USB Device Class drivers + # + # CONFIG_OBSOLETE_OSS_USB_DRIVER is not set + # CONFIG_USB_ACM is not set + CONFIG_USB_PRINTER=y + + # + # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' + # + + # + # may also be needed; see USB_STORAGE Help for more information + # + CONFIG_USB_STORAGE=y + # CONFIG_USB_STORAGE_DEBUG is not set + # CONFIG_USB_STORAGE_DATAFAB is not set + # CONFIG_USB_STORAGE_FREECOM is not set + # CONFIG_USB_STORAGE_ISD200 is not set + # CONFIG_USB_STORAGE_DPCM is not set + # CONFIG_USB_STORAGE_USBAT is not set + # CONFIG_USB_STORAGE_SDDR09 is not set + # CONFIG_USB_STORAGE_SDDR55 is not set + # CONFIG_USB_STORAGE_JUMPSHOT is not set + # CONFIG_USB_STORAGE_ALAUDA is not set + # CONFIG_USB_LIBUSUAL is not set + + # + # USB Input Devices + # + CONFIG_USB_HID=y + CONFIG_USB_HIDINPUT=y + # CONFIG_USB_HIDINPUT_POWERBOOK is not set + # CONFIG_HID_FF is not set + # CONFIG_USB_HIDDEV is not set + # CONFIG_USB_AIPTEK is not set + # CONFIG_USB_WACOM is not set + # CONFIG_USB_ACECAD is not set + # CONFIG_USB_KBTAB is not set + # CONFIG_USB_POWERMATE is not set + # CONFIG_USB_MTOUCH is not set + # CONFIG_USB_ITMTOUCH is not set + # CONFIG_USB_EGALAX is not set + # CONFIG_USB_YEALINK is not set + # CONFIG_USB_XPAD is not set + # CONFIG_USB_ATI_REMOTE is not set + # CONFIG_USB_ATI_REMOTE2 is not set + # CONFIG_USB_KEYSPAN_REMOTE is not set + # CONFIG_USB_APPLETOUCH is not set + + # + # USB Imaging devices + # + # CONFIG_USB_MDC800 is not set + # CONFIG_USB_MICROTEK is not set + + # + # USB Multimedia devices + # + # CONFIG_USB_DABUSB is not set + + # + # Video4Linux support is needed for USB Multimedia device support + # + + # + # USB Network Adapters + # + # CONFIG_USB_CATC is not set + # CONFIG_USB_KAWETH is not set + # CONFIG_USB_PEGASUS is not set + # CONFIG_USB_RTL8150 is not set + # CONFIG_USB_USBNET is not set + CONFIG_USB_MON=y + + # + # USB port drivers + # + + # + # USB Serial Converter support + # + # CONFIG_USB_SERIAL is not set + + # + # USB Miscellaneous drivers + # + # CONFIG_USB_EMI62 is not set + # CONFIG_USB_EMI26 is not set + # CONFIG_USB_AUERSWALD is not set + # CONFIG_USB_RIO500 is not set + # CONFIG_USB_LEGOTOWER is not set + # CONFIG_USB_LCD is not set + # CONFIG_USB_LED is not set + # CONFIG_USB_CYTHERM is not set + # CONFIG_USB_PHIDGETKIT is not set + # CONFIG_USB_PHIDGETSERVO is not set + # CONFIG_USB_IDMOUSE is not set + # CONFIG_USB_SISUSBVGA is not set + # CONFIG_USB_LD is not set + # CONFIG_USB_TEST is not set + + # + # USB DSL modem support + # + + # + # USB Gadget Support + # + # CONFIG_USB_GADGET is not set + + # + # MMC/SD Card support + # + # CONFIG_MMC is not set + + # + # InfiniBand support + # + # CONFIG_INFINIBAND is not set + + # + # SN Devices + # + + # + # EDAC - error detection and reporting (RAS) + # + # CONFIG_EDAC is not set + + # + # Firmware Drivers + # + # CONFIG_EDD is not set + # CONFIG_DELL_RBU is not set + # CONFIG_DCDBAS is not set + + # + # File systems + # + CONFIG_EXT2_FS=y + CONFIG_EXT2_FS_XATTR=y + CONFIG_EXT2_FS_POSIX_ACL=y + # CONFIG_EXT2_FS_SECURITY is not set + # CONFIG_EXT2_FS_XIP is not set + CONFIG_EXT3_FS=y + CONFIG_EXT3_FS_XATTR=y + CONFIG_EXT3_FS_POSIX_ACL=y + # CONFIG_EXT3_FS_SECURITY is not set + CONFIG_JBD=y + # CONFIG_JBD_DEBUG is not set + CONFIG_FS_MBCACHE=y + CONFIG_REISERFS_FS=y + # CONFIG_REISERFS_CHECK is not set + # CONFIG_REISERFS_PROC_INFO is not set + CONFIG_REISERFS_FS_XATTR=y + CONFIG_REISERFS_FS_POSIX_ACL=y + # CONFIG_REISERFS_FS_SECURITY is not set + # CONFIG_JFS_FS is not set + CONFIG_FS_POSIX_ACL=y + # CONFIG_XFS_FS is not set + # CONFIG_OCFS2_FS is not set + # CONFIG_MINIX_FS is not set + # CONFIG_ROMFS_FS is not set + CONFIG_INOTIFY=y + # CONFIG_QUOTA is not set + CONFIG_DNOTIFY=y + CONFIG_AUTOFS_FS=y + CONFIG_AUTOFS4_FS=y + # CONFIG_FUSE_FS is not set + + # + # CD-ROM/DVD Filesystems + # + CONFIG_ISO9660_FS=y + CONFIG_JOLIET=y + # CONFIG_ZISOFS is not set + # CONFIG_UDF_FS is not set + + # + # DOS/FAT/NT Filesystems + # + CONFIG_FAT_FS=y + CONFIG_MSDOS_FS=y + CONFIG_VFAT_FS=y + CONFIG_FAT_DEFAULT_CODEPAGE=437 + CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" + # CONFIG_NTFS_FS is not set + + # + # Pseudo filesystems + # + CONFIG_PROC_FS=y + CONFIG_PROC_KCORE=y + CONFIG_SYSFS=y + CONFIG_TMPFS=y + CONFIG_HUGETLBFS=y + CONFIG_HUGETLB_PAGE=y + CONFIG_RAMFS=y + CONFIG_RELAYFS_FS=y + # CONFIG_CONFIGFS_FS is not set + + # + # Miscellaneous filesystems + # + # CONFIG_ADFS_FS is not set + # CONFIG_AFFS_FS is not set + # CONFIG_HFS_FS is not set + # CONFIG_HFSPLUS_FS is not set + # CONFIG_BEFS_FS is not set + # CONFIG_BFS_FS is not set + # CONFIG_EFS_FS is not set + # CONFIG_CRAMFS is not set + # CONFIG_VXFS_FS is not set + # CONFIG_HPFS_FS is not set + # CONFIG_QNX4FS_FS is not set + # CONFIG_SYSV_FS is not set + # CONFIG_UFS_FS is not set + + # + # Network File Systems + # + CONFIG_NFS_FS=y + CONFIG_NFS_V3=y + # CONFIG_NFS_V3_ACL is not set + # CONFIG_NFS_V4 is not set + # CONFIG_NFS_DIRECTIO is not set + CONFIG_NFSD=y + CONFIG_NFSD_V3=y + # CONFIG_NFSD_V3_ACL is not set + # CONFIG_NFSD_V4 is not set + CONFIG_NFSD_TCP=y + CONFIG_ROOT_NFS=y + CONFIG_LOCKD=y + CONFIG_LOCKD_V4=y + CONFIG_EXPORTFS=y + CONFIG_NFS_COMMON=y + CONFIG_SUNRPC=y + # CONFIG_RPCSEC_GSS_KRB5 is not set + # CONFIG_RPCSEC_GSS_SPKM3 is not set + # CONFIG_SMB_FS is not set + # CONFIG_CIFS is not set + # CONFIG_NCP_FS is not set + # CONFIG_CODA_FS is not set + # CONFIG_AFS_FS is not set + # CONFIG_9P_FS is not set + + # + # Partition Types + # + # CONFIG_PARTITION_ADVANCED is not set + CONFIG_MSDOS_PARTITION=y + + # + # Native Language Support + # + CONFIG_NLS=y + CONFIG_NLS_DEFAULT="iso8859-1" + CONFIG_NLS_CODEPAGE_437=y + # CONFIG_NLS_CODEPAGE_737 is not set + # CONFIG_NLS_CODEPAGE_775 is not set + # CONFIG_NLS_CODEPAGE_850 is not set + # CONFIG_NLS_CODEPAGE_852 is not set + # CONFIG_NLS_CODEPAGE_855 is not set + # CONFIG_NLS_CODEPAGE_857 is not set + # CONFIG_NLS_CODEPAGE_860 is not set + # CONFIG_NLS_CODEPAGE_861 is not set + # CONFIG_NLS_CODEPAGE_862 is not set + # CONFIG_NLS_CODEPAGE_863 is not set + # CONFIG_NLS_CODEPAGE_864 is not set + # CONFIG_NLS_CODEPAGE_865 is not set + # CONFIG_NLS_CODEPAGE_866 is not set + # CONFIG_NLS_CODEPAGE_869 is not set + # CONFIG_NLS_CODEPAGE_936 is not set + # CONFIG_NLS_CODEPAGE_950 is not set + # CONFIG_NLS_CODEPAGE_932 is not set + # CONFIG_NLS_CODEPAGE_949 is not set + # CONFIG_NLS_CODEPAGE_874 is not set + # CONFIG_NLS_ISO8859_8 is not set + # CONFIG_NLS_CODEPAGE_1250 is not set + # CONFIG_NLS_CODEPAGE_1251 is not set + CONFIG_NLS_ASCII=y + CONFIG_NLS_ISO8859_1=y + # CONFIG_NLS_ISO8859_2 is not set + # CONFIG_NLS_ISO8859_3 is not set + # CONFIG_NLS_ISO8859_4 is not set + # CONFIG_NLS_ISO8859_5 is not set + # CONFIG_NLS_ISO8859_6 is not set + # CONFIG_NLS_ISO8859_7 is not set + # CONFIG_NLS_ISO8859_9 is not set + # CONFIG_NLS_ISO8859_13 is not set + # CONFIG_NLS_ISO8859_14 is not set + CONFIG_NLS_ISO8859_15=y + # CONFIG_NLS_KOI8_R is not set + # CONFIG_NLS_KOI8_U is not set + CONFIG_NLS_UTF8=y + + # + # Instrumentation Support + # + CONFIG_PROFILING=y + CONFIG_OPROFILE=y + CONFIG_KPROBES=y + + # + # Kernel hacking + # + # CONFIG_PRINTK_TIME is not set + CONFIG_MAGIC_SYSRQ=y + CONFIG_DEBUG_KERNEL=y + CONFIG_LOG_BUF_SHIFT=18 + CONFIG_DETECT_SOFTLOCKUP=y + # CONFIG_SCHEDSTATS is not set + # CONFIG_DEBUG_SLAB is not set + # CONFIG_DEBUG_MUTEXES is not set + # CONFIG_DEBUG_SPINLOCK is not set + # CONFIG_DEBUG_SPINLOCK_SLEEP is not set + # CONFIG_DEBUG_KOBJECT is not set + # CONFIG_DEBUG_INFO is not set + CONFIG_DEBUG_FS=y + # CONFIG_DEBUG_VM is not set + # CONFIG_FRAME_POINTER is not set + # CONFIG_FORCED_INLINING is not set + # CONFIG_RCU_TORTURE_TEST is not set + # CONFIG_DEBUG_RODATA is not set + # CONFIG_IOMMU_DEBUG is not set + + # + # Security options + # + # CONFIG_KEYS is not set + # CONFIG_SECURITY is not set + + # + # Cryptographic options + # + # CONFIG_CRYPTO is not set + + # + # Hardware crypto devices + # + + # + # Library routines + # + # CONFIG_CRC_CCITT is not set + # CONFIG_CRC16 is not set + CONFIG_CRC32=y + # CONFIG_LIBCRC32C is not set diff -c -w -r -N linux-2.6.16-ng-natt/.config linux-2.6.16-ng-natt-klips/.config *** linux-2.6.16-ng-natt/.config 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/.config 2008-06-01 17:37:12.000000000 -0400 *************** *** 0 **** --- 1,147 ---- + + # + # RCSID $Id: defconfig,v 1.30 2005/09/15 02:31:12 paul Exp $ + # + + # + # Libreswan 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_KLIPS=m + + # To do tunnel mode IPSec, this must be enabled. + CONFIG_KLIPS_IPIP=y + + # To enable authentication, say 'y'. (Highly recommended) + CONFIG_KLIPS_AH=y + + # Authentication algorithm(s): + CONFIG_KLIPS_AUTH_HMAC_MD5=y + CONFIG_KLIPS_AUTH_HMAC_SHA1=y + + # To enable encryption, say 'y'. (Highly recommended) + CONFIG_KLIPS_ESP=y + + # modular algo extensions (and new ALGOs) + CONFIG_KLIPS_ALG=y + + # Encryption algorithm(s): + CONFIG_KLIPS_ENC_3DES=y + CONFIG_KLIPS_ENC_AES=y + + # Use CryptoAPI for ALG? - by default, no. + CONFIG_KLIPS_ENC_CRYPTOAPI=n + + # IP Compression: new, probably still has minor bugs. + CONFIG_KLIPS_IPCOMP=y + + # To enable userspace-switchable KLIPS debugging, say 'y'. + CONFIG_KLIPS_DEBUG=y + + # + # + # $Log: defconfig,v $ + # Revision 1.30 2005/09/15 02:31:12 paul + # Changed a FreeS/WAN occurance to Libreswan + # + # Revision 1.29 2005/08/24 22:10:05 mcr + # do not list NAT_TRAVERSAL as a default for KLIPS, + # let it live in the packaging "MODULE_DEF_CONFIG" files. + # + # Revision 1.28 2005/05/11 03:15:42 mcr + # adjusted makefiles to sanely build modules properly. + # + # Revision 1.27 2005/03/20 03:00:05 mcr + # default configuration should enable NAT_TRAVERSAL. + # + # Revision 1.26 2004/07/10 19:11:18 mcr + # CONFIG_IPSEC -> CONFIG_KLIPS. + # + # 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 libreswan + # + # 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 + # 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. + # + # diff -c -w -r -N linux-2.6.16-ng-natt/include/crypto/aes_cbc.h linux-2.6.16-ng-natt-klips/include/crypto/aes_cbc.h *** linux-2.6.16-ng-natt/include/crypto/aes_cbc.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/crypto/aes_cbc.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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); diff -c -w -r -N linux-2.6.16-ng-natt/include/crypto/aes.h linux-2.6.16-ng-natt-klips/include/crypto/aes.h *** linux-2.6.16-ng-natt/include/crypto/aes.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/crypto/aes.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 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 + #else + # include + #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 diff -c -w -r -N linux-2.6.16-ng-natt/include/crypto/aes_xcbc_mac.h linux-2.6.16-ng-natt-klips/include/crypto/aes_xcbc_mac.h *** linux-2.6.16-ng-natt/include/crypto/aes_xcbc_mac.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/crypto/aes_xcbc_mac.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/include/crypto/cbc_generic.h linux-2.6.16-ng-natt-klips/include/crypto/cbc_generic.h *** linux-2.6.16-ng-natt/include/crypto/cbc_generic.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/crypto/cbc_generic.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,110 ---- + #ifndef _CBC_GENERIC_H + #define _CBC_GENERIC_H + /* + * CBC macro helpers + * + * Author: JuanJo Ciarlante + * + * 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 . + * + * 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=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=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 */ diff -c -w -r -N linux-2.6.16-ng-natt/include/crypto/des.h linux-2.6.16-ng-natt-klips/include/crypto/des.h *** linux-2.6.16-ng-natt/include/crypto/des.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/crypto/des.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,286 ---- + /* 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 + #else + #include + #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); + + 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 */ + /* 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 */ + /* 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 diff -c -w -r -N linux-2.6.16-ng-natt/include/crypto/ocf_assist.h linux-2.6.16-ng-natt-klips/include/crypto/ocf_assist.h *** linux-2.6.16-ng-natt/include/crypto/ocf_assist.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/crypto/ocf_assist.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,63 ---- + #ifndef _OCF_ASSIST_H + #define _OCF_ASSIST_H 1 + /****************************************************************************/ + /* The various hw_assist functions return these bits */ + + #define OCF_PROVIDES_AES 0x0001 + #define OCF_PROVIDES_DES_3DES 0x0002 + + /****************************************************************************/ + #if !defined(OCF_ASSIST) + /****************************************************************************/ + /* + * stub it all out just in case + */ + + #define ocf_aes_assist() (0) + #define ocf_aes_set_key(a1,a2,a3,a4) + #define ocf_aes_cbc_encrypt(a1,a2,a3,a4,a5,a6) + + #define ocf_des_assist() (0) + #define ocf_des_set_key(a, b) + #define ocf_des_cbc_encrypt(a1,a2,a3,a4,a5,a6) + #define ocf_des_encrypt(a1,a2,a3) + #define ocf_des_ede3_cbc_encrypt(a1,a2,a3,a4,a5,a6,a7,a8) + #define ocf_des_ncbc_encrypt(a1,a2,a3,a4,a5,a6) + #define ocf_des_ecb_encrypt(a1,a2,a3,a4) + + /****************************************************************************/ + #else + /****************************************************************************/ + + #include + #include "aes.h" + #include "des.h" + + extern int ocf_aes_assist(void); + extern void ocf_aes_set_key(aes_context *cx, const unsigned char in_key[], + int n_bytes, const int f); + extern int ocf_aes_cbc_encrypt(aes_context *ctx, u8 *input, + u8 *output, + long length, + u8 *ivec, int enc); + + extern int ocf_des_assist(void); + extern int ocf_des_set_key(des_cblock *key, des_key_schedule schedule); + extern void ocf_des_cbc_encrypt(des_cblock *input, des_cblock *output, + long length, des_key_schedule schedule, + des_cblock *ivec, int enc); + extern void ocf_des_encrypt(DES_LONG *data, des_key_schedule ks, int enc); + extern void ocf_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); + extern void ocf_des_ncbc_encrypt(des_cblock *input, des_cblock *output, + long length, des_key_schedule schedule, + des_cblock *ivec, int enc); + extern void ocf_des_ecb_encrypt(des_cblock *input, des_cblock *output, + des_key_schedule ks, int enc); + + /****************************************************************************/ + #endif /* !defined(OCF_ASSIST) */ + /****************************************************************************/ + #endif /* _OCF_ASSIST_H */ diff -c -w -r -N linux-2.6.16-ng-natt/include/des/des_locl.h linux-2.6.16-ng-natt-klips/include/des/des_locl.h *** linux-2.6.16-ng-natt/include/des/des_locl.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/des/des_locl.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,506 ---- + /* 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 + * 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 + #include + #include + #include + #ifndef RAND + #define RAND + #endif + #undef NOPROTO + #endif + + #if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) + #ifndef __KERNEL__ + #include + #else + #include + #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 + + #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); \ + } \ + } + + #define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) + + /* 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 + * 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<>(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 diff -c -w -r -N linux-2.6.16-ng-natt/include/des/des_ver.h linux-2.6.16-ng-natt-klips/include/des/des_ver.h *** linux-2.6.16-ng-natt/include/des/des_ver.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/des/des_ver.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/include/des/podd.h linux-2.6.16-ng-natt-klips/include/des/podd.h *** linux-2.6.16-ng-natt/include/des/podd.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/des/podd.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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}; diff -c -w -r -N linux-2.6.16-ng-natt/include/des/sk.h linux-2.6.16-ng-natt-klips/include/des/sk.h *** linux-2.6.16-ng-natt/include/des/sk.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/des/sk.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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, + }}; diff -c -w -r -N linux-2.6.16-ng-natt/include/des/spr.h linux-2.6.16-ng-natt-klips/include/des/spr.h *** linux-2.6.16-ng-natt/include/des/spr.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/des/spr.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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, + }}; diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipcomp.h linux-2.6.16-ng-natt-klips/include/libreswan/ipcomp.h *** linux-2.6.16-ng-natt/include/libreswan/ipcomp.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipcomp.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,58 ---- + /* + * IPCOMP zlib interface code. + * Copyright (C) 2000 Svenning Soerensen + * Copyright (C) 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 . + * + * 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.14 2004/07/10 19:08:41 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 */ + + #include "libreswan/ipsec_sysctl.h" + + 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; + + #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 */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_ah.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_ah.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_ah.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_ah.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,201 ---- + /* + * 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 . + * + * 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.26 2004/09/13 02:22:10 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__ + + #ifndef CONFIG_XFRM_ALTERNATE_STACK + extern struct inet_protocol ah_protocol; + #endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + 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[]; + + #include "libreswan/ipsec_sysctl.h" + + #endif /* __KERNEL__ */ + + /* + * $Log: ipsec_ah.h,v $ + * Revision 1.26 2004/09/13 02:22:10 mcr + * #define inet_protocol if necessary. + * + * Revision 1.25 2004/09/06 18:35:41 mcr + * 2.6.8.1 gets rid of inet_protocol->net_protocol compatibility, + * so adjust for that. + * + * Revision 1.24 2004/07/10 19:08:41 mcr + * CONFIG_IPSEC -> CONFIG_KLIPS. + * + * 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_alg_3des.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_alg_3des.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_alg_3des.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_alg_3des.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,12 ---- + struct TripleDES_context { + des_key_schedule s1; + des_key_schedule s2; + des_key_schedule s3; + }; + typedef struct TripleDES_context TripleDES_context; + + #define ESP_3DES_KEY_SZ 3*(sizeof(des_cblock)) + #define ESP_3DES_CBC_BLK_LEN 8 + + + diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_alg.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_alg.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_alg.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_alg.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,248 ---- + /* + * Modular extensions service and registration functions interface + * + * Author: JuanJo Ciarlante + * + * 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 . + * + * 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 + #include + #include + #include + + /* + * 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 + * + ***************************************************************/ + + #define ixt_alg_type ixt_support.ias_exttype + #define ixt_alg_id ixt_support.ias_id + + #define IPSEC_ALG_ST_SUPP 0x01 + #define IPSEC_ALG_ST_REGISTERED 0x02 + #define IPSEC_ALG_ST_EXCL 0x04 + struct ipsec_alg { + 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 */ \ + + struct ipsec_alg_supported ixt_support; + }; + /* + * 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 { + struct ipsec_alg ixt_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 { + struct ipsec_alg ixt_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 */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_auth.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_auth.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_auth.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_auth.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,100 ---- + /* + * Authentication Header declarations + * Copyright (C) 2003 Michael Richardson + * + * 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 . + * + * 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_encap.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_encap.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_encap.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_encap.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_eroute.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_eroute.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_eroute.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_eroute.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,112 ---- + /* + * @(#) declarations of eroute structures + * + * Copyright (C) 1996, 1997 John Ioannidis. + * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs + * Copyright (C) 2001 Michael Richardson + * + * 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 . + * + * 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: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_errs.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_errs.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_errs.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_errs.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,53 ---- + /* + * @(#) definition of ipsec_errs structure + * + * Copyright (C) 2001 Richard Guy Briggs + * and Michael Richardson + * + * 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 . + * + * 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: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_esp.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_esp.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_esp.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_esp.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,159 ---- + /* + * 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 . + * + * 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.28 2004/09/13 02:22:10 mcr Exp $ + */ + + #include "libreswan/ipsec_md5h.h" + #include "libreswan/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; + }; + + #ifndef CONFIG_XFRM_ALTERNATE_STACK + extern struct inet_protocol esp_protocol; + #endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + 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_KLIPS_DEBUG + extern int debug_esp; + #endif /* CONFIG_KLIPS_DEBUG */ + #endif /* __KERNEL__ */ + + /* + * $Log: ipsec_esp.h,v $ + * Revision 1.28 2004/09/13 02:22:10 mcr + * #define inet_protocol if necessary. + * + * Revision 1.27 2004/09/06 18:35:41 mcr + * 2.6.8.1 gets rid of inet_protocol->net_protocol compatibility, + * so adjust for that. + * + * Revision 1.26 2004/07/10 19:08:41 mcr + * CONFIG_IPSEC -> CONFIG_KLIPS. + * + * 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_ipcomp.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_ipcomp.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_ipcomp.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_ipcomp.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,97 ---- + /* + * IP compression header declations + * + * Copyright (C) 2003 Michael Richardson + * + * 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 . + * + * 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.4 2004/07/10 19:08:41 mcr Exp $ + */ + + #ifndef IPSEC_IPCOMP_H + #define IPSEC_IPCOMP_H + + #include "libreswan/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_KLIPS_DEBUG + extern int sysctl_ipsec_debug_ipcomp; + #endif /* CONFIG_KLIPS_DEBUG */ + + struct ipcomphdr { /* IPCOMP header */ + __u8 ipcomp_nh; /* Next header (protocol) */ + __u8 ipcomp_flags; /* Reserved, must be 0 */ + __u16 ipcomp_cpi; /* Compression Parameter Index */ + }; + + #ifndef CONFIG_XFRM_ALTERNATE_STACK + extern struct inet_protocol comp_protocol; + #endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + 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.4 2004/07/10 19:08:41 mcr + * CONFIG_IPSEC -> CONFIG_KLIPS. + * + * 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. + * + * + * + */ + + + diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_ipe4.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_ipe4.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_ipe4.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_ipe4.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_ipip.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_ipip.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_ipip.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_ipip.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,45 ---- + /* + * Copyright (C) 2003 Michael Richardson + * + * 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 . + * + * 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_kern24.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_kern24.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_kern24.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_kern24.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,152 ---- + /* + * @(#) routines to makes kernel 2.4 compatible with 2.6 usage. + * + * Copyright (C) 2004 Michael Richardson + * + * 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 . + * + * 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_kern24.h,v 1.5 2005/08/05 08:48:38 mcr Exp $ + */ + + #ifndef _IPSEC_KERN24_H + + #ifdef NET_21 + # include + #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 + #if 0 + #ifndef NETDEV_25 + #define device net_device + #endif + #endif + # 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 + /* 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 + + #ifndef NET_26 + #define sk_receive_queue receive_queue + #define sk_destruct destruct + #define sk_reuse reuse + #define sk_zapped zapped + #define sk_family family + #define sk_protocol protocol + #define sk_protinfo protinfo + #define sk_sleep sleep + #define sk_state_change state_change + #define sk_shutdown shutdown + #define sk_err err + #define sk_stamp stamp + #define sk_socket socket + #define sk_sndbuf sndbuf + #define sock_flag(sk, flag) sk->dead + #define sk_for_each(sk, node, plist) for(sk=*plist; sk!=NULL; sk = sk->next) + #endif + + /* deal with 2.4 vs 2.6 issues with module counts */ + + /* in 2.6, all refcounts are maintained *outside* of the + * module to deal with race conditions. + */ + + #ifdef NET_26 + #define KLIPS_INC_USE /* nothing */ + #define KLIPS_DEC_USE /* nothing */ + + #else + #define KLIPS_INC_USE MOD_INC_USE_COUNT + #define KLIPS_DEC_USE MOD_DEC_USE_COUNT + #endif + + extern int printk_ratelimit(void); + + + #define _IPSEC_KERN24_H 1 + + #endif /* _IPSEC_KERN24_H */ + diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_kversion.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_kversion.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_kversion.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_kversion.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,241 ---- + #ifndef _LIBRESWAN_KVERSIONS_H + /* + * header file for Libreswan library functions + * Copyright (C) 1998, 1999, 2000 Henry Spencer. + * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs + * Copyright (C) 2003 - 2008 Paul Wouters + * + * 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 . + * + * 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. + * + */ + #define _LIBRESWAN_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 + #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 + #error "KLIPS is no longer supported on Linux 2.0. Sorry" + #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 + #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) + # if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) && defined(CONFIG_NETFILTER)) + # define SKB_RESET_NFCT + # elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + # if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + # define SKB_RESET_NFCT + # endif + # endif + #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 + #define NET_26 + #define NETDEV_25 + #endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8) + #define NEED_INET_PROTOCOL + #endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) + #define HAVE_SOCK_ZAPPED + #define NET_26_12_SKALLOC + #endif + + /* see */ + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + #define HAVE_SOCK_SECURITY + /* skb->nf_debug disappared completely in 2.6.13 */ + #define HAVE_SKB_NF_DEBUG + #endif + + /* skb->stamp changed to skb->tstamp in 2.6.14 */ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) + #define HAVE_TSTAMP + #define HAVE_INET_SK_SPORT + #else + #define HAVE_SKB_LIST + #endif + + #define SYSCTL_IPSEC_DEFAULT_TTL sysctl_ip_default_ttl + /* it seems 2.6.14 accidentally removed sysctl_ip_default_ttl */ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) + #undef SYSCTL_IPSEC_DEFAULT_TTL + #define SYSCTL_IPSEC_DEFAULT_TTL IPSEC_DEFAULT_TTL + #endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + #define HAVE_NEW_SKB_LINEARIZE + #endif + + /* this is the best we can do to detect XEN, which makes + * patches to linux/skbuff.h, making it look like 2.6.18 version + */ + #ifdef CONFIG_XEN + # HAVE_NEW_SKB_LINEARIZE + #endif + + /* And the same for SuSe kernels who have it before it got into the + * linus kernel. + */ + #ifdef SLE_VERSION_CODE + # if SLE_VERSION_CODE >= 655616 + # define HAVE_NEW_SKB_LINEARIZE + # else + # warning "A Suse kernel was detected, but we are unsure if it requires HAVE_NEW_SKB_LINEARIZE" + # endif + #endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) + #define VOID_SOCK_UNREGISTER + #endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + /* skb->nfmark changed to skb->mark in 2.6.20 */ + #define nfmark mark + #endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + #define ipsec_register_sysctl_table(a,b) register_sysctl_table(a) + #define CTL_TABLE_PARENT + #else + #define ipsec_register_sysctl_table(a,b) register_sysctl_table(a,b) + #endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + /* need to include ip.h early, no longer pick it up in skbuff.h */ + #include + # define HAVE_KERNEL_TSTAMP + # define HAVE_KMEM_CACHE_MACRO + /* type of sock.sk_stamp changed from timeval to ktime */ + # define grab_socket_timeval(tv, sock) { (tv) = ktime_to_timeval((sock).sk_stamp); } + #else + # define grab_socket_timeval(tv, sock) { (tv) = (sock).sk_stamp; } + /* internals of struct skbuff changed */ + # define HAVE_DEV_NEXT + # define ip_hdr(skb) ((skb)->nh.iph) + # define skb_tail_pointer(skb) ((skb)->tail) + # define skb_end_pointer(skb) ((skb)->end) + # define skb_network_header(skb) ((skb)->nh.raw) + # define skb_set_network_header(skb,off) ((skb)->nh.raw = (skb)->data + (off)) + # define tcp_hdr(skb) ((skb)->h.th) + # define udp_hdr(skb) ((skb)->h.uh) + # define skb_transport_header(skb) ((skb)->h.raw) + # define skb_set_transport_header(skb,off) ((skb)->h.raw = (skb)->data + (off)) + # define skb_mac_header(skb) ((skb)->mac.raw) + # define skb_set_mac_header(skb,off) ((skb)->mac.raw = (skb)->data + (off)) + #endif + /* turn a pointer into an offset for above macros */ + #define ipsec_skb_offset(skb, ptr) (((unsigned char *)(ptr)) - (skb)->data) + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + /* Try using the new kernel encaps hook for nat-t, instead of udp.c */ + #ifdef NOT_YET_FINISHED + # define HAVE_UDP_ENCAP_CONVERT + # endif + #endif + + #ifdef NET_21 + # include + #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 + + #if __KERNEL__ + #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + #include "libreswan/ipsec_kern24.h" + #else + #error "kernels before 2.4 are not supported at this time" + #endif + #endif + #endif + + #endif /* _LIBRESWAN_KVERSIONS_H */ + diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_life.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_life.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_life.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_life.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,112 ---- + /* + * Definitions relevant to IPSEC lifetimes + * Copyright (C) 2001 Richard Guy Briggs + * and Michael Richardson + * + * 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 . + * + * 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: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_mast.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_mast.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_mast.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_mast.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,59 ---- + #ifndef _IPSEC_MAST_H + #define _IPSEC_MAST_H + + #ifdef CONFIG_KLIPS_DEBUG + #define DB_MAST_INIT 0x0001 + #define DB_MAST_PROCFS 0x0002 + #define DB_MAST_XMIT 0x0010 + #define DB_MAST_OHDR 0x0020 + #define DB_MAST_CROUT 0x0040 + #define DB_MAST_OXFS 0x0080 + #define DB_MAST_REVEC 0x0100 + #define DB_MAST_ENCAP 0x0200 + #endif /* CONFIG_KLIPS_DEBUG */ + + struct ipsecmastconf { + __u32 cf_cmd; + union + { + char cfu_name[12]; + } cf_u; + #define cf_name cf_u.cfu_name + }; + + struct mastpriv + { + struct sk_buff_head sendq; + struct wait_queue *wait_queue; + int (*hard_header) (struct sk_buff *skb, + struct net_device *dev, + unsigned short type, + void *daddr, + void *saddr, + unsigned len); + #if 0 + char locked; + int (*hard_start_xmit) (struct sk_buff *skb, + struct net_device *dev); + int (*rebuild_header)(struct sk_buff *skb); + int (*set_mac_address)(struct net_device *dev, void *addr); + void (*header_cache_bind)(struct hh_cache **hhp, struct net_device *dev, + unsigned short htype, __u32 daddr); + void (*header_cache_update)(struct hh_cache *hh, + struct net_device *dev, + unsigned char * haddr); + struct net_device_stats *(*get_stats)(struct net_device *dev); + #endif + struct net_device_stats mystats; + int mtu; /* What is the desired MTU? */ + }; + + extern int ipsec_mast_init_devices(void); + extern int ipsec_mast_deletenum(int vifnum); + extern int ipsec_mast_createnum(int vifnum); + extern struct net_device *ipsec_mast_get_device(int vifnum); + extern unsigned int ipsec_mast_is_transport(int vifnum); + + + + #endif diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_md5h.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_md5h.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_md5h.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_md5h.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,143 ---- + /* + * RCSID $Id: ipsec_md5h.h,v 1.10 2004/09/08 17:21:35 ken 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 osMD5Init PROTO_LIST ((void *)); + void osMD5Update PROTO_LIST + ((void *, unsigned char *, __u32)); + void osMD5Final PROTO_LIST ((unsigned char [16], void *)); + + #endif /* _IPSEC_MD5H_H_ */ + + /* + * $Log: ipsec_md5h.h,v $ + * Revision 1.10 2004/09/08 17:21:35 ken + * Rename MD5* -> osMD5 functions to prevent clashes with other symbols exported by kernel modules (CIFS in 2.6 initiated this) + * + * 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_param.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_param.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_param.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_param.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,268 ---- + /* + * @(#) Libreswan tunable paramaters + * + * Copyright (C) 2001 Richard Guy Briggs + * and Michael Richardson + * Copyright (C) 2004 Michael Richardson + * + * 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 . + * + * 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. + * + * + */ + + /* + * 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 "libreswan/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. */ + #ifdef CONFIG_KLIPS_IF_MAX + #define IPSEC_NUM_IFMAX CONFIG_KLIPS_IF_MAX + #endif + #ifndef IPSEC_NUM_IFMAX + #define IPSEC_NUM_IFMAX 64 + #endif + + /* default number of ipsecX devices to create */ + #define IPSEC_NUM_IF 2 + + /* 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" + #define MAST_DEV_FORMAT "mast%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_KLIPS_DYNDEV + #define CONFIG_KLIPS_DYNDEV 1 + #endif /* CONFIG_KLIPS_DYNDEV */ + + + #ifdef CONFIG_KLIPS_BIGGATE + # define SADB_HASHMOD 8069 + #else /* CONFIG_KLIPS_BIGGATE */ + # define SADB_HASHMOD 257 + #endif /* CONFIG_KLIPS_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_IDX_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_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 + + /* always turn on IPIP mode */ + #ifndef CONFIG_KLIPS_IPIP + #define CONFIG_KLIPS_IPIP 1 + #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 /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *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_KLIPS_REGRESS + + /* + * should pfkey_acquire() become 100% lossy? + * + */ + extern int sysctl_ipsec_regress_pfkey_lossage; + #ifndef KLIPS_PFKEY_ACQUIRE_LOSSAGE + # ifdef CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE + # define KLIPS_PFKEY_ACQUIRE_LOSSAGE 100 + # else /* CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE */ + /* not by default! */ + # define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0 + # endif /* CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE */ + #endif /* KLIPS_PFKEY_ACQUIRE_LOSSAGE */ + + #endif /* CONFIG_KLIPS_REGRESS */ + + + /* + * debugging routines. + */ + #ifdef CONFIG_KLIPS_DEBUG + #define KLIPS_ERROR(flag, format, args...) if(printk_ratelimit() || flag) printk(KERN_ERR "KLIPS " format, ## args) + #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) + #define KLIPS_SATOT(flag, sa, format, dst, dstlen) \ + ((flag) ? satot(sa, format, dst, dstlen) : 0) + #else /* CONFIG_KLIPS_DEBUG */ + #define KLIPS_ERROR(flag, format, args...) if(printk_ratelimit()) printk(KERN_ERR "KLIPS " format, ## args) + #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) + #define KLIPS_SATOT(flag, sa, format, dst, dstlen) (0) + #endif /* CONFIG_KLIPS_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__ */ + + #ifdef NEED_INET_PROTOCOL + #define inet_protocol net_protocol + #endif + + #if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && CONFIG_IPSEC_NAT_TRAVERSAL + #define NAT_TRAVERSAL 1 + #else + /* let people either #undef, or #define = 0 it */ + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + #undef CONFIG_IPSEC_NAT_TRAVERSAL + #endif + #endif + + #ifndef IPSEC_DEFAULT_TTL + #define IPSEC_DEFAULT_TTL 64 + #endif + + #define _IPSEC_PARAM_H_ + #endif /* _IPSEC_PARAM_H_ */ + + /* + * Local variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_policy.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_policy.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_policy.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_policy.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,217 ---- + #ifndef _IPSEC_POLICY_H + /* + * policy interface file between pluto and applications + * Copyright (C) 2003 Michael Richardson + * + * 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 . + * + * 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.8 2005/07/26 01:12:38 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, /* 128 bit AES */ + }; + + /* 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_LZJH= 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_int8_t proto; /* TCP, ICMP, etc. */ + 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/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 */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_proto.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_proto.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_proto.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_proto.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,148 ---- + /* + * @(#) prototypes for FreeSWAN functions + * + * Copyright (C) 2001 Richard Guy Briggs + * and Michael Richardson + * + * 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 . + * + * 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.14 2005/04/29 04:50:03 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. + * + */ + + /* forward references */ + enum ipsec_direction; + enum ipsec_life_type; + struct ipsec_lifetime64; + struct ident; + struct sockaddr_encap; + struct ipsec_sa; + + /* 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 int ipsec_sadb_cleanup(__u8); + + extern struct ipsec_sa *ipsec_sa_alloc(int*error); + + + extern struct ipsec_sa *ipsec_sa_getbyid(ip_said *); + extern int ipsec_sa_put(struct ipsec_sa *); + extern /* void */ int ipsec_sa_add(struct ipsec_sa *); + + extern int ipsec_sa_init(struct ipsec_sa *ipsp); + extern int ipsec_sa_wipe(struct ipsec_sa *ipsp); + + /* debug declarations */ + + /* ipsec_proc.c */ + extern int ipsec_proc_init(void); + extern void ipsec_proc_cleanup(void); + + /* ipsec_rcv.c */ + extern int ipsec_rcv(struct sk_buff *skb); + extern int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type); + + /* ipsec_xmit.c */ + struct ipsec_xmit_state; + extern enum ipsec_xmit_value ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs); + extern enum ipsec_xmit_value ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs); + extern void ipsec_print_ip(struct iphdr *ip); + + + + /* 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); + + /* ipsec_snprintf.c */ + extern int ipsec_snprintf(char * buf, ssize_t size, const char *fmt, ...); + extern void ipsec_dmp_block(char *s, caddr_t bb, int len); + + + /* ipsec_alg.c */ + extern int ipsec_alg_init(void); + + + #ifdef CONFIG_KLIPS_DEBUG + + extern int debug_xform; + extern int debug_eroute; + extern int debug_spi; + extern int debug_netlink; + + #endif /* CONFIG_KLIPS_DEBUG */ + + + + + #define _IPSEC_PROTO_H + #endif /* _IPSEC_PROTO_H_ */ + + /* + * + * Local variables: + * c-file-style: "linux" + * End: + * + */ + diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_radij.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_radij.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_radij.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_radij.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,179 ---- + /* + * @(#) 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 . + * + * 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.22 2004/07/10 19:08:41 mcr Exp $ + */ + + #ifndef _IPSEC_RADIJ_H + + #include + + 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_KLIPS_DEBUG + extern int debug_radij; + void rj_dumptrees(void); + + #define DB_RJ_DUMPTREES 0x0001 + #define DB_RJ_FINDROUTE 0x0002 + #endif /* CONFIG_KLIPS_DEBUG */ + + #define _IPSEC_RADIJ_H + #endif + + /* + * $Log: ipsec_radij.h,v $ + * Revision 1.22 2004/07/10 19:08:41 mcr + * CONFIG_IPSEC -> CONFIG_KLIPS. + * + * 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 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_rcv.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_rcv.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_rcv.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_rcv.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,157 ---- + /* + * + * 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 . + * + * 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_RCV_H + #define IPSEC_RCV_H + + #include "libreswan/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__ + #ifndef AUTOCONF_INCLUDED + #include + #endif /* for CONFIG_IP_FORWARD */ + #ifdef CONFIG_MODULES + #include + #endif + #include + #include + + #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; /* the IP header */ + struct ipsec_sa *ipsp; /* current SA being processed */ + int len; /* length of packet */ + int ilen; /* length of inner payload (-authlen) */ + int authlen; /* how big is the auth data at end */ + int hard_header_len; /* layer 2 size */ + int iphlen; /* how big is IP header */ + unsigned int transport_direct:1; + 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, + unsigned short xlen); + #endif /* PROTO_HANDLER_SINGLE_PARM */ + + #ifdef CONFIG_KLIPS_DEBUG + extern int debug_rcv; + #define ipsec_rcv_dmp(_x,_y, _z) if (debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z) + #else + #define ipsec_rcv_dmp(_x,_y, _z) do {} while(0) + #endif /* CONFIG_KLIPS_DEBUG */ + + extern int sysctl_ipsec_inbound_policy_check; + #endif /* __KERNEL__ */ + + extern int klips26_udp_encap_rcv(struct sock *sk, struct sk_buff *skb); + extern int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type); + + // manage ipsec rcv state objects + extern int ipsec_rcv_state_cache_init (void); + extern void ipsec_rcv_state_cache_cleanup (void); + + #endif /* IPSEC_RCV_H */ + + /* + * Local Variables: + * c-basic-offset:8 + * c-style:linux + * End: + * + */ + + diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_sa.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_sa.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_sa.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_sa.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,274 ---- + /* + * @(#) Definitions of IPsec Security Association (ipsec_sa) + * + * Copyright (C) 2001, 2002, 2003 + * Richard Guy Briggs + * and Michael Richardson + * + * 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 . + * + * 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.23.2.1 2007/09/05 02:31:15 paul 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 "libreswan/ipsec_stats.h" + #include "libreswan/ipsec_life.h" + #include "libreswan/ipsec_eroute.h" + #endif /* __KERNEL__ */ + #include "libreswan/ipsec_param.h" + + #include "libreswan/pfkeyv2.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_MAX (~IPSEC_SAREF_NULL) + #define IPSEC_SAREF_FIRST 1 + #define IPSEC_SA_REF_MASK (IPSEC_SA_REF_MAX >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) + #define IPSEC_SA_REF_TABLE_MASK ((IPSEC_SA_REF_MAX >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) + #define IPSEC_SA_REF_ENTRY_MASK (IPSEC_SA_REF_MAX >> (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 + { + atomic_t ips_refcount; /* reference count for this struct */ + int ips_marked_deleted; /* used with reference counting */ + IPsecSAref_t ips_ref; /* reference table entry number */ + IPsecSAref_t ips_refhim; /* ref of paired SA, if any */ + struct ipsec_sa *ips_next; /* pointer to next xform */ + + struct ipsec_sa *ips_hnext; /* next in hash chain */ + + struct ifnet *ips_rcvif; /* related rcv encap interface */ + + struct xform_functions *ips_xformfuncs; /* pointer to routines to process this SA */ + + struct net_device *ips_out; /* what interface to emerge on */ + __u8 ips_transport_direct; /* if true, punt directly to + * the protocol layer */ + struct socket *ips_sock; /* cache of transport socket */ + + 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 */ + enum sadb_sastate 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 */ + + /* these are included even if CONFIG_KLIPS_IPCOMP is off */ + __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 */ + + /* these are included even if CONFIG_IPSEC_NAT_TRAVERSAL is off */ + __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; + + #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; + }; + + 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); + + #define ipsec_sa_get(ips) __ipsec_sa_get(ips, __FUNCTION__, __LINE__) + extern int __ipsec_sa_get(struct ipsec_sa *ips, const char *func, int line); + extern int ipsec_sa_put(struct ipsec_sa *ips); + extern int ipsec_sa_add(struct ipsec_sa *ips); + extern void ipsec_sa_rm(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); + extern int ipsec_sa_intern(struct ipsec_sa *ips); + extern struct ipsec_sa *ipsec_sa_getbyref(IPsecSAref_t ref); + + #endif /* __KERNEL__ */ + + enum ipsec_direction { + ipsec_incoming = 1, + ipsec_outgoing = 2 + }; + + #define _IPSEC_SA_H_ + #endif /* _IPSEC_SA_H_ */ + + /* + * Local variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_sha1.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_sha1.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_sha1.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_sha1.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + 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 + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_stats.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_stats.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_stats.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_stats.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,76 ---- + /* + * @(#) definition of ipsec_stats structure + * + * Copyright (C) 2001 Richard Guy Briggs + * and Michael Richardson + * + * 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 . + * + * 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.7 2005/04/14 01:17:45 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 */ + }; + + #define _IPSEC_STATS_H_ + #endif /* _IPSEC_STATS_H_ */ + + /* + * $Log: ipsec_stats.h,v $ + * Revision 1.7 2005/04/14 01:17:45 mcr + * add prototypes for snprintf. + * + * 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 libreswan + * + * 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: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_sysctl.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_sysctl.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_sysctl.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_sysctl.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,20 ---- + #ifndef LIBRESWAN_SYSCTL_H + #define LIBRESWAN_SYSCTL_H + + extern int debug_ah; + extern int debug_esp; + extern int debug_xform; + extern int debug_eroute; + extern int debug_spi; + extern int debug_netlink; + extern int debug_radij; + extern int debug_rcv; + extern int debug_tunnel; + extern int debug_xmit; + extern int debug_mast; + + extern int sysctl_ip_default_ttl; + extern int sysctl_ipsec_inbound_policy_check; + extern int sysctl_ipsec_debug_ipcomp; + extern int sysctl_ipsec_debug_verbose; + #endif diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_tunnel.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_tunnel.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_tunnel.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_tunnel.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,280 ---- + /* + * IPSEC tunneling code + * Copyright (C) 1996, 1997 John Ioannidis. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. + * Copyright (C) 2006 Michael Richardson + * + * 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 . + * + * 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.33 2005/06/04 16:06:05 mcr Exp $ + */ + + + # 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); + + + #if defined(KLIPS) + /* + * 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 + { + uint32_t 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) + #define IPSEC_UDP_ENCAP_CONVERT (SIOCDEVPRIVATE + 3) + #endif + + #ifdef __KERNEL__ + #include + #ifndef KERNEL_VERSION + # define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) + #endif + struct ipsecpriv + { + struct sk_buff_head sendq; + struct net_device *dev; + struct wait_queue *wait_queue; + int vifnum; + char locked; + int (*hard_start_xmit) (struct sk_buff *skb, + struct net_device *dev); + int (*hard_header) (struct sk_buff *skb, + struct net_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 net_device *dev, + unsigned long raddr, struct sk_buff *skb); + #endif /* NET_21 */ + int (*set_mac_address)(struct net_device *dev, void *addr); + #ifndef NET_21 + void (*header_cache_bind)(struct hh_cache **hhp, struct net_device *dev, + unsigned short htype, __u32 daddr); + #endif /* !NET_21 */ + void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr); + struct net_device_stats *(*get_stats)(struct net_device *dev); + struct net_device_stats mystats; + int mtu; /* What is the desired MTU? */ + }; + + extern char ipsec_tunnel_c_version[]; + + extern struct net_device *ipsecdevices[IPSEC_NUM_IFMAX]; + extern int ipsecdevices_max; + + 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 net_device *dev); + extern struct net_device *ipsec_get_device(int inst); + + #ifdef CONFIG_KLIPS_DEBUG + extern int debug_tunnel; + extern int sysctl_ipsec_debug_verbose; + #endif /* CONFIG_KLIPS_DEBUG */ + #endif /* __KERNEL__ */ + + #ifdef CONFIG_KLIPS_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 + #define DB_TN_ENCAP 0x0200 + #endif /* CONFIG_KLIPS_DEBUG */ + + extern int ipsec_tunnel_deletenum(int vifnum); + extern int ipsec_tunnel_createnum(int vifnum); + extern struct net_device *ipsec_tunnel_get_device(int vifnum); + + + /* manage ipsec xmit state objects */ + extern int ipsec_xmit_state_cache_init (void); + extern void ipsec_xmit_state_cache_cleanup (void); + + /* + * $Log: ipsec_tunnel.h,v $ + * Revision 1.33 2005/06/04 16:06:05 mcr + * better patch for nat-t rcv-device code. + * + * Revision 1.32 2005/05/21 03:18:35 mcr + * added additional debug flag tunnelling. + * + * Revision 1.31 2004/08/03 18:18:02 mcr + * in 2.6, use "net_device" instead of #define device->net_device. + * this probably breaks 2.0 compiles. + * + * Revision 1.30 2004/07/10 19:08:41 mcr + * CONFIG_IPSEC -> CONFIG_KLIPS. + * + * 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 + * 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 . + * + * 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_xform.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_xform.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_xform.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_xform.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,264 ---- + /* + * 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 + * + * 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 . + * + * 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.42 2005/08/05 08:50:45 mcr Exp $ + */ + + #ifndef _IPSEC_XFORM_H_ + + #include + + #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_LZJH 4 + + #define XFT_AUTH 0x0001 + #define XFT_CONF 0x0100 + + /* available if CONFIG_KLIPS_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__ + #include + + struct ipsec_rcv_state; + struct ipsec_xmit_state; + + struct xform_functions { + u8 protocol; + 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_KLIPS_DEBUG + extern void ipsec_dmp(char *s, caddr_t bb, int len); + #else /* CONFIG_KLIPS_DEBUG */ + #define ipsec_dmp(_x, _y, _z) + #endif /* CONFIG_KLIPS_DEBUG */ + + + #define _IPSEC_XFORM_H_ + #endif /* _IPSEC_XFORM_H_ */ + + /* + * $Log: ipsec_xform.h,v $ + * Revision 1.42 2005/08/05 08:50:45 mcr + * move #include of skbuff.h to a place where + * we know it will be kernel only code. + * + * Revision 1.41 2004/07/10 19:08:41 mcr + * CONFIG_IPSEC -> CONFIG_KLIPS. + * + * 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: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/ipsec_xmit.h linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_xmit.h *** linux-2.6.16-ng-natt/include/libreswan/ipsec_xmit.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/ipsec_xmit.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,211 ---- + /* + * 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 . + * + * 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.14 2005/05/11 01:00:26 mcr Exp $ + */ + + #include "libreswan/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 net_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; /* ipsec_sa pointers */ + //struct ipsec_sa *ipsp_outer; /* last SA applied by encap_bundle */ + 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 net_device *physdev; + /* struct device *virtdev; */ + short physmtu; + short cur_mtu; /* copy of prv->mtu, cause prv may == NULL */ + short mtudiff; + #ifdef NET_21 + struct rtable *route; + #endif /* NET_21 */ + ip_said outgoing_said; + #ifdef NET_21 + int pass; + #endif /* NET_21 */ + 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); + + enum ipsec_xmit_value + ipsec_xmit_encap_bundle_2(struct ipsec_xmit_state *ixs); + + extern void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er); + + extern enum ipsec_xmit_value + ipsec_xmit_send(struct ipsec_xmit_state*ixs, struct flowi *fl); + + extern enum ipsec_xmit_value + ipsec_nat_encap(struct ipsec_xmit_state*ixs); + + extern enum ipsec_xmit_value + ipsec_tunnel_send(struct ipsec_xmit_state *ixs); + + extern void ipsec_xmit_cleanup(struct ipsec_xmit_state*ixs); + + + extern int ipsec_xmit_trap_count; + extern int ipsec_xmit_trap_sendcount; + + #ifdef CONFIG_KLIPS_DEBUG + extern int debug_xmit; + extern int debug_mast; + + #define ipsec_xmit_dmp(_x,_y, _z) if (debug_xmit && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z) + #else + #define ipsec_xmit_dmp(_x,_y, _z) do {} while(0) + + #endif /* CONFIG_KLIPS_DEBUG */ + + extern int sysctl_ipsec_debug_verbose; + extern int sysctl_ipsec_icmp; + extern int sysctl_ipsec_tos; + + + /* + * $Log: ipsec_xmit.h,v $ + * Revision 1.14 2005/05/11 01:00:26 mcr + * do not call debug routines if !defined KLIPS_DEBUG. + * + * Revision 1.13 2005/04/29 05:01:38 mcr + * use ipsec_dmp_block. + * added cur_mtu to ixs instead of using ixs->dev. + * + * Revision 1.12 2004/08/20 21:45:37 mcr + * CONFIG_KLIPS_NAT_TRAVERSAL is not used in an attempt to + * be 26sec compatible. But, some defines where changed. + * + * Revision 1.11 2004/08/03 18:18:21 mcr + * in 2.6, use "net_device" instead of #define device->net_device. + * this probably breaks 2.0 compiles. + * + * Revision 1.10 2004/07/10 19:08:41 mcr + * CONFIG_IPSEC -> CONFIG_KLIPS. + * + * 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 + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/mast.h linux-2.6.16-ng-natt-klips/include/libreswan/mast.h *** linux-2.6.16-ng-natt/include/libreswan/mast.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/mast.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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); + + diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/passert.h linux-2.6.16-ng-natt-klips/include/libreswan/passert.h *** linux-2.6.16-ng-natt/include/libreswan/passert.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/passert.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,75 ---- + /* + * sanitize a string into a printable format. + * + * Copyright (C) 1998-2002 D. Hugh Redelmeier. + * Copyright (C) 2003 Michael Richardson + * + * 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 . + * + * 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.7.8.1 2007/09/05 02:32:24 paul Exp $ + */ + + #include "libreswan.h" + + #ifndef _LIBRESWAN_PASSERT_H + #define _LIBRESWAN_PASSERT_H + /* our versions of assert: log result */ + + #ifdef DEBUG + + typedef void (*libreswan_passert_fail_t)(const char *pred_str, + const char *file_str, + unsigned long line_no) NEVER_RETURNS; + + extern libreswan_passert_fail_t libreswan_passert_fail; + + extern void pexpect_log(const char *pred_str + , const char *file_str, unsigned long line_no); + + # define impossible() do { \ + if(libreswan_passert_fail) { \ + (*libreswan_passert_fail)("impossible", __FILE__, __LINE__); \ + }} while(0) + + extern void libreswan_switch_fail(int n + , const char *file_str, unsigned long line_no) NEVER_RETURNS; + + # define bad_case(n) libreswan_switch_fail((int) n, __FILE__, __LINE__) + + # define passert(pred) do { \ + if (!(pred)) \ + if(libreswan_passert_fail) { \ + (*libreswan_passert_fail)(#pred, __FILE__, __LINE__); \ + } \ + } while(0) + + # define pexpect(pred) do { \ + if (!(pred)) \ + pexpect_log(#pred, __FILE__, __LINE__); \ + } while(0) + + /* assert that an err_t is NULL; evaluate exactly once */ + # define happy(x) { \ + err_t ugh = x; \ + if (ugh != NULL) \ + if(libreswan_passert_fail) { (*libreswan_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*/ + + #endif /* _LIBRESWAN_PASSERT_H */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/pfkey_debug.h linux-2.6.16-ng-natt-klips/include/libreswan/pfkey_debug.h *** linux-2.6.16-ng-natt/include/libreswan/pfkey_debug.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/pfkey_debug.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,54 ---- + /* + * sanitize a string into a printable format. + * + * Copyright (C) 1998-2002 D. Hugh Redelmeier. + * Copyright (C) 2003 Michael Richardson + * + * 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 . + * + * 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 int (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); + extern int (*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 diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/pfkey.h linux-2.6.16-ng-natt-klips/include/libreswan/pfkey.h *** linux-2.6.16-ng-natt/include/libreswan/pfkey.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/pfkey.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,383 ---- + /* + * Libreswan specific PF_KEY headers + * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. + * Copyright (C) 2006-2007 Michael Richardson + * + * 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 . + * + * 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.52 2005/11/09 00:30:37 mcr Exp $ + */ + + #ifndef __NET_IPSEC_PF_KEY_H + #define __NET_IPSEC_PF_KEY_H + + #include "pfkeyv2.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); + + 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[]; + + struct ipsec_alg_supported + { + uint16_t ias_exttype; + uint8_t ias_id; + uint8_t ias_ivlen; + uint16_t ias_keyminbits; + uint16_t ias_keymaxbits; + char *ias_name; + }; + + extern struct supported_list *pfkey_supported_list[]; + struct supported_list + { + struct ipsec_alg_supported *supportedp; + struct supported_list *next; + }; + extern int pfkey_list_insert_supported(struct ipsec_alg_supported*, struct supported_list**); + extern int pfkey_list_remove_supported(struct ipsec_alg_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; + int outif; + IPsecSAref_t sarefme; + IPsecSAref_t sarefhim; + }; + + /* forward reference */ + struct sadb_ext; + struct sadb_msg; + struct sockaddr; + struct sadb_comb; + struct sadb_sadb; + struct sadb_alg; + + 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 libreswan_keying_debug_func_t pfkey_debug_func; + extern libreswan_keying_debug_func_t pfkey_error_func; + 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)->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) (DIVUP(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; + }; + + enum pfkey_ext_required { + EXT_BITS_IN=0, + EXT_BITS_OUT=1 + }; + + enum pfkey_ext_perm { + EXT_BITS_PERM=0, + EXT_BITS_REQ=1 + }; + + + typedef uint64_t pfkey_ext_track; + static inline void pfkey_mark_extension(enum sadb_extension_t exttype, + pfkey_ext_track *exten_track) + { + *exten_track |= (1 << exttype); + } + + extern int pfkey_extensions_missing(enum pfkey_ext_required inout, + enum sadb_msg_t sadb_operation, + pfkey_ext_track extensions_seen); + extern int pfkey_required_extension(enum pfkey_ext_required inout, + enum sadb_msg_t sadb_operation, + enum sadb_extension_t exttype); + extern int pfkey_permitted_extension(enum pfkey_ext_required inout, + enum sadb_msg_t sadb_operation, + enum sadb_extension_t exttype); + + + extern void pfkey_extensions_init(struct sadb_ext *extensions[]); + extern void pfkey_extensions_free(struct sadb_ext *extensions[]); + 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); + + extern int + pfkey_saref_build(struct sadb_ext **pfkey_ext, + IPsecSAref_t in, IPsecSAref_t out); + + 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, + unsigned 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 __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); + + 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); + + struct sadb_builds { + struct k_sadb_sa sa_base; + }; + + int + pfkey_sa_builds(struct sadb_ext **pfkey_ext, + struct sadb_builds sab); + + extern int + pfkey_outif_build(struct sadb_ext **pfkey_ext, + uint16_t outif); + + #endif /* __NET_IPSEC_PF_KEY_H */ + diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan/pfkeyv2.h linux-2.6.16-ng-natt-klips/include/libreswan/pfkeyv2.h *** linux-2.6.16-ng-natt/include/libreswan/pfkeyv2.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan/pfkeyv2.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,331 ---- + /* + * RCSID $Id: pfkeyv2.h,v 1.31 2005/04/14 01:14:54 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 + + #include + + #define PF_KEY_V2 2 + #define PFKEYV2_REVISION 199806L + + enum sadb_msg_t { + K_SADB_RESERVED=SADB_RESERVED, + K_SADB_GETSPI=SADB_GETSPI, + K_SADB_UPDATE=SADB_UPDATE, + K_SADB_ADD=SADB_ADD, + K_SADB_DELETE=SADB_DELETE, + K_SADB_GET=SADB_GET, + K_SADB_ACQUIRE=SADB_ACQUIRE, + K_SADB_REGISTER=SADB_REGISTER, + K_SADB_EXPIRE=SADB_EXPIRE, + K_SADB_FLUSH=SADB_FLUSH, + K_SADB_DUMP=SADB_DUMP, + K_SADB_X_PROMISC=SADB_X_PROMISC, + K_SADB_X_PCHANGE=SADB_X_PCHANGE, + K_SADB_X_GRPSA=13, + K_SADB_X_ADDFLOW=14, + K_SADB_X_DELFLOW=15, + K_SADB_X_DEBUG=16, + K_SADB_X_NAT_T_NEW_MAPPING=17, + K_SADB_X_PLUMBIF=18, + K_SADB_X_UNPLUMBIF=19, + K_SADB_MAX=19 + }; + + #define SADB_X_GRPSA K_SADB_X_GRPSA + #define SADB_X_ADDFLOW K_SADB_X_ADDFLOW + #define SADB_X_DELFLOW K_SADB_X_DELFLOW + #define SADB_X_DEBUG K_SADB_X_DEBUG + #define SADB_X_PLUMBIF K_SADB_X_PLUMBIF + #define SADB_X_UNPLUMBIF K_SADB_X_UNPLUMBIF + + struct k_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]; + } __attribute__((packed)); + + 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; + } __attribute__((packed)); + + 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]; + } __attribute__((packed)); + + 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]; + } __attribute__((packed)); + + /* + * a plumbif extension can appear in + * - a plumbif message to create the interface. + * - a unplumbif message to delete the interface. + * - a sadb add/replace to indicate which interface + * a decrypted packet should emerge on. + * + * the create/delete part could/should be replaced with netlink equivalents, + * or better yet, FORCES versions of same. + * + */ + struct sadb_x_plumbif { + uint16_t sadb_x_outif_len; + uint16_t sadb_x_outif_exttype; + uint16_t sadb_x_outif_ifnum; + } __attribute__((packed)); + + /* + * the ifnum describes a device that you wish to create refer to. + * + * devices 0-40959 are mastXXX devices. + * devices 40960-49141 are mastXXX devices with transport set. + * devices 49152-65536 are deprecated ipsecXXX devices. + */ + #define IPSECDEV_OFFSET (48*1024) + #define MASTTRANSPORT_OFFSET (40*1024) + + /* + * an saref extension sets the SA's reference number, and + * may also set the paired SA's reference number. + * + */ + struct sadb_x_saref { + uint16_t sadb_x_saref_len; + uint16_t sadb_x_saref_exttype; + uint32_t sadb_x_saref_me; + uint32_t sadb_x_saref_him; + } __attribute__((packed)); + + /* + * 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; + } __attribute__((packed)); + + /* + * NOTE that there is a limit of 31 extensions due to current implementation + * in pfkeyv2_ext_bits.c + */ + enum sadb_extension_t { + K_SADB_EXT_RESERVED=SADB_RESERVED, + K_SADB_EXT_SA= SADB_EXT_SA, + K_SADB_EXT_LIFETIME_CURRENT=SADB_EXT_LIFETIME_CURRENT, + K_SADB_EXT_LIFETIME_HARD= SADB_EXT_LIFETIME_HARD, + K_SADB_EXT_LIFETIME_SOFT= SADB_EXT_LIFETIME_SOFT, + K_SADB_EXT_ADDRESS_SRC= SADB_EXT_ADDRESS_SRC, + K_SADB_EXT_ADDRESS_DST= SADB_EXT_ADDRESS_DST, + K_SADB_EXT_ADDRESS_PROXY= SADB_EXT_ADDRESS_PROXY, + K_SADB_EXT_KEY_AUTH= SADB_EXT_KEY_AUTH, + K_SADB_EXT_KEY_ENCRYPT= SADB_EXT_KEY_ENCRYPT, + K_SADB_EXT_IDENTITY_SRC= SADB_EXT_IDENTITY_SRC, + K_SADB_EXT_IDENTITY_DST= SADB_EXT_IDENTITY_DST, + K_SADB_EXT_SENSITIVITY= SADB_EXT_SENSITIVITY, + K_SADB_EXT_PROPOSAL= SADB_EXT_PROPOSAL, + K_SADB_EXT_SUPPORTED_AUTH= SADB_EXT_SUPPORTED_AUTH, + K_SADB_EXT_SUPPORTED_ENCRYPT=SADB_EXT_SUPPORTED_ENCRYPT, + K_SADB_EXT_SPIRANGE= SADB_EXT_SPIRANGE, + K_SADB_X_EXT_KMPRIVATE= SADB_X_EXT_KMPRIVATE, + K_SADB_X_EXT_SATYPE2= 18, + K_SADB_X_EXT_POLICY= SADB_X_EXT_POLICY, + K_SADB_X_EXT_SA2= SADB_X_EXT_SA2, + K_SADB_X_EXT_ADDRESS_DST2= 20, + K_SADB_X_EXT_ADDRESS_SRC_FLOW=21, + K_SADB_X_EXT_ADDRESS_DST_FLOW=22, + K_SADB_X_EXT_ADDRESS_SRC_MASK=23, + K_SADB_X_EXT_ADDRESS_DST_MASK=24, + K_SADB_X_EXT_DEBUG= 25, + K_SADB_X_EXT_PROTOCOL= 26, + K_SADB_X_EXT_NAT_T_TYPE= 27, + K_SADB_X_EXT_NAT_T_SPORT= 28, + K_SADB_X_EXT_NAT_T_DPORT= 29, + K_SADB_X_EXT_NAT_T_OA= 30, + K_SADB_X_EXT_PLUMBIF= 31, + K_SADB_X_EXT_SAREF= 32, + K_SADB_EXT_MAX= 32, + }; + + + #define SADB_X_EXT_SATYPE2 K_SADB_X_EXT_SATYPE2 + #define SADB_X_EXT_ADDRESS_DST2 K_SADB_X_EXT_ADDRESS_DST2 + #define SADB_X_EXT_ADDRESS_SRC_FLOW K_SADB_X_EXT_ADDRESS_SRC_FLOW + #define SADB_X_EXT_ADDRESS_DST_FLOW K_SADB_X_EXT_ADDRESS_DST_FLOW + #define SADB_X_EXT_ADDRESS_SRC_MASK K_SADB_X_EXT_ADDRESS_SRC_MASK + #define SADB_X_EXT_ADDRESS_DST_MASK K_SADB_X_EXT_ADDRESS_DST_MASK + #define SADB_X_EXT_DEBUG K_SADB_X_EXT_DEBUG + #define SADB_X_EXT_PROTOCOL K_SADB_X_EXT_PROTOCOL + + #undef SADB_X_EXT_NAT_T_TYPE + #undef SADB_X_EXT_NAT_T_SPORT + #undef SADB_X_EXT_NAT_T_DPORT + #undef SADB_X_EXT_NAT_T_OA + #define SADB_X_EXT_PLUMBIF K_SADB_X_EXT_PLUMBIF + + + + /* K_SADB_X_DELFLOW required over and above K_SADB_X_SAFLAGS_CLEARFLOW */ + #define K_SADB_X_EXT_ADDRESS_DELFLOW \ + ( (1<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 . + * + * 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. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/include/libreswan.h linux-2.6.16-ng-natt-klips/include/libreswan.h *** linux-2.6.16-ng-natt/include/libreswan.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/libreswan.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,563 ---- + #ifndef _LIBRESWAN_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 . + * + * 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: libreswan.h,v 1.95 2005/08/25 01:24:40 paul Exp $ + */ + #define _LIBRESWAN_H /* seen it, no need to see it again */ + + /* you'd think this should be builtin to compiler... */ + #ifndef TRUE + #define TRUE 1 + #endif + + #ifndef FALSE + #define FALSE 0 + #endif + + + + /* + * 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 */ + #if defined(linux) + #if defined(__KERNEL__) + #include + #include + #include + #include + #include + #include + #include + #include + #define user_assert(foo) /*nothing*/ + + #else /* NOT in kernel */ + #include + #include + #include + #include + #include + #define user_assert(foo) assert(foo) + #include + + # define uint8_t u_int8_t + # define uint16_t u_int16_t + # define uint32_t u_int32_t + # define uint64_t u_int64_t + + + + #endif /* __KERNEL__ */ + + #endif /* linux */ + + #define DEBUG_NO_STATIC static + + /* + * Yes Virginia, we have started a windows port. + */ + #if defined(__CYGWIN32__) + #if !defined(WIN32_KERNEL) + /* get windows equivalents */ + #include + #include + #include + #include + #include + #include + #define user_assert(foo) assert(foo) + #endif /* _KERNEL */ + #endif /* WIN32 */ + + /* + * Kovacs? A macosx port? + */ + #if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #define user_assert(foo) assert(foo) + #define __u32 unsigned int + #define __u8 unsigned char + #define s6_addr16 __u6_addr.__u6_addr16 + #define DEBUG_NO_STATIC static + #endif + + /* + * FreeBSD + */ + #if defined(__FreeBSD__) + # define DEBUG_NO_STATIC static + #include + #include + #include + #include + #include + #include + #define user_assert(foo) assert(foo) + /* apparently this way to deal with an IPv6 address is not standard. */ + #define s6_addr16 __u6_addr.__u6_addr16 + #endif + + + #ifndef IPPROTO_COMP + # define IPPROTO_COMP 108 + #endif /* !IPPROTO_COMP */ + + #ifndef IPPROTO_INT + # define IPPROTO_INT 61 + #endif /* !IPPROTO_INT */ + + #if !defined(ESPINUDP_WITH_NON_IKE) + #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 */ + #if !defined(s6_addr16) && defined(__CYGWIN32__) + struct in6_addr { + union + { + u_int8_t u6_addr8[16]; + u_int16_t u6_addr16[8]; + u_int32_t 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; + + /* Translation to/from nfmark. + * + * use bits 16-31. Leave bit 32 as a indicate that IPsec processing + * has already been done. + */ + #define IPSEC_SA_REF_TABLE_IDX_WIDTH 15 + #define IPSEC_SA_REF_TABLE_OFFSET 16 + #define IPSEC_SA_REF_MAASK ((1<> IPSEC_SA_REF_TABLE_OFFSET)&IPSEC_SA_REF_MASK) + + #define IPSEC_SAREF_NULL ((IPsecSAref_t)0) + #define IPSEC_SAREF_NA ((IPsecSAref_t)0xffff0001) + + /* 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 + + + /* + * function to log stuff from libraries that may be used in multiple + * places. + */ + typedef int (*libreswan_keying_debug_func_t)(const char *message, ...); + + + + /* + * 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 */ + + /* looks up names in DNS */ + err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst); + + /* does not look up names in DNS */ + err_t ttoaddr_num(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 unsigned 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 add_port(int af, ip_address *addr, unsigned short port); + 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 isvalidsubnet(const ip_subnet *a); + 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 unsigned 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 unsigned 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 + ); + + + + /* + * 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, + KDF_NATT = 13, + }; + + + /* + * 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 /* _LIBRESWAN_H */ diff -c -w -r -N linux-2.6.16-ng-natt/include/zlib/zconf.h linux-2.6.16-ng-natt-klips/include/zlib/zconf.h *** linux-2.6.16-ng-natt/include/zlib/zconf.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/zlib/zconf.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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.4 2004/07/10 07:48:40 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 + # 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 + # 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 /* for off_t */ + # include /* 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/include/zlib/zlib.h linux-2.6.16-ng-natt-klips/include/zlib/zlib.h *** linux-2.6.16-ng-natt/include/zlib/zlib.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/zlib/zlib.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/include/zlib/zutil.h linux-2.6.16-ng-natt-klips/include/zlib/zutil.h *** linux-2.6.16-ng-natt/include/zlib/zutil.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/include/zlib/zutil.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + #define HAVE_MEMCPY + + #if 0 // #ifdef STDC + # include + # include + # include + #endif + #ifndef __KERNEL__ + #ifdef NO_ERRNO_H + extern int errno; + #else + # include + #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 + # endif + # else /* MSC or DJGPP */ + # include + # 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 /* 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 + 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/addrtoa.c linux-2.6.16-ng-natt-klips/net/ipsec/addrtoa.c *** linux-2.6.16-ng-natt/net/ipsec/addrtoa.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/addrtoa.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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.10 2004/07/10 07:43:47 mcr Exp $ + */ + #include "libreswan.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 libreswan.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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/addrtot.c linux-2.6.16-ng-natt-klips/net/ipsec/addrtot.c *** linux-2.6.16-ng-natt/net/ipsec/addrtot.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/addrtot.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,348 ---- + /* + * 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 . + * + * 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. + * + */ + + #if defined(__KERNEL__) && defined(__HAVE_ARCH_STRSTR) + #include + #endif + + #include "libreswan.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); + + #if defined(__KERNEL__) && !defined(__HAVE_ARCH_STRSTR) + #define strstr ipsec_strstr + /* + * Find the first occurrence of find in s. + * (from NetBSD 1.6's /src/lib/libc/string/strstr.c) + */ + static char *strstr(const char *s, const char *find); + + static char * + strstr(s, find) + const char *s, *find; + { + char c, sc; + size_t len; + + if ((c = *find++) != 0) { + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return (NULL); + } while (sc != c); + } while (strncmp(s, find, len) != 0); + s--; + } + /* LINTED interface specification */ + return ((char *)s); + } + #endif + + /* + - 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, "", dstlen); + return sizeof(""); + } + + 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 + #include + #include + #include + #include + + 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 */ + + /* + * Local variables: + * c-file-style: "linux" + * End: + */ + + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/addrtypeof.c linux-2.6.16-ng-natt-klips/net/ipsec/addrtypeof.c *** linux-2.6.16-ng-natt/net/ipsec/addrtypeof.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/addrtypeof.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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.10 2004/07/10 07:43:47 mcr Exp $ + */ + #include "libreswan.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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/adler32.c linux-2.6.16-ng-natt-klips/net/ipsec/adler32.c *** linux-2.6.16-ng-natt/net/ipsec/adler32.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/adler32.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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.6 2004/07/10 19:11:18 mcr Exp $ */ + + #include + #include + + #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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/aes/aes.c linux-2.6.16-ng-natt-klips/net/ipsec/aes/aes.c *** linux-2.6.16-ng-natt/net/ipsec/aes/aes.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/aes/aes.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 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); + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/aes/aes_cbc.c linux-2.6.16-ng-natt-klips/net/ipsec/aes/aes_cbc.c *** linux-2.6.16-ng-natt/net/ipsec/aes/aes_cbc.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/aes/aes_cbc.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,46 ---- + /* + // 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 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 + #else + #include + #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.2 2004/07/10 07:48:40 mcr + * Moved from linux/crypto/ciphers/aes/aes_cbc.c,v + * + * Revision 1.1 2004/04/06 02:48:12 mcr + * pullup of AES cipher from alg-branch. + * + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/aes/aes-i586.S linux-2.6.16-ng-natt-klips/net/ipsec/aes/aes-i586.S *** linux-2.6.16-ng-natt/net/ipsec/aes/aes-i586.S 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/aes/aes-i586.S 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,892 ---- + // + // Copyright (c) 2001, Dr Brian Gladman , 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) diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/aes/aes_xcbc_mac.c linux-2.6.16-ng-natt-klips/net/ipsec/aes/aes_xcbc_mac.c *** linux-2.6.16-ng-natt/net/ipsec/aes/aes_xcbc_mac.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/aes/aes_xcbc_mac.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,67 ---- + #ifdef __KERNEL__ + #include + #include + #define AES_DEBUG(x) + #else + #include + #include + #define AES_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) { + AES_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) { + AES_DEBUG(printf("using k3\n")); + xor_block(out, ctxm->k3); + } + else + { + AES_DEBUG(printf("using k2\n")); + xor_block(out, ctxm->k2); + } + aes_encrypt(&ctxm->ctx_k1, (u_int8_t *)out, hash); + return ret; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/aes/ipsec_alg_aes.c linux-2.6.16-ng-natt-klips/net/ipsec/aes/ipsec_alg_aes.c *** linux-2.6.16-ng-natt/net/ipsec/aes/ipsec_alg_aes.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/aes/ipsec_alg_aes.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,300 ---- + /* + * ipsec_alg AES cipher stubs + * + * Author: JuanJo Ciarlante + * + * 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 . + * + * 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 + * Fixes list: + * PK: make XCBC comply with latest draft (keylength) + * + */ + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + + /* + * special case: ipsec core modular with this static algo inside: + * must avoid MODULE magic for this file + */ + #if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_AES) + #undef MODULE + #endif + + #include + #include + + #include /* printk() */ + #include /* error codes */ + #include /* size_t */ + #include + + /* Check if __exit is defined, if not null it */ + #ifndef __exit + #define __exit + #endif + + /* Low freeswan header coupling */ + #include + #include "libreswan/ipsec_alg.h" + #include "crypto/aes_cbc.h" + + #define CONFIG_KLIPS_ENC_AES_MAC 1 + + #define AES_CONTEXT_T aes_context + static int debug_aes=0; + static int test_aes=0; + static int excl_aes=0; + static int keyminbits=0; + static int keymaxbits=0; + #if defined(CONFIG_KLIPS_ENC_AES_MODULE) + MODULE_AUTHOR("JuanJo Ciarlante "); + #ifdef module_param + module_param(debug_aes,int,0664); + module_param(test_aes,int,0664); + module_param(excl_aes,int,0664); + module_param(keyminbits,int,0664); + module_param(keymaxbits,int,0664); + #else + MODULE_PARM(debug_aes, "i"); + MODULE_PARM(test_aes, "i"); + MODULE_PARM(excl_aes, "i"); + MODULE_PARM(keyminbits, "i"); + MODULE_PARM(keymaxbits, "i"); + #endif + #endif + + #if CONFIG_KLIPS_ENC_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 + #if 0 + #ifdef MODULE_PARM + MODULE_PARM(auth_id, "i"); + #else + module_param(auth_id,int,0664); + #endif + #endif + #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_aes > 0) + printk(KERN_DEBUG "klips_debug:_aes_set_key:" + "ret=%d key_e=%p key=%p keysize=%ld\n", + ret, key_e, key, (unsigned long int) 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_aes > 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_KLIPS_ENC_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_common: { ixt_version: IPSEC_ALG_VERSION, + ixt_refcnt: ATOMIC_INIT(0), + ixt_name: "aes_mac", + ixt_blocksize: ESP_AES_MAC_BLK_LEN, + ixt_support: { + ias_exttype: IPSEC_ALG_TYPE_AUTH, + ias_id: 0, + ias_keyminbits: ESP_AES_MAC_KEY_SZ*8, + ias_keymaxbits: ESP_AES_MAC_KEY_SZ*8, + }, + }, + #if defined(CONFIG_KLIPS_ENC_AES_MODULE) + ixt_module: THIS_MODULE, + #endif + 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_KLIPS_ENC_AES_MAC */ + static struct ipsec_alg_enc ipsec_alg_AES = { + ixt_common: { ixt_version: IPSEC_ALG_VERSION, + ixt_refcnt: ATOMIC_INIT(0), + ixt_name: "aes", + ixt_blocksize: ESP_AES_CBC_BLK_LEN, + ixt_support: { + ias_exttype: IPSEC_ALG_TYPE_ENCRYPT, + //ias_ivlen: 128, + ias_id: ESP_AES, + ias_keyminbits: ESP_AES_KEY_SZ_MIN*8, + ias_keymaxbits: ESP_AES_KEY_SZ_MAX*8, + }, + }, + #if defined(CONFIG_KLIPS_ENC_AES_MODULE) + ixt_module: THIS_MODULE, + #endif + 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_KLIPS_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_common.ixt_support.ias_keyminbits=keyminbits; + if (keymaxbits) { + ipsec_alg_AES.ixt_common.ixt_support.ias_keymaxbits=keymaxbits; + if (keymaxbits*8>ipsec_alg_AES.ixt_common.ixt_support.ias_keymaxbits) + ipsec_alg_AES.ixt_e_keylen=keymaxbits*8; + } + if (excl_aes) ipsec_alg_AES.ixt_common.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_common.ixt_support.ias_exttype, + ipsec_alg_AES.ixt_common.ixt_support.ias_id, + ipsec_alg_AES.ixt_common.ixt_name, + ret); + if (ret==0 && test_aes) { + test_ret=ipsec_alg_test( + ipsec_alg_AES.ixt_common.ixt_support.ias_exttype , + ipsec_alg_AES.ixt_common.ixt_support.ias_id, + test_aes); + printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", + ipsec_alg_AES.ixt_common.ixt_support.ias_exttype , + ipsec_alg_AES.ixt_common.ixt_support.ias_id, + test_ret); + } + #if CONFIG_KLIPS_ENC_AES_MAC + if (auth_id!=0){ + int ret; + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_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_common.ixt_support.ias_exttype, + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, + ipsec_alg_AES_MAC.ixt_common.ixt_name, + ret); + if (ret==0 && test_aes) { + test_ret=ipsec_alg_test( + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype, + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, + test_aes); + printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype, + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_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_KLIPS_ENC_AES_MAC */ + return ret; + } + + #if defined(CONFIG_KLIPS_ENC_AES_MODULE) + IPSEC_ALG_MODULE_EXIT_MOD( ipsec_aes_fini ) + #else + IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_aes_fini ) + #endif + { + #if CONFIG_KLIPS_ENC_AES_MAC + if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC); + #endif /* CONFIG_KLIPS_ENC_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 + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/aes/Makefile linux-2.6.16-ng-natt-klips/net/ipsec/aes/Makefile *** linux-2.6.16-ng-natt/net/ipsec/aes/Makefile 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/aes/Makefile 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,56 ---- + # Makefile for KLIPS 3DES kernel code as a module for 2.6 kernels + # + # Makefile for KLIPS kernel code as a module + # Copyright (C) 2002-2004 Michael Richardson + # + # 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 . + # + # 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.fs2_6,v 1.2 2005/08/12 14:13:58 mcr 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). + # + + obj-$(CONFIG_KLIPS_ENC_AES) += ipsec_alg_aes.o + obj-$(CONFIG_KLIPS_ENC_AES) += aes_xcbc_mac.o + obj-$(CONFIG_KLIPS_ENC_AES) += aes_cbc.o + + ifeq ($(strip ${SUBARCH}),) + SUBARCH:=${ARCH} + endif + + # the assembly version expects frame pointers, which are + # optional in many kernel builds. If you want speed, you should + # probably use cryptoapi code instead. + USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} + ifeq (${USEASSEMBLY},i386y) + obj-$(CONFIG_KLIPS_ENC_AES) += aes-i586.o + else + obj-$(CONFIG_KLIPS_ENC_AES) += aes.o + endif + + + # + # $Log: Makefile.fs2_6,v $ + # Revision 1.2 2005/08/12 14:13:58 mcr + # do not use assembly code with there are no frame pointers, + # as it does not have the right linkages. + # + # Revision 1.1 2004/08/17 03:31:34 mcr + # klips 2.6 edits. + # + # + # Local Variables: + # compile-command: "(cd ../../.. && source umlsetup.sh && make -C ${POOLSPACE} module/ipsec.o)" + # End Variables: + # + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/alg/Config.alg_aes.in linux-2.6.16-ng-natt-klips/net/ipsec/alg/Config.alg_aes.in *** linux-2.6.16-ng-natt/net/ipsec/alg/Config.alg_aes.in 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/alg/Config.alg_aes.in 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,3 ---- + if [ "$CONFIG_IPSEC_ALG" = "y" ]; then + tristate ' AES encryption algorithm' CONFIG_IPSEC_ENC_AES + fi diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/alg/Config.alg_cryptoapi.in linux-2.6.16-ng-natt-klips/net/ipsec/alg/Config.alg_cryptoapi.in *** linux-2.6.16-ng-natt/net/ipsec/alg/Config.alg_cryptoapi.in 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/alg/Config.alg_cryptoapi.in 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/alg/Config.in linux-2.6.16-ng-natt-klips/net/ipsec/alg/Config.in *** linux-2.6.16-ng-natt/net/ipsec/alg/Config.in 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/alg/Config.in 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,3 ---- + #Placeholder + source net/ipsec/alg/Config.alg_aes.in + source net/ipsec/alg/Config.alg_cryptoapi.in diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/alg/ipsec_alg_cryptoapi.c linux-2.6.16-ng-natt-klips/net/ipsec/alg/ipsec_alg_cryptoapi.c *** linux-2.6.16-ng-natt/net/ipsec/alg/ipsec_alg_cryptoapi.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/alg/ipsec_alg_cryptoapi.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,442 ---- + /* + * ipsec_alg to linux cryptoapi GLUE + * + * Authors: CODE.ar TEAM + * Harpo MAxx + * JuanJo Ciarlante + * Luciano Ruete + * + * 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 . + * + * 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) + */ + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + + /* + * 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 + #include + + #include /* printk() */ + #include /* error codes */ + #include /* size_t */ + #include + + /* 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 "libreswan/ipsec_alg.h" + + #include + #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 + #include + #include + + #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; + static int test=0; + static int excl=0; + #ifdef module_param + module_param(debug, int, 0664); + module_param(test, int, 0664); + module_param(excl, int, 0664); + #else + MODULE_PARM(debug, "i"); + MODULE_PARM(test, "i"); + MODULE_PARM(excl, "i"); + #endif + + static int noauto = 0; + #ifdef module_param + module_param(noauto,int, 0664); + #else + MODULE_PARM(noauto,"i"); + #endif + 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}; + + #ifdef module_param_array + module_param_array(des_ede3,int,NULL,0); + module_param_array(aes,int,NULL,0); + module_param_array(blowfish,int,NULL,0); + module_param_array(cast,int,NULL,0); + module_param_array(serpent,int,NULL,0); + module_param_array(twofish,int,NULL,0); + #else + 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"); + #endif + 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/alg/Makefile.alg_aes linux-2.6.16-ng-natt-klips/net/ipsec/alg/Makefile.alg_aes *** linux-2.6.16-ng-natt/net/ipsec/alg/Makefile.alg_aes 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/alg/Makefile.alg_aes 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,18 ---- + 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 $(LIBCRYPTO)/libaes/libaes.a + + + $(MOD_AES): $(AES_OBJS) + $(LD) $(EXTRA_LDFLAGS) -r $(AES_OBJS) -o $@ + + $(LIBCRYPTO)/libaes/libaes.a: + $(MAKE) -C $(LIBCRYPTO)/libaes CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' libaes.a + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/alg/Makefile.alg_cryptoapi linux-2.6.16-ng-natt-klips/net/ipsec/alg/Makefile.alg_cryptoapi *** linux-2.6.16-ng-natt/net/ipsec/alg/Makefile.alg_cryptoapi 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/alg/Makefile.alg_cryptoapi 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 $@ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/alg/scripts/mk-static_init.c.sh linux-2.6.16-ng-natt-klips/net/ipsec/alg/scripts/mk-static_init.c.sh *** linux-2.6.16-ng-natt/net/ipsec/alg/scripts/mk-static_init.c.sh 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/alg/scripts/mk-static_init.c.sh 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,18 ---- + #!/bin/sh + cat << EOF + #include + #include + #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 diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/anyaddr.c linux-2.6.16-ng-natt-klips/net/ipsec/anyaddr.c *** linux-2.6.16-ng-natt/net/ipsec/anyaddr.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/anyaddr.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,150 ---- + /* + * 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 . + * + * 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.10 2004/07/10 07:43:47 mcr Exp $ + */ + #include "libreswan.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; + + case 0: + /* a zeroed structure is considered any address */ + return 1; + + 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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/datatot.c linux-2.6.16-ng-natt-klips/net/ipsec/datatot.c *** linux-2.6.16-ng-natt/net/ipsec/datatot.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/datatot.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,234 ---- + /* + * 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 . + * + * 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.9 2005/08/30 21:15:26 mcr Exp $ + */ + #include "libreswan.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 unsigned 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 */ + unsigned 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; + } + + user_assert(inblocksize < sizeof(inblock)); + user_assert(outblocksize < sizeof(outblock)); + user_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; + } + + user_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((const char *)src, nreal, format, out); + needed += outblocksize; + sincebreak += outblocksize; + if (dst < stop) { + if (out != dst) { + user_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; + } + } + + user_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; + + user_assert(nreal > 0); + switch (format) { + case 'x': + user_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: + user_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 unsigned 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 unsigned 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); + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/defconfig linux-2.6.16-ng-natt-klips/net/ipsec/defconfig *** linux-2.6.16-ng-natt/net/ipsec/defconfig 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/defconfig 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,147 ---- + + # + # RCSID $Id: defconfig,v 1.30 2005/09/15 02:31:12 paul Exp $ + # + + # + # Libreswan 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_KLIPS=m + + # To do tunnel mode IPSec, this must be enabled. + CONFIG_KLIPS_IPIP=y + + # To enable authentication, say 'y'. (Highly recommended) + CONFIG_KLIPS_AH=y + + # Authentication algorithm(s): + CONFIG_KLIPS_AUTH_HMAC_MD5=y + CONFIG_KLIPS_AUTH_HMAC_SHA1=y + + # To enable encryption, say 'y'. (Highly recommended) + CONFIG_KLIPS_ESP=y + + # modular algo extensions (and new ALGOs) + CONFIG_KLIPS_ALG=y + + # Encryption algorithm(s): + CONFIG_KLIPS_ENC_3DES=y + CONFIG_KLIPS_ENC_AES=y + + # Use CryptoAPI for ALG? - by default, no. + CONFIG_KLIPS_ENC_CRYPTOAPI=n + + # IP Compression: new, probably still has minor bugs. + CONFIG_KLIPS_IPCOMP=y + + # To enable userspace-switchable KLIPS debugging, say 'y'. + CONFIG_KLIPS_DEBUG=y + + # + # + # $Log: defconfig,v $ + # Revision 1.30 2005/09/15 02:31:12 paul + # Changed a FreeS/WAN occurance to Libreswan + # + # Revision 1.29 2005/08/24 22:10:05 mcr + # do not list NAT_TRAVERSAL as a default for KLIPS, + # let it live in the packaging "MODULE_DEF_CONFIG" files. + # + # Revision 1.28 2005/05/11 03:15:42 mcr + # adjusted makefiles to sanely build modules properly. + # + # Revision 1.27 2005/03/20 03:00:05 mcr + # default configuration should enable NAT_TRAVERSAL. + # + # Revision 1.26 2004/07/10 19:11:18 mcr + # CONFIG_IPSEC -> CONFIG_KLIPS. + # + # 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 libreswan + # + # 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 + # 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. + # + # diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/deflate.c linux-2.6.16-ng-natt-klips/net/ipsec/deflate.c *** linux-2.6.16-ng-natt/net/ipsec/deflate.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/deflate.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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.4 2004/07/10 07:48:37 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)<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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/deflate.h linux-2.6.16-ng-natt-klips/net/ipsec/deflate.h *** linux-2.6.16-ng-natt/net/ipsec/deflate.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/deflate.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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.5 2004/07/10 07:48:38 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/asm/des-586.pl linux-2.6.16-ng-natt-klips/net/ipsec/des/asm/des-586.pl *** linux-2.6.16-ng-natt/net/ipsec/des/asm/des-586.pl 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/asm/des-586.pl 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,251 ---- + #!/usr/local/bin/perl + # + # The inner loop instruction sequence and the IP/FP modifications are from + # Svend Olaf Mikkelsen + # + + 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); + } + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/asm/des686.pl linux-2.6.16-ng-natt-klips/net/ipsec/des/asm/des686.pl *** linux-2.6.16-ng-natt/net/ipsec/des/asm/des686.pl 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/asm/des686.pl 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,230 ---- + #!/usr/local/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 "); + &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]); + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/asm/desboth.pl linux-2.6.16-ng-natt-klips/net/ipsec/des/asm/desboth.pl *** linux-2.6.16-ng-natt/net/ipsec/des/asm/desboth.pl 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/asm/desboth.pl 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,79 ---- + #!/usr/local/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); + } + + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/asm/readme linux-2.6.16-ng-natt-klips/net/ipsec/des/asm/readme *** linux-2.6.16-ng-natt/net/ipsec/des/asm/readme 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/asm/readme 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 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. + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/cbc_enc.c linux-2.6.16-ng-natt-klips/net/ipsec/des/cbc_enc.c *** linux-2.6.16-ng-natt/net/ipsec/des/cbc_enc.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/cbc_enc.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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/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; + } + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/COPYRIGHT linux-2.6.16-ng-natt-klips/net/ipsec/des/COPYRIGHT *** linux-2.6.16-ng-natt/net/ipsec/des/COPYRIGHT 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/COPYRIGHT 2008-06-01 17:37:11.000000000 -0400 *************** *** 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. diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/des.doc linux-2.6.16-ng-natt-klips/net/ipsec/des/des.doc *** linux-2.6.16-ng-natt/net/ipsec/des/des.doc 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/des.doc 2008-06-01 17:37:11.000000000 -0400 *************** *** 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. diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/des_enc.c linux-2.6.16-ng-natt-klips/net/ipsec/des/des_enc.c *** linux-2.6.16-ng-natt/net/ipsec/des/des_enc.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/des_enc.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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/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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/des_opts.c linux-2.6.16-ng-natt-klips/net/ipsec/des/des_opts.c *** linux-2.6.16-ng-natt/net/ipsec/des/des_opts.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/des_opts.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + #ifndef MSDOS + #include + #else + #include + extern void exit(); + #endif + #include + #ifndef VMS + #ifndef _IRIX + #include + #endif + #ifdef TIMES + #include + #include + #endif + #else /* VMS */ + #include + 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 + #endif + + #ifdef sun + #include + #include + #endif + + #include "des/des_locl.h" + #include "des/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 + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/dx86unix.S linux-2.6.16-ng-natt-klips/net/ipsec/des/dx86unix.S *** linux-2.6.16-ng-natt/net/ipsec/des/dx86unix.S 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/dx86unix.S 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,3160 ---- + /* + * This file was originally generated by Michael Richardson + * 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" diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/ecb_enc.c linux-2.6.16-ng-natt-klips/net/ipsec/des/ecb_enc.c *** linux-2.6.16-ng-natt/net/ipsec/des/ecb_enc.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/ecb_enc.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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/des_locl.h" + #include "des/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.8 2004/08/04 15:57:22 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; + } + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/INSTALL linux-2.6.16-ng-natt-klips/net/ipsec/des/INSTALL *** linux-2.6.16-ng-natt/net/ipsec/des/INSTALL 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/INSTALL 2008-06-01 17:37:11.000000000 -0400 *************** *** 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. diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/ipsec_alg_3des.c linux-2.6.16-ng-natt-klips/net/ipsec/des/ipsec_alg_3des.c *** linux-2.6.16-ng-natt/net/ipsec/des/ipsec_alg_3des.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/ipsec_alg_3des.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,182 ---- + /* + * ipsec_alg 3DES cipher stubs + * + * Copyright (C) 2005 Michael Richardson + * + * Adapted from ipsec_alg_aes.c by JuanJo Ciarlante + * + * 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 . + * + * 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 AUTOCONF_INCLUDED + #include + #endif + #include + + /* + * special case: ipsec core modular with this static algo inside: + * must avoid MODULE magic for this file + */ + #if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_3DES) + #undef MODULE + #endif + + #include + #include + + #include /* printk() */ + #include /* error codes */ + #include /* size_t */ + #include + + /* Low freeswan header coupling */ + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_alg.h" + #include "crypto/des.h" + #include "libreswan/ipsec_alg_3des.h" + + #define AES_CONTEXT_T aes_context + static int debug_3des=0; + static int test_3des=0; + static int excl_3des=0; + + #if defined(CONFIG_KLIPS_ENC_3DES_MODULE) + MODULE_AUTHOR("Michael Richardson "); + #ifdef module_param + module_param(debug_3des, int, 0664); + module_param(test_des, int, 0664); + module_param(excl_des, int, 0664); + #else + MODULE_PARM(debug_3des, "i"); + MODULE_PARM(test_des, "i"); + MODULE_PARM(excl_des, "i"); + #endif + #endif + + #define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ + #define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ + + static int _3des_set_key(struct ipsec_alg_enc *alg, + __u8 * key_e, const __u8 * key, + size_t keysize) + { + int ret = 0; + TripleDES_context *ctx = (TripleDES_context*)key_e; + + if(keysize != 192/8) { + return EINVAL; + } + + des_set_key((des_cblock *)(key + DES_KEY_SZ*0), ctx->s1); + des_set_key((des_cblock *)(key + DES_KEY_SZ*1), ctx->s2); + des_set_key((des_cblock *)(key + DES_KEY_SZ*2), ctx->s3); + + if (debug_3des > 0) + printk(KERN_DEBUG "klips_debug:_3des_set_key:" + "ret=%d key_e=%p key=%p keysize=%ld\n", + ret, key_e, key, (unsigned long int) keysize); + return ret; + } + + static int _3des_cbc_encrypt(struct ipsec_alg_enc *alg, + __u8 * key_e, + __u8 * in, + int ilen, const __u8 * iv, + int encrypt) + { + TripleDES_context *ctx=(TripleDES_context*)key_e; + des_cblock miv; + + memcpy(&miv, iv, sizeof(miv)); + + if (debug_3des > 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); + + des_ede3_cbc_encrypt((des_cblock *)in, + (des_cblock *)in, + ilen, + ctx->s1, + ctx->s2, + ctx->s3, + &miv, encrypt); + return 1; + } + + static struct ipsec_alg_enc ipsec_alg_3DES = { + ixt_common: { ixt_version: IPSEC_ALG_VERSION, + ixt_refcnt: ATOMIC_INIT(0), + ixt_name: "3des", + ixt_blocksize: ESP_3DES_CBC_BLK_LEN, + ixt_support: { + ias_exttype: IPSEC_ALG_TYPE_ENCRYPT, + ias_id: ESP_3DES, + //ias_ivlen: 64, + ias_keyminbits: ESP_3DES_KEY_SZ*8, + ias_keymaxbits: ESP_3DES_KEY_SZ*8, + }, + }, + #if defined(MODULE_KLIPS_ENC_3DES_MODULE) + ixt_module: THIS_MODULE, + #endif + ixt_e_keylen: ESP_3DES_KEY_SZ*8, + ixt_e_ctx_size: sizeof(TripleDES_context), + ixt_e_set_key: _3des_set_key, + ixt_e_cbc_encrypt:_3des_cbc_encrypt, + }; + + #if defined(CONFIG_KLIPS_ENC_3DES_MODULE) + IPSEC_ALG_MODULE_INIT_MOD( ipsec_3des_init ) + #else + IPSEC_ALG_MODULE_INIT_STATIC( ipsec_3des_init ) + #endif + { + int ret, test_ret; + + if (excl_3des) ipsec_alg_3DES.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL; + ret=register_ipsec_alg_enc(&ipsec_alg_3DES); + printk("ipsec_3des_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", + ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, + ipsec_alg_3DES.ixt_common.ixt_support.ias_id, + ipsec_alg_3DES.ixt_common.ixt_name, + ret); + if (ret==0 && test_3des) { + test_ret=ipsec_alg_test( + ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, + ipsec_alg_3DES.ixt_common.ixt_support.ias_id, + test_3des); + printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", + ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, + ipsec_alg_3DES.ixt_common.ixt_support.ias_id, + test_ret); + } + return ret; + } + + #if defined(CONFIG_KLIPS_ENC_3DES_MODULE) + IPSEC_ALG_MODULE_EXIT_MOD( ipsec_3des_fini ) + #else + IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_3des_fini ) + #endif + { + unregister_ipsec_alg_enc(&ipsec_alg_3DES); + return; + } + + /* Dual, because 3des code is 4-clause BSD licensed */ + #ifdef MODULE_LICENSE + MODULE_LICENSE("Dual BSD/GPL"); + #endif + + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/Makefile linux-2.6.16-ng-natt-klips/net/ipsec/des/Makefile *** linux-2.6.16-ng-natt/net/ipsec/des/Makefile 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/Makefile 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,60 ---- + # Makefile for KLIPS kernel code as a module for 2.6 kernels + # + # Makefile for KLIPS kernel code as a module + # Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. + # Copyright (C) 2002-2004 Michael Richardson + # + # 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 . + # + # 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.fs2_6,v 1.3 2005/08/12 14:13:59 mcr 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). + # + + obj-$(CONFIG_KLIPS_ENC_3DES) += ipsec_alg_3des.o + obj-$(CONFIG_KLIPS_ENC_3DES) += cbc_enc.o + obj-$(CONFIG_KLIPS_ENC_3DES) += ecb_enc.o + obj-$(CONFIG_KLIPS_ENC_3DES) += set_key.o + + ifeq ($(strip ${SUBARCH}),) + SUBARCH:=${ARCH} + endif + + # the assembly version expects frame pointers, which are + # optional in many kernel builds. If you want speed, you should + # probably use cryptoapi code instead. + USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} + ifeq (${USEASSEMBLY},i386y) + obj-$(CONFIG_KLIPS_ENC_3DES) += dx86unix.o + else + obj-$(CONFIG_KLIPS_ENC_3DES) += des_enc.o + endif + + # + # $Log: Makefile.fs2_6,v $ + # Revision 1.3 2005/08/12 14:13:59 mcr + # do not use assembly code with there are no frame pointers, + # as it does not have the right linkages. + # + # Revision 1.2 2005/04/29 05:13:07 mcr + # 3DES algorithm code. + # + # Revision 1.1 2004/08/17 03:27:30 mcr + # klips 2.6 edits. + # + # + # Local Variables: + # compile-command: "(cd ../../.. && source umlsetup.sh && make -C ${POOLSPACE} module/ipsec.o)" + # End Variables: + # + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/README linux-2.6.16-ng-natt-klips/net/ipsec/des/README *** linux-2.6.16-ng-natt/net/ipsec/des/README 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/README 2008-06-01 17:37:11.000000000 -0400 *************** *** 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) + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/README.freeswan linux-2.6.16-ng-natt-klips/net/ipsec/des/README.freeswan *** linux-2.6.16-ng-natt/net/ipsec/des/README.freeswan 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/README.freeswan 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 and , 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.12 2004/07/10 08:06:51 mcr Exp $ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/set_key.c linux-2.6.16-ng-natt-klips/net/ipsec/des/set_key.c *** linux-2.6.16-ng-natt/net/ipsec/des/set_key.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/set_key.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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/des_locl.h" + #include "des/podd.h" + #include "des/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>(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>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)); + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/des/VERSION linux-2.6.16-ng-natt-klips/net/ipsec/des/VERSION *** linux-2.6.16-ng-natt/net/ipsec/des/VERSION 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/des/VERSION 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + The 'n' bit ofb code was wrong, it was not shifting the shift + register. It worked correctly for n == 64. Thanks to + Gigi Ankeny 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 . + + 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 . 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 . */ + + 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 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 + + 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 + for the patch. + + Version 3.21 22/11/95 + After some emailing back and forth with + Colin Plumb , 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 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 + 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 for pointing this + one out. + + Version 3.12 08/05/95 + As pointed out by The Crypt Keeper , + 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 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 . + + 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 + + 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 + + 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 + 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 , 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 + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/goodmask.c linux-2.6.16-ng-natt-klips/net/ipsec/goodmask.c *** linux-2.6.16-ng-natt/net/ipsec/goodmask.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/goodmask.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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.12 2004/07/10 07:43:47 mcr Exp $ + */ + #include "libreswan.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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/infblock.c linux-2.6.16-ng-natt-klips/net/ipsec/infblock.c *** linux-2.6.16-ng-natt/net/ipsec/infblock.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/infblock.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + #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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/infblock.h linux-2.6.16-ng-natt-klips/net/ipsec/infblock.h *** linux-2.6.16-ng-natt/net/ipsec/infblock.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/infblock.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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)); diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/infcodes.c linux-2.6.16-ng-natt-klips/net/ipsec/infcodes.c *** linux-2.6.16-ng-natt/net/ipsec/infcodes.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/infcodes.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + #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")); + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/infcodes.h linux-2.6.16-ng-natt-klips/net/ipsec/infcodes.h *** linux-2.6.16-ng-natt/net/ipsec/infcodes.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/infcodes.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/inffast.c linux-2.6.16-ng-natt-klips/net/ipsec/inffast.c *** linux-2.6.16-ng-natt/net/ipsec/inffast.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/inffast.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + #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)<avail_in-n;c=(k>>3)>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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/inffast.h linux-2.6.16-ng-natt-klips/net/ipsec/inffast.h *** linux-2.6.16-ng-natt/net/ipsec/inffast.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/inffast.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/inffixed.h linux-2.6.16-ng-natt-klips/net/ipsec/inffixed.h *** linux-2.6.16-ng-natt/net/ipsec/inffixed.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/inffixed.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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} + }; diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/inflate.c linux-2.6.16-ng-natt-klips/net/ipsec/inflate.c *** linux-2.6.16-ng-natt/net/ipsec/inflate.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/inflate.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + #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<state->wbits)) + { + length = (1<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); + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/inftrees.c linux-2.6.16-ng-natt-klips/net/ipsec/inftrees.c *** linux-2.6.16-ng-natt/net/ipsec/inftrees.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/inftrees.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + #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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/inftrees.h linux-2.6.16-ng-natt-klips/net/ipsec/inftrees.h *** linux-2.6.16-ng-natt/net/ipsec/inftrees.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/inftrees.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/infutil.c linux-2.6.16-ng-natt-klips/net/ipsec/infutil.c *** linux-2.6.16-ng-natt/net/ipsec/infutil.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/infutil.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + #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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/infutil.h linux-2.6.16-ng-natt-klips/net/ipsec/infutil.h *** linux-2.6.16-ng-natt/net/ipsec/infutil.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/infutil.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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)<>=(j);k-=(j);} + /* output bytes */ + #define WAVAIL (uInt)(qread?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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/initaddr.c linux-2.6.16-ng-natt-klips/net/ipsec/initaddr.c *** linux-2.6.16-ng-natt/net/ipsec/initaddr.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/initaddr.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,85 ---- + /* + * 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 . + * + * 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.6 2004/07/10 07:43:47 mcr Exp $ + */ + #include "libreswan.h" + + err_t + add_port(af, addr, port) + int af; + ip_address *addr; + unsigned short port; + { + switch (af) { + case AF_INET: + addr->u.v4.sin_port = port; + break; + case AF_INET6: + addr->u.v6.sin6_port = port; + break; + default: + return "unknown address family in add_port"; + break; + } + return NULL; + } + + /* + - 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"; + #if !defined(__KERNEL__) + /* On BSD, the kernel compares the entire struct sockaddr when + * using bind(). However, this is as large as the largest + * address family, so the 'remainder' has to be 0. Linux + * compares interface addresses with the length of sa_len, + * instead of sizeof(struct sockaddr), so in that case padding + * is not needed. + * + * Patch by Stefan Arentz + */ + bzero(&dst->u.v4, sizeof(dst->u.v4)); + #endif + dst->u.v4.sin_family = af; + dst->u.v4.sin_port = 0; + 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"; + #if !defined(__KERNEL__) + bzero(&dst->u.v6, sizeof(dst->u.v6)); + #endif + dst->u.v6.sin6_family = af; + dst->u.v6.sin6_flowinfo = 0; /* unused */ + dst->u.v6.sin6_port = 0; + memcpy((char *)&dst->u.v6.sin6_addr, src, srclen); + break; + default: + return "unknown address family in initaddr"; + break; + } + return NULL; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipcomp.c linux-2.6.16-ng-natt-klips/net/ipsec/ipcomp.c *** linux-2.6.16-ng-natt/net/ipsec/ipcomp.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipcomp.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,694 ---- + /* + * IPCOMP zlib interface code. + * implementation of RFC 3173. + * + * Copyright (C) 2000 Svenning Soerensen + * Copyright (C) 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 . + * + * 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. + */ + + /* SSS */ + + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + + #define __NO_VERSION__ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include + #include + #include + #include + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + #include + + #include + + #include + + #include "libreswan/ipsec_kern24.h" + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */ + #include "libreswan/ipsec_proto.h" + #include "libreswan/ipcomp.h" + #include "zlib/zlib.h" + #include "zlib/zutil.h" + + #include /* SADB_X_CALG_DEFLATE */ + + 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); + } + + /* + * We use this function because sometimes we want to pass a negative offset + * into skb_put(), this does not work on 64bit platforms because long to + * unsigned int casting. + */ + static inline unsigned char * + safe_skb_put(struct sk_buff *skb, int extend) + { + unsigned char *ptr; + + if (extend>0) { + // increase the size of the packet + ptr = skb_put(skb, extend); + } else { + // shrink the size of the packet + ptr = skb_tail_pointer(skb); + skb_trim (skb, skb->len + extend); + } + + return ptr; + } + + 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 = ip_hdr(skb); + #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_KLIPS_DEBUG + if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { + __u8 *c; + + c = (__u8*)iph + iphlen; + ipsec_dmp_block("compress before", c, pyldsz); + } + #endif /* CONFIG_KLIPS_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 */ + safe_skb_put (skb, cpyldsz + sizeof(struct ipcomphdr) - pyldsz); + + #ifdef CONFIG_KLIPS_DEBUG + if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { + __u8 *c; + + c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr); + ipsec_dmp_block("compress result", c, cpyldsz); + } + #endif /* CONFIG_KLIPS_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 = ip_hdr(skb); + #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_KLIPS_DEBUG + if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { + __u8 *c; + + c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr); + ipsec_dmp_block("decompress before", c, cpyldsz); + } + #endif /* CONFIG_KLIPS_DEBUG */ + + #ifdef NET_21 + iph = ip_hdr(nskb); + #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 */ + safe_skb_put(nskb, -zs.avail_out); + + ipsec_kfree_skb(skb); + + if (iph->protocol == IPPROTO_COMP) + { + #ifdef CONFIG_KLIPS_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_KLIPS_DEBUG */ + + ipsec_kfree_skb(nskb); + return NULL; + } + + #ifdef CONFIG_KLIPS_DEBUG + if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { + __u8 *c; + + c = (__u8*)iph + iphlen; + ipsec_dmp_block("decompress result", c, pyldsz); + } + #endif /* CONFIG_KLIPS_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 = ip_hdr(skb); + #else /* NET_21 */ + iph = skb->ip_hdr; + #endif /* NET_21 */ + if (!iph) return NULL; + iphlen = iph->ihl << 2; + + n=alloc_skb(skb_end_pointer(skb) - 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 */ + safe_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); + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + n->list=NULL; + #endif + n->next=NULL; + n->prev=NULL; + n->sk=NULL; + n->dev=skb->dev; + if (skb_transport_header(skb)) + skb_set_transport_header(n, offset); + n->protocol=skb->protocol; + #ifdef NET_21 + n->csum = 0; + n->priority=skb->priority; + n->dst=dst_clone(skb->dst); + skb_set_network_header(n, offset); + #ifndef NETDEV_23 + n->is_clone=0; + #endif /* NETDEV_23 */ + atomic_set(&n->users, 1); + n->destructor = NULL; + #ifdef HAVE_SOCK_SECURITY + n->security=skb->security; + #endif + 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_header(skb)) + skb_set_mac_header(n, offset); + #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; + #ifdef HAVE_TSTAMP + n->tstamp = skb->tstamp; + #else + n->stamp=skb->stamp; + #endif + #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 */ + + return n; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_ah.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_ah.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_ah.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_ah.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,360 ---- + /* + * processing code for AH + * Copyright (C) 2003-2004 Michael Richardson + * + * 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 . + * + * 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 AUTOCONF_INCLUDED + #include + #endif + #include + + #define __NO_VERSION__ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *lock* */ + # endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + + #include + #include + + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_rcv.h" + #include "libreswan/ipsec_xmit.h" + + #include "libreswan/ipsec_auth.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_proto.h" + + __u32 zeroes[AH_AMAX]; + + 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_transport_header(skb); + + 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_transport_header(skb) + ahhlen, + skb->len - 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_network_header(skb) + ahhlen), + (void *)(skb_network_header(skb)), 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); + + skb_set_network_header(skb, ahhlen); + irs->ipp = ip_hdr(skb); + + ipsec_rcv_dmp("ah postpull", (void *)ip_hdr(skb), 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_KLIPS_AUTH_HMAC_MD5 + MD5_CTX md5; + #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + SHA1_CTX sha1; + #endif /* CONFIG_KLIPS_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_KLIPS_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)); + osMD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); + ipsec_xmit_dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Update(&tctx.md5, (unsigned char *)ahp, + sizeof(struct ahhdr) - sizeof(ahp->ah_data)); + ipsec_xmit_dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); + ipsec_xmit_dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Update(&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)); + osMD5Final(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)); + osMD5Update(&tctx.md5, hash, AHMD596_ALEN); + ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Final(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_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_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_KLIPS_AUTH_HMAC_SHA1 */ + default: + ixs->stats->tx_errors++; + return IPSEC_XMIT_AH_BADALG; + } + #ifdef NET_21 + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ahp)); + #endif /* NET_21 */ + + return IPSEC_XMIT_OK; + } + + struct xform_functions ah_xform_funcs[]={ + { + protocol: IPPROTO_AH, + 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, + }, + }; + + + #ifndef CONFIG_XFRM_ALTERNATE_STACK + #ifdef NET_26 + struct inet_protocol ah_protocol = { + .handler = ipsec_rcv, + .no_policy = 1, + }; + #else + 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 /* NET_26 */ + #endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + /* + * Local variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_alg.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_alg.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_alg.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_alg.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1045 ---- + /* + * Modular extensions service and registration functions + * + * Author: JuanJo Ciarlante + * + * 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 . + * + * 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 AUTOCONF_INCLUDED + #include + #endif + #include + + #define __NO_VERSION__ + #include + #include /* printk() */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + #include + #include + #include /* memcmp() */ + #include /* get_random_bytes() */ + #include /* error codes */ + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *lock* */ + # endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + + #include "libreswan/ipsec_param.h" + #include + #include "libreswan/ipsec_sa.h" + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_rcv.h" + #if defined(CONFIG_KLIPS_ESP) || defined(CONFIG_KLIPS_AH) + # include "libreswan/ipsec_ah.h" + #endif /* defined(CONFIG_KLIPS_ESP) || defined(CONFIG_KLIPS_AH) */ + #ifdef CONFIG_KLIPS_ESP + # include "libreswan/ipsec_esp.h" + #endif /* !CONFIG_KLIPS_ESP */ + #ifdef CONFIG_KLIPS_IPCOMP + # include "libreswan/ipcomp.h" + #endif /* CONFIG_KLIPS_COMP */ + + #include + #include + + #include "libreswan/ipsec_alg.h" + #include "libreswan/ipsec_proto.h" + + #if K_SADB_EALG_MAX < 255 + #warning Compiling with limited ESP support ( K_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 { struct ipsec_alg *ixtc = (struct ipsec_alg *)ixt; printk(KERN_ERR "%s: (%s) " fmt, __FUNCTION__, ixtc->ixt_name , ## args) \ + ; goto out; } while(0) + + #ifdef NET_26 + /* + * Must be already protected by lock + */ + static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) + { + #ifdef MODULE + if (ixt->ixt_module) + try_module_get(ixt->ixt_module); + #endif + atomic_inc(&ixt->ixt_refcnt); + } + static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) { + atomic_dec(&ixt->ixt_refcnt); + #ifdef MODULE + if (ixt->ixt_module) + module_put(ixt->ixt_module); + #endif + } + + #else + + /* + * Must be already protected by lock + */ + static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) { + #ifdef MODULE + if (ixt->ixt_module) { + __MOD_INC_USE_COUNT(ixt->ixt_module); + } + #endif + atomic_inc(&ixt->ixt_refcnt); + } + static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) { + atomic_dec(&ixt->ixt_refcnt); + #ifdef MODULE + if (ixt->ixt_module) + __MOD_DEC_USE_COUNT(ixt->ixt_module); + #endif + } + #endif + + /* + * 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; + #ifdef CONFIG_KLIPS_DEBUG + int debug_flag = (encrypt==IPSEC_ALG_ENCRYPT ? + debug_tunnel : debug_rcv); + #endif + + KLIPS_PRINT(debug_flag, + "klips_debug:ipsec_alg_esp_encrypt: " + "entering with encalg=%d, ixt_e=%p\n", + sa_p->ips_encalg, ixt_e); + if (ixt_e == NULL) { + KLIPS_ERROR(debug_flag, + "klips_debug:ipsec_alg_esp_encrypt: " + "NULL ipsec_alg_enc object\n"); + return -1; + } + KLIPS_PRINT(debug_flag, + "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_flag, + "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_common.ixt_support.ias_id) { + case ESP_3DES: + keyminbits=keymaxbits=192;break; + case ESP_DES: + keyminbits=keymaxbits=64;break; + default: + keyminbits=ixt_e->ixt_common.ixt_support.ias_keyminbits; + keymaxbits=ixt_e->ixt_common.ixt_support.ias_keymaxbits; + } + if(sa_p->ips_key_bits_eips_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_common.ixt_support.ias_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_common.ixt_support.ias_keyminbits; + keymaxbits=ixt_a->ixt_common.ixt_support.ias_keymaxbits; + if(sa_p->ips_key_bits_aips_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_common.ixt_blocksize==0) /* || ixt->ixt_common.ixt_blocksize%2) need for ESP_NULL */ + barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_common.ixt_blocksize); + if (ixt->ixt_common.ixt_support.ias_keyminbits==0 + && ixt->ixt_common.ixt_support.ias_keymaxbits==0 + && ixt->ixt_e_keylen==0) + goto zero_key_ok; + + if (ixt->ixt_common.ixt_support.ias_keyminbits==0) + barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits); + + if (ixt->ixt_common.ixt_support.ias_keymaxbits==0) + barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_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_common.ixt_support.ias_id==0 || ixt->ixt_common.ixt_support.ias_id > K_SADB_AALG_MAX) + barf_out("invalid alg_id=%d > %d (K_SADB_AALG_MAX)\n", + ixt->ixt_common.ixt_support.ias_id, K_SADB_AALG_MAX); + + if (ixt->ixt_common.ixt_blocksize==0 + || ixt->ixt_common.ixt_blocksize%2) + barf_out(KERN_ERR "invalid blocksize=%d\n", + ixt->ixt_common.ixt_blocksize); + + if (ixt->ixt_common.ixt_blocksize>AH_BLKLEN_MAX) + barf_out(KERN_ERR "sorry blocksize=%d > %d. " + "Please increase AH_BLKLEN_MAX and recompile\n", + ixt->ixt_common.ixt_blocksize, + AH_BLKLEN_MAX); + if (ixt->ixt_common.ixt_support.ias_keyminbits==0 && ixt->ixt_common.ixt_support.ias_keymaxbits==0 && ixt->ixt_a_keylen==0) + goto zero_key_ok; + if (ixt->ixt_common.ixt_support.ias_keyminbits==0) + barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits); + if (ixt->ixt_common.ixt_support.ias_keymaxbits==0) + barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_keymaxbits); + if (ixt->ixt_common.ixt_support.ias_keymaxbits!=ixt->ixt_common.ixt_support.ias_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 + */ + if (ixt->ixt_support.ias_ivlen == 0 + && ixt->ixt_blocksize > 1) { + ixt->ixt_support.ias_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_support.ias_id, ret); + + + ret = pfkey_list_insert_supported((struct ipsec_alg_supported *)&ixt->ixt_support + , &(pfkey_supported_list[K_SADB_SATYPE_ESP])); + + if (ret==0) { + ixt->ixt_state |= IPSEC_ALG_ST_SUPP; + /* send register event to userspace */ + pfkey_register_reply(K_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 ipsec_alg_supported *)&ixt->ixt_support + , &(pfkey_supported_list[K_SADB_SATYPE_ESP])); + + /* send register event to userspace */ + pfkey_register_reply(K_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_common.ixt_support.ias_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_common.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_common.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_common.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), + K_SADB_EALG_MAX, K_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_KLIPS_ENC_AES) && CONFIG_KLIPS_ENC_AES && !defined(CONFIG_KLIPS_ENC_AES_MODULE) + #if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI + #warning "Using built-in AES rather than CryptoAPI AES" + #endif + { + extern int ipsec_aes_init(void); + ipsec_aes_init(); + } + #endif + + #if defined(CONFIG_KLIPS_ENC_3DES) && !defined(CONFIG_KLIPS_ENC_3DES_MODULE) + #if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI + #warning "Using built-in 3des rather than CryptoAPI 3des" + #endif + { + extern int ipsec_3des_init(void); + ipsec_3des_init(); + } + #endif + + /* If we are doing CryptoAPI, then init */ + #if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI && !defined(CONFIG_KLIPS_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_support.ias_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_support.ias_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; + inext; 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_support.ias_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_support.ias_ivlen, ixt->ixt_support.ias_keyminbits, ixt->ixt_support.ias_keymaxbits); + + len += ipsec_snprintf(buffer+len, length-len, + "IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", + ixt->ixt_support.ias_ivlen, ixt->ixt_support.ias_keyminbits, ixt->ixt_support.ias_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. + */ + + #ifdef CONFIG_MODULES + #ifndef NET_26 + #if 0 + #ifndef EXPORT_SYMBOL_GPL + #undef EXPORT_SYMBOL_GPL + #define EXPORT_SYMBOL_GPL EXPORT_SYMBOL + #endif + #endif + EXPORT_SYMBOL(register_ipsec_alg); + EXPORT_SYMBOL(unregister_ipsec_alg); + EXPORT_SYMBOL(ipsec_alg_test); + #endif + #endif diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_alg_cryptoapi.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_alg_cryptoapi.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_alg_cryptoapi.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_alg_cryptoapi.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,450 ---- + /* + * ipsec_alg to linux cryptoapi GLUE + * + * Authors: CODE.ar TEAM + * Harpo MAxx + * JuanJo Ciarlante + * Luciano Ruete + * + * 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 . + * + * 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) + */ + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + + /* + * special case: ipsec core modular with this static algo inside: + * must avoid MODULE magic for this file + */ + #if CONFIG_KLIPS_MODULE && CONFIG_KLIPS_ENC_CRYPTOAPI + #undef MODULE + #endif + + #include + #include + + #include /* printk() */ + #include /* error codes */ + #include /* size_t */ + #include + + /* 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 + + #include "libreswan.h" + #include "libreswan/ipsec_alg.h" + #include "libreswan/ipsec_policy.h" + + #include + #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 + #include + #include + + #define CIPHERNAME_AES "aes" + #define CIPHERNAME_1DES "des" + #define CIPHERNAME_3DES "des3_ede" + #define CIPHERNAME_BLOWFISH "blowfish" + #define CIPHERNAME_CAST "cast5" + #define CIPHERNAME_SERPENT "serpent" + #define CIPHERNAME_TWOFISH "twofish" + + #define ESP_SERPENT 252 /* from ipsec drafts */ + #define ESP_TWOFISH 253 /* from ipsec drafts */ + + #define DIGESTNAME_MD5 "md5" + #define DIGESTNAME_SHA1 "sha1" + + MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); + static int debug_crypto=0; + static int test_crypto=0; + static int excl_crypto=0; + #ifdef module_param + module_param(debug_crypto, int, 0664); + module_param(test_crypto, int, 0664); + module_param(excl_crypto, int, 0664); + #else + MODULE_PARM(debug_crypto, "i"); + MODULE_PARM(test_crypto, "i"); + MODULE_PARM(excl_crypto, "i"); + #endif + + static int noauto = 0; + MODULE_PARM(noauto,"i"); + MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones"); + + #ifdef CONFIG_KLIPS_ENC_1DES + static int des_ede1[] = {-1, -1}; + #endif + 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}; + + #ifdef module_param_array + #ifdef CONFIG_KLIPS_ENC_1DES + module_param_array(des_ede1,int,NULL,0); + #endif + module_param_array(des_ede3,int,NULL,0); + module_param_array(aes,int,NULL,0); + module_param_array(blowfish,int,NULL,0); + module_param_array(cast,int,NULL,0); + module_param_array(serpent,int,NULL,0); + module_param_array(twofish,int,NULL,0); + #else + #ifdef CONFIG_KLIPS_ENC_1DES + MODULE_PARM(des_ede1,"1-2i"); + #endif + 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"); + #endif + MODULE_PARM_DESC(des_ede1, "0: disable | 1: force_enable | min,max: dontuse"); + 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_common:{ ixt_support:{ ias_id: ESP_AES}}}}, + { CIPHERNAME_TWOFISH, 16, 128, 256, twofish, { ixt_common:{ ixt_support:{ ias_id: ESP_TWOFISH,}}}}, + { CIPHERNAME_SERPENT, 16, 128, 256, serpent, { ixt_common:{ ixt_support:{ ias_id: ESP_SERPENT,}}}}, + { CIPHERNAME_CAST, 8, 128, 128, cast , { ixt_common:{ ixt_support:{ ias_id: ESP_CAST,}}}}, + { CIPHERNAME_BLOWFISH, 8, 96, 448, blowfish, { ixt_common:{ ixt_support:{ ias_id: ESP_BLOWFISH,}}}}, + { CIPHERNAME_3DES, 8, 192, 192, des_ede3, { ixt_common:{ ixt_support:{ ias_id: ESP_3DES,}}}}, + #ifdef CONFIG_KLIPS_ENC_1DES + { CIPHERNAME_1DES, 8, 64, 64, des_ede1, { ixt_common:{ ixt_support:{ ias_id: ESP_DES,}}}}, + #endif + { 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_common.ixt_version = IPSEC_ALG_VERSION; + cptr->alg.ixt_common.ixt_module = THIS_MODULE; + atomic_set (& cptr->alg.ixt_common.ixt_refcnt, 0); + strncpy (cptr->alg.ixt_common.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_common.ixt_name)); + + cptr->alg.ixt_common.ixt_blocksize=cptr->blocksize; + cptr->alg.ixt_common.ixt_support.ias_keyminbits=cptr->minbits; + cptr->alg.ixt_common.ixt_support.ias_keymaxbits=cptr->maxbits; + cptr->alg.ixt_common.ixt_state = 0; + if (excl_crypto) cptr->alg.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL; + cptr->alg.ixt_e_keylen=cptr->alg.ixt_common.ixt_support.ias_keymaxbits/8; + cptr->alg.ixt_e_ctx_size = 0; + cptr->alg.ixt_common.ixt_support.ias_exttype = 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_common.ixt_data = cptr; + + ret=register_ipsec_alg_enc(&cptr->alg); + printk(KERN_INFO "KLIPS cryptoapi interface: " + "alg_type=%d alg_id=%d name=%s " + "keyminbits=%d keymaxbits=%d, %s(%d)\n", + cptr->alg.ixt_common.ixt_support.ias_exttype, + cptr->alg.ixt_common.ixt_support.ias_id, + cptr->alg.ixt_common.ixt_name, + cptr->alg.ixt_common.ixt_support.ias_keyminbits, + cptr->alg.ixt_common.ixt_support.ias_keymaxbits, + ret ? "not found" : "found", 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_crypto > 0) + printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" + "name=%s key_e=%p \n", + alg->ixt_common.ixt_name, key_e); + if (!key_e) { + printk(KERN_ERR "klips_debug: _capi_destroy_key:" + "name=%s NULL key_e!\n", + alg->ixt_common.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_common.ixt_data; + if (!cptr) { + printk(KERN_ERR "_capi_new_key(): " + "NULL ixt_data (?!) for \"%s\" algo\n" + , alg->ixt_common.ixt_name); + goto err; + } + if (debug_crypto > 0) + printk(KERN_DEBUG "klips_debug:_capi_new_key:" + "name=%s cptr=%p key=%p keysize=%d\n", + alg->ixt_common.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_common.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_common.ixt_name, keylen); + crypto_free_tfm(tfm); + tfm=NULL; + } + err: + if (debug_crypto > 0) + printk(KERN_DEBUG "klips_debug:_capi_new_key:" + "name=%s key=%p keylen=%d tfm=%p\n", + alg->ixt_common.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_crypto > 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_crypto > 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_crypto>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(cptr->alg.ixt_common.ixt_support.ias_name == NULL) { + cptr->alg.ixt_common.ixt_support.ias_name = cptr->ciphername; + } + + if( setup_cipher(cptr->ciphername) ) { + if (debug_crypto > 0) + printk(KERN_DEBUG "klips_debug:" + "setup_cipher_list():" + "ciphername=%s found\n" + , cptr->ciphername); + + if (setup_ipsec_alg_capi_cipher(cptr) != 0) { + printk(KERN_ERR "klips_debug:" + "setup_cipher_list():" + "ciphername=%s failed ipsec_alg_register\n" + , cptr->ciphername); + } + } else { + printk(KERN_INFO "KLIPS: 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_common.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_common.ixt_state & IPSEC_ALG_ST_REGISTERED) { + test_ret=ipsec_alg_test( + cptr->alg.ixt_common.ixt_support.ias_exttype, + cptr->alg.ixt_common.ixt_support.ias_id, + test_crypto); + printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", + cptr->alg.ixt_common.ixt_support.ias_exttype, + cptr->alg.ixt_common.ixt_support.ias_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_crypto) { + 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 + + #endif /* NO_CRYPTOAPI_SUPPORT */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_esp.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_esp.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_esp.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_esp.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,547 ---- + /* + * processing code for ESP + * Copyright (C) 2003 Michael Richardson + * + * 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 . + * + * 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 AUTOCONF_INCLUDED + #include + #endif + #include + + #define __NO_VERSION__ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *lock* */ + # endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + + #include + #include + + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_rcv.h" + #include "libreswan/ipsec_xmit.h" + + #include "libreswan/ipsec_auth.h" + + #ifdef CONFIG_KLIPS_ESP + #include "libreswan/ipsec_esp.h" + #endif /* CONFIG_KLIPS_ESP */ + + #include "libreswan/ipsec_proto.h" + #include "libreswan/ipsec_alg.h" + + #ifdef CONFIG_KLIPS_DEBUG + #define ESP_DMP(_x,_y,_z) if(debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z) + #else + #define ESP_DMP(_x,_y,_z) + #endif + + #ifdef CONFIG_KLIPS_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_transport_header(skb); + 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; + //unsigned char *idat = (unsigned char *)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_transport_header(skb)[irs->ilen]); + + 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; + + 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; + } + aa = irs->authfuncs; + + /* copy the initialized keying material */ + memcpy(&tctx, irs->ictx, irs->ictx_len); + + #ifdef HASH_DEBUG + ESP_DMP("ictx", irs->ictx, irs->ictx_len); + + ESP_DMP("mac_esp", (caddr_t)espp, irs->ilen); + #endif + (*aa->update)((void *)&tctx, (caddr_t)espp, irs->ilen); + + (*aa->final)(irs->hash, (void *)&tctx); + + #ifdef HASH_DEBUG + ESP_DMP("hash1", irs->hash, aa->hashlen); + #endif + + memcpy(&tctx, irs->octx, irs->octx_len); + + #ifdef HASH_DEBUG + ESP_DMP("octx", irs->octx, irs->octx_len); + #endif + + (*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 i; + int pad = 0, padlen; + int badpad = 0; + int esphlen = 0; + __u8 *idat; /* pointer to content to be decrypted/authenticated */ + int encaplen = 0; + struct sk_buff *skb; + struct ipsec_alg_enc *ixt_e=NULL; + + skb=irs->skb; + + idat = skb_transport_header(skb); + + /* encaplen is the distance between the end of the IP + * header and the beginning of the ESP header. + * on ESP headers it is zero, but on UDP-encap ESP + * it includes the space for the UDP header. + * + * Note: UDP-encap code has already moved the + * skb->data forward to accomodate this. + */ + encaplen = skb_transport_header(skb) - (skb_network_header(skb) + irs->iphlen); + + ixt_e=ipsp->ips_alg_enc; + esphlen = ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8; + KLIPS_PRINT(debug_rcv, + "klips_debug:ipsec_rcv: " + "encalg=%d esphlen=%d\n", + ipsp->ips_encalg, esphlen); + + idat += esphlen; + irs->ilen -= esphlen; + + if (ipsec_alg_esp_encrypt(ipsp, + idat, irs->ilen, espp->esp_iv, + IPSEC_ALG_DECRYPT) <= 0) { + KLIPS_ERROR(debug_rcv, "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; + } + + ESP_DMP("postdecrypt", idat, irs->ilen); + + 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: 0x 0x ...\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. + * + * XXX this is really unnecessary, since odds we are in tunnel + * mode, and we will be *removing* this IP header. + * + */ + memmove((void *)(idat - irs->iphlen), + (void *)(skb_network_header(skb)), irs->iphlen); + + ESP_DMP("esp postmove", (idat - irs->iphlen), + irs->iphlen + irs->ilen); + + /* 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); + skb_set_network_header(skb, ipsec_skb_offset(skb, idat - irs->iphlen)); + irs->ipp = ip_hdr(skb); + + ESP_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) + { + #ifdef CONFIG_KLIPS_ENC_3DES + __u32 iv[2]; + #endif + struct esphdr *espp; + int ilen = 0; + int padlen = 0, i; + unsigned char *dat; + unsigned char *idat, *pad; + __u8 hash[AH_AMAX]; + union { + #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + MD5_CTX md5; + #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + SHA1_CTX sha1; + #endif /* CONFIG_KLIPS_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_KLIPS_ENC_3DES) + #ifdef CONFIG_KLIPS_ENC_3DES + case ESP_3DES: + #endif /* CONFIG_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_ENC_3DES */ + default: + ixs->stats->tx_errors++; + return IPSEC_XMIT_ESP_BADALG; + } + + switch(ixs->ipsp->ips_encalg) { + #if defined(CONFIG_KLIPS_ENC_3DES) + #ifdef CONFIG_KLIPS_ENC_3DES + case ESP_3DES: + #endif /* CONFIG_KLIPS_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_KLIPS_ENC_3DES) */ + default: + ixs->stats->tx_errors++; + return IPSEC_XMIT_ESP_BADALG; + } + + switch(ixs->ipsp->ips_authalg) { + #ifdef CONFIG_KLIPS_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)); + osMD5Update(&tctx.md5, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); + ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Final(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)); + osMD5Update(&tctx.md5, hash, AHMD596_ALEN); + ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Final(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_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_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_KLIPS_AUTH_HMAC_SHA1 */ + case AH_NONE: + break; + default: + ixs->stats->tx_errors++; + return IPSEC_XMIT_AH_BADALG; + } + + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, espp)); + + return IPSEC_XMIT_OK; + } + + + struct xform_functions esp_xform_funcs[]={ + { + protocol: IPPROTO_ESP, + 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, + }, + }; + + #ifndef CONFIG_XFRM_ALTERNATE_STACK + #ifdef NET_26 + struct inet_protocol esp_protocol = { + .handler = ipsec_rcv, + .no_policy = 1, + }; + #else + 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 /* NET_26 */ + #endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + #endif /* !CONFIG_KLIPS_ESP */ + + /* + * Local variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_init.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_init.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_init.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_init.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,454 ---- + /* + * @(#) Initialization code. + * Copyright (C) 1996, 1997 John Ioannidis. + * Copyright (C) 1998 - 2002 Richard Guy Briggs + * 2001 - 2004 Michael Richardson + * + * 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 . + * + * 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. + * + */ + + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include /* struct sockaddr_in */ + #include + #include /* get_random_bytes() */ + #include + + #include + + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* 23_SPINLOCK */ + # include /* *lock* */ + # endif /* 23_SPINLOCK */ + #endif /* SPINLOCK */ + + #include + + #ifdef CONFIG_PROC_FS + # include + #endif /* CONFIG_PROC_FS */ + + #ifdef NETLINK_SOCK + # include + #else + # include + #endif + + #include "libreswan/radij.h" + + #include "libreswan/ipsec_life.h" + #include "libreswan/ipsec_stats.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_mast.h" + + #include "libreswan/ipsec_rcv.h" + #include "libreswan/ipsec_xmit.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + + #ifdef CONFIG_KLIPS_IPCOMP + # include "libreswan/ipcomp.h" + #endif /* CONFIG_KLIPS_IPCOMP */ + + #include "libreswan/ipsec_proto.h" + #include "libreswan/ipsec_alg.h" + + #include + #include + + #if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + #include + #endif + + #ifndef HAVE_UDP_ENCAP_CONVERT + # if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(HAVE_XFRM4_UDP_REGISTER) + # warning "You are trying to build KLIPS2.6 with NAT-T support, but you did not" + # error "properly apply the NAT-T patch to your 2.6 kernel source tree." + # endif + #endif + + #if !defined(CONFIG_KLIPS_ESP) && !defined(CONFIG_KLIPS_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 + + struct prng ipsec_prng; + + + #if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + xfrm4_rcv_encap_t klips_old_encap = NULL; + #endif + + 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 + + /* + * inet_*_protocol returns void on 2.4.x, int on 2.6.x + * So we need our own wrapper + */ + #ifdef NET_26 + static inline int + libreswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol, char *protstr) + { + int err = inet_add_protocol(prot, protocol); + if (err) + printk(KERN_ERR "KLIPS: can not register %s protocol - recompile with CONFIG_INET_%s disabled or as module\n", protstr,protstr); + return err; + } + + static inline int + libreswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol) + { + return inet_del_protocol(prot, protocol); + } + + #else + static inline int + libreswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol) + { + inet_add_protocol(prot); + return 0; + } + + static inline int + libreswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol) + { + inet_del_protocol(prot); + return 0; + } + + #endif + + /* void */ + int + ipsec_klips_init(void) + { + int error = 0; + unsigned char seed[256]; + #ifdef CONFIG_KLIPS_ENC_3DES + extern int des_check_key; + + /* turn off checking of keys */ + des_check_key=0; + #endif /* CONFIG_KLIPS_ENC_3DES */ + + KLIPS_PRINT(1, "klips_info:ipsec_init: " + "KLIPS startup, Libreswan KLIPS IPsec stack version: %s\n", + ipsec_version_code()); + + error = ipsec_xmit_state_cache_init (); + if (error) + goto error_xmit_state_cache; + + error = ipsec_rcv_state_cache_init (); + if (error) + goto error_rcv_state_cache; + + error |= ipsec_proc_init(); + if (error) + goto error_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(); + if (error) + goto error_sadb_init; + + error |= ipsec_radijinit(); + if (error) + goto error_radijinit; + + error |= pfkey_init(); + if (error) + goto error_pfkey_init; + + error |= register_netdevice_notifier(&ipsec_dev_notifier); + if (error) + goto error_netdev_notifier; + + #ifdef CONFIG_XFRM_ALTERNATE_STACK + error = xfrm_register_alternate_rcv (ipsec_rcv); + if (error) + goto error_xfrm_register; + + #else // CONFIG_XFRM_ALTERNATE_STACK + + #ifdef CONFIG_KLIPS_ESP + error |= libreswan_inet_add_protocol(&esp_protocol, IPPROTO_ESP,"ESP"); + if (error) + goto error_libreswan_inet_add_protocol_esp; + + #endif /* CONFIG_KLIPS_ESP */ + + #ifdef CONFIG_KLIPS_AH + error |= libreswan_inet_add_protocol(&ah_protocol, IPPROTO_AH,"AH"); + if (error) + goto error_libreswan_inet_add_protocol_ah; + #endif /* CONFIG_KLIPS_AH */ + + /* we never actually link IPCOMP to the stack */ + #ifdef IPCOMP_USED_ALONE + #ifdef CONFIG_KLIPS_IPCOMP + error |= libreswan_inet_add_protocol(&comp_protocol, IPPROTO_COMP,"IPCOMP"); + if (error) + goto error_libreswan_inet_add_protocol_comp; + #endif /* CONFIG_KLIPS_IPCOMP */ + #endif + + #endif // CONFIG_XFRM_ALTERNATE_STACK + + error |= ipsec_tunnel_init_devices(); + if (error) + goto error_tunnel_init_devices; + + error |= ipsec_mast_init_devices(); + + #if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + /* register our ESP-UDP handler */ + if(udp4_register_esp_rcvencap(klips26_rcv_encap + , &klips_old_encap)!=0) { + printk(KERN_ERR "KLIPS: can not register klips_rcv_encap function\n"); + } + #endif + + + #ifdef CONFIG_SYSCTL + error |= ipsec_sysctl_register(); + if (error) + goto error_sysctl_register; + #endif + + ipsec_alg_init(); + + get_random_bytes((void *)seed, sizeof(seed)); + prng_init(&ipsec_prng, seed, sizeof(seed)); + + return error; + + // undo ipsec_sysctl_register + error_sysctl_register: + ipsec_tunnel_cleanup_devices(); + error_tunnel_init_devices: + #ifdef CONFIG_XFRM_ALTERNATE_STACK + xfrm_deregister_alternate_rcv(ipsec_rcv); + error_xfrm_register: + #else // CONFIG_XFRM_ALTERNATE_STACK + #ifdef IPCOMP_USED_ALONE + #ifdef CONFIG_KLIPS_IPCOMP + error_libreswan_inet_add_protocol_comp: + libreswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP); + #endif /* CONFIG_KLIPS_IPCOMP */ + #endif + #ifdef CONFIG_KLIPS_AH + error_libreswan_inet_add_protocol_ah: + libreswan_inet_del_protocol(&ah_protocol, IPPROTO_AH); + #endif + #ifdef CONFIG_KLIPS_ESP + error_libreswan_inet_add_protocol_esp: + libreswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP); + #endif + #endif + unregister_netdevice_notifier(&ipsec_dev_notifier); + error_netdev_notifier: + pfkey_cleanup(); + error_pfkey_init: + ipsec_radijcleanup(); + error_radijinit: + ipsec_sadb_cleanup(0); + ipsec_sadb_free(); + error_sadb_init: + error_proc_init: + // ipsec_proc_init() does not cleanup after itself, so we have to do it here + // TODO: ipsec_proc_init() should roll back what it chaned on failure + ipsec_proc_cleanup(); + ipsec_rcv_state_cache_cleanup (); + error_rcv_state_cache: + ipsec_xmit_state_cache_cleanup (); + error_xmit_state_cache: + return error; + } + + + /* void */ + int + ipsec_cleanup(void) + { + int error = 0; + + #ifdef CONFIG_SYSCTL + ipsec_sysctl_unregister(); + #endif + #if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + if(udp4_unregister_esp_rcvencap(klips_old_encap) < 0) { + printk(KERN_ERR "KLIPS: can not unregister klips_rcv_encap function\n"); + } + #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"); + + #ifdef CONFIG_XFRM_ALTERNATE_STACK + + xfrm_deregister_alternate_rcv(ipsec_rcv); + + #else // CONFIG_XFRM_ALTERNATE_STACK + + /* we never actually link IPCOMP to the stack */ + #ifdef IPCOMP_USED_ALONE + #ifdef CONFIG_KLIPS_IPCOMP + if (libreswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP) < 0) + printk(KERN_INFO "klips_debug:ipsec_cleanup: " + "comp close: can't remove protocol\n"); + #endif /* CONFIG_KLIPS_IPCOMP */ + #endif /* IPCOMP_USED_ALONE */ + + #ifdef CONFIG_KLIPS_AH + if (libreswan_inet_del_protocol(&ah_protocol, IPPROTO_AH) < 0) + printk(KERN_INFO "klips_debug:ipsec_cleanup: " + "ah close: can't remove protocol\n"); + #endif /* CONFIG_KLIPS_AH */ + + #ifdef CONFIG_KLIPS_ESP + if (libreswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP) < 0) + printk(KERN_INFO "klips_debug:ipsec_cleanup: " + "esp close: can't remove protocol\n"); + #endif /* CONFIG_KLIPS_ESP */ + + #endif // CONFIG_XFRM_ALTERNATE_STACK + + 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_rcv_state_cache_cleanup (); + ipsec_xmit_state_cache_cleanup (); + + ipsec_rcv_state_cache_cleanup (); + ipsec_xmit_state_cache_cleanup (); + + ipsec_proc_cleanup(); + + prng_final(&ipsec_prng); + + return error; + } + + #ifdef MODULE + int + init_module(void) + { + int error = 0; + + error |= ipsec_klips_init(); + + return error; + } + + #ifndef NET_26 + void + cleanup_module(void) + { + KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ + "klips_debug:cleanup_module: " + "calling ipsec_cleanup.\n"); + + ipsec_cleanup(); + + KLIPS_PRINT(1, "klips_info:cleanup_module: " + "ipsec module unloaded.\n"); + } + #endif + #endif /* MODULE */ + + /* + * + * Local variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_ipcomp.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_ipcomp.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_ipcomp.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_ipcomp.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,254 ---- + /* + * processing code for IPCOMP + * Copyright (C) 2003 Michael Richardson + * + * 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 . + * + * 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 AUTOCONF_INCLUDED + #include + #endif + #include + + #define __NO_VERSION__ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *lock* */ + # endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + + #include + + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_rcv.h" + #include "libreswan/ipsec_xmit.h" + + #include "libreswan/ipsec_auth.h" + + #ifdef CONFIG_KLIPS_IPCOMP + #include "libreswan/ipsec_ipcomp.h" + #endif /* CONFIG_KLIPS_IPCOMP */ + + #include "libreswan/ipsec_proto.h" + + #ifdef CONFIG_KLIPS_IPCOMP + enum ipsec_rcv_value + ipsec_rcv_ipcomp_checks(struct ipsec_rcv_state *irs, + struct sk_buff *skb) + { + int ipcompminlen; + + ipcompminlen = 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_transport_header(skb); + 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_transport_header(skb), skb->len); + + if(ipsp == NULL) { + return IPSEC_RCV_SAIDNOTFOUND; + } + + if(sysctl_ipsec_inbound_policy_check && + ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) != (ntohl(irs->said.spi) & 0x0000ffff)) && + (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 = KLIPS_SATOT(debug_rcv, &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 = ip_hdr(skb); + #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_KLIPS_DEBUG + unsigned int old_tot_len = ntohs(ixs->iph->tot_len); + #endif /* CONFIG_KLIPS_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 = ip_hdr(ixs->skb); + #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_KLIPS_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_KLIPS_DEBUG */ + + return IPSEC_XMIT_OK; + } + + struct xform_functions ipcomp_xform_funcs[]={ + { + protocol: IPPROTO_COMP, + 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) */ + #ifndef CONFIG_XFRM_ALTERNATE_STACK + #ifdef CONFIG_KLIPS_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_KLIPS_IPCOMP */ + #endif /* CONFIG_XFRM_ALTERNATE_STACK */ + #endif + + #endif /* CONFIG_KLIPS_IPCOMP */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_ipip.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_ipip.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_ipip.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_ipip.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,123 ---- + /* + * processing code for IPIP + * Copyright (C) 2003 Michael Richardson + * + * 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 . + * + * 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 AUTOCONF_INCLUDED + #include + #endif + #include + + #define __NO_VERSION__ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *lock* */ + # endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + + #include + + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_rcv.h" + #include "libreswan/ipsec_xmit.h" + + #include "libreswan/ipsec_auth.h" + #include "libreswan/ipsec_ipip.h" + #include "libreswan/ipsec_param.h" + + #include "libreswan/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 = ip_hdr(ixs->skb)->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; + } + ixs->iph->ttl = SYSCTL_IPSEC_DEFAULT_TTL; + 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 + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ip_hdr(ixs->skb))); + #endif /* NET_21 */ + return IPSEC_XMIT_OK; + } + + struct xform_functions ipip_xform_funcs[]={ + { + protocol: IPPROTO_IPIP, + 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, + }, + }; + + + + + + + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_kern24.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_kern24.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_kern24.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_kern24.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,74 ---- + /* + * Copyright 2005 (C) Michael Richardson + * + * This is a file of functions which are present in 2.6 kernels, + * but are not available by default in the 2.4 series. + * + * As such this code is usually from the Linux kernel, and is covered by + * GPL. + * + * 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 . + * + * 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. + * + * $Id: ipsec_kern24.c,v 1.2 2005/05/20 03:19:18 mcr Exp $ + * + */ + + #include + #include + #include + + /* + * printk rate limiting, lifted from the networking subsystem. + * + * This enforces a rate limit: not more than one kernel message + * every printk_ratelimit_jiffies to make a denial-of-service + * attack impossible. + */ + static spinlock_t ratelimit_lock = SPIN_LOCK_UNLOCKED; + + int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst) + { + static unsigned long toks = 10*5*HZ; + static unsigned long last_msg; + static int missed; + unsigned long flags; + unsigned long now = jiffies; + + spin_lock_irqsave(&ratelimit_lock, flags); + toks += now - last_msg; + last_msg = now; + if (toks > (ratelimit_burst * ratelimit_jiffies)) + toks = ratelimit_burst * ratelimit_jiffies; + if (toks >= ratelimit_jiffies) { + int lost = missed; + missed = 0; + toks -= ratelimit_jiffies; + spin_unlock_irqrestore(&ratelimit_lock, flags); + if (lost) + printk(KERN_WARNING "printk: %d messages suppressed.\n", lost); + return 1; + } + missed++; + spin_unlock_irqrestore(&ratelimit_lock, flags); + return 0; + } + + /* minimum time in jiffies between messages */ + int printk_ratelimit_jiffies = 5*HZ; + + /* number of messages we send before ratelimiting */ + int printk_ratelimit_burst = 10; + + int printk_ratelimit(void) + { + return __printk_ratelimit(printk_ratelimit_jiffies, + printk_ratelimit_burst); + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_life.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_life.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_life.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_life.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,221 ---- + /* + * @(#) lifetime structure utilities + * + * Copyright (C) 2001 Richard Guy Briggs + * and Michael Richardson + * + * 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 . + * + * 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. + * + * + */ + + /* + * 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 + #ifndef AUTOCONF_INCLUDED + #include + #endif /* for CONFIG_IP_FORWARD */ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #include /* struct device, struct net_device_stats and other headers */ + #include /* eth_type_trans */ + #include + #include + #include + + #include "libreswan/radij.h" + #include "libreswan/ipsec_life.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_eroute.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + + #include "libreswan/ipsec_sa.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_ipe4.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + + #ifdef CONFIG_KLIPS_IPCOMP + #include "libreswan/ipcomp.h" + #endif /* CONFIG_KLIPS_IPCOMP */ + + #include + #include + + #include "libreswan/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 != K_SADB_SASTATE_DYING) { + pfkey_expire(ips, 0); + } + ips->ips_state = K_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; + } + } + } + + + /* + * + * Local variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_mast.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_mast.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_mast.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_mast.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,841 ---- + /* + * IPSEC MAST code. + * Copyright (C) 2005 Michael Richardson + * + * 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 . + * + * 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.7 2005/04/29 05:10:22 mcr Exp $"; + + #define __NO_VERSION__ + #include + #ifndef AUTOCONF_INCLUDED + #include + #endif /* for CONFIG_IP_FORWARD */ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include + #include + #include + #include + + #include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + + #include + + #include /* icmp_send() */ + #include + #ifdef NETDEV_23 + # include + #endif /* NETDEV_23 */ + + #include + + #include "libreswan/ipsec_kversion.h" + #include "libreswan/radij.h" + #include "libreswan/ipsec_life.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_eroute.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_sa.h" + #include "libreswan/ipsec_xmit.h" + #include "libreswan/ipsec_mast.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_ipe4.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + #include "libreswan/ipsec_kern24.h" + + #include + #include + + #include "libreswan/ipsec_proto.h" + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + #include + #endif + + int ipsec_mastdevice_count = -1; + int debug_mast; + + static __u32 zeroes[64]; + + DEBUG_NO_STATIC int + ipsec_mast_open(struct net_device *dev) + { + struct mastpriv *prv = dev->priv; + + prv = prv; + + /* + * Can't open until attached. + */ + + KLIPS_PRINT(debug_mast & DB_MAST_INIT, + "klips_debug:ipsec_mast_open: " + "dev = %s\n", + dev->name); + + return 0; + } + + DEBUG_NO_STATIC int + ipsec_mast_close(struct net_device *dev) + { + return 0; + } + + static inline int ipsec_mast_xmit2(struct sk_buff *skb) + { + return dst_output(skb); + } + + int ip_cmsg_send_ipsec(struct cmsghdr *cmsg, struct ipcm_cookie *ipc) + { + struct ipsec_sa *sa1; + xfrm_sec_unique_t *ref; + struct sec_path *sp; + + if(cmsg->cmsg_len != CMSG_LEN(sizeof(xfrm_sec_unique_t))) { + return -EINVAL; + } + + ref = (xfrm_sec_unique_t *)CMSG_DATA(cmsg); + + sp = secpath_dup(NULL); + if(!sp) { + return -EINVAL; + } + + sp->ref = *ref; + KLIPS_PRINT(debug_mast, "sending with saref=%u\n", sp->ref); + + sa1 = ipsec_sa_getbyref(sp->ref); + if(sa1 && sa1->ips_out) { + ipc->oif = sa1->ips_out->ifindex; + KLIPS_PRINT(debug_mast, "setting oif: %d\n", ipc->oif); + } + ipsec_sa_put(sa1); + + ipc->sp = sp; + + return 0; + } + + #if 0 + /* Paul: This seems to be unused dead code */ + 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->ifindex /* 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 < skb_network_header(ixs->skb) - 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)(skb_network_header(ixs->skb) - ixs->skb->data), + ixs->skb->len); + return IPSEC_XMIT_PUSHPULLERR; + } + __skb_pull(ixs->skb, skb_network_header(ixs->skb)- 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; + } + #endif + + /* + * 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 net_device *dev) + { + struct ipsec_xmit_state ixs_mem; + struct ipsec_xmit_state *ixs = &ixs_mem; + enum ipsec_xmit_value stat = IPSEC_XMIT_OK; + IPsecSAref_t SAref; + + if(skb == NULL) { + printk("mast start_xmit passed NULL\n"); + return 0; + } + + memset(&ixs_mem, 0, sizeof(struct ipsec_xmit_state)); + + ixs->skb = skb; + SAref = 0; + if(skb->nfmark & 0x80000000) { + SAref = NFmark2IPsecSAref(skb->nfmark); + KLIPS_PRINT(debug_mast, "getting SAref=%d from nfmark\n", + SAref); + } + + if(skb->sp && skb->sp->ref != IPSEC_SAREF_NULL) { + SAref = skb->sp->ref; + KLIPS_PRINT(debug_mast, "getting SAref=%d from sec_path\n", + SAref); + } + + KLIPS_PRINT(debug_mast, "skb=%p\n", skb); + + ipsec_xmit_sanity_check_skb(ixs); + + ixs->ipsp = ipsec_sa_getbyref(SAref); + if(ixs->ipsp == NULL) { + KLIPS_ERROR(debug_mast, "%s: no SA for saref=%d (sp=%p)\n", + dev->name, SAref, skb->sp); + ipsec_kfree_skb(skb); + return 0; + } + + /* + * we should be calculating the MTU by looking up a route + * based upon the destination in the SA, and then cache + * it into the SA, but we don't do that right now. + */ + ixs->cur_mtu = 1460; + ixs->physmtu = 1460; + + stat = ipsec_xmit_encap_bundle_2(ixs); + + if(stat != IPSEC_XMIT_OK) { + /* SA processing failed */ + /* log it somehow */ + goto failed; + } + + /* do any final NAT-encapsulation */ + stat = ipsec_nat_encap(ixs); + if(stat != IPSEC_XMIT_OK) { + goto failed; + } + + /* now send the packet again */ + { + struct flowi fl; + + memset(&fl, 0, sizeof(fl)); + ipsec_xmit_send(ixs, &fl); + } + + failed: + ipsec_xmit_cleanup(ixs); + + if(ixs->ipsp) { + ipsec_sa_put(ixs->ipsp); + ixs->ipsp=NULL; + } + if(ixs->skb) { + ipsec_kfree_skb(ixs->skb); + ixs->skb=NULL; + } + return 0; + } + + DEBUG_NO_STATIC struct net_device_stats * + ipsec_mast_get_stats(struct net_device *dev) + { + return &(((struct mastpriv *)(dev->priv))->mystats); + } + + #if 0 + /* + * 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 net_device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len) + { + struct mastpriv *prv = dev->priv; + struct net_device_stats *stats; /* This device's statistics */ + int ret = 0; + + 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\n", + 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); + + /* 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; + } + } else { + KLIPS_PRINT(debug_mast, + "klips_debug:ipsec_mast_hard_header: " + "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); + } + + return ret; + } + + DEBUG_NO_STATIC int + ipsec_mast_rebuild_header(struct sk_buff *skb) + { + struct mastpriv *prv = skb->dev->priv; + + prv = prv; + return 0; + } + + DEBUG_NO_STATIC int + ipsec_mast_set_mac_address(struct net_device *dev, void *addr) + { + struct mastpriv *prv = dev->priv; + + prv = prv; + return 0; + + } + + DEBUG_NO_STATIC void + ipsec_mast_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr) + { + struct mastpriv *prv = dev->priv; + + 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; + } + + KLIPS_PRINT(debug_mast & DB_MAST_REVEC, + "klips_debug:ipsec_mast: " + "Revectored cache_update\n"); + return; + } + #endif + + 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 net_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; + } + + DEBUG_NO_STATIC int + ipsec_mast_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { + struct ipsecmastconf *cf = (struct ipsecmastconf *)&ifr->ifr_data; + struct ipsecpriv *prv = dev->priv; + + cf = cf; + prv=prv; + + 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) { + 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 net_device *dev = ptr; + struct mastpriv *priv = dev->priv; + + priv = priv; + + 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; + } + 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_probe(struct net_device *dev) + { + int i; + + KLIPS_PRINT(debug_mast, + "klips_debug:ipsec_mast_init: " + "allocating %lu bytes initialising device: %s\n", + (unsigned long) sizeof(struct mastpriv), + 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 mastpriv), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset((caddr_t)(dev->priv), 0, sizeof(struct mastpriv)); + + 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 = 8+20+20+8; + dev->mtu = 0; + dev->addr_len = 0; + dev->type = ARPHRD_NONE; + dev->tx_queue_len = 10; + memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ + + /* New-style flags. */ + dev->flags = IFF_NOARP; + + /* We're done. Have I forgotten anything? */ + return 0; + } + + struct net_device *mastdevices[IPSEC_NUM_IFMAX]; + int mastdevices_max=-1; + + int ipsec_mast_createnum(int vifnum) + { + struct net_device *im; + int vifentry; + + if(vifnum > IPSEC_NUM_IFMAX) { + return -ENOENT; + } + + if(mastdevices[vifnum]!=NULL) { + return -EEXIST; + } + + /* no identical device */ + if(vifnum > mastdevices_max) { + mastdevices_max=vifnum; + } + vifentry = vifnum; + + im = (struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL); + if(im == NULL) { + printk(KERN_ERR "failed to allocate space for mast%d device\n", vifnum); + return -ENOMEM; + } + + memset((caddr_t)im, 0, sizeof(struct net_device)); + snprintf(im->name, IFNAMSIZ, MAST_DEV_FORMAT, vifnum); + + #ifdef HAVE_NEXT_DEV + im->next = NULL; + #endif + im->init = ipsec_mast_probe; + + if(register_netdev(im) != 0) { + printk(KERN_ERR "ipsec_mast: failed to register %s\n", + im->name); + return -EIO; + } + + dev_hold(im); + mastdevices[vifentry]=im; + + return 0; + } + + + int + ipsec_mast_deletenum(int vifnum) + { + struct net_device *dev_ipsec; + + if(vifnum > IPSEC_NUM_IFMAX) { + return -ENOENT; + } + + dev_ipsec = mastdevices[vifnum]; + if(dev_ipsec == NULL) { + return -ENOENT; + } + + /* release reference */ + mastdevices[vifnum]=NULL; + ipsec_dev_put(dev_ipsec); + + KLIPS_PRINT(debug_tunnel, "Unregistering %s (refcnt=%d)\n", + dev_ipsec->name, + atomic_read(&dev_ipsec->refcnt)); + unregister_netdev(dev_ipsec); + KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", dev_ipsec->name); + #ifndef NETDEV_23 + kfree(dev_ipsec->name); + dev_ipsec->name=NULL; + #endif /* !NETDEV_23 */ + kfree(dev_ipsec->priv); + dev_ipsec->priv=NULL; + + return 0; + } + + + struct net_device * + ipsec_mast_get_device(int vifnum) + { + int ovifnum = vifnum; + + if(vifnum > IPSECDEV_OFFSET) { + return ipsec_tunnel_get_device(vifnum-IPSECDEV_OFFSET); + } else { + struct net_device *nd; + + if(vifnum >= MASTTRANSPORT_OFFSET) { + vifnum -= MASTTRANSPORT_OFFSET; + } + + if(vifnum <= mastdevices_max) { + nd = mastdevices[vifnum]; + + if(nd) dev_hold(nd); + return nd; + } else { + KLIPS_ERROR(debug_tunnel, + "no such vif %d (ovif=%d)\n", vifnum, ovifnum); + return NULL; + } + } + } + + unsigned int + ipsec_mast_is_transport(int vifnum) + { + if(vifnum > MASTTRANSPORT_OFFSET && vifnum priv); + dev_mast->priv=NULL; + dev_put(mastdevices[i]); + mastdevices[i]=NULL; + } + } + return error; + } + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ + + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_md5c.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_md5c.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_md5c.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_md5c.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,406 ---- + /* + * RCSID $Id: ipsec_md5c.c,v 1.10 2005/04/15 01:25:57 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 + #include + + #include "libreswan/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 here; 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 osMD5Init(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 osMD5Update (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 osMD5Final (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); + osMD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + osMD5Update (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 + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_proc.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_proc.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_proc.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_proc.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1042 ---- + /* + * @(#) /proc file system interface code. + * + * Copyright (C) 1996, 1997 John Ioannidis. + * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs + * 2001 Michael Richardson + * + * 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 . + * + * 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. + */ + + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + #define __NO_VERSION__ + #include + #include /* printk() */ + #include /* struct iphdr */ + + #include "libreswan/ipsec_kversion.h" + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct sockaddr_in */ + #include + #include /* copy_from_user */ + #include + #ifdef SPINLOCK + #ifdef SPINLOCK_23 + #include /* *lock* */ + #else /* SPINLOCK_23 */ + #include /* *lock* */ + #endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + + #include + #ifdef CONFIG_PROC_FS + #include + #endif /* CONFIG_PROC_FS */ + #ifdef NETLINK_SOCK + #include + #else + #include + #endif + + #include "libreswan/radij.h" + + #include "libreswan/ipsec_life.h" + #include "libreswan/ipsec_stats.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_xmit.h" + + #include "libreswan/ipsec_rcv.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + #include "libreswan/ipsec_kern24.h" + + #ifdef CONFIG_KLIPS_IPCOMP + #include "libreswan/ipcomp.h" + #endif /* CONFIG_KLIPS_IPCOMP */ + + #include "libreswan/ipsec_proto.h" + + #include + #include + + #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; + + #ifdef CONFIG_KLIPS_DEBUG + int debug_esp = 0; + int debug_ah = 0; + int sysctl_ipsec_inbound_policy_check = 1; + int debug_tunnel = 0; + int debug_xmit = 0; + int debug_xform = 0; + int debug_eroute = 0; + int debug_spi = 0; + int debug_radij = 0; + int debug_pfkey = 0; + int debug_rcv = 0; + int debug_netlink = 0; + int sysctl_ipsec_debug_verbose = 0; + int sysctl_ipsec_debug_ipcomp =0; + int sysctl_ipsec_icmp = 0; + int sysctl_ipsec_tos = 0; + #endif /* CONFIG_KLIPS_DEBUG */ + + #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_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_KLIPS_DEBUG + if (debug_radij & DB_RJ_DUMPTREES) + rj_dumptrees(); /* XXXXXXXXX */ + #endif /* CONFIG_KLIPS_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) { + ipsec_sa_get(sa_p); + 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_KLIPS_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_KLIPS_IPCOMP */ + + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + { + char *natttype_name; + + switch(sa_p->ips_natt_type) + { + case 0: + natttype_name="none"; + break; + 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); + } + #else + len += ipsec_snprintf(buffer + len, length-len, " natencap=na"); + #endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ + + /* we decrement by one, because this SA has been referenced in order to dump this info */ + len += ipsec_snprintf(buffer + len,length-len, " refcount=%d", + atomic_read(&sa_p->ips_refcount)-1); + + len += ipsec_snprintf(buffer+len, length-len, " ref=%d", + sa_p->ips_ref); + len += ipsec_snprintf(buffer+len, length-len, " refhim=%d", + sa_p->ips_refhim); + + if(sa_p->ips_out) { + len += ipsec_snprintf(buffer+len, length-len, " outif=%s:%d", + sa_p->ips_out->name, + sa_p->ips_transport_direct); + } + #ifdef CONFIG_KLIPS_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_KLIPS_DEBUG */ + + len += ipsec_snprintf(buffer+len, length-len, "\n"); + + ipsec_sa_put(sa_p); + + 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) + { + sa_p2 = sa_p; + while(sa_p2 != NULL) { + struct ipsec_sa *sa2n; + sa_len = satot(&sa_p2->ips_said, + 'x', sa, sizeof(sa)); + + len += ipsec_snprintf(buffer+len, length-len, "%s ", + sa_len ? sa : " (error)"); + + sa2n = sa_p2->ips_next; + sa_p2 = sa2n; + } + len += ipsec_snprintf(buffer+len, length-len, "\n"); + + 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 net_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 net_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, "Libreswan 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; + } + + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + unsigned int natt_available = 1; + #else + unsigned int natt_available = 0; + #endif + #ifdef module_param + module_param(natt_available, int, 0444); + #else + MODULE_PARM("natt_available","i"); + #endif + + IPSEC_PROCFS_DEBUG_NO_STATIC + int + ipsec_natt_get_info(char *buffer, + char **start, + off_t offset, + int length IPSEC_PROC_LAST_ARG) + { + int len = 0; + off_t begin = 0; + + len += ipsec_snprintf(buffer + len, + length-len, "%d\n", + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + 1 + #else + 0 + #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; + + KLIPS_INC_USE; + if(count > IPSEC_BIRTH_TEMPLATE_MAXLEN) { + len = IPSEC_BIRTH_TEMPLATE_MAXLEN; + } else { + len = count; + } + + if(copy_from_user(ibr->packet_template, buffer, len)) { + KLIPS_DEC_USE; + return -EFAULT; + } + ibr->packet_template_len = len; + + KLIPS_DEC_USE; + + return len; + } + + + #ifdef CONFIG_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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}, + {"natt", &proc_net_ipsec_dir, NULL, ipsec_natt_get_info, NULL, NULL}, + {"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_KLIPS_DEBUG + error |= proc_register_dynamic(&proc_net, &ipsec_klipsdebug); + #endif /* CONFIG_KLIPS_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_KLIPS_DEBUG + error |= proc_register(proc_net, &ipsec_klipsdebug); + #endif /* CONFIG_KLIPS_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_KLIPS_DEBUG + if (proc_net_unregister(ipsec_klipsdebug.low_ino) != 0) + printk("klips_debug:ipsec_cleanup: " + "cannot unregister /proc/net/ipsec_klipsdebug\n"); + #endif /* CONFIG_KLIPS_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_KLIPS_DEBUG + remove_proc_entry("ipsec_klipsdebug", proc_net); + #endif /* CONFIG_KLIPS_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 */ + } + + /* + * + * Local variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_radij.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_radij.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_radij.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_radij.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,554 ---- + /* + * 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 . + * + * 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 AUTOCONF_INCLUDED + #include + #endif + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, struct net_device_stats and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* 23_SPINLOCK */ + # include /* *lock* */ + # endif /* 23_SPINLOCK */ + #endif /* SPINLOCK */ + + #include + + #include "libreswan/ipsec_eroute.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_tunnel.h" /* struct ipsecpriv */ + #include "libreswan/ipsec_xform.h" + + #include + #include + + #include "libreswan/ipsec_proto.h" + + 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 = 0; + + 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_KLIPS_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_KLIPS_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 0; + } + + 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_KLIPS_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; ier_eaddr = *eaddr; + retrt->er_emask = *emask; + retrt->er_said = said; + retrt->er_pid = pid; + retrt->er_count = 0; + retrt->er_lasttime = jiffies/HZ; + + { + /* this is because gcc 3. doesn't like cast's as lvalues */ + struct rjtentry *rje = (struct rjtentry *)&(retrt->er_rjt); + caddr_t er = (caddr_t)&(retrt->er_eaddr); + + rje->rd_nodes->rj_key= er; + } + + 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 = KLIPS_SATOT(debug_eroute, &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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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; + } + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_rcv.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_rcv.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_rcv.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_rcv.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1859 ---- + /* + * receive code + * Copyright (C) 1996, 1997 John Ioannidis. + * Copyright (C) 1998-2003 Richard Guy Briggs. + * Copyright (C) 2004-2007 Michael Richardson + * Copyright (C) 2007-2008 Paul Wouters + * + * 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 . + * + * 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 AUTOCONF_INCLUDED + #include + #endif + #include + + #define __NO_VERSION__ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + + #include + #include + #include + #include + #include + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *lock* */ + # endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + + #include + + #include "libreswan/ipsec_kern24.h" + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_mast.h" + #include "libreswan/ipsec_rcv.h" + + #include "libreswan/ipsec_auth.h" + + #include "libreswan/ipsec_esp.h" + + #ifdef CONFIG_KLIPS_AH + #include "libreswan/ipsec_ah.h" + #endif /* CONFIG_KLIPS_AH */ + + #ifdef CONFIG_KLIPS_IPCOMP + #include "libreswan/ipsec_ipcomp.h" + #endif /* CONFIG_KLIPS_COMP */ + + #include + #include + + #include "libreswan/ipsec_proto.h" + #include "libreswan/ipsec_alg.h" + #include "libreswan/ipsec_kern24.h" + + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + #include + #endif + + /* 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 + + /* + * 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_KLIPS_AUTH_HMAC_MD5 + struct auth_alg ipsec_rcv_md5[]={ + {osMD5Init, osMD5Update, osMD5Final, AHMD596_ALEN} + }; + + #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + + #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + struct auth_alg ipsec_rcv_sha1[]={ + {SHA1Init, SHA1Update, SHA1Final, AHSHA196_ALEN} + }; + #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + + static inline void ipsec_rcv_redodebug(struct ipsec_rcv_state *irs) + { + struct iphdr * ipp = irs->ipp; + struct in_addr ipsaddr, ipdaddr; + + 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)); + } + + /* + * look up the SA from the said in the header. + * + */ + enum ipsec_rcv_value + ipsec_rcv_decap_lookup(struct ipsec_rcv_state *irs + , struct xform_functions *proto_funcs + , struct ipsec_sa **pnewipsp) + { + __u8 proto; + struct ipsec_sa *newipsp; + struct iphdr *ipp; + struct sk_buff *skb; + + skb = irs->skb; + ipp = irs->ipp; + proto = ipp->protocol; + + 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; + + /* note: rcv_checks set up the said.spi value, if appropriate */ + 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; + } + + /* If it is in larval state, drop the packet, we cannot process yet. */ + if(newipsp->ips_state == K_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 == K_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_ERROR(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_next != newipsp) { + KLIPS_ERROR(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)"); + } + + + + + + + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + if (proto == IPPROTO_ESP) { + 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 + } + + *pnewipsp = newipsp; + return IPSEC_RCV_OK; + } + + void ip_cmsg_recv_ipsec(struct msghdr *msg, struct sk_buff *skb) + { + struct ipsec_sa *sa1; + struct sec_path *sp; + xfrm_sec_unique_t refs[2]; + + sp = skb->sp; + + if(sp==NULL) return; + + KLIPS_PRINT(debug_rcv, "retrieving saref=%u from skb=%p\n", + sp->ref, skb); + + sa1 = ipsec_sa_getbyref(sp->ref); + if(sa1) { + refs[1]= sa1->ips_refhim; + } + refs[0]=sp->ref; + + put_cmsg(msg, SOL_IP, IP_IPSEC_REFINFO, + sizeof(xfrm_sec_unique_t)*2, &refs); + } + + + /* + * decapsulate a single layer of ESP/AH/IPCOMP. + * + * the following things should be setup to enter this function. + * + * irs->stats == stats structure (or NULL) + * irs->ipp = IP header. + * irs->len = total length of packet + * skb->nh.iph = ipp; + * skb->h.raw = start of payload + * irs->ipsp = NULL. + * irs->iphlen = N/A = is recalculated. + * irs->ilen = 0; + * irs->authlen = 0; + * irs->authfuncs = NULL; + * irs->skb = the skb; + * + * proto_funcs should be from ipsec_esp.c, ipsec_ah.c or ipsec_ipcomp.c. + * + */ + enum ipsec_rcv_value + ipsec_rcv_decap_once(struct ipsec_rcv_state *irs + , struct xform_functions *proto_funcs) + { + int iphlen; + __u8 proto; + struct ipsec_sa* ipsnext = NULL; /* next SA towards inside of packet */ + int replay = 0; /* replay value in AH or ESP packet */ + struct iphdr *ipp; + struct sk_buff *skb; + struct ipsec_alg_auth *ixt_a=NULL; + + skb = irs->skb; + irs->len = skb->len; + ipp = irs->ipp; + proto = ipp->protocol; + ipsec_rcv_redodebug(irs); + + iphlen = ipp->ihl << 2; + irs->iphlen=iphlen; + ipp->check= 0; /* we know the sum is good */ + + /* note: rcv_checks set up the said.spi value, if appropriate */ + if(proto_funcs->rcv_checks) { + enum ipsec_rcv_value retval = + (*proto_funcs->rcv_checks)(irs, skb); + + if(retval < 0) { + return retval; + } + } + + /* 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) { + + /* + * disconnect SA from the hash table, so it can not be + * found again. + */ + ipsec_sa_rm(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; + } + + #if 0 + /* + * This is removed for some reasons: + * 1) it needs to happen *after* authentication. + * 2) do we really care, if it authenticates, if it came + * from the wrong location? + * 3) the NAT_KA messages in IKE will also get to pluto + * and it will figure out that stuff has moved. + * 4) the 2.6 udp-esp encap function does not pass us + * the originating port number, and I can't tell + * if skb->sk is guaranteed to be valid here. + * 2005-04-16: mcr@xelerance.com + */ + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + /* + * + * XXX we should ONLY update pluto if the SA passes all checks, + * which we clearly do not now. + */ + 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; + struct sockaddr_in *psin = (struct sockaddr_in*)(newipsp->ips_addr_s); + + /** 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 [%08x:%u] (notifying pluto of change).\n", + irs->sa_len ? irs->sa : " (error)", + irs->ipsaddr_txt, irs->natt_sport, + psin->sin_addr.s_addr, + newipsp->ips_natt_sport); + if(irs->stats) { + irs->stats->rx_dropped++; + } + ipsec_sa_put(newipsp); + return IPSEC_RCV_FAILEDINBOUND; + } + } + #endif + #endif + + irs->authfuncs=NULL; + + /* authenticate, if required */ + 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 + switch(irs->ipsp->ips_authalg) { + #ifdef CONFIG_KLIPS_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_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_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_KLIPS_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; + } + + /* ilen counts number of bytes in ESP portion */ + irs->ilen = ((irs->skb->data + irs->skb->len) - skb_transport_header(irs->skb)) - 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; + } + + if(irs->authfuncs || ixt_a) { + 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_ERROR(debug_rcv & DB_RX_INAU, + "klips_debug:ipsec_rcv: " + "auth failed on incoming packet from %s (replay=%d): calculated hash=%08x%08x%08x received hash=%08x%08x%08x, dropped\n", + irs->ipsaddr_txt, + replay, + 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 */) { + + /* we need to remove it from the sadb hash, so that it can't be found again */ + ipsec_sa_rm(irs->ipsp); + + KLIPS_ERROR(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_ERROR(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; + ipp = irs->ipp = ip_hdr(skb); + irs->iphlen = ipp->ihl<<2; + skb_set_transport_header(skb, ipsec_skb_offset(skb, skb_network_header(skb) + irs->iphlen)); + + /* zero any options that there might be */ + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); + ipsec_rcv_redodebug(irs); + + /* + * 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 *)ip_hdr(skb), irs->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_next; + if(sysctl_ipsec_inbound_policy_check) { + if(ipsnext) { + if( + ipp->protocol != IPPROTO_AH + && ipp->protocol != IPPROTO_ESP + #ifdef CONFIG_KLIPS_IPCOMP + && ipp->protocol != IPPROTO_COMP + && (ipsnext->ips_said.proto != IPPROTO_COMP + || ipsnext->ips_next) + #endif /* CONFIG_KLIPS_IPCOMP */ + && ipp->protocol != IPPROTO_IPIP + && ipp->protocol != IPPROTO_ATT_HEARTBEAT /* 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_KLIPS_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_KLIPS_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; + } + + void ipsec_rcv_setoutif(struct ipsec_rcv_state *irs) + { + struct sk_buff *skb = irs->skb; + + if(skb!=NULL && irs->ipsp->ips_out) { + if(skb->dev != irs->ipsp->ips_out) { + KLIPS_PRINT(debug_rcv, + "changing originating interface from %s to %s\n", + skb->dev->name, + irs->ipsp->ips_out->name); + } + skb->dev = irs->ipsp->ips_out; + + if(skb->dev && skb->dev->get_stats) { + struct net_device_stats *stats = skb->dev->get_stats(skb->dev); + irs->stats = stats; + } + } + } + + static enum ipsec_rcv_value + ipsec_rcv_decap_ipip(struct ipsec_rcv_state *irs) + { + struct ipsec_sa *ipsp = NULL; + struct ipsec_sa* ipsnext = NULL; + struct iphdr *ipp; + struct sk_buff *skb; + enum ipsec_rcv_value result = IPSEC_RCV_DECAPFAIL; + + ipp = irs->ipp; + ipsp = irs->ipsp; + skb = irs->skb; + irs->sa_len = satot(&irs->said, 0, irs->sa, sizeof(irs->sa)); + if((ipp->protocol != IPPROTO_IPIP) && + (ipp->protocol != IPPROTO_ATT_HEARTBEAT)) { /* AT&T heartbeats to SIG/GIG */ + 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(irs->stats) { + irs->stats->rx_dropped++; + } + goto rcvleave; + } + if(sysctl_ipsec_inbound_policy_check) { + struct sockaddr_in *psin = (struct sockaddr_in*)(ipsp->ips_addr_s); + if((ipsnext = ipsp->ips_next)) { + char sa2[SATOT_BUF]; + size_t sa_len2; + sa_len2 = satot(&ipsnext->ips_said, 0, sa2, sizeof(sa2)); + 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(irs->stats) { + irs->stats->rx_dropped++; + } + goto rcvleave; + } + if(ipp->saddr != psin->sin_addr.s_addr) { + KLIPS_PRINT(debug_rcv, + "klips_debug:ipsec_rcv: " + "SA:%s, src=%s(%08x) does match expected 0x%08x.\n", + irs->sa_len ? irs->sa : " (error)", + irs->ipsaddr_txt, + ipp->saddr, psin->sin_addr.s_addr); + if(irs->stats) { + irs->stats->rx_dropped++; + } + goto rcvleave; + } + } + + ipsec_rcv_setoutif(irs); + + 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) { + 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; + } + + /* + * we need to pull up by size of IP header, + * options, but also by any UDP/ESP encap there might + * have been, and this deals with all cases. + */ + skb_pull(skb, (skb_transport_header(skb) - skb_network_header(skb))); + + /* new L3 header is where L4 payload was */ + skb_set_network_header(skb, ipsec_skb_offset(skb, skb_transport_header(skb))); + + /* now setup new L4 payload location */ + ipp = (struct iphdr *)skb_network_header(skb); + skb_set_transport_header(skb, ipsec_skb_offset(skb, skb_network_header(skb) + (ipp->ihl << 2))); + + + /* remove any saved options that we might have, + * since we have a new IP header. + */ + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); + + #if 0 + KLIPS_PRINT(debug_rcv, "csum: %d\n", ip_fast_csum((u8 *)ipp, ipp->ihl)); + #endif + + /* re-do any strings for debugging */ + irs->ipp = ipp; + ipsec_rcv_redodebug(irs); + + 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)); + 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(irs->stats) { + irs->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 */ + + result = IPSEC_RCV_OK; + + rcvleave: + return result; + } + + + /* + * core decapsulation loop for all protocols. + * + * the following things should be setup to enter this function. + * + * irs->stats == stats structure (or NULL) + * irs->ipp = IP header. + * irs->ipsp = NULL. + * irs->ilen = 0; + * irs->authlen = 0; + * irs->authfuncs = NULL; + * irs->skb = skb; + * skb->nh.iph = ipp; + * skb->h.raw = start of payload + * + */ + enum ipsec_rcv_value + ipsec_rcv_decap(struct ipsec_rcv_state *irs) + { + struct iphdr *ipp; + struct sk_buff *skb = NULL; + struct ipsec_sa *lastipsp; + enum ipsec_rcv_value irv; + struct xform_functions *proto_funcs; + int decap_stat; + + lastipsp=NULL; + + /* 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. + */ + + /* probably can go away now */ + spin_lock(&tdb_lock); + + switch(irs->ipp->protocol) { + case IPPROTO_ESP: + proto_funcs = esp_xform_funcs; + break; + + #ifdef CONFIG_KLIPS_AH + case IPPROTO_AH: + proto_funcs = ah_xform_funcs; + break; + #endif /* !CONFIG_KLIPS_AH */ + + #ifdef CONFIG_KLIPS_IPCOMP + case IPPROTO_COMP: + proto_funcs = ipcomp_xform_funcs; + break; + #endif /* !CONFIG_KLIPS_IPCOMP */ + default: + if(irs->stats) { + irs->stats->rx_errors++; + } + decap_stat = IPSEC_RCV_BADPROTO; + goto rcvleave; + } + + /* look up the first SA -- we need the protocol functions to figure + * out how to do that. + */ + { + struct ipsec_sa *newipsp; + /* look up the first SA */ + irv = ipsec_rcv_decap_lookup(irs, proto_funcs, &newipsp); + if(irv != IPSEC_RCV_OK) { + return irv; + } + + /* newipsp is already referenced by the get() function */ + irs->ipsp=newipsp; + } + + do { + ipsec_rcv_setoutif(irs); + + proto_funcs = irs->ipsp->ips_xformfuncs; + if(proto_funcs == NULL) { + decap_stat = IPSEC_RCV_BADPROTO; + goto rcvleave; + } + + if(proto_funcs->protocol != irs->ipp->protocol) { + if(proto_funcs->protocol == IPPROTO_COMP) { + /* loops like an IPCOMP that we can skip */ + goto skipipcomp; + } + + if(irs->stats) { + irs->stats->rx_errors++; + } + decap_stat = IPSEC_RCV_FAILEDINBOUND; + 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; + } + + /* okay, acted on this SA, so free any previous SA, and record a new one*/ + skipipcomp: + if(irs->ipsp) { + struct ipsec_sa *newipsp = NULL; + newipsp = irs->ipsp->ips_next; + if(newipsp) { + ipsec_sa_get(newipsp); + } + if(lastipsp) { + ipsec_sa_put(lastipsp); + } + lastipsp = irs->ipsp; + irs->ipsp=newipsp; + } + + /* end decapsulation loop here */ + } while((irs->ipp->protocol == IPPROTO_ESP + || irs->ipp->protocol == IPPROTO_AH + || irs->ipp->protocol == IPPROTO_COMP) + && irs->ipsp != NULL); + + /* end of decap loop */ + ipp =irs->ipp; + skb = irs->skb; + + /* + * if there is an IPCOMP, but we didn't process it, + * then we can just skip it + */ + #ifdef CONFIG_KLIPS_IPCOMP + if(irs->ipsp && irs->ipsp->ips_said.proto == IPPROTO_COMP) { + struct ipsec_sa *newipsp = NULL; + newipsp = irs->ipsp->ips_next; + if(newipsp) { + ipsec_sa_get(newipsp); + } + if(lastipsp) { + ipsec_sa_put(lastipsp); + } + lastipsp = irs->ipsp; + irs->ipsp=newipsp; + } + #endif /* CONFIG_KLIPS_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 = lastipsp->ips_natt_oa ? + ((struct sockaddr_in*)(lastipsp->ips_natt_oa))->sin_addr.s_addr : 0; + + if(natt_oa != 0) { + /* reset source address to what it was before NAT */ + ipp->saddr = natt_oa; + ipp->check = 0; + ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); + KLIPS_PRINT(debug_rcv, "csum: %04x\n", ipp->check); + } + } + #endif + + /* + * the SA is still locked from the loop + */ + if(irs->ipsp && irs->ipsp->ips_xformfuncs->protocol == IPPROTO_IPIP) { + enum ipsec_rcv_value decap_stat; + + decap_stat = ipsec_rcv_decap_ipip(irs); + if(decap_stat != IPSEC_RCV_OK) { + spin_unlock(&tdb_lock); + goto rcvleave; + } + } + + spin_unlock(&tdb_lock); + + if(irs->stats) { + irs->stats->rx_bytes += skb->len; + } + + /* + * if we are supposed to return the packet directly to the transport + * layer, then dump it out correctly. + */ + if(lastipsp->ips_transport_direct) { + KLIPS_PRINT(debug_rcv, "receiving packet as transport direct\n"); + skb->ip_summed=CHECKSUM_UNNECESSARY; + /* STUFF */ + } + + if(skb->sp) { + secpath_put(skb->sp); + } + skb->sp = secpath_dup(NULL); + skb->sp->ref = lastipsp->ips_ref; + + /* release the dst that was attached, since we have likely + * changed the actual destination of the packet. + */ + if(skb->dst) { + dst_release(skb->dst); + skb->dst = NULL; + } + skb->pkt_type = PACKET_HOST; + if(irs->hard_header_len && + (skb_mac_header(skb) != (skb_network_header(skb) - irs->hard_header_len)) && + (irs->hard_header_len <= skb_headroom(skb))) { + /* copy back original MAC header */ + memmove(skb_network_header(skb) - irs->hard_header_len, + skb_mac_header(skb), irs->hard_header_len); + skb_set_mac_header(skb, ipsec_skb_offset(skb, skb_network_header(skb) - irs->hard_header_len)); + } + + /* + * make sure that data now starts at IP header, since we are going + * to pass this back to ip_input (aka netif_rx). Rules for what the + * pointers wind up a different for 2.6 vs 2.4, so we just fudge it here. + */ + #ifdef NET_26 + irs->skb->data = skb_push(irs->skb, skb_transport_header(irs->skb) - skb_network_header(irs->skb)); + #else + irs->skb->data = skb_network_header(irs->skb); + { + struct iphdr *iph = ip_hdr(irs->skb); + int len = ntohs(iph->tot_len); + irs->skb->len = len; + } + #endif + + #ifdef SKB_RESET_NFCT + nf_conntrack_put(skb->nfct); + skb->nfct = NULL; + #if defined(CONFIG_NETFILTER_DEBUG) && defined(HAVE_SKB_NF_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(%s) called.\n", skb->dev->name); + netif_rx(skb); + skb=NULL; + + rcvleave: + if(lastipsp) { + ipsec_sa_put(lastipsp); + lastipsp=NULL; + } + if(irs->ipsp) { + ipsec_sa_put(irs->ipsp); + } + irs->ipsp=NULL; + + if(skb) { + ipsec_kfree_skb(skb); + } + + return(0); + } + + struct sk_buff *ipsec_rcv_unclone(struct sk_buff *skb, + struct ipsec_rcv_state *irs) + { + /* 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); + } + return skb; + + rcvleave: + ipsec_kfree_skb(skb); + return NULL; + } + + + #if !defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + /* + * decapsulate a UDP encapsulated ESP packet + */ + struct sk_buff *ipsec_rcv_natt_decap(struct sk_buff *skb + , struct ipsec_rcv_state *irs + , int *udp_decap_ret_p) + { + *udp_decap_ret_p = 0; + 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)); + *udp_decap_ret_p = 0; + return NULL; + } + 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"); + *udp_decap_ret_p = -1; + return NULL; + } + } + else { + return NULL; + } + } + return skb; + } + #endif + + /* management of buffers */ + static struct ipsec_rcv_state * ipsec_rcv_state_new (void); + static void ipsec_rcv_state_delete (struct ipsec_rcv_state *irs); + + int + ipsec_rcv(struct sk_buff *skb + #ifndef PROTO_HANDLER_SINGLE_PARM + unsigned short xlen + #endif /* PROTO_HANDLER_SINGLE_PARM */ + ) + { + #ifdef CONFIG_KLIPS_DEBUG + struct net_device *dev = skb->dev; + #endif /* CONFIG_KLIPS_DEBUG */ + unsigned char protoc; + struct net_device_stats *stats = NULL; /* This device's statistics */ + struct ipsec_rcv_state nirs, *irs = &nirs; + struct iphdr *ipp; + int i; + + /* Don't unlink in the middle of a turnaround */ + KLIPS_INC_USE; + + memset(&nirs, 0, sizeof(struct ipsec_rcv_state)); + + if (skb == NULL) { + KLIPS_PRINT(debug_rcv, + "klips_debug:ipsec_rcv: " + "NULL skb passed in.\n"); + goto error_no_skb; + } + + if (skb->data == NULL) { + KLIPS_PRINT(debug_rcv, + "klips_debug:ipsec_rcv: " + "NULL skb->data passed in, packet is bogus, dropping.\n"); + goto error_bad_skb; + } + + #if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26) + { + /* NET_26 NAT-T is handled by seperate function */ + struct sk_buff *nskb; + int udp_decap_ret = 0; + + nskb = ipsec_rcv_natt_decap(skb, irs, &udp_decap_ret); + if(nskb == NULL) { + /* return with non-zero, because UDP.c code + * need to send it upstream. + */ + if(skb && udp_decap_ret == 0) { + ipsec_kfree_skb(skb); + } + KLIPS_DEC_USE; + return(udp_decap_ret); + } + skb = nskb; + } + #endif /* NAT_T */ + + /* dev->hard_header_len is unreliable and should not be used */ + /* klips26_rcv_encap will have already set hard_header_len for us?? */ + if (irs->hard_header_len == 0) { + irs->hard_header_len = skb_mac_header(skb) ? (skb_network_header(skb) - skb_mac_header(skb)) : 0; + if((irs->hard_header_len < 0) || (irs->hard_header_len > skb_headroom(skb))) + irs->hard_header_len = 0; + } + + skb = ipsec_rcv_unclone(skb, irs); + if(skb == NULL) { + goto rcvleave; + } + + #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)) { + #ifdef HAVE_NEW_SKB_LINEARIZE + if (skb_linearize_cow(skb) != 0) + #else + if (skb_linearize(skb, GFP_ATOMIC) != 0) + #endif + { + goto rcvleave; + } + } + #endif /* IP_FRAGMENT_LINEARIZE */ + + #if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26) + if (irs->natt_len) { + /** + * Now, we are sure packet is ESPinUDP, and we have a private + * copy that has been linearized, 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 = skb->nh.iph; + 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; + } + + /* advance payload pointer to point past the UDP header */ + skb->h.raw = skb->h.raw + irs->natt_len; + + /* modify protocol */ + ipp->protocol = IPPROTO_ESP; + + skb->sk = NULL; + + KLIPS_IP_PRINT(debug_rcv, skb->nh.iph); + } + #endif + + /* ipp = skb->nh.iph; */ + ipp = ip_hdr(skb); + + irs->ipp = ipp; + ipsec_rcv_redodebug(irs); + + 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_KLIPS_IPCOMP_disabled_until_we_register_IPCOMP_HANDLER + (protoc != IPPROTO_COMP) && + #endif /* CONFIG_KLIPS_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 there is an attached ipsec device, then use that device for + * stats until we know better. + */ + if(skb->dev) { + struct ipsecpriv *prvdev = NULL; + struct net_device *ipsecdev = NULL; + + for(i = 0; i <= ipsecdevices_max; i++) { + if(ipsecdevices[i] == NULL) continue; + prvdev = ipsecdevices[i]->priv; + + if(prvdev == NULL) continue; + + if(prvdev->dev == skb->dev) { + ipsecdev = ipsecdevices[i]; + break; + } + } + + if(ipsecdev) { + skb->dev = ipsecdev; + } else { + skb->dev = ipsec_mast_get_device(0); + + /* ipsec_mast_get takes the device */ + if(skb->dev) dev_put(skb->dev); + } + + if(prvdev) { + stats = (struct net_device_stats *) &(prvdev->mystats); + } + } + + if(stats) { + stats->rx_packets++; + } + + KLIPS_IP_PRINT(debug_rcv, ipp); + + /* 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; + + (void)ipsec_rcv_decap(irs); + + ipsec_rcv_state_delete (irs); + KLIPS_DEC_USE; + return(0); + + rcvleave: + ipsec_rcv_state_delete (irs); + + error_bad_skb: + ipsec_kfree_skb(skb); + error_no_skb: + + KLIPS_DEC_USE; + return(0); + + } + + #ifdef NET_26 + /* + * this entry point is not a protocol entry point, so the entry + * is a bit different. + * + * skb->iph->tot_len has been byte-swapped, and reduced by the size of + * the IP header (and options). + * + * skb->h.raw has been pulled up the ESP header. + * + * skb->iph->protocol = 50 IPPROTO_ESP; + * + */ + int klips26_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) + { + return klips26_rcv_encap(skb, udp_sk(sk)->encap_type); + } + + int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type) + { + struct ipsec_rcv_state *irs = NULL; + struct iphdr *ipp; + + /* Don't unlink in the middle of a turnaround */ + KLIPS_INC_USE; + + irs = ipsec_rcv_state_new (); + if (unlikely (! irs)) { + KLIPS_PRINT(debug_rcv, + "klips_debug:ipsec_rcv: " + "failled to allocate a rcv state object\n"); + goto error_alloc; + } + + /* XXX fudge it so that all nat-t stuff comes from ipsec0 */ + /* eventually, the SA itself will determine which device + * it comes from + */ + { + skb->dev = ipsec_get_device(0); + } + + /* set up for decap loop */ + irs->hard_header_len = skb->dev->hard_header_len; + + skb = ipsec_rcv_unclone(skb, irs); + + #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)) { + #ifdef HAVE_NEW_SKB_LINEARIZE + if (skb_linearize_cow(skb) != 0) + #else + if (skb_linearize(skb, GFP_ATOMIC) != 0) + #endif + { + goto rcvleave; + } + } + #endif /* IP_FRAGMENT_LINEARIZE */ + + /* ipp = skb->nh.iph; */ + ipp =ip_hdr(skb); + + irs->ipp = ipp; + ipsec_rcv_redodebug(irs); + + irs->iphlen = ipp->ihl << 2; + + KLIPS_IP_PRINT(debug_rcv, ipp); + + irs->stats= NULL; + irs->ipp = ipp; + irs->ipsp = NULL; + irs->ilen = 0; + irs->authlen=0; + irs->authfuncs=NULL; + irs->skb = skb; + + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + switch(encap_type) { + case UDP_ENCAP_ESPINUDP: + irs->natt_type = ESPINUDP_WITH_NON_ESP; + break; + + case UDP_ENCAP_ESPINUDP_NON_IKE: + irs->natt_type = ESPINUDP_WITH_NON_IKE; + break; + + default: + if(printk_ratelimit()) { + printk(KERN_INFO "KLIPS received unknown UDP-ESP encap type %u\n", + encap_type); + } + return -1; + } + + #endif + ipsec_rcv_decap(irs); + + KLIPS_DEC_USE; + ipsec_rcv_state_delete (irs); + return 0; + + rcvleave: + if(skb) { + ipsec_kfree_skb(skb); + } + ipsec_rcv_state_delete (irs); + error_alloc: + KLIPS_DEC_USE; + return 0; + } + #endif + + // ------------------------------------------------------------------------ + // this handles creating and managing state for recv path + + static spinlock_t irs_cache_lock = SPIN_LOCK_UNLOCKED; + #ifdef HAVE_KMEM_CACHE_MACRO + static struct kmem_cache *irs_cache_allocator = NULL; + #else + static kmem_cache_t *irs_cache_allocator = NULL; + #endif + static unsigned irs_cache_allocated_count = 0; + + int + ipsec_rcv_state_cache_init (void) + { + if (irs_cache_allocator) + return -EBUSY; + + spin_lock_init(&irs_cache_lock); + #ifdef HAVE_KMEM_CACHE_MACRO + /* irs_cache_allocator = KMEM_CACHE(ipsec_irs,0); */ + irs_cache_allocator = kmem_cache_create ("ipsec_irs", + sizeof (struct ipsec_rcv_state), 0, + 0, NULL); + #else + irs_cache_allocator = kmem_cache_create ("ipsec_irs", + sizeof (struct ipsec_rcv_state), 0, + 0, NULL, NULL); + #endif + if (! irs_cache_allocator) + return -ENOMEM; + + return 0; + } + + void + ipsec_rcv_state_cache_cleanup (void) + { + if (unlikely (irs_cache_allocated_count)) + printk ("ipsec: deleting ipsec_irs kmem_cache while in use\n"); + + if (irs_cache_allocator) { + kmem_cache_destroy (irs_cache_allocator); + irs_cache_allocator = NULL; + } + irs_cache_allocated_count = 0; + } + + static struct ipsec_rcv_state * + ipsec_rcv_state_new (void) + { + struct ipsec_rcv_state *irs; + + spin_lock_bh (&irs_cache_lock); + + irs = kmem_cache_alloc (irs_cache_allocator, GFP_ATOMIC); + + if (likely (irs != NULL)) + irs_cache_allocated_count++; + + spin_unlock_bh (&irs_cache_lock); + + if (unlikely (NULL == irs)) + goto bail; + + // initialize the object + memset((caddr_t)irs, 0, sizeof(*irs)); + + bail: + return irs; + } + + static void + ipsec_rcv_state_delete (struct ipsec_rcv_state *irs) + { + if (unlikely (! irs)) + return; + + spin_lock_bh (&irs_cache_lock); + + irs_cache_allocated_count--; + kmem_cache_free (irs_cache_allocator, irs); + + spin_unlock_bh (&irs_cache_lock); + } + + /* + * + * Local Variables: + * c-set-style: linux + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_sa.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_sa.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_sa.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_sa.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1525 ---- + /* + * 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 . + * + * 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.31 2005/11/11 04:38:56 paul Exp $ + * + * This is the file formerly known as "ipsec_xform.h" + * + */ + + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* vmalloc() */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + #ifdef SPINLOCK + #ifdef SPINLOCK_23 + #include /* *lock* */ + #else /* SPINLOCK_23 */ + #include /* *lock* */ + #endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + + #include + + #include "libreswan/radij.h" + + #include "libreswan/ipsec_stats.h" + #include "libreswan/ipsec_life.h" + #include "libreswan/ipsec_sa.h" + #include "libreswan/ipsec_xform.h" + + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_ipe4.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + #include "libreswan/ipsec_ipip.h" + #ifdef CONFIG_KLIPS_IPCOMP + #include "libreswan/ipsec_ipcomp.h" + #endif /* CONFIG_KLIPS_COMP */ + + #include + #include + + #include "libreswan/ipsec_proto.h" + #include "libreswan/ipsec_alg.h" + + + #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; + + /* 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) + + int + ipsec_SAref_recycle(void) + { + int table, i; + int error = 0; + int entry; + int addone; + + ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; + ipsec_sadb.refFreeListTail = IPSEC_SAREF_NULL; + + 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 = IPSEC_SAREF_FIRST; + } + + 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)); + + /* add one additional table entry */ + addone = 0; + + ipsec_sadb.refFreeListHead = IPSEC_SAREF_FIRST; + for(i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) { + table = IPsecSAref2table(ipsec_sadb.refFreeListCont); + if(addone == 0 && ipsec_sadb.refTable[table] == NULL) { + addone = 1; + 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 = IPSEC_SAREF_FIRST; + ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; + KLIPS_PRINT(debug_xform, + "klips_debug:ipsec_SAref_recycle: " + "SArefFreeList refilled.\n"); + return 0; + } + } + } + ipsec_sadb.refFreeListCont++; + ipsec_sadb.refFreeListTail=i; + } + + if(ipsec_sadb.refFreeListTail == IPSEC_SAREF_NULL) { + KLIPS_PRINT(debug_xform, + "klips_debug:ipsec_SAref_recycle: " + "out of room in the SArefTable.\n"); + + return(-ENOSPC); + } + + ipsec_sadb.refFreeListHead = IPSEC_SAREF_FIRST; + 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; + } + + int + ipsec_saref_verify_slot(IPsecSAref_t ref) + { + int ref_table=IPsecSAref2table(ref); + + if(ipsec_sadb.refTable[ref_table] == NULL) { + return ipsec_SArefSubTable_alloc(ref_table); + } + return 0; + } + + 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 = IPSEC_SAREF_NULL; + ipsec_sadb.refFreeListCont = IPSEC_SAREF_FIRST; + ipsec_sadb.refFreeListTail = IPSEC_SAREF_NULL; + + 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 */ + + + /* 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(); + return error; + } + + IPsecSAref_t + ipsec_SAref_alloc(int*error) /* pass in error var by pointer */ + { + IPsecSAref_t SAref; + + KLIPS_PRINT(debug_xform, + "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 == IPSEC_SAREF_NULL) { + KLIPS_PRINT(debug_xform, + "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_ERROR(debug_xform, + "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, + "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, + "ipsec_SAref_alloc: " + "last FreeList entry allocated, resetting list head to empty.\n"); + ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; + } + + return SAref; + } + + 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_next != NULL) { + printk(" next=0p%p", ips->ips_next); + } + 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, + "ipsec_sa_alloc: " + "memory allocation error\n"); + *error = -ENOMEM; + return NULL; + } + memset((caddr_t)ips, 0, sizeof(*ips)); + + /* return with at least counter = 1 */ + ipsec_sa_get(ips); + + *error = 0; + return(ips); + } + + void + ipsec_sa_untern(struct ipsec_sa *ips) + { + IPsecSAref_t ref = ips->ips_ref; + int error; + + /* verify that we are removing correct item! */ + error = ipsec_saref_verify_slot(ref); + if(error) { + return; + } + + if(IPsecSAref2SA(ref) == ips) { + IPsecSAref2SA(ref) = NULL; + ipsec_sa_put(ips); + } else { + KLIPS_PRINT(debug_xform, + "ipsec_sa_untern: " + "ref=%u -> %p but untern'ing %p\n", ref, + IPsecSAref2SA(ref), ips); + } + + } + + int + ipsec_sa_intern(struct ipsec_sa *ips) + { + int error; + IPsecSAref_t ref = ips->ips_ref; + + if(ref == IPSEC_SAREF_NULL) { + ref = ipsec_SAref_alloc(&error); /* pass in error return by pointer */ + KLIPS_PRINT(debug_xform, + "ipsec_sa_intern: " + "allocated ref=%u for sa %p\n", ref, ips); + + if(ref == IPSEC_SAREF_NULL) { + KLIPS_PRINT(debug_xform, + "ipsec_sa_intern: " + "SAref allocation error\n"); + return error; + } + + ips->ips_ref = ref; + } + + error = ipsec_saref_verify_slot(ref); + if(error) { + return error; + } + + ipsec_sa_get(ips); + /* + * if there is an existing SA at this reference, then free it + * note, that nsa might == ips!. That's okay, we just incremented + * the reference count above. + */ + { + struct ipsec_sa *nsa = IPsecSAref2SA(ref); + if(nsa) { + ipsec_sa_put(nsa); + } + } + + KLIPS_PRINT(debug_xform, + "ipsec_sa_alloc: " + "SAref[%d]=%p\n", + ips->ips_ref, ips); + IPsecSAref2SA(ips->ips_ref) = ips; + + /* return OK */ + return 0; + } + + + 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, + "ipsec_sa_getbyid: " + "null pointer passed in!\n"); + return NULL; + } + + hashval = IPS_HASH(said); + + sa_len = KLIPS_SATOT(debug_xform, said, 0, sa, sizeof(sa)); + KLIPS_PRINT(debug_xform, + "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, + "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)) { + ipsec_sa_get(ips); + return ips; + } + } + + KLIPS_PRINT(debug_xform, + "ipsec_sa_getbyid: " + "no entry in linked list for hash=%d of SA:%s.\n", + hashval, + sa_len ? sa : " (error)"); + return NULL; + } + + struct ipsec_sa * + ipsec_sa_getbyref(IPsecSAref_t ref) + { + struct ipsec_sa *ips; + struct IPsecSArefSubTable *st = ipsec_sadb.refTable[IPsecSAref2table(ref)]; + + if(st == NULL) { + return NULL; + } + + ips = st->entry[IPsecSAref2entry(ref)]; + if(ips) { + ipsec_sa_get(ips); + } + return ips; + } + + int + ipsec_sa_put(struct ipsec_sa *ips) + { + char sa[SATOT_BUF]; + size_t sa_len; + + if(ips == NULL) { + KLIPS_PRINT(debug_xform, + "ipsec_sa_put: " + "null pointer passed in!\n"); + return -1; + } + + if(debug_xform) { + sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); + + KLIPS_PRINT(debug_xform, + "ipsec_sa_put: " + "ipsec_sa %p SA:%s, ref:%d reference count (%d--) decremented.\n", + ips, + sa_len ? sa : " (error)", + ips->ips_ref, + atomic_read(&ips->ips_refcount)); + } + + if(atomic_dec_and_test(&ips->ips_refcount)) { + KLIPS_PRINT(debug_xform, + "ipsec_sa_put: freeing %p\n", + ips); + /* it was zero */ + ipsec_sa_wipe(ips); + } + + return 0; + } + + int + __ipsec_sa_get(struct ipsec_sa *ips, const char *func, int line) + { + char sa[SATOT_BUF]; + size_t sa_len; + + if(debug_xform) { + sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); + + KLIPS_PRINT(debug_xform, + "ipsec_sa_get: " + "ipsec_sa %p SA:%s, ref:%d reference count (%d++) incremented by %s:%d.\n", + ips, + sa_len ? sa : " (error)", + ips->ips_ref, + atomic_read(&ips->ips_refcount), + func, line); + } + + atomic_inc(&ips->ips_refcount); + return atomic_read(&ips->ips_refcount); + } + + /* + 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); + + ipsec_sa_get(ips); + spin_lock_bh(&tdb_lock); + + ips->ips_hnext = ipsec_sadb_hash[hashval]; + ipsec_sadb_hash[hashval] = ips; + + spin_unlock_bh(&tdb_lock); + + return error; + } + + /* + * remove it from the hash chain, decrementing hash count + */ + void ipsec_sa_rm(struct ipsec_sa *ips) + { + unsigned int hashval; + char sa[SATOT_BUF]; + size_t sa_len; + + + if(ips == NULL) return; + + + hashval = IPS_HASH(&ips->ips_said); + + sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); + KLIPS_PRINT(debug_xform, + "klips_debug:ipsec_sa_del: " + "unhashing SA:%s (ref=%u), hashval=%d.\n", + sa_len ? sa : " (error)", + ips->ips_ref, + hashval); + + if(ipsec_sadb_hash[hashval] == NULL) { + return; + } + + if (ips == ipsec_sadb_hash[hashval]) { + ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; + ips->ips_hnext = NULL; + ipsec_sa_put(ips); + KLIPS_PRINT(debug_xform, + "klips_debug:ipsec_sa_del: " + "successfully unhashed first ipsec_sa in chain.\n"); + return; + } else { + struct ipsec_sa *ipstp; + + 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; + ipsec_sa_put(ips); + KLIPS_PRINT(debug_xform, + "klips_debug:ipsec_sa_del: " + "successfully unhashed link in ipsec_sa chain.\n"); + return; + } + } + } + } + + + #if 0 + /* + * The ipsec_sa table better be locked before it is handed in, + * or races might happen. + * + * this routine assumes the SA has a refcount==0, and we free it. + * we also assume that the pointers are already cleaned up. + */ + static 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_ERROR(debug_xform, + "klips_error:ipsec_sa_del: " + "null pointer passed in!\n"); + return -ENODATA; + } + + if(ips->ips_next) { + struct ipsec_sa *in = ips->ips_next; + + ips->ips_next=NULL; + ipsec_sa_put(in); + } + + sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); + hashval = IPS_HASH(&ips->ips_said); + + KLIPS_PRINT(debug_xform, + "klips_debug:ipsec_sa_del: " + "deleting SA:%s (ref=%u), hashval=%d.\n", + sa_len ? sa : " (error)", + ips->ips_ref, + hashval); + + if(ipsec_sadb_hash[hashval] == NULL) { + /* if this is NULL, then we can be sure that the SA was never + * added to the SADB, so we just free it. + */ + KLIPS_PRINT(debug_xform, + "klips_debug:ipsec_sa_del: " + "no entries in ipsec_sa table for hash=%d (ref=%u) of SA:%s.\n", + hashval, + ips->ips_ref, + 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; + + ipsec_sa_put(ips); + 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; + ipsec_sa_put(ips); + 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; + } + #endif + + int + ipsec_sadb_cleanup(__u8 proto) + { + unsigned i; + int error = 0; + struct ipsec_sa *ips; + //struct ipsec_sa *ipsnext, **ipsprev; + //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++) { + ips = ipsec_sadb_hash[i]; + + while(ips) { + ipsec_sadb_hash[i]=ips->ips_hnext; + ips->ips_hnext=NULL; + ipsec_sa_put(ips); + + ips = ipsec_sadb_hash[i]; + } + } + + //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) { + struct ipsec_sa *sa1 = ipsec_sadb.refTable[table]->entry[entry]; + ipsec_sa_put(sa1); + 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) { + struct ipsec_sa *sa1 = ipsec_sadb.refTable[table]->entry[entry]; + + BUG_ON(atomic_read(&sa1->ips_refcount) == 1); + ipsec_sa_put(sa1); + 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 IPSEC_SA_REF_CODE + /* remove me from the SArefTable */ + if(debug_xform) + { + char sa[SATOT_BUF]; + size_t sa_len; + struct IPsecSArefSubTable *subtable = NULL; + + if(IPsecSAref2table(IPsecSA2SAref(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)), + subtable, + subtable ? IPsecSAref2entry(IPsecSA2SAref(ips)) : 0); + } + + if(ips->ips_ref != IPSEC_SAREF_NULL) { + struct IPsecSArefSubTable *subtable = NULL; + int ref_table=IPsecSAref2table(IPsecSA2SAref(ips)); + int ref_entry=IPsecSAref2entry(IPsecSA2SAref(ips)); + + if(ref_table < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { + subtable = ipsec_sadb.refTable[ref_table]; + if(subtable!=NULL && subtable->entry[ref_entry] == ips) { + + subtable->entry[ref_entry] = NULL; + } + } + ips->ips_ref = IPSEC_SAREF_NULL; + } + #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) { + 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 + { + memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); + kfree(ips->ips_key_e); + } + } + 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; + + if (ips->ips_alg_enc||ips->ips_alg_auth) { + ipsec_alg_sa_wipe(ips); + } + + BUG_ON(atomic_read(&ips->ips_refcount) != 0); + + memset((caddr_t)ips, 0, sizeof(*ips)); + kfree(ips); + ips = NULL; + + return 0; + } + + extern int sysctl_ipsec_debug_verbose; + + int ipsec_sa_init(struct ipsec_sa *ipsp) + { + 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_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) + unsigned char kb[AHMD596_BLKLEN]; + #endif + struct ipsec_alg_enc *ixt_e = NULL; + struct ipsec_alg_auth *ixt_a = NULL; + + if(ipsp == NULL) { + KLIPS_PRINT(debug_pfkey, + "ipsec_sa_init: " + "ipsp is NULL, fatal\n"); + SENDERR(EINVAL); + } + + sa_len = KLIPS_SATOT(debug_pfkey, &ipsp->ips_said, 0, sa, sizeof(sa)); + + KLIPS_PRINT(debug_pfkey, + "ipsec_sa_init: " + "(pfkey defined) called for SA:%s\n", + sa_len ? sa : " (error)"); + + KLIPS_PRINT(debug_pfkey, + "ipsec_sa_init: " + "calling init routine of %s%s%s\n", + IPS_XFORM_NAME(ipsp)); + + switch(ipsp->ips_said.proto) { + #ifdef CONFIG_KLIPS_IPIP + case IPPROTO_IPIP: { + ipsp->ips_xformfuncs = ipip_xform_funcs; + 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, + "ipsec_sa_init: " + "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", + ipaddr_txt, + ipaddr2_txt); + } + break; + #endif /* !CONFIG_KLIPS_IPIP */ + + #ifdef CONFIG_KLIPS_AH + case IPPROTO_AH: + ipsp->ips_xformfuncs = ah_xform_funcs; + + switch(ipsp->ips_authalg) { + # ifdef CONFIG_KLIPS_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, + "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, + "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, + "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); + osMD5Init(ictx); + osMD5Update(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); + osMD5Init(octx); + osMD5Update(octx, kb, AHMD596_BLKLEN); + + # if KLIPS_DIVULGE_HMAC_KEY + KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, + "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_KLIPS_AUTH_HMAC_MD5 */ + # ifdef CONFIG_KLIPS_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, + "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, + "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, + "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, + "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_KLIPS_AUTH_HMAC_SHA1 */ + default: + KLIPS_PRINT(debug_pfkey, + "ipsec_sa_init: " + "authalg=%d support not available in the kernel", + ipsp->ips_authalg); + SENDERR(EINVAL); + } + break; + #endif /* CONFIG_KLIPS_AH */ + + #ifdef CONFIG_KLIPS_ESP + case IPPROTO_ESP: + ipsp->ips_xformfuncs = esp_xform_funcs; + { + #if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) + unsigned char *akp; + unsigned int aks; + #endif + + ipsec_alg_sa_init(ipsp); + ixt_e=ipsp->ips_alg_enc; + + if (ixt_e == NULL) { + if(printk_ratelimit()) { + printk(KERN_ERR + "ipsec_sa_init: " + "encalg=%d support not available in the kernel", + ipsp->ips_encalg); + } + SENDERR(ENOENT); + } + + ipsp->ips_iv_size = ixt_e->ixt_common.ixt_support.ias_ivlen/8; + + /* 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; + } + + if ((error=ipsec_alg_enc_key_create(ipsp)) < 0) + SENDERR(-error); + + if ((ixt_a=ipsp->ips_alg_auth)) { + if ((error=ipsec_alg_auth_key_create(ipsp)) < 0) + SENDERR(-error); + } else + + switch(ipsp->ips_authalg) { + # ifdef CONFIG_KLIPS_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, + "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, + "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, + "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); + osMD5Init(ictx); + osMD5Update(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); + osMD5Init(octx); + osMD5Update(octx, kb, AHMD596_BLKLEN); + + # if KLIPS_DIVULGE_HMAC_KEY + KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, + "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_KLIPS_AUTH_HMAC_MD5 */ + # ifdef CONFIG_KLIPS_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, + "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, + "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, + "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, + "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_KLIPS_AUTH_HMAC_SHA1 */ + case AH_NONE: + break; + default: + KLIPS_PRINT(debug_pfkey, + "ipsec_sa_init: " + "authalg=%d support not available in the kernel.\n", + ipsp->ips_authalg); + SENDERR(EINVAL); + } + } + break; + #endif /* !CONFIG_KLIPS_ESP */ + #ifdef CONFIG_KLIPS_IPCOMP + case IPPROTO_COMP: + ipsp->ips_xformfuncs = ipcomp_xform_funcs; + 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_KLIPS_IPCOMP */ + default: + printk(KERN_ERR "KLIPS sa initialization: " + "proto=%d unknown.\n", + ipsp->ips_said.proto); + SENDERR(EINVAL); + } + + errlab: + return(error); + } + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_sha1.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_sha1.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_sha1.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_sha1.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,177 ---- + /* + * 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 + #include + + #include "libreswan/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 + } + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_snprintf.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_snprintf.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_snprintf.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_snprintf.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,121 ---- + /* + * @(#) ipsec_snprintf() function + * + * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs + * 2001 Michael Richardson + * Copyright (C) 2005 Michael Richardson + * + * 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 . + * + * 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_proc.c. + */ + + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + #define __NO_VERSION__ + #include + #include /* printk() */ + + #include "libreswan/ipsec_kversion.h" + #include "libreswan/ipsec_param.h" + + #include + + #include "libreswan/radij.h" + + #include "libreswan/ipsec_life.h" + #include "libreswan/ipsec_stats.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_xmit.h" + + #include "libreswan/ipsec_rcv.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + #include "libreswan/ipsec_kern24.h" + + #ifdef CONFIG_KLIPS_IPCOMP + #include "libreswan/ipcomp.h" + #endif /* CONFIG_KLIPS_IPCOMP */ + + #include "libreswan/ipsec_proto.h" + + #include + #include + + /* 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; + } + + + void ipsec_dmp_block(char *s, caddr_t bb, int len) + { + int i; + unsigned char *b = bb; + + printk(KERN_INFO "klips_dmp: " + "at %s, len=%d:\n", s, len); + + for(i = 0; i < len; i++ /*, c++*/) { + if(!(i % 16)) { + printk(KERN_INFO + "klips_debug: @%03x:", + i); + } + printk(" %02x", b[i]); + if(!((i + 1) % 16)) { + printk("\n"); + } + } + if(i % 16) { + printk("\n"); + } + } + + /* + * Local Variables: + * c-file-style: "linux" + * End: + * + */ + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_tunnel.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_tunnel.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_tunnel.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_tunnel.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1876 ---- + /* + * 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 . + * + * 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. + */ + + #define __NO_VERSION__ + #include + #ifndef AUTOCONF_INCLUDED + #include + #endif /* for CONFIG_IP_FORWARD */ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include + #include + #include + + #include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include + + #include + + #ifdef NET_21 + # include + # define ip_chk_addr inet_addr_type + # define IS_MYADDR RTN_LOCAL + # include + # undef dev_kfree_skb + # define dev_kfree_skb(a,b) kfree_skb(a) + # define PHYSDEV_TYPE + #endif /* NET_21 */ + + #include /* icmp_send() */ + #include + #ifdef NETDEV_23 + # include + #endif /* NETDEV_23 */ + + #include + #include + + #include "libreswan/ipsec_kversion.h" + #include "libreswan/radij.h" + #include "libreswan/ipsec_life.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_eroute.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_sa.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_xmit.h" + #include "libreswan/ipsec_ipe4.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + #include "libreswan/ipsec_kern24.h" + + #include + #include + + #include "libreswan/ipsec_proto.h" + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + #include + #endif + + static __u32 zeroes[64]; + + DEBUG_NO_STATIC int + ipsec_tunnel_open(struct net_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; + + KLIPS_INC_USE; + return 0; + } + + DEBUG_NO_STATIC int + ipsec_tunnel_close(struct net_device *dev) + { + KLIPS_DEC_USE; + return 0; + } + + 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 + } + + 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 + * . + */ + 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_KLIPS_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_KLIPS_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) + { + unsigned int bypass; + + bypass = FALSE; + + /* + * 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) { + struct udphdr *t = NULL; + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + "klips_debug:udp port check: " + "fragoff: %d len: %d>%ld \n", + ntohs(ixs->iph->frag_off) & IP_OFFSET, + (ixs->skb->len - ixs->hard_header_len), + (unsigned long int) ((ixs->iph->ihl << 2) + sizeof(struct udphdr))); + + if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 && + ((ixs->skb->len - ixs->hard_header_len) >= + ((ixs->iph->ihl << 2) + sizeof(struct udphdr)))) + { + t =((struct udphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2))); + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + "klips_debug:udp port in packet: " + "port %d -> %d\n", + ntohs(t->source), ntohs(t->dest)); + } + + ixs->sport=0; ixs->dport=0; + + if(ixs->skb->sk) { + #ifdef NET_26 + #ifdef HAVE_INET_SK_SPORT + ixs->sport = ntohs(inet_sk(ixs->skb->sk)->sport); + ixs->dport = ntohs(inet_sk(ixs->skb->sk)->dport); + #else + struct udp_sock *us; + + us = (struct udp_sock *)ixs->skb->sk; + + ixs->sport = ntohs(us->inet.sport); + ixs->dport = ntohs(us->inet.dport); + #endif + #else + ixs->sport = ntohs(ixs->skb->sk->sport); + ixs->dport = ntohs(ixs->skb->sk->dport); + #endif + + } + + if(t != NULL) { + if(ixs->sport == 0) { + ixs->sport = ntohs(t->source); + } + if(ixs->dport == 0) { + ixs->dport = ntohs(t->dest); + } + } + } + + /* + * practically identical to above, but let's be careful about + * tcp vs udp headers + */ + if(ixs->iph->protocol == IPPROTO_TCP) { + struct tcphdr *t = NULL; + + if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 && + ((ixs->skb->len - ixs->hard_header_len) >= + ((ixs->iph->ihl << 2) + sizeof(struct tcphdr)))) { + t =((struct tcphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2))); + } + + ixs->sport=0; ixs->dport=0; + + if(ixs->skb->sk) { + #ifdef NET_26 + #ifdef HAVE_INET_SK_SPORT + ixs->sport = ntohs(inet_sk(ixs->skb->sk)->sport); + ixs->dport = ntohs(inet_sk(ixs->skb->sk)->dport); + #else + struct tcp_tw_bucket *tw; + tw = (struct tcp_tw_bucket *)ixs->skb->sk; + ixs->sport = ntohs(tw->tw_sport); + ixs->dport = ntohs(tw->tw_dport); + #endif + #else + ixs->sport = ntohs(ixs->skb->sk->sport); + ixs->dport = ntohs(ixs->skb->sk->dport); + #endif + } + + if(t != NULL) { + if(ixs->sport == 0) { + ixs->sport = ntohs(t->source); + } + if(ixs->dport == 0) { + ixs->dport = ntohs(t->dest); + } + } + } + + /* 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); + + /* + * 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==NULL + || 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->iph->protocol == IPPROTO_UDP && + (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"); + } + bypass = TRUE; + } + + #ifdef KLIPS_EXCEPT_DNS53 + /* + * + * if we are udp/53 or tcp/53, also let it through a %trap or %hold, + * since it is DNS, but *also* follow the %trap. + * + * we do not do this for tunnels, only %trap's and %hold's. + * + */ + + if (ip_chk_addr((unsigned long)ixs->iph->saddr) == IS_MYADDR + && (ixs->eroute==NULL + || 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->iph->protocol == IPPROTO_UDP + || ixs->iph->protocol == IPPROTO_TCP) + && ixs->dport == 53)) { + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + "klips_debug:ipsec_xmit_SAlookup: " + "possible DNS packet\n"); + + if(ixs->eroute) + { + if(ixs->eroute->er_said.spi == htonl(SPI_TRAP) + || ixs->eroute->er_said.spi == htonl(SPI_HOLD)) + { + ixs->outgoing_said.spi = htonl(SPI_PASSTRAP); + bypass = TRUE; + } + } + else + { + ixs->outgoing_said.spi = htonl(SPI_PASSTRAP); + bypass = TRUE; + } + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + "klips_debug:ipsec_xmit_SAlookup: " + "bypass = %d\n", bypass); + + if(bypass + && !(ixs->skb->sk) + && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0)) + { + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + "klips_debug:ipsec_xmit_SAlookup: " + "local port 53 (probably DNS) passthrough:" + "base fragment, rest of fragments will " + "probably get filtered.\n"); + } + } + #endif + + if (bypass==FALSE && 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]; + } + } + } + + 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; + } + + /* management of buffers */ + static struct ipsec_xmit_state * ipsec_xmit_state_new (void); + static void ipsec_xmit_state_delete (struct ipsec_xmit_state *ixs); + + + /* + * 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 net_device *dev) + { + struct ipsec_xmit_state *ixs = NULL; + enum ipsec_xmit_value stat; + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + "\n\nipsec_tunnel_start_xmit: STARTING"); + + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + ixs->natt_type = 0, ixs->natt_head = 0; + ixs->natt_sport = 0, ixs->natt_dport = 0; + #endif + stat = IPSEC_XMIT_ERRMEMALLOC; + ixs = ipsec_xmit_state_new (); + if (! ixs) { + goto alloc_error; + } + + 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_nat_encap(ixs); + if(stat != IPSEC_XMIT_OK) { + goto cleanup; + } + + stat = ipsec_tunnel_restore_hard_header(ixs); + if(stat != IPSEC_XMIT_OK) { + goto cleanup; + } + + bypass: + stat = ipsec_tunnel_send(ixs); + + cleanup: + ipsec_xmit_cleanup(ixs); + + ipsec_xmit_state_delete (ixs); + alloc_error: + return 0; + } + + DEBUG_NO_STATIC struct net_device_stats * + ipsec_tunnel_get_stats(struct net_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 net_device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len) + { + struct ipsecpriv *prv = dev->priv; + struct net_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(ip_hdr(skb)->saddr), + (__u32)ntohl(ip_hdr(skb)->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 net_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(ip_hdr(skb)->saddr), + (__u32)ntohl(ip_hdr(skb)->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 net_device *dev, + unsigned long raddr, struct sk_buff *skb) + #endif /* NET_21 */ + { + struct ipsecpriv *prv = skb->dev->priv; + struct net_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(ip_hdr(skb)->saddr), + (__u32)ntohl(ip_hdr(skb)->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(ip_hdr(skb)->saddr), + (__u32)ntohl(ip_hdr(skb)->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 net_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 net_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 net_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 net_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 net_device *dev, struct net_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; iaddr_len; i++) { + dev->dev_addr[i] = physdev->dev_addr[i]; + } + #ifdef CONFIG_KLIPS_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_KLIPS_DEBUG */ + + return 0; + } + + /* + * We call the detach routine to detach the ipsec tunnel from another device. + */ + + DEBUG_NO_STATIC int + ipsec_tunnel_detach(struct net_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; idev_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 net_device *ipsecdev = NULL, *prvdev; + struct ipsecpriv *prv; + 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 net_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", + ipsecdev->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, ipsecdev->name, prvdev->name); + return ret; + } + } + } + } + } + return 0; + } + + DEBUG_NO_STATIC int + ipsec_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { + struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data; + struct ipsecpriv *prv = dev->priv; + struct net_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); + 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(); + + #ifdef HAVE_UDP_ENCAP_CONVERT + case IPSEC_UDP_ENCAP_CONVERT: + { + unsigned int *socknum =(unsigned int *)&ifr->ifr_data; + struct socket *sock; + int err, fput_needed; + + /* that's a static function in socket.c + * sock = sockfd_lookup_light(*socknum, &err, &fput_needed); */ + sock = sockfd_lookup(*socknum, &err); + if (!sock) + goto encap_out; + + /* check that it's a UDP socket */ + udp_sk(sk)->encap_type = UDP_ENCAP_ESPINUDP_NON_IKE; + udp_sk(sk)->encap_rcv = klips26_udp_encap_rcv; + + KLIPS_PRINT(debug_tunnel + , "UDP socket: %u set to NON-IKE encap mode\n" + , socknum); + + err = 0; + + encap_output: + fput_light(sock->file, fput_needed); + encap_out: + return err; + #endif + + default: + KLIPS_PRINT(debug_tunnel & DB_TN_INIT, + "klips_debug:ipsec_tunnel_ioctl: " + "unknown command %d.\n", + cmd); + return -EOPNOTSUPP; + } + } + + struct net_device *ipsec_get_device(int inst) + { + struct net_device *ipsec_dev; + + ipsec_dev = NULL; + + if(inst < IPSEC_NUM_IF) { + ipsec_dev = ipsecdevices[inst]; + } + + return ipsec_dev; + } + + int + ipsec_device_event(struct notifier_block *unused, unsigned long event, void *ptr) + { + struct net_device *dev = ptr; + struct net_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 net_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 net_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 */; + + /* 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 net_device *dev) + { + ipsec_tunnel_init(dev); + return 0; + } + + struct net_device *ipsecdevices[IPSEC_NUM_IFMAX]; + int ipsecdevices_max=-1; + + + int + ipsec_tunnel_createnum(int ifnum) + { + char name[IFNAMSIZ]; + struct net_device *dev_ipsec; + int vifentry; + + if(ifnum > IPSEC_NUM_IFMAX) { + return -ENOENT; + } + + if(ipsecdevices[ifnum]!=NULL) { + return -EEXIST; + } + + /* no identical device */ + if(ifnum > ipsecdevices_max) { + ipsecdevices_max=ifnum; + } + vifentry = ifnum; + + KLIPS_PRINT(debug_tunnel & DB_TN_INIT, + "klips_debug:ipsec_tunnel_init_devices: " + "creating and registering IPSEC_NUM_IF=%u device\n", + ifnum); + + sprintf(name, IPSEC_DEV_FORMAT, ifnum); + dev_ipsec = (struct net_device*)kmalloc(sizeof(struct net_device), GFP_KERNEL); + if (dev_ipsec == NULL) { + printk(KERN_ERR "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 net_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 */ + #ifdef HAVE_DEV_NEXT + dev_ipsec->next = NULL; + #endif + 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[vifentry]=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; + } + + + int + ipsec_tunnel_init_devices(void) + { + int i; + int error; + + 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 net_device) + IFNAMSIZ), + IFNAMSIZ); + + for(i = 0; i < IPSEC_NUM_IF; i++) { + error = ipsec_tunnel_createnum(i); + + if(error) break; + } + return 0; + } + + int + ipsec_tunnel_deletenum(int vifnum) + { + struct net_device *dev_ipsec; + + if(vifnum > IPSEC_NUM_IFMAX) { + return -ENOENT; + } + + dev_ipsec = ipsecdevices[vifnum]; + if(dev_ipsec == NULL) { + return -ENOENT; + } + + /* release reference */ + ipsecdevices[vifnum]=NULL; + ipsec_dev_put(dev_ipsec); + + KLIPS_PRINT(debug_tunnel, "Unregistering %s (refcnt=%d)\n", + dev_ipsec->name, + atomic_read(&dev_ipsec->refcnt)); + unregister_netdev(dev_ipsec); + KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", dev_ipsec->name); + #ifndef NETDEV_23 + kfree(dev_ipsec->name); + dev_ipsec->name=NULL; + #endif /* !NETDEV_23 */ + kfree(dev_ipsec->priv); + dev_ipsec->priv=NULL; + + return 0; + } + + + struct net_device * + ipsec_tunnel_get_device(int vifnum) + { + struct net_device *nd; + + if(vifnum < ipsecdevices_max) { + nd = ipsecdevices[vifnum]; + + if(nd) dev_hold(nd); + return nd; + } else { + return NULL; + } + } + + + /* void */ + int + ipsec_tunnel_cleanup_devices(void) + { + int error = 0; + int i; + struct net_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", + dev_ipsec->name, + atomic_read(&dev_ipsec->refcnt)); + unregister_netdev(dev_ipsec); + KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", dev_ipsec->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; + } + + // ------------------------------------------------------------------------ + // this handles creating and managing state for xmit path + + static spinlock_t ixs_cache_lock = SPIN_LOCK_UNLOCKED; + #ifdef HAVE_KMEM_CACHE_MACRO + static struct kmem_cache *ixs_cache_allocator = NULL; + #else + static kmem_cache_t *ixs_cache_allocator = NULL; + #endif + static unsigned ixs_cache_allocated_count = 0; + + int + ipsec_xmit_state_cache_init (void) + { + #ifdef HAVE_KMEM_CACHE_MACRO + struct ipsec_xmit_state ipsec_ixs; + #endif + if (ixs_cache_allocator) + return -EBUSY; + + spin_lock_init(&ixs_cache_lock); + #ifdef HAVE_KMEM_CACHE_MACRO + /* ixs_cache_allocator = KMEM_CACHE(ipsec_ixs,0); */ + ixs_cache_allocator = kmem_cache_create ("ipsec_ixs", + sizeof (struct ipsec_xmit_state), 0, + 0, NULL); + #else + ixs_cache_allocator = kmem_cache_create ("ipsec_ixs", + sizeof (struct ipsec_xmit_state), 0, + 0, NULL, NULL); + #endif + if (! ixs_cache_allocator) + return -ENOMEM; + + return 0; + } + + void + ipsec_xmit_state_cache_cleanup (void) + { + if (unlikely (ixs_cache_allocated_count)) + printk ("ipsec: deleting ipsec_ixs kmem_cache while in use\n"); + + if (ixs_cache_allocator) { + kmem_cache_destroy (ixs_cache_allocator); + ixs_cache_allocator = NULL; + } + ixs_cache_allocated_count = 0; + } + + static struct ipsec_xmit_state * + ipsec_xmit_state_new (void) + { + struct ipsec_xmit_state *ixs; + + spin_lock_bh (&ixs_cache_lock); + + ixs = kmem_cache_alloc (ixs_cache_allocator, GFP_ATOMIC); + + if (likely (ixs != NULL)) + ixs_cache_allocated_count++; + + spin_unlock_bh (&ixs_cache_lock); + + if (unlikely (NULL == ixs)) + goto bail; + + // initialize the object + memset((caddr_t)ixs, 0, sizeof(*ixs)); + + bail: + return ixs; + } + + static void + ipsec_xmit_state_delete (struct ipsec_xmit_state *ixs) + { + if (unlikely (! ixs)) + return; + + spin_lock_bh (&ixs_cache_lock); + + ixs_cache_allocated_count--; + kmem_cache_free (ixs_cache_allocator, ixs); + + spin_unlock_bh (&ixs_cache_lock); + } + + /* + * + * Local Variables: + * c-style: linux + * End: + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_xform.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_xform.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_xform.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_xform.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,75 ---- + /* + * 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 . + * + * 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.65 2005/04/29 05:10:22 mcr Exp $ + */ + + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + #include /* printk() */ + + #include "freeswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #include /* get_random_bytes() */ + #include + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *lock* */ + # endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + + #include + + #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 + #include + + #ifdef SPINLOCK + spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED; + #else /* SPINLOCK */ + spinlock_t tdb_lock; + #endif /* SPINLOCK */ + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ipsec_xmit.c linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_xmit.c *** linux-2.6.16-ng-natt/net/ipsec/ipsec_xmit.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ipsec_xmit.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1940 ---- + /* + * IPSEC Transmit code. + * Copyright (C) 1996, 1997 John Ioannidis. + * Copyright (C) 1998-2003 Richard Guy Briggs. + * Copyright (C) 2004-2005 Michael Richardson + * + * 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 . + * + * 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. + */ + + #define __NO_VERSION__ + #include + #ifndef AUTOCONF_INCLUDED + #include + #endif /* for CONFIG_IP_FORWARD */ + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + + #include + #include + #include + + #include + #include + #include + #ifdef NET_21 + # define MSS_HACK_ /* experimental */ + # include + # include + # define proto_priv cb + #endif /* NET_21 */ + + #include /* icmp_send() */ + #include + #ifdef NETDEV_23 + # include + #endif /* NETDEV_23 */ + + #include + #ifdef MSS_HACK + # include /* TCP options */ + #endif /* MSS_HACK */ + + #include "libreswan/ipsec_kern24.h" + #include "libreswan/radij.h" + #include "libreswan/ipsec_life.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_eroute.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xmit.h" + #include "libreswan/ipsec_sa.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_ipe4.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + + #ifdef CONFIG_KLIPS_IPCOMP + #include "libreswan/ipcomp.h" + #endif /* CONFIG_KLIPS_IPCOMP */ + + #include + #include + + #include "libreswan/ipsec_proto.h" + #include "libreswan/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 */ + + + + #if defined(CONFIG_KLIPS_AH) + static __u32 zeroes[64]; + #endif + + int ipsec_xmit_trap_count = 0; + int ipsec_xmit_trap_sendcount = 0; + + #ifdef CONFIG_KLIPS_DEBUG + #define dmp(_x,_y,_z) if(debug_xmit && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z) + #else /* CONFIG_KLIPS_DEBUG */ + #define dmp(_x, _y, _z) + #endif /* CONFIG_KLIPS_DEBUG */ + + + #if !defined(SKB_COPY_EXPAND) || defined(KLIPS_UNIT_TESTS) + /* + * This is mostly skbuff.c:skb_copy(). + */ + struct sk_buff * + skb_copy_expand(const 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; + #ifdef HAVE_SOCK_SECURITY + n->security=skb->security; + #endif + #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_KLIPS_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)"); + if(ip->protocol == IPPROTO_ESP) + printk(" (ESP)"); + if(ip->protocol == IPPROTO_AH) + printk(" (AH)"); + if(ip->protocol == IPPROTO_COMP) + printk(" (COMP)"); + 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 len = ntohs(ip->tot_len) - ip->ihl*4; + + c = ((__u8*)ip) + ip->ihl*4; + ipsec_dmp_block("ip_print", c, len); + } + } + #endif /* CONFIG_KLIPS_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->cur_mtu = 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; + } + + /* 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; + } + } + + ixs->iph = ip_hdr(ixs->skb); + + /* 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_KLIPS_ESP + struct esphdr *espp; + unsigned char *idat, *pad; + int authlen = 0, padlen = 0, i; + #endif /* !CONFIG_KLIPS_ESP */ + #ifdef CONFIG_KLIPS_AH + struct iphdr ipo; + struct ahhdr *ahp; + #endif /* CONFIG_KLIPS_AH */ + #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) + union { + #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + MD5_CTX md5; + #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + SHA1_CTX sha1; + #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + } tctx; + __u8 hash[AH_AMAX]; + #endif /* defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMACn_SHA1) */ + int headroom = 0, tailroom = 0, ilen = 0, len = 0; + unsigned char *dat; + int blocksize = 8; /* XXX: should be inside ixs --jjo */ + struct ipsec_alg_enc *ixt_e = NULL; + struct ipsec_alg_auth *ixt_a = NULL; + + ixs->iphlen = ixs->iph->ihl << 2; + ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen; + ixs->sa_len = KLIPS_SATOT(debug_tunnel, &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_KLIPS_AH + case IPPROTO_AH: + headroom += sizeof(struct ahhdr); + break; + #endif /* CONFIG_KLIPS_AH */ + + #ifdef CONFIG_KLIPS_ESP + case IPPROTO_ESP: + ixt_e=ixs->ipsp->ips_alg_enc; + if (ixt_e) { + blocksize = ixt_e->ixt_common.ixt_blocksize; + headroom += ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8; + } else { + ixs->stats->tx_errors++; + return IPSEC_XMIT_ESP_BADALG; + } + + ixt_a=ixs->ipsp->ips_alg_auth; + if (ixt_a) { + tailroom += AHHMAC_HASHLEN; + authlen = AHHMAC_HASHLEN; + } else + switch(ixs->ipsp->ips_authalg) { + #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + case AH_MD5: + authlen = AHHMAC_HASHLEN; + break; + #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + case AH_SHA: + authlen = AHHMAC_HASHLEN; + break; + #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + case AH_NONE: + break; + default: + ixs->stats->tx_errors++; + return IPSEC_XMIT_ESP_BADALG; + } + tailroom += blocksize != 1 ? + ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : + ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; + tailroom += authlen; + break; + #endif /* CONFIG_KLIPS_ESP */ + + #ifdef CONFIG_KLIPS_IPIP + case IPPROTO_IPIP: + headroom += sizeof(struct iphdr); + ixs->iphlen = sizeof(struct iphdr); + break; + #endif /* !CONFIG_KLIPS_IPIP */ + + #ifdef CONFIG_KLIPS_IPCOMP + case IPPROTO_COMP: + break; + #endif /* CONFIG_KLIPS_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_KLIPS_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)); + + if (!ixt_e) { + 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_KLIPS_DEBUG + if(debug_tunnel & DB_TN_ENCAP) { + dmp("pre-encrypt", dat, len); + } + #endif + + /* + * Do all operations here: + * copy IV->ESP, encrypt, update ips IV + * + */ + { + int ret; + memcpy(espp->esp_iv, + ixs->ipsp->ips_iv, + ixs->ipsp->ips_iv_size); + ret=ipsec_alg_esp_encrypt(ixs->ipsp, + idat, ilen, espp->esp_iv, + IPSEC_ALG_ENCRYPT); + + prng_bytes(&ipsec_prng, + (char *)ixs->ipsp->ips_iv, + ixs->ipsp->ips_iv_size); + } + + if (ixt_a) { + ipsec_alg_sa_esp_hash(ixs->ipsp, + (caddr_t)espp, len - ixs->iphlen - authlen, + &(dat[len - authlen]), authlen); + + } else + switch(ixs->ipsp->ips_authalg) { + #ifdef CONFIG_KLIPS_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)); + osMD5Update(&tctx.md5, (caddr_t)espp, len - ixs->iphlen - authlen); + dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Final(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)); + osMD5Update(&tctx.md5, hash, AHMD596_ALEN); + dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Final(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_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_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_KLIPS_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;*/ + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, espp)); + #endif /* NET_21 */ + break; + #endif /* !CONFIG_KLIPS_ESP */ + #ifdef CONFIG_KLIPS_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_KLIPS_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)); + osMD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); + dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); + dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); + dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Update(&tctx.md5, dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom); + dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Final(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)); + osMD5Update(&tctx.md5, hash, AHMD596_ALEN); + dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); + osMD5Final(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_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_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_KLIPS_AUTH_HMAC_SHA1 */ + default: + ixs->stats->tx_errors++; + return IPSEC_XMIT_AH_BADALG; + } + #ifdef NET_21 + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ahp)); + #endif /* NET_21 */ + break; + #endif /* CONFIG_KLIPS_AH */ + #ifdef CONFIG_KLIPS_IPIP + case IPPROTO_IPIP: + ixs->iph->version = 4; + switch(sysctl_ipsec_tos) { + case 0: + #ifdef NET_21 + ixs->iph->tos = ip_hdr(ixs->skb)->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; + } + ixs->iph->ttl = SYSCTL_IPSEC_DEFAULT_TTL; + 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 + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ip_hdr(ixs->skb))); + #endif /* NET_21 */ + break; + #endif /* !CONFIG_KLIPS_IPIP */ + #ifdef CONFIG_KLIPS_IPCOMP + case IPPROTO_COMP: + { + unsigned int flags = 0; + #ifdef CONFIG_KLIPS_DEBUG + unsigned int old_tot_len = ntohs(ixs->iph->tot_len); + #endif /* CONFIG_KLIPS_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 = ip_hdr(ixs->skb); + #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_KLIPS_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_KLIPS_DEBUG */ + } + break; + #endif /* CONFIG_KLIPS_IPCOMP */ + default: + ixs->stats->tx_errors++; + return IPSEC_XMIT_BADPROTO; + } + + #ifdef NET_21 + skb_set_network_header(ixs->skb, ipsec_skb_offset(ixs->skb, 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_next; + + 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_KLIPS_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_KLIPS_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_2(struct ipsec_xmit_state *ixs) + { + struct ipsec_alg_enc *ixt_e = NULL; + struct ipsec_alg_auth *ixt_a = NULL; + int blocksize = 8; + enum ipsec_xmit_value bundle_stat = IPSEC_XMIT_OK; + struct ipsec_sa *saved_ipsp; + + 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? + */ + saved_ipsp = ixs->ipsp; /* save the head of the ipsec_sa chain */ + while (ixs->ipsp) { + if (debug_tunnel & DB_TN_XMIT) { + ixs->sa_len = KLIPS_SATOT(debug_tunnel, &ixs->ipsp->ips_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); + if(ixs->sa_len == 0) { + strcpy(ixs->sa_txt, "(error)"); + } + } else { + *ixs->sa_txt = 0; + ixs->sa_len = 0; + } + + /* If it is in larval state, drop the packet, we cannot process yet. */ + if(ixs->ipsp->ips_state == K_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)"); + if(ixs->stats) { + ixs->stats->tx_errors++; + } + bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; + goto cleanup; + } + + if(ixs->ipsp->ips_state == K_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_rm(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_rm(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_KLIPS_AH + case IPPROTO_AH: + ixs->headroom += sizeof(struct ahhdr); + break; + #endif /* CONFIG_KLIPS_AH */ + #ifdef CONFIG_KLIPS_ESP + case IPPROTO_ESP: + ixt_e=ixs->ipsp->ips_alg_enc; + if (ixt_e) { + blocksize = ixt_e->ixt_common.ixt_blocksize; + ixs->headroom += ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8; + } + else { + ixs->stats->tx_errors++; + bundle_stat = IPSEC_XMIT_ESP_BADALG; + goto cleanup; + } + + if ((ixt_a=ixs->ipsp->ips_alg_auth)) { + ixs->tailroom += AHHMAC_HASHLEN; + } else + switch(ixs->ipsp->ips_authalg) { + #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + case AH_MD5: + ixs->tailroom += AHHMAC_HASHLEN; + break; + #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + case AH_SHA: + ixs->tailroom += AHHMAC_HASHLEN; + break; + #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + case AH_NONE: + break; + default: + ixs->stats->tx_errors++; + bundle_stat = IPSEC_XMIT_AH_BADALG; + goto cleanup; + } + ixs->tailroom += blocksize != 1 ? + ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : + ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; + #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_KLIPS_ESP */ + #ifdef CONFIG_KLIPS_IPIP + case IPPROTO_IPIP: + ixs->headroom += sizeof(struct iphdr); + break; + #endif /* !CONFIG_KLIPS_IPIP */ + case IPPROTO_COMP: + #ifdef CONFIG_KLIPS_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_KLIPS_IPCOMP */ + default: + ixs->stats->tx_errors++; + bundle_stat = IPSEC_XMIT_BADPROTO; + goto cleanup; + } + ixs->ipsp = ixs->ipsp->ips_next; + 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 = saved_ipsp; /* 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->cur_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->cur_mtu, ixs->physmtu, + ixs->tot_headroom, ixs->tot_tailroom, ixs->mtudiff, ntohs(ixs->iph->tot_len)); + if(ixs->cur_mtu == 0 || 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 ? ixs->dev->name : "ifX", + ixs->cur_mtu, + ixs->cur_mtu - newmtu, + newmtu); + ixs->cur_mtu = newmtu; + + /* this would seem to adjust the MTU of the route as well */ + #if 0 + ixs->skb->dst->pmtu = ixs->prv->mtu; /* RGB */ + #endif /* 0 */ + } + + /* + 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->cur_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->cur_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->cur_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->cur_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 force destination address to sane value + */ + + struct sockaddr_in *sv4=(struct sockaddr_in *)ixs->ipsp->ips_addr_d; + __u32 natt_d = sv4->sin_addr.s_addr; + struct iphdr *ipp = ixs->iph; + + /* set the destination address to what it needs to be for the + * NAT encapsulation. + */ + KLIPS_PRINT(debug_tunnel, + "xmit: setting ND=%08x\n", natt_d); + ipp->daddr = natt_d; + ipp->check = 0; + ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); + } + #endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ + + if(!ixs->hard_header_stripped && ixs->hard_header_len>0) { + 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); + + if(tskb && ixs->skb->sk) { + skb_set_owner_w(tskb, ixs->skb->sk); + } + + 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)); + } + + #ifdef CONFIG_KLIPS_DEBUG + if(debug_tunnel & DB_TN_ENCAP) { + ipsec_print_ip(ixs->iph); + } + #endif + + /* + * Apply grouped transforms to packet + */ + while (ixs->ipsp) { + enum ipsec_xmit_value encap_stat = IPSEC_XMIT_OK; + + encap_stat = ipsec_xmit_encap_once(ixs); + + #ifdef CONFIG_KLIPS_DEBUG + if(debug_tunnel & DB_TN_ENCAP) { + ipsec_print_ip(ixs->iph); + } + #endif + + 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: + return bundle_stat; + } + + /* + * upon entry to this function, ixs->skb should be setup + * as follows: + * + * data = beginning of IP packet <- differs from ipsec_rcv(). + * nh.raw = beginning of IP packet. + * h.raw = data after the IP packet. + * + */ + enum ipsec_xmit_value + ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs) + { + 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_KLIPS_DEBUG + char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF]; + #endif /* CONFIG_KLIPS_DEBUG */ + + /* Signal all listening KMds with a PF_KEY ACQUIRE */ + + memset(&src, 0, sizeof(src)); + memset(&dst, 0, sizeof(dst)); + 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; + + 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: " + "K_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) */ + + /* ipsec_sa_getbyid() takes a reference to the ixs */ + 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)"); + if(ixs->stats) { + ixs->stats->tx_dropped++; + } + bundle_stat = IPSEC_XMIT_SAIDNOTFOUND; + goto cleanup; + } + + bundle_stat = ipsec_xmit_encap_bundle_2(ixs); + + /* we are done with this SA */ + ipsec_sa_put(ixs->ipsp); + + cleanup: + return bundle_stat; + } + + void + ipsec_xmit_cleanup(struct ipsec_xmit_state*ixs) + { + if(ixs->dev) { + #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); + ixs->saved_header = NULL; + } + if(ixs->skb) { + dev_kfree_skb(ixs->skb); + ixs->skb=NULL; + } + if(ixs->oskb) { + dev_kfree_skb(ixs->oskb); + ixs->oskb=NULL; + } + if (ixs->ips.ips_ident_s.data) { + kfree(ixs->ips.ips_ident_s.data); + ixs->ips.ips_ident_s.data=NULL; + } + if (ixs->ips.ips_ident_d.data) { + kfree(ixs->ips.ips_ident_d.data); + ixs->ips.ips_ident_d.data=NULL; + } + } + + #ifdef NETDEV_23 + static inline int ipsec_xmit_send2(struct sk_buff *skb) + { + #ifdef NETDEV_25 /* 2.6 kernels */ + return dst_output(skb); + #else + return ip_send(skb); + #endif + } + #endif /* NETDEV_23 */ + + #ifdef CONFIG_IPSEC_NAT_TRAVERSAL + enum ipsec_xmit_value ipsec_nat_encap(struct ipsec_xmit_state *ixs) + { + if (ixs->natt_type && ixs->natt_head) { + #if 0 + struct iphdr *ipp = ixs->skb->nh.iph; + #endif + struct iphdr *ipp = ixs->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); + + #if 0 + /* set IP destination address (matters in transport mode) */ + { + struct sockaddr_in *d = (struct sockaddr_in *)ixs->ipsp->ips_addr_d; + ipp->daddr = d->sin_addr.s_addr; + } + #endif + + /* 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); + } + return IPSEC_XMIT_OK; + } + #endif + + /* avoid forward reference complain on <2.5 */ + struct flowi; + + enum ipsec_xmit_value + ipsec_xmit_send(struct ipsec_xmit_state*ixs, struct flowi *fl) + { + int error; + + #ifdef NETDEV_25 + #if 0 + 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; + #endif + fl->nl_u.ip4_u.daddr = ixs->iph->daddr; + fl->nl_u.ip4_u.saddr = ixs->pass ? 0 : ixs->iph->saddr; + fl->nl_u.ip4_u.tos = RT_TOS(ixs->iph->tos); + fl->proto = ixs->iph->protocol; + + if ((error = ip_route_output_key(&ixs->route, fl))) { + #else + /*skb_orphan(ixs->skb);*/ + if((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", + 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; + if(ixs->stats) { + ixs->stats->tx_bytes += ixs->skb->len; + } + + #if 0 + if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { + #endif + if(ixs->skb->len < skb_network_header(ixs->skb) - ixs->skb->data) { + if(ixs->stats) { + 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)(skb_network_header(ixs->skb) - ixs->skb->data), + ixs->skb->len); + return IPSEC_XMIT_PUSHPULLERR; + } + __skb_pull(ixs->skb, skb_network_header(ixs->skb) - ixs->skb->data); + #ifdef SKB_RESET_NFCT + if(!ixs->pass) { + nf_conntrack_put(ixs->skb->nfct); + ixs->skb->nfct = NULL; + } + #if defined(CONFIG_NETFILTER_DEBUG) && defined(HAVE_SKB_NF_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"); + #if 0 + KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->skb->nh.iph); + #endif + KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ip_hdr(ixs->skb)); + #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_xmit_send2); + 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); + if(ixs->stats) { + 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 */ + if(ixs->stats) { + ixs->stats->tx_packets++; + } + + ixs->skb = NULL; + + return IPSEC_XMIT_OK; + } + + #ifdef NETDEV_25 + enum ipsec_xmit_value + ipsec_tunnel_send(struct ipsec_xmit_state *ixs) + { + struct flowi fl; + + memset(&fl, 0, sizeof(fl)); + + /* new route/dst cache code from James Morris */ + ixs->skb->dev = ixs->physdev; + fl.oif = ixs->physdev->iflink; + + return ipsec_xmit_send(ixs, &fl); + } + #else + enum ipsec_xmit_value + ipsec_tunnel_send(struct ipsec_xmit_state *ixs) + { + return ipsec_xmit_send(ixs, NULL); + } + #endif + + + + /* + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/Kconfig linux-2.6.16-ng-natt-klips/net/ipsec/Kconfig *** linux-2.6.16-ng-natt/net/ipsec/Kconfig 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/Kconfig 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,161 ---- + # + # IPSEC configuration + # Copyright (C) 2004 Michael Richardson + # + # 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 . + # + # 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: Kconfig,v 1.6.2.1 2006/04/20 16:33:06 mcr Exp $ + + config KLIPS + tristate "Libreswan IPsec (KLIPS)" + default n + select NF_CONNTRACK && NETFILTER + help + KLIPS is the Libreswan (www.libreswan.org) Kernel Level IP Security + system. It is extensively tested, and has interoperated with + many other systems. + It provides "ipsecX" devices on which one can do firewalling. + The Libreswan userland, is compatible with both KLIPS and NETKEY + You cannot build KLIPS and NETKEY inline into the kernel. + + menu "KLIPS options" + depends on KLIPS + + config KLIPS_ESP + bool 'Encapsulating Security Payload - ESP ("VPN")' + default y + help + This option provides support for the IPSEC Encapsulation Security + Payload (IP protocol 50) which provides packet layer content + hiding, and content authentication. + It is recommended to enable this. RFC2406 + + config KLIPS_AH + bool 'Authentication Header - AH' + default n + help + This option provides support for the IPSEC Authentication Header + (IP protocol 51) which provides packet layer sender and content + authentication. It does not provide for confidentiality. + It is not recommended to enable this. RFC2402 + + config KLIPS_AUTH_HMAC_MD5 + bool 'HMAC-MD5 authentication algorithm' + default y + help + The HMAC-MD5 algorithm is used by ESP (and AH) to guarantee packet + integrity. There is little reason not to include it. + + config KLIPS_AUTH_HMAC_SHA1 + bool 'HMAC-SHA1 authentication algorithm' + default y + help + The HMAC-SHA1 algorithm is used by ESP (and AH) to guarantee packet + integrity. SHA1 is a little slower than MD5, but is said to be + a bit more secure. There is little reason not to include it. + + config KLIPS_ENC_CRYPTOAPI + bool 'CryptoAPI algorithm interface' + default n + help + Enable the algorithm interface to make all CryptoAPI 1.0 algorithms + available to KLIPS. + + config KLIPS_ENC_1DES + bool 'Include 1DES with CryptoAPI' + default n + depends on KLIPS_ENC_CRYPTOAPI + help + The CryptoAPI interface does not include support for every algorithm + yet, and one that it doesn't support by default is the VERY WEAK + 1DES. Select this if you are terminally stupid. + + config KLIPS_ENC_3DES + bool '3DES encryption algorithm' + default y + help + The 3DES algorithm is used by ESP to provide for packet privacy. + 3DES is 3-repeats of the DES algorithm. 3DES is widely supported, + and analyzed and is considered very secure. 1DES is not supported. + + config KLIPS_ENC_AES + bool 'AES encryption algorithm' + default y + help + The AES algorithm is used by ESP to provide for packet privacy. + AES the NIST replacement for DES. AES is being widely analyzed, + and is very fast. + + config KLIPS_IPCOMP + bool 'IP compression' + default y + help + The IPcomp protocol is used prior to ESP to make the packet + smaller. Once encrypted, compression will fail, so any link + layer efforts (e.g. PPP) will not work. + + config KLIPS_DEBUG + bool 'IPsec debugging' + default y + help + KLIPS includes a lot of debugging code. Unless there is a real + tangible benefit to removing this code, it should be left in place. + Debugging connections without access to kernel level debugging is + essentially impossible. Leave this on. + + config KLIPS_IF_MAX + int 'Maximum number of virtual interfaces' + default 64 + range 4 256 + help + KLIPS creates virtual interfaces for tunnel purposes. At present + it keeps track of certain items in an array (FIX ME), and needs + to preallocate this array. Only a pointer is used per item. + + endmenu + + # + # + # $Log: Kconfig,v $ + # Revision 1.6.2.1 2006/04/20 16:33:06 mcr + # remove all of CONFIG_KLIPS_ALG --- one can no longer build without it. + # Fix in-kernel module compilation. Sub-makefiles do not work. + # + # Revision 1.6 2005/05/18 20:55:27 mcr + # default cryptoapi to n. + # + # Revision 1.5 2005/05/11 01:23:25 mcr + # added 1DES option to cryptoapi. + # + # Revision 1.4 2005/04/29 05:29:54 mcr + # add option to include cryptoapi algorithms. + # + # Revision 1.3 2004/08/17 03:27:23 mcr + # klips 2.6 edits. + # + # Revision 1.2 2004/08/14 03:27:39 mcr + # 2.6 kernel build/configuration files. + # + # Revision 1.1 2004/08/14 02:47:55 mcr + # kernel build/config patches + # + # Revision 1.3 2004/02/24 17:17:04 mcr + # s/CONFIG_IPSEC/CONFIG_KLIPS/ as 26sec uses "CONFIG_IPSEC" to + # turn it on/off as well. + # + # Revision 1.2 2004/02/22 06:50:42 mcr + # kernel 2.6 port - merged with 2.4 code. + # + # Revision 1.1.2.1 2004/02/20 02:07:53 mcr + # module configuration for KLIPS 2.6 + # + # + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/Makefile linux-2.6.16-ng-natt-klips/net/ipsec/Makefile *** linux-2.6.16-ng-natt/net/ipsec/Makefile 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/Makefile 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,190 ---- + # Makefile for KLIPS kernel code as a module for 2.6 kernels + # + # Makefile for KLIPS kernel code as a module + # Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. + # Copyright (C) 2002-2004 Michael Richardson + # + # 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 . + # + # 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.fs2_6,v 1.8.2.1 2006/04/20 16:33:06 mcr 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). + # + + LIBRESWANSRCDIR?=. + KLIPS_TOP?=. + + -include ${LIBRESWANSRCDIR}/Makefile.ver + + base-klips-objs := + + base-klips-objs+= ipsec_init.o ipsec_sa.o ipsec_radij.o radij.o + base-klips-objs+= ipsec_life.o ipsec_proc.o + base-klips-objs+= ipsec_tunnel.o ipsec_xmit.o ipsec_rcv.o ipsec_ipip.o + base-klips-objs+= ipsec_snprintf.o + base-klips-objs+= ipsec_mast.o + base-klips-objs+= sysctl_net_ipsec.o + base-klips-objs+= pfkey_v2.o pfkey_v2_parser.o pfkey_v2_ext_process.o + base-klips-objs+= version.o + + base-klips-objs+= satot.o + base-klips-objs+= addrtot.o + base-klips-objs+= ultot.o + base-klips-objs+= addrtypeof.o + base-klips-objs+= anyaddr.o + base-klips-objs+= initaddr.o + base-klips-objs+= ultoa.o + base-klips-objs+= addrtoa.o + base-klips-objs+= subnettoa.o + base-klips-objs+= subnetof.o + base-klips-objs+= goodmask.o + base-klips-objs+= datatot.o + base-klips-objs+= rangetoa.o + base-klips-objs+= prng.o + base-klips-objs+= pfkey_v2_parse.o + base-klips-objs+= pfkey_v2_build.o + base-klips-objs+= pfkey_v2_debug.o + base-klips-objs+= pfkey_v2_ext_bits.o + base-klips-objs+= version.o + + obj-${CONFIG_KLIPS} += ipsec.o + + ipsec-objs += ${base-klips-objs} + + ipsec-$(CONFIG_KLIPS_ESP) += ipsec_esp.o + ipsec-$(CONFIG_KLIPS_IPCOMP) += ipsec_ipcomp.o + ipsec-$(CONFIG_KLIPS_AUTH_HMAC_MD5) += ipsec_md5c.o + ipsec-$(CONFIG_KLIPS_AUTH_HMAC_SHA1) += ipsec_sha1.o + + # AH, if you really think you need it. + ipsec-$(CONFIG_KLIPS_AH) += ipsec_ah.o + + ipsec-y += ipsec_alg.o + + # include code from DES subdir + crypto-$(CONFIG_KLIPS_ENC_3DES) += des/ipsec_alg_3des.o + crypto-$(CONFIG_KLIPS_ENC_3DES) += des/cbc_enc.o + crypto-$(CONFIG_KLIPS_ENC_3DES) += des/ecb_enc.o + crypto-$(CONFIG_KLIPS_ENC_3DES) += des/set_key.o + + ifeq ($(strip ${SUBARCH}),) + SUBARCH:=${ARCH} + endif + + # the assembly version expects frame pointers, which are + # optional in many kernel builds. If you want speed, you should + # probably use cryptoapi code instead. + USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} + ifeq (${USEASSEMBLY},i386y) + crypto-$(CONFIG_KLIPS_ENC_3DES) += des/dx86unix.o + else + crypto-$(CONFIG_KLIPS_ENC_3DES) += des/des_enc.o + endif + + # include code from AES subdir + crypto-$(CONFIG_KLIPS_ENC_AES) += aes/ipsec_alg_aes.o + crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes_xcbc_mac.o + crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes_cbc.o + + ifeq ($(strip ${SUBARCH}),) + SUBARCH:=${ARCH} + endif + + USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} + ifeq (${USEASSEMBLY},i386y) + crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes-i586.o + else + crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes.o + endif + + ipsec-y += ${crypto-y} + + ipsec-$(CONFIG_KLIPS_ENC_CRYPTOAPI) += ipsec_alg_cryptoapi.o + + # IPcomp stuff + base-ipcomp-objs := ipcomp.o + base-ipcomp-objs += adler32.o + base-ipcomp-objs += deflate.o + base-ipcomp-objs += infblock.o + base-ipcomp-objs += infcodes.o + base-ipcomp-objs += inffast.o + base-ipcomp-objs += inflate.o + base-ipcomp-objs += inftrees.o + base-ipcomp-objs += infutil.o + base-ipcomp-objs += trees.o + base-ipcomp-objs += zutil.o + asm-ipcomp-obj-$(CONFIG_M586) += match586.o + asm-ipcomp-obj-$(CONFIG_M586TSC) += match586.o + asm-ipcomp-obj-$(CONFIG_M586MMX) += match586.o + asm-ipcomp-obj-$(CONFIG_M686) += match686.o + asm-ipcomp-obj-$(CONFIG_MPENTIUMIII) += match686.o + asm-ipcomp-obj-$(CONFIG_MPENTIUM4) += match686.o + asm-ipcomp-obj-$(CONFIG_MK6) += match586.o + asm-ipcomp-obj-$(CONFIG_MK7) += match686.o + asm-ipcomp-obj-$(CONFIG_MCRUSOE) += match586.o + asm-ipcomp-obj-$(CONFIG_MWINCHIPC6) += match586.o + asm-ipcomp-obj-$(CONFIG_MWINCHIP2) += match686.o + asm-ipcomp-obj-$(CONFIG_MWINCHIP3D) += match686.o + base-ipcomp-objs += ${asm-ipcomp-obj-y} + + ipsec-$(CONFIG_KLIPS_IPCOMP) += ${base-ipcomp-objs} + + EXTRA_CFLAGS += -DIPCOMP_PREFIX -DKLIPS + + # + # $Log: Makefile.fs2_6,v $ + # Revision 1.8.2.1 2006/04/20 16:33:06 mcr + # remove all of CONFIG_KLIPS_ALG --- one can no longer build without it. + # Fix in-kernel module compilation. Sub-makefiles do not work. + # + # Revision 1.8 2005/05/11 03:15:42 mcr + # adjusted makefiles to sanely build modules properly. + # + # Revision 1.7 2005/04/13 22:52:12 mcr + # moved KLIPS specific snprintf() wrapper to seperate file. + # + # Revision 1.6 2004/08/22 05:02:03 mcr + # organized symbols such that it is easier to build modules. + # + # Revision 1.5 2004/08/18 01:43:56 mcr + # adjusted makefile enumation so that it can be used by module + # wrapper. + # + # Revision 1.4 2004/08/17 03:27:23 mcr + # klips 2.6 edits. + # + # Revision 1.3 2004/08/04 16:50:13 mcr + # removed duplicate definition of dx86unix.o + # + # Revision 1.2 2004/08/03 18:21:09 mcr + # only set KLIPS_TOP and LIBRESWANSRCDIR if not already set. + # + # Revision 1.1 2004/07/26 15:02:22 mcr + # makefile for KLIPS module for 2.6. + # + # Revision 1.3 2004/02/24 17:17:04 mcr + # s/CONFIG_IPSEC/CONFIG_KLIPS/ as 26sec uses "CONFIG_IPSEC" to + # turn it on/off as well. + # + # Revision 1.2 2004/02/22 06:50:42 mcr + # kernel 2.6 port - merged with 2.4 code. + # + # Revision 1.1.2.1 2004/02/20 02:07:53 mcr + # module configuration for KLIPS 2.6 + # + # + # Local Variables: + # compile-command: "(cd ../../.. && source umlsetup.sh && make -C ${POOLSPACE} module/ipsec.o)" + # End Variables: + # + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/Makefile.ver linux-2.6.16-ng-natt-klips/net/ipsec/Makefile.ver *** linux-2.6.16-ng-natt/net/ipsec/Makefile.ver 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/Makefile.ver 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1 ---- + IPSECVERSION='2.5.51s' diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/match586.S linux-2.6.16-ng-natt-klips/net/ipsec/match586.S *** linux-2.6.16-ng-natt/net/ipsec/match586.S 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/match586.S 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,357 ---- + /* match.s -- Pentium-optimized version of longest_match() + * Written for zlib 1.1.2 + * Copyright (C) 1998 Brian Raiter + * + * 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 diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/match686.S linux-2.6.16-ng-natt-klips/net/ipsec/match686.S *** linux-2.6.16-ng-natt/net/ipsec/match686.S 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/match686.S 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,330 ---- + /* match.s -- Pentium-Pro-optimized version of longest_match() + * Written for zlib 1.1.2 + * Copyright (C) 1998 Brian Raiter + * + * 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 diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_build.c linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_build.c *** linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_build.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_build.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1448 ---- + /* + * 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 . + * + * 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.53 2005/11/09 00:30:37 mcr Exp $ + */ + + /* + * Template from klips/net/ipsec/ipsec/ipsec_parser.c. + */ + + char pfkey_v2_build_c_version[] = "$Id: pfkey_v2_build.c,v 1.53 2005/11/09 00:30:37 mcr Exp $"; + + /* + * Some ugly stuff to allow consistent debugging code for use in the + * kernel and in user space + */ + + #if defined(__KERNEL__) && defined(linux) + + # include /* for printk */ + + # include "libreswan/ipsec_kversion.h" /* for malloc switch */ + # ifdef MALLOC_SLAB + # include /* kmalloc() */ + # else /* MALLOC_SLAB */ + # include /* kmalloc() */ + # endif /* MALLOC_SLAB */ + # include /* error codes */ + # include /* size_t */ + # include /* mark_bh */ + + # include /* struct device, and other headers */ + # include /* eth_type_trans */ + # include /* struct iphdr */ + # if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + # include /* struct ipv6hdr */ + # endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ + + # define MALLOC(size) kmalloc(size, GFP_ATOMIC) + # define FREE(obj) kfree(obj) + # include + #else /* __KERNEL__ */ + + # include + # include + # include + # include + # include + # include /* memset */ + + # include + + #endif /* __KERNEL__ */ + + #include + #include + + #ifdef __KERNEL__ + #include "libreswan/radij.h" /* rd_nodes */ + #include "libreswan/ipsec_encap.h" /* sockaddr_encap */ + #endif /* __KERNEL__ */ + + + #include "libreswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ + #include "libreswan/pfkey_debug.h" + + + #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) + + void + pfkey_extensions_init(struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]) + { + int i; + + for (i = 0; i != K_SADB_EXT_MAX + 1; i++) { + extensions[i] = NULL; + } + } + + void + pfkey_extensions_free(struct sadb_ext *extensions[K_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 != K_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) { + ERROR("pfkey_msg_hdr_build: " + "why is pfkey_msg already pointing to something?\n"); + SENDERR(EINVAL); + } + + if(!msg_type) { + ERROR("pfkey_msg_hdr_build: " + "msg type not set, must be non-zero..\n"); + SENDERR(EINVAL); + } + + if(msg_type > K_SADB_MAX) { + ERROR("pfkey_msg_hdr_build: " + "msg type too large:%d.\n", + msg_type); + SENDERR(EINVAL); + } + + if(satype > K_SADB_SATYPE_MAX) { + ERROR("pfkey_msg_hdr_build: " + "satype %d > max %d\n", + satype, SADB_SATYPE_MAX); + SENDERR(EINVAL); + } + + pfkey_msg = (struct sadb_msg*)MALLOC(sizeof(struct sadb_msg)); + *pfkey_ext = (struct sadb_ext*)pfkey_msg; + + if(pfkey_msg == NULL) { + ERROR("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_builds(struct sadb_ext **pfkey_ext, + struct sadb_builds sab) + { + int error = 0; + struct k_sadb_sa *pfkey_sa = (struct k_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(sab.sa_base.sadb_sa_spi), /* in network order */ + sab.sa_base.sadb_sa_replay, + sab.sa_base.sadb_sa_state, + sab.sa_base.sadb_sa_auth, + sab.sa_base.sadb_sa_encrypt, + sab.sa_base.sadb_sa_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(sab.sa_base.sadb_sa_exttype != SADB_EXT_SA && + sab.sa_base.sadb_sa_exttype != K_SADB_X_EXT_SA2) { + DEBUGGING(PF_KEY_DEBUG_BUILD, + "pfkey_sa_build: " + "invalid exttype=%d.\n", + sab.sa_base.sadb_sa_exttype); + SENDERR(EINVAL); + } + + if(sab.sa_base.sadb_sa_replay > 64) { + DEBUGGING(PF_KEY_DEBUG_BUILD, + "pfkey_sa_build: " + "replay window size: %d -- must be 0 <= size <= 64\n", + sab.sa_base.sadb_sa_replay); + SENDERR(EINVAL); + } + + if(sab.sa_base.sadb_sa_auth > SADB_AALG_MAX) { + DEBUGGING(PF_KEY_DEBUG_BUILD, + "pfkey_sa_build: " + "auth=%d > SADB_AALG_MAX=%d.\n", + sab.sa_base.sadb_sa_auth, + SADB_AALG_MAX); + SENDERR(EINVAL); + } + + #if K_SADB_EALG_MAX < 255 + if(sab.sa_base.sadb_sa_encrypt > K_SADB_EALG_MAX) { + DEBUGGING(PF_KEY_DEBUG_BUILD, + "pfkey_sa_build: " + "encrypt=%d > K_SADB_EALG_MAX=%d.\n", + sab.sa_base.sadb_sa_encrypt, + K_SADB_EALG_MAX); + SENDERR(EINVAL); + } + #endif + + if(sab.sa_base.sadb_sa_state > K_SADB_SASTATE_MAX) { + DEBUGGING(PF_KEY_DEBUG_BUILD, + "pfkey_sa_build: " + "sa_state=%d exceeds MAX=%d.\n", + sab.sa_base.sadb_sa_state, + K_SADB_SASTATE_MAX); + SENDERR(EINVAL); + } + + if(sab.sa_base.sadb_sa_state == K_SADB_SASTATE_DEAD) { + DEBUGGING(PF_KEY_DEBUG_BUILD, + "pfkey_sa_build: " + "sa_state=%d is DEAD=%d is not allowed.\n", + sab.sa_base.sadb_sa_state, + K_SADB_SASTATE_DEAD); + SENDERR(EINVAL); + } + + if((IPSEC_SAREF_NULL != sab.sa_base.sadb_x_sa_ref) && (sab.sa_base.sadb_x_sa_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", + sab.sa_base.sadb_x_sa_ref, + IPSEC_SAREF_NULL, + IPSEC_SA_REF_TABLE_NUM_ENTRIES); + SENDERR(EINVAL); + } + + pfkey_sa = (struct k_sadb_sa*)MALLOC(sizeof(struct k_sadb_sa)); + *pfkey_ext = (struct sadb_ext*)pfkey_sa; + + if(pfkey_sa == NULL) { + DEBUGGING(PF_KEY_DEBUG_BUILD, + "pfkey_sa_build: " + "memory allocation failed\n"); + SENDERR(ENOMEM); + } + memset(pfkey_sa, 0, sizeof(struct k_sadb_sa)); + + *pfkey_sa = sab.sa_base; + pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN; + + 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) + { + struct sadb_builds sab; + + memset(&sab, 0, sizeof(sab)); + sab.sa_base.sadb_sa_exttype = exttype; + sab.sa_base.sadb_sa_spi = spi; + sab.sa_base.sadb_sa_replay = replay_window; + sab.sa_base.sadb_sa_state = sa_state; + sab.sa_base.sadb_sa_auth = auth; + sab.sa_base.sadb_sa_encrypt = encrypt; + sab.sa_base.sadb_sa_flags = flags; + sab.sa_base.sadb_x_sa_ref = IPSEC_SAREF_NULL; + + return pfkey_sa_builds(pfkey_ext, sab); + } + + 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); + } + + pfkey_lifetime = (struct sadb_lifetime*)MALLOC(sizeof(struct sadb_lifetime)); + *pfkey_ext = (struct sadb_ext*) pfkey_lifetime; + + if(pfkey_lifetime == NULL) { + 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; + + 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 K_SADB_X_EXT_ADDRESS_DST2: + case K_SADB_X_EXT_ADDRESS_SRC_FLOW: + case K_SADB_X_EXT_ADDRESS_DST_FLOW: + case K_SADB_X_EXT_ADDRESS_SRC_MASK: + case K_SADB_X_EXT_ADDRESS_DST_MASK: + #ifdef NAT_TRAVERSAL + case K_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, + unsigned 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); + } + + pfkey_key = (struct sadb_key*) + MALLOC(sizeof(struct sadb_key) + + DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); + + *pfkey_ext = (struct sadb_ext*)pfkey_key; + + if(pfkey_key == NULL) { + 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 + + pfkey_ident = (struct sadb_ident*) + MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN); + + *pfkey_ext = (struct sadb_ext*)pfkey_ident; + + if(pfkey_ident == NULL) { + 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 */ + + pfkey_sens = (struct sadb_sens*) + MALLOC(sizeof(struct sadb_sens) + + (sens_len + integ_len) * sizeof(uint64_t)); + + *pfkey_ext = (struct sadb_ext*)pfkey_sens; + + if(pfkey_sens == NULL) { + 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); + } + + pfkey_prop = (struct sadb_prop*) + MALLOC(sizeof(struct sadb_prop) + + comb_num * sizeof(struct sadb_comb)); + + *pfkey_ext = (struct sadb_ext*)pfkey_prop; + + if(pfkey_prop == NULL) { + 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); + } + + pfkey_supported = (struct sadb_supported*) + MALLOC(sizeof(struct sadb_supported) + + alg_num * + sizeof(struct sadb_alg)); + + *pfkey_ext = (struct sadb_ext*)pfkey_supported; + + if(pfkey_supported == NULL) { + 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); + } + + pfkey_spirange = (struct sadb_spirange*) + MALLOC(sizeof(struct sadb_spirange)); + + *pfkey_ext = (struct sadb_ext*)pfkey_spirange; + + if(pfkey_spirange == NULL) { + 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 */ + + pfkey_x_kmprivate = (struct sadb_x_kmprivate*) + MALLOC(sizeof(struct sadb_x_kmprivate)); + + *pfkey_ext = (struct sadb_ext*)pfkey_x_kmprivate; + + if(pfkey_x_kmprivate == NULL) { + 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 = K_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 > K_SADB_SATYPE_MAX) { + ERROR("pfkey_x_satype_build: " + "satype %d > max %d\n", + satype, K_SADB_SATYPE_MAX); + SENDERR(EINVAL); + } + + pfkey_x_satype = (struct sadb_x_satype*) + MALLOC(sizeof(struct sadb_x_satype)); + + *pfkey_ext = (struct sadb_ext*)pfkey_x_satype; + if(pfkey_x_satype == NULL) { + 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 = K_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); + + pfkey_x_debug = (struct sadb_x_debug*) + MALLOC(sizeof(struct sadb_x_debug)); + + *pfkey_ext = (struct sadb_ext*)pfkey_x_debug; + + if(pfkey_x_debug == NULL) { + 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 = K_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); + + pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*) + MALLOC(sizeof(struct sadb_x_nat_t_type)); + + *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type; + + if(pfkey_x_nat_t_type == NULL) { + 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 = K_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 K_SADB_X_EXT_NAT_T_SPORT: + case K_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); + + pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*) + MALLOC(sizeof(struct sadb_x_nat_t_port)); + + *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port; + + if(pfkey_x_nat_t_port == NULL) { + 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) / IPSEC_PFKEYv2_ALIGN; + p->sadb_protocol_exttype = K_SADB_X_EXT_PROTOCOL; + p->sadb_protocol_proto = protocol; + p->sadb_protocol_flags = 0; + p->sadb_protocol_reserved2 = 0; + errlab: + return error; + } + + int pfkey_outif_build(struct sadb_ext **pfkey_ext, + uint16_t outif) + { + int error = 0; + struct sadb_x_plumbif * p = (struct sadb_x_plumbif *)*pfkey_ext; + + if ((p = (struct sadb_x_plumbif*)MALLOC(sizeof(*p))) == 0) { + ERROR("pfkey_build: memory allocation failed\n"); + SENDERR(ENOMEM); + } + *pfkey_ext = (struct sadb_ext *)p; + + p->sadb_x_outif_len = IPSEC_PFKEYv2_WORDS(sizeof(*p)); + p->sadb_x_outif_exttype = K_SADB_X_EXT_PLUMBIF; + p->sadb_x_outif_ifnum = outif; + + errlab: + return error; + } + + + int pfkey_saref_build(struct sadb_ext **pfkey_ext, + IPsecSAref_t in, IPsecSAref_t out) + { + int error = 0; + struct sadb_x_saref* s; + + /* +4 because sadb_x_saref is not a multiple of 8 bytes */ + + if ((s = (struct sadb_x_saref*)MALLOC(sizeof(*s)+4)) == 0) { + ERROR("pfkey_build: memory allocation failed\n"); + SENDERR(ENOMEM); + } + *pfkey_ext = (struct sadb_ext *)s; + + s->sadb_x_saref_len = IPSEC_PFKEYv2_WORDS(sizeof(*s)); + s->sadb_x_saref_exttype = K_SADB_X_EXT_SAREF; + s->sadb_x_saref_me = in; + s->sadb_x_saref_him = out; + + errlab: + return error; + } + + + #if defined(I_DONT_THINK_THIS_WILL_BE_USEFUL) && I_DONT_THINK_THIS_WILL_BE_USEFUL + int (*ext_default_builders[K_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; + pfkey_ext_track extensions_seen = 0; + #ifndef __KERNEL__ + struct sadb_ext *extensions_check[K_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 <= K_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 <= K_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(!pfkey_permitted_extension(dir,(*pfkey_msg)->sadb_msg_type,ext)) { + ERROR("ext type %d not permitted for %d/%d (build)\n", + ext, + dir,(*pfkey_msg)->sadb_msg_type); + 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); + + { + char *pfkey_ext_c = (char *)pfkey_ext; + + pfkey_ext_c += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN; + + #if 0 + printf("memcpy(%p,%p,%d) -> %p %p:%p\n", pfkey_ext, + extensions[ext], + (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN, + pfkey_ext_c, (*pfkey_msg), (char *)(*pfkey_msg)+(total_size*IPSEC_PFKEYv2_ALIGN)); + #endif + memcpy(pfkey_ext, + extensions[ext], + (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); + pfkey_ext = (struct sadb_ext *)pfkey_ext_c; + } + + /* Mark that we have seen this extension */ + pfkey_mark_extension(ext,&extensions_seen); + } + } + + if(pfkey_extensions_missing(dir,(*pfkey_msg)->sadb_msg_type,extensions_seen)) { + ERROR("required extensions missing. seen=%08llx\n", (unsigned long long)extensions_seen); + 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; + } + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/pfkey_v2.c linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2.c *** linux-2.6.16-ng-natt/net/ipsec/pfkey_v2.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1555 ---- + /* + * @(#) 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 . + * + * 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. + * + */ + + /* + * 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 + #include + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + + #include "libreswan/ipsec_param.h" + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include /* struct socket */ + #include + #include + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include + #include + #include + #include /* struct sock */ + #include + /* #include */ + #include + #ifdef CONFIG_PROC_FS + # include + #endif /* CONFIG_PROC_FS */ + + #include + + #include + + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_sa.h" + + #include + #include + + #include "libreswan/ipsec_proto.h" + #include "libreswan/ipsec_kern24.h" + #include "libreswan/ipsec_sysctl.h" + + #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) + + #ifndef SOCKOPS_WRAPPED + #define SOCKOPS_WRAPPED(name) name + #endif /* SOCKOPS_WRAPPED */ + + + #ifdef NET_26 + static rwlock_t pfkey_sock_lock = RW_LOCK_UNLOCKED; + HLIST_HEAD(pfkey_sock_list); + static DECLARE_WAIT_QUEUE_HEAD(pfkey_sock_wait); + static atomic_t pfkey_sock_users = ATOMIC_INIT(0); + #else + struct sock *pfkey_sock_list = NULL; + #endif + + struct supported_list *pfkey_supported_list[K_SADB_SATYPE_MAX+1]; + + struct socket_list *pfkey_open_sockets = NULL; + struct socket_list *pfkey_registered_sockets[K_SADB_SATYPE_MAX+1]; + + int pfkey_msg_interp(struct sock *, struct sadb_msg *); + + DEBUG_NO_STATIC int pfkey_create(struct socket *sock, int protocol); + DEBUG_NO_STATIC int pfkey_shutdown(struct socket *sock, int mode); + DEBUG_NO_STATIC int pfkey_release(struct socket *sock); + + #ifdef NET_26 + DEBUG_NO_STATIC int pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len); + DEBUG_NO_STATIC int pfkey_recvmsg(struct kiocb *kiocb, struct socket *sock, struct msghdr *msg + , size_t size, int flags); + #else + DEBUG_NO_STATIC int pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm); + DEBUG_NO_STATIC int pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm); + #endif + + struct net_proto_family pfkey_family_ops = { + .owner = THIS_MODULE, + .family = PF_KEY, + .create = pfkey_create + }; + + struct proto_ops SOCKOPS_WRAPPED(pfkey_ops) = { + #ifdef NETDEV_23 + owner: THIS_MODULE, + 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 + SOCKOPS_WRAP(pfkey, PF_KEY); + #endif /* NETDEV_23 */ + + #ifdef NET_26 + static void pfkey_sock_list_grab(void) + { + write_lock_bh(&pfkey_sock_lock); + + if (atomic_read(&pfkey_sock_users)) { + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue_exclusive(&pfkey_sock_wait, &wait); + for(;;) { + set_current_state(TASK_UNINTERRUPTIBLE); + if (atomic_read(&pfkey_sock_users) == 0) + break; + write_unlock_bh(&pfkey_sock_lock); + schedule(); + write_lock_bh(&pfkey_sock_lock); + } + + __set_current_state(TASK_RUNNING); + remove_wait_queue(&pfkey_sock_wait, &wait); + } + } + + static __inline__ void pfkey_sock_list_ungrab(void) + { + write_unlock_bh(&pfkey_sock_lock); + wake_up(&pfkey_sock_wait); + } + + static __inline__ void pfkey_lock_sock_list(void) + { + /* read_lock() synchronizes us to pfkey_table_grab */ + + read_lock(&pfkey_sock_lock); + atomic_inc(&pfkey_sock_users); + read_unlock(&pfkey_sock_lock); + } + + static __inline__ void pfkey_unlock_sock_list(void) + { + if (atomic_dec_and_test(&pfkey_sock_users)) + wake_up(&pfkey_sock_wait); + } + #endif + + 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 ipsec_alg_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 ipsec_alg_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; + } + + #ifdef NET_26 + DEBUG_NO_STATIC void + pfkey_insert_socket(struct sock *sk) + { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_insert_socket: " + "sk=0p%p\n", + sk); + pfkey_sock_list_grab(); + sk_add_node(sk, &pfkey_sock_list); + pfkey_sock_list_ungrab(); + } + + DEBUG_NO_STATIC void + pfkey_remove_socket(struct sock *sk) + { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_remove_socket: 0p%p\n", sk); + pfkey_sock_list_grab(); + sk_del_node_init(sk); + pfkey_sock_list_ungrab(); + return; + } + #else + + 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; + + s = NULL; + 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; + } + #endif + + DEBUG_NO_STATIC void + pfkey_destroy_socket(struct sock *sk) + { + struct sk_buff *skb; + + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_destroy_socket: 0p%p\n",sk); + pfkey_remove_socket(sk); + + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_destroy_socket: " + "pfkey_remove_socket called, sk=0p%p\n",sk); + + 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->sk_receive_queue), + sk->sk_receive_queue.next, + sk->sk_receive_queue.prev); + + while(sk && ((skb=skb_dequeue(&(sk->sk_receive_queue)))!=NULL)) { + #ifdef CONFIG_KLIPS_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(" sk:0p%p", skb->sk); + 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_transport_header(skb)); + printk(" nh:0p%p", skb_network_header(skb)); + printk(" mac:0p%p", skb_mac_header(skb)); + 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); + #ifdef HAVE_SOCK_SECURITY + printk(" security:%d", skb->security); + #endif + printk(" truesize:%d", skb->truesize); + printk(" head:0p%p", skb->head); + printk(" data:0p%p", skb->data); + printk(" tail:0p%p", skb_tail_pointer(skb)); + printk(" end:0p%p", skb_end_pointer(skb)); + if(sysctl_ipsec_debug_verbose) { + unsigned char* i; + printk(" data"); + for(i = skb->head; i < skb_end_pointer(skb); i++) { + printk(":%2x", (unsigned char)(*(i))); + } + } + printk(" destructor:0p%p", skb->destructor); + printk("\n"); + } + #endif /* CONFIG_KLIPS_DEBUG */ + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_destroy_socket: " + "skb=0p%p freed.\n", + skb); + ipsec_kfree_skb(skb); + } + + #ifdef NET_26 + sock_set_flag(sk, SOCK_DEAD); + #else + sk->dead = 1; + #endif + 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; + } + + sk = sock->sk; + + 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_set_transport_header(skb, ipsec_skb_offset(skb, skb_put(skb, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN))); + memcpy(skb_transport_header(skb), pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); + + 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; + } + + #ifdef NET_26_12_SKALLOC + static struct proto key_proto = { + .name = "KEY", + .owner = THIS_MODULE, + .obj_size = sizeof(struct sock), + + }; + #endif + + 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; + } + + sock->state = SS_UNCONNECTED; + + KLIPS_INC_USE; + + #ifdef NET_26 + #ifdef NET_26_12_SKALLOC + sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, &key_proto, 1); + #else + sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL); + #endif + #else + /* 2.4 interface */ + sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1); + #endif + + if(sk == NULL) + { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_create: " + "Out of memory trying to allocate.\n"); + KLIPS_DEC_USE; + return -ENOMEM; + } + + sock_init_data(sock, sk); + + sk->sk_destruct = NULL; + sk->sk_reuse = 1; + sock->ops = &pfkey_ops; + + sk->sk_family = PF_KEY; + /* sk->num = protocol; */ + sk->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->sk_sleep); + + 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; + } + + 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; */ + } + + sk=sock->sk; + + /* 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); + + if(sock_flag(sk, SOCK_DEAD)) + if(sk->sk_state_change) { + sk->sk_state_change(sk); + } + + sock->sk = NULL; + + /* 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 = K_SADB_SATYPE_UNSPEC; i <= K_SADB_SATYPE_MAX; i++) { + pfkey_list_remove_socket(sock, &(pfkey_registered_sockets[i])); + } + + KLIPS_DEC_USE; + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_release: " + "succeeded.\n"); + + return 0; + } + + 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; + } + + sk=sock->sk; + + 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->sk_shutdown|=SEND_SHUTDOWN; + sk->sk_state_change(sk); + } + + if(mode&RCV_SHUTDOWN) { + sk->sk_shutdown|=RCV_SHUTDOWN; + sk->sk_state_change(sk); + } + return 0; + } + + /* + * Send PF_KEY data down. + */ + + DEBUG_NO_STATIC int + #ifdef NET_26 + pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) + #else + pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) + #endif + { + 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); + } + + sk = sock->sk; + + 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->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); + } + + if(msg->msg_control) + { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_sendmsg: " + "can't set flags or set msg_control.\n"); + SENDERR(EINVAL); + } + + if(sk->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", (int)len); + SENDERR(EMSGSIZE); + } + + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_sendmsg: " + "allocating %d bytes for downward message.\n", + (int)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", + (int)len, (int)IPSEC_PFKEYv2_ALIGN); + SENDERR(EMSGSIZE); + } + + 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 > K_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))) { + 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_26 + pfkey_recvmsg(struct kiocb *kiocb + , struct socket *sock + , struct msghdr *msg + , size_t size + , int flags) + #else + pfkey_recvmsg(struct socket *sock + , struct msghdr *msg + , int size, int flags + , struct scm_cookie *scm) + #endif + { + struct sock *sk; + int noblock = flags & MSG_DONTWAIT; + struct sk_buff *skb; + int error; + + if(sock == NULL) { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_recvmsg: " + "Null socket passed in.\n"); + return -EINVAL; + } + + sk = sock->sk; + + 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, (int)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; + } + + msg->msg_namelen = 0; /* sizeof(*ska); */ + + if(sk->sk_err) { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_sendmsg: " + "sk->sk_err=%d.\n", sk->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; + } + else if(size len) { + msg->msg_flags |= MSG_TRUNC; + } + + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size); + #ifdef HAVE_KERNEL_TSTAMP + sk->sk_stamp = skb->tstamp; + #elif defined(HAVE_TSTAMP) + sk->sk_stamp.tv_sec = skb->tstamp.off_sec; + sk->sk_stamp.tv_usec = skb->tstamp.off_usec; + #else + sk->sk_stamp=skb->stamp; + #endif + + skb_free_datagram(sk, skb); + return size; + } + + #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; /* limit of useful snprintf output */ + #ifdef NET_26 + struct hlist_node *node; + #endif + off_t begin=0; + int len=0; + struct sock *sk; + + #ifdef CONFIG_KLIPS_DEBUG + if(!sysctl_ipsec_debug_verbose) { + #endif /* CONFIG_KLIPS_DEBUG */ + len += ipsec_snprintf(buffer, length, + " sock pid socket next prev e n p sndbf Flags Type St\n"); + #ifdef CONFIG_KLIPS_DEBUG + } else { + len += ipsec_snprintf(buffer, length, + " sock pid d sleep socket next prev e r z n p sndbf stamp Flags Type St\n"); + } + #endif /* CONFIG_KLIPS_DEBUG */ + + sk_for_each(sk, node, &pfkey_sock_list) { + + #ifdef CONFIG_KLIPS_DEBUG + if(!sysctl_ipsec_debug_verbose) { + #endif /* CONFIG_KLIPS_DEBUG */ + len += ipsec_snprintf(buffer+len, length-len, + "%8p %5d %8p %d %d %5d %08lX %8X %2X\n", + sk, + key_pid(sk), + sk->sk_socket, + sk->sk_err, + sk->sk_protocol, + sk->sk_sndbuf, + sk->sk_socket->flags, + sk->sk_socket->type, + sk->sk_socket->state); + #ifdef CONFIG_KLIPS_DEBUG + } else { + struct timeval t; + grab_socket_timeval(t, *sk); + len += ipsec_snprintf(buffer+len, length-len, + "%8p %5d %d %8p %8p %d %d %d %d %5d %d.%06d %08lX %8X %2X\n", + sk, + key_pid(sk), + sock_flag(sk, SOCK_DEAD), + sk->sk_sleep, + sk->sk_socket, + sk->sk_err, + sk->sk_reuse, + #ifdef HAVE_SOCK_ZAPPED + sock_flag(sk, SOCK_ZAPPED), + #else + sk->sk_zapped, + #endif + sk->sk_protocol, + sk->sk_sndbuf, + (unsigned int)t.tv_sec, + (unsigned int)t.tv_usec, + sk->sk_socket->flags, + sk->sk_socket->type, + sk->sk_socket->state); + } + #endif /* CONFIG_KLIPS_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; + } + } + } + + *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 */ + ) + { + /* limit of useful snprintf output */ + const int max_content = length > 0? length-1 : 0; + off_t begin=0; + int len=0; + int satype; + struct supported_list *ps; + + len += ipsec_snprintf(buffer, length, + "satype exttype alg_id ivlen minbits maxbits name\n"); + + for(satype = K_SADB_SATYPE_UNSPEC; satype <= K_SADB_SATYPE_MAX; satype++) { + ps = pfkey_supported_list[satype]; + while(ps) { + struct ipsec_alg_supported *alg = ps->supportedp; + unsigned char *n = alg->ias_name; + if(n == NULL) n = "unknown"; + + len += ipsec_snprintf(buffer+len, length-len, + " %2d %2d %2d %3d %3d %3d %20s\n", + satype, + alg->ias_exttype, + alg->ias_id, + alg->ias_ivlen, + alg->ias_keyminbits, + alg->ias_keymaxbits, + 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; /* 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; + } + } + + ps = ps->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; /* limit of useful snprintf output */ + 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 = K_SADB_SATYPE_UNSPEC; satype <= K_SADB_SATYPE_MAX; satype++) { + pfkey_sockets = pfkey_registered_sockets[satype]; + while(pfkey_sockets) { + 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); + + 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 ipsec_alg_supported supported[], int size) + { + int i; + int error = 0; + + KLIPS_PRINT(debug_pfkey, + "klips_debug:init_pfkey: " + "sizeof(supported_init_)[%d]/sizeof(struct ipsec_alg_supported)[%d]=%d.\n", + satype, + size, + (int)sizeof(struct ipsec_alg_supported), + (int)(size/sizeof(struct ipsec_alg_supported))); + + for(i = 0; i < size / sizeof(struct ipsec_alg_supported); i++) { + + unsigned char *n = supported[i].ias_name; + if(n == NULL) n="unknown"; + + KLIPS_PRINT(debug_pfkey, + "klips_debug:init_pfkey: " + "i=%d inserting satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d name=%s.\n", + i, + satype, + supported[i].ias_exttype, + supported[i].ias_id, + supported[i].ias_ivlen, + supported[i].ias_keyminbits, + supported[i].ias_keymaxbits, + n); + + 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 ipsec_alg_supported*supportedp; + + while(pfkey_supported_list[satype]) { + unsigned char *n; + supportedp = pfkey_supported_list[satype]->supportedp; + + n = supportedp->ias_name; + if(n == NULL) n="unknown"; + + KLIPS_PRINT(debug_pfkey, + "klips_debug:init_pfkey: " + "removing satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d name=%s.\n", + satype, + supportedp->ias_exttype, + supportedp->ias_id, + supportedp->ias_ivlen, + supportedp->ias_keyminbits, + supportedp->ias_keymaxbits, n); + + error |= pfkey_list_remove_supported(supportedp, + &(pfkey_supported_list[satype])); + } + return error; + } + + int + pfkey_init(void) + { + int error = 0; + int i; + + static struct ipsec_alg_supported supported_init_ah[] = { + #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + {K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_MD5HMAC, 0, 128, 128}, + #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + {K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_SHA1HMAC, 0, 160, 160} + #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + }; + static struct ipsec_alg_supported supported_init_esp[] = { + #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + {K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_MD5HMAC, 0, 128, 128}, + #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + {K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_SHA1HMAC, 0, 160, 160}, + #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + #ifdef CONFIG_KLIPS_ENC_3DES + {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_EALG_3DESCBC, 64, 168, 168}, + #endif /* CONFIG_KLIPS_ENC_3DES */ + }; + static struct ipsec_alg_supported supported_init_ipip[] = { + {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv4_in_IPv4, 0, 32, 32} + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + , {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv6_in_IPv4, 0, 128, 32} + , {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv4_in_IPv6, 0, 32, 128} + , {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv6_in_IPv6, 0, 128, 128} + #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ + }; + #ifdef CONFIG_KLIPS_IPCOMP + static struct ipsec_alg_supported supported_init_ipcomp[] = { + {K_SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_CALG_DEFLATE, 0, 1, 1} + }; + #endif /* CONFIG_KLIPS_IPCOMP */ + + #if 0 + printk(KERN_INFO + "klips_info:pfkey_init: " + "FreeS/WAN: initialising PF_KEYv2 domain sockets.\n"); + #endif + + for(i = K_SADB_SATYPE_UNSPEC; i <= K_SADB_SATYPE_MAX; i++) { + pfkey_registered_sockets[i] = NULL; + pfkey_supported_list[i] = NULL; + } + + error |= supported_add_all(K_SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah)); + error |= supported_add_all(K_SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp)); + #ifdef CONFIG_KLIPS_IPCOMP + error |= supported_add_all(K_SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp)); + #endif /* CONFIG_KLIPS_IPCOMP */ + error |= supported_add_all(K_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 VOID_SOCK_UNREGISTER + sock_unregister(PF_KEY); + #else + error |= sock_unregister(PF_KEY); + #endif + + error |= supported_remove_all(K_SADB_SATYPE_AH); + error |= supported_remove_all(K_SADB_SATYPE_ESP); + #ifdef CONFIG_KLIPS_IPCOMP + error |= supported_remove_all(K_SADB_X_SATYPE_COMP); + #endif /* CONFIG_KLIPS_IPCOMP */ + error |= supported_remove_all(K_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 */ + struct net_protocol; + void pfkey_proto_init(struct net_protocol *pro) + { + pfkey_init(); + } + #endif /* MODULE */ + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_debug.c linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_debug.c *** linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_debug.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_debug.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,144 ---- + /* + * @(#) pfkey version 2 debugging messages + * + * Copyright (C) 2001 Richard Guy Briggs + * and Michael Richardson + * + * 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 . + * + * 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.11 2005/04/06 17:45:16 mcr Exp $ + * + */ + + #ifdef __KERNEL__ + + # include /* for printk */ + + # include "libreswan/ipsec_kversion.h" /* for malloc switch */ + # ifdef MALLOC_SLAB + # include /* kmalloc() */ + # else /* MALLOC_SLAB */ + # include /* kmalloc() */ + # endif /* MALLOC_SLAB */ + # include /* error codes */ + # include /* size_t */ + # include /* mark_bh */ + + # include /* struct device, and other headers */ + # include /* eth_type_trans */ + extern int debug_pfkey; + + #else /* __KERNEL__ */ + + #if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) + # include + #else + # include + # include + # include + #endif + + #endif /* __KERNEL__ */ + + #include "libreswan.h" + #include "libreswan/pfkeyv2.h" + #include "libreswan/pfkey.h" + + /* + * This file provides ASCII translations of PF_KEY magic numbers. + * + */ + + static char *pfkey_sadb_ext_strings[]={ + "reserved", /* K_SADB_EXT_RESERVED 0 */ + "security-association", /* K_SADB_EXT_SA 1 */ + "lifetime-current", /* K_SADB_EXT_LIFETIME_CURRENT 2 */ + "lifetime-hard", /* K_SADB_EXT_LIFETIME_HARD 3 */ + "lifetime-soft", /* K_SADB_EXT_LIFETIME_SOFT 4 */ + "source-address", /* K_SADB_EXT_ADDRESS_SRC 5 */ + "destination-address", /* K_SADB_EXT_ADDRESS_DST 6 */ + "proxy-address", /* K_SADB_EXT_ADDRESS_PROXY 7 */ + "authentication-key", /* K_SADB_EXT_KEY_AUTH 8 */ + "cipher-key", /* K_SADB_EXT_KEY_ENCRYPT 9 */ + "source-identity", /* K_SADB_EXT_IDENTITY_SRC 10 */ + "destination-identity", /* K_SADB_EXT_IDENTITY_DST 11 */ + "sensitivity-label", /* K_SADB_EXT_SENSITIVITY 12 */ + "proposal", /* K_SADB_EXT_PROPOSAL 13 */ + "supported-auth", /* K_SADB_EXT_SUPPORTED_AUTH 14 */ + "supported-cipher", /* K_SADB_EXT_SUPPORTED_ENCRYPT 15 */ + "spi-range", /* K_SADB_EXT_SPIRANGE 16 */ + "X-kmpprivate", /* K_SADB_X_EXT_KMPRIVATE 17 */ + "X-satype2", /* K_SADB_X_EXT_SATYPE2 18 */ + "X-security-association", /* K_SADB_X_EXT_SA2 19 */ + "X-destination-address2", /* K_SADB_X_EXT_ADDRESS_DST2 20 */ + "X-source-flow-address", /* K_SADB_X_EXT_ADDRESS_SRC_FLOW 21 */ + "X-dest-flow-address", /* K_SADB_X_EXT_ADDRESS_DST_FLOW 22 */ + "X-source-mask", /* K_SADB_X_EXT_ADDRESS_SRC_MASK 23 */ + "X-dest-mask", /* K_SADB_X_EXT_ADDRESS_DST_MASK 24 */ + "X-set-debug", /* K_SADB_X_EXT_DEBUG 25 */ + /* NAT_TRAVERSAL */ + "X-ext-protocol", /* K_SADB_X_EXT_PROTOCOL 26 */ + "X-NAT-T-type", /* K_SADB_X_EXT_NAT_T_TYPE 27 */ + "X-NAT-T-sport", /* K_SADB_X_EXT_NAT_T_SPORT 28 */ + "X-NAT-T-dport", /* K_SADB_X_EXT_NAT_T_DPORT 29 */ + "X-NAT-T-OA", /* K_SADB_X_EXT_NAT_T_OA 30 */ + "X-plumbif", /* K_SADB_X_EXT_PLUMBIF 31 */ + "X-saref", /* K_SADB_X_EXT_SAREF 32 */ + }; + + const char * + pfkey_v2_sadb_ext_string(int ext) + { + if(ext <= K_SADB_EXT_MAX) { + return pfkey_sadb_ext_strings[ext]; + } else { + return "unknown-ext"; + } + } + + + static char *pfkey_sadb_type_strings[]={ + "reserved", /* K_SADB_RESERVED */ + "getspi", /* K_SADB_GETSPI */ + "update", /* K_SADB_UPDATE */ + "add", /* K_SADB_ADD */ + "delete", /* K_SADB_DELETE */ + "get", /* K_SADB_GET */ + "acquire", /* K_SADB_ACQUIRE */ + "register", /* K_SADB_REGISTER */ + "expire", /* K_SADB_EXPIRE */ + "flush", /* K_SADB_FLUSH */ + "dump", /* K_SADB_DUMP */ + "x-promisc", /* K_SADB_X_PROMISC */ + "x-pchange", /* K_SADB_X_PCHANGE */ + "x-groupsa", /* K_SADB_X_GRPSA */ + "x-addflow(eroute)", /* K_SADB_X_ADDFLOW */ + "x-delflow(eroute)", /* K_SADB_X_DELFLOW */ + "x-debug", /* K_SADB_X_DEBUG */ + }; + + const char * + pfkey_v2_sadb_type_string(int sadb_type) + { + if(sadb_type <= K_SADB_MAX) { + return pfkey_sadb_type_strings[sadb_type]; + } else { + return "unknown-sadb-type"; + } + } + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_ext_bits.c linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_ext_bits.c *** linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_ext_bits.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_ext_bits.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,814 ---- + /* + * 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 . + * + * 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.22 2005/05/11 01:45:31 mcr 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.22 2005/05/11 01:45:31 mcr Exp $"; + + /* + * Some ugly stuff to allow consistent debugging code for use in the + * kernel and in user space + */ + + #if defined(__KERNEL__) && defined(linux) + + # include /* for printk */ + + # include "libreswan/ipsec_kversion.h" /* for malloc switch */ + # ifdef MALLOC_SLAB + # include /* kmalloc() */ + # else /* MALLOC_SLAB */ + # include /* kmalloc() */ + # endif /* MALLOC_SLAB */ + # include /* error codes */ + # include /* size_t */ + # include /* mark_bh */ + + # include /* struct device, and other headers */ + # include /* eth_type_trans */ + # include /* struct iphdr */ + # if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + # include + # endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ + + #else /* __KERNEL__ */ + + # include + # include + # include + #endif + + #include + #include + #include + + #include "libreswan/pfkey_debug.h" + + + pfkey_ext_track extensions_bitmaps[2/*in/out*/][2/*perm/req*/][K_SADB_MAX+1]={ + + /* INBOUND EXTENSIONS */ + { + + /* PERMITTED IN */ + { + /* K_SADB_RESERVED */ + 0 + , + /* SADB_GETSPI */ + 1ULL< + * + * 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 . + * + * 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. + * + */ + + /* + * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. + */ + + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + + #include + + #include + + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *lock* */ + # endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + #ifdef NET_21 + # include + # define ip_chk_addr inet_addr_type + # define IS_MYADDR RTN_LOCAL + #endif + + #include + #ifdef NETLINK_SOCK + # include + #else + # include + #endif + + #include /* get_random_bytes() */ + + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_rcv.h" + #include "libreswan/ipcomp.h" + + #include + #include + + #include "libreswan/ipsec_proto.h" + #include "libreswan/ipsec_alg.h" + + #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) + + /* returns 0 on success */ + int + pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) + { + struct k_sadb_sa *k_pfkey_sa = (struct k_sadb_sa *)pfkey_ext; + 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 K_SADB_EXT_SA: + ipsp = extr->ips; + break; + case K_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; + + if(k_pfkey_sa->sadb_sa_len > sizeof(struct sadb_sa)/IPSEC_PFKEYv2_ALIGN) { + ipsp->ips_ref = k_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 = K_SADB_EALG_NONE; + break; + case IPPROTO_ESP: + ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; + ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; + ipsec_alg_sa_init(ipsp); + break; + case IPPROTO_IPIP: + ipsp->ips_authalg = AH_NONE; + ipsp->ips_encalg = ESP_NONE; + break; + #ifdef CONFIG_KLIPS_IPCOMP + case IPPROTO_COMP: + ipsp->ips_authalg = AH_NONE; + ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; + break; + #endif /* CONFIG_KLIPS_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 K_SADB_EXT_LIFETIME_CURRENT: + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_lifetime_process: " + "lifetime_current not supported yet.\n"); + SENDERR(EINVAL); + break; + case K_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 K_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); + if (debug_pfkey) + 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 K_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 K_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 K_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 K_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 K_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 K_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 K_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 K_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 K_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 K_SADB_EXT_ADDRESS_SRC: + case K_SADB_EXT_ADDRESS_DST: + case K_SADB_EXT_ADDRESS_PROXY: + case K_SADB_X_EXT_ADDRESS_DST2: + #ifdef NAT_TRAVERSAL + case K_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); + } + { + *(struct in_addr *)sap = ((struct sockaddr_in *)s)->sin_addr; + } + + if (portp != 0) + *portp = ((struct sockaddr_in*)s)->sin_port; + #ifdef CONFIG_KLIPS_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_KLIPS_DEBUG */ + } + + ipsp = extr->ips; + switch(pfkey_address->sadb_address_exttype) { + case K_SADB_X_EXT_ADDRESS_DST2: + ipsp = extr->ips2; + case K_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; + if (debug_pfkey) + 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 K_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 K_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 K_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 K_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, + "pfkey_x_satype_process: .\n"); + + if(!extr || !extr->ips) { + KLIPS_PRINT(debug_pfkey, + "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_ERROR(debug_pfkey, + "pfkey_x_satype_process: " + "proto lookup from satype=%d failed.\n", + pfkey_x_satype->sadb_x_satype_satype); + SENDERR(EINVAL); + } + KLIPS_PRINT(debug_pfkey, + "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 K_SADB_X_EXT_NAT_T_SPORT: + extr->ips->ips_natt_sport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; + break; + case K_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_KLIPS_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_KLIPS_IPCOMP + sysctl_ipsec_debug_ipcomp |= pfkey_x_debug->sadb_x_debug_ipcomp; + #endif /* CONFIG_KLIPS_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_KLIPS_IPCOMP + sysctl_ipsec_debug_ipcomp &= pfkey_x_debug->sadb_x_debug_ipcomp; + #endif /* CONFIG_KLIPS_IPCOMP */ + sysctl_ipsec_debug_verbose &= pfkey_x_debug->sadb_x_debug_verbose; + } + #else /* CONFIG_KLIPS_DEBUG */ + printk("klips_debug:pfkey_x_debug_process: " + "debugging not enabled\n"); + SENDERR(EINVAL); + #endif /* CONFIG_KLIPS_DEBUG */ + + errlab: + return error; + } + + /* + * Local variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_parse.c linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_parse.c *** linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_parse.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_parse.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1597 ---- + /* + * 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 . + * + * 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.65 2005/04/06 17:46:05 mcr Exp $ + */ + + /* + * Template from klips/net/ipsec/ipsec/ipsec_parser.c. + */ + + char pfkey_v2_parse_c_version[] = "$Id: pfkey_v2_parse.c,v 1.65 2005/04/06 17:46:05 mcr Exp $"; + + /* + * Some ugly stuff to allow consistent debugging code for use in the + * kernel and in user space + */ + + #ifdef __KERNEL__ + + # include /* for printk */ + + #include "libreswan/ipsec_kversion.h" /* for malloc switch */ + + # ifdef MALLOC_SLAB + # include /* kmalloc() */ + # else /* MALLOC_SLAB */ + # include /* kmalloc() */ + # endif /* MALLOC_SLAB */ + # include /* error codes */ + # include /* size_t */ + # include /* mark_bh */ + + # include /* struct device, and other headers */ + # include /* eth_type_trans */ + # include /* struct iphdr */ + # if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + # include /* struct ipv6hdr */ + # endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ + extern int debug_pfkey; + + # include + + #include "libreswan/ipsec_encap.h" + + #else /* __KERNEL__ */ + + # include + # include + # include + + # include + # include "constants.h" + + #endif /* __KERNEL__ */ + + + #include + #include + + #include "libreswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ + + /* + * how to handle debugging for pfkey. + */ + #include + + unsigned int pfkey_lib_debug = PF_KEY_DEBUG_PARSE_NONE; + int (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); + int (*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, K_SADB_SATYPE_ESP, "ESP" }, + { IPPROTO_AH, K_SADB_SATYPE_AH, "AH" }, + { IPPROTO_IPIP, K_SADB_X_SATYPE_IPIP, "IPIP" }, + #ifdef CONFIG_KLIPS_IPCOMP + { IPPROTO_COMP, K_SADB_X_SATYPE_COMP, "COMP" }, + #endif /* CONFIG_KLIPS_IPCOMP */ + { IPPROTO_INT, K_SADB_X_SATYPE_INT, "INT" }, + #else /* __KERNEL__ */ + { SA_ESP, K_SADB_SATYPE_ESP, "ESP" }, + { SA_AH, K_SADB_SATYPE_AH, "AH" }, + { SA_IPIP, K_SADB_X_SATYPE_IPIP, "IPIP" }, + { SA_COMP, K_SADB_X_SATYPE_COMP, "COMP" }, + { SA_INT, K_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 k_sadb_sa *pfkey_sa = (struct k_sadb_sa *)pfkey_ext; + + /* sanity checks... */ + if(!pfkey_sa) { + ERROR("pfkey_sa_parse: " + "NULL pointer passed in.\n"); + SENDERR(EINVAL); + } + + + + if(pfkey_sa->sadb_sa_len !=sizeof(struct k_sadb_sa)/IPSEC_PFKEYv2_ALIGN + && 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 k_sadb_sa)); + SENDERR(EINVAL); + } + + #if K_SADB_EALG_MAX < 255 + if(pfkey_sa->sadb_sa_encrypt > K_SADB_EALG_MAX) { + ERROR( + "pfkey_sa_parse: " + "pfkey_sa->sadb_sa_encrypt=%d > K_SADB_EALG_MAX=%d.\n", + pfkey_sa->sadb_sa_encrypt, + K_SADB_EALG_MAX); + SENDERR(EINVAL); + } + #endif + + #if K_SADB_AALG_MAX < 255 + if(pfkey_sa->sadb_sa_auth > K_SADB_AALG_MAX) { + ERROR( + "pfkey_sa_parse: " + "pfkey_sa->sadb_sa_auth=%d > K_SADB_AALG_MAX=%d.\n", + pfkey_sa->sadb_sa_auth, + K_SADB_AALG_MAX); + SENDERR(EINVAL); + } + #endif + + #if K_SADB_SASTATE_MAX < 255 + if(pfkey_sa->sadb_sa_state > K_SADB_SASTATE_MAX) { + ERROR( + "pfkey_sa_parse: " + "state=%d exceeds MAX=%d.\n", + pfkey_sa->sadb_sa_state, + K_SADB_SASTATE_MAX); + SENDERR(EINVAL); + } + #endif + + if(pfkey_sa->sadb_sa_state == K_SADB_SASTATE_DEAD) { + ERROR( + "pfkey_sa_parse: " + "state=%d is DEAD=%d.\n", + pfkey_sa->sadb_sa_state, + K_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 == K_SADB_EXT_SA) || + (pfkey_sa->sadb_sa_exttype == K_SADB_X_EXT_SA2))) + { + ERROR( + "pfkey_sa_parse: " + "unknown exttype=%d, expecting K_SADB_EXT_SA=%d or K_SADB_X_EXT_SA2=%d.\n", + pfkey_sa->sadb_sa_exttype, + K_SADB_EXT_SA, + K_SADB_X_EXT_SA2); + SENDERR(EINVAL); + } + + if(pfkey_sa->sadb_sa_len > sizeof(struct sadb_sa)/IPSEC_PFKEYv2_ALIGN) { + if(pfkey_sa->sadb_x_sa_ref == IPSEC_SAREF_NULL || + pfkey_sa->sadb_x_sa_ref == ~(IPSEC_SAREF_NULL)) + { + pfkey_sa->sadb_x_sa_ref = IPSEC_SAREF_NULL; + } + } + + 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 != K_SADB_EXT_LIFETIME_HARD) && + (pfkey_lifetime->sadb_lifetime_exttype != K_SADB_EXT_LIFETIME_SOFT) && + (pfkey_lifetime->sadb_lifetime_exttype != K_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.\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); + 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 K_SADB_EXT_ADDRESS_SRC: + case K_SADB_EXT_ADDRESS_DST: + case K_SADB_EXT_ADDRESS_PROXY: + case K_SADB_X_EXT_ADDRESS_DST2: + case K_SADB_X_EXT_ADDRESS_SRC_FLOW: + case K_SADB_X_EXT_ADDRESS_DST_FLOW: + case K_SADB_X_EXT_ADDRESS_SRC_MASK: + case K_SADB_X_EXT_ADDRESS_DST_MASK: + #ifdef NAT_TRAVERSAL + case K_SADB_X_EXT_NAT_T_OA: + #endif + break; + default: + ERROR( + "pfkey_address_parse: " + "unexpected ext_type=%d.\n", + pfkey_address->sadb_address_exttype); + SENDERR(ENODEV); + } + + 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 == K_SADB_EXT_KEY_AUTH) || + (pfkey_key->sadb_key_exttype == K_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 > K_SADB_IDENTTYPE_MAX) { + ERROR( + "pfkey_ident_parse: " + "ident_type=%d out of range, must be less than %d.\n", + pfkey_ident->sadb_ident_type, + K_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 == K_SADB_EXT_IDENTITY_SRC) || + (pfkey_ident->sadb_ident_exttype == K_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 k_sadb_comb *k_pfkey_comb = (struct k_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++) { + struct sadb_comb *pfkey_comb = (struct sadb_comb *)k_pfkey_comb; + if(pfkey_comb->sadb_comb_auth > K_SADB_AALG_MAX) { + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + "pfkey_prop_parse: " + "pfkey_comb[%d]->sadb_comb_auth=%d > K_SADB_AALG_MAX=%d.\n", + i, + pfkey_comb->sadb_comb_auth, + K_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 K_SADB_EALG_MAX < 255 + if(pfkey_comb->sadb_comb_encrypt > K_SADB_EALG_MAX) { + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + "pfkey_comb_parse: " + "pfkey_comb[%d]->sadb_comb_encrypt=%d > K_SADB_EALG_MAX=%d.\n", + i, + pfkey_comb->sadb_comb_encrypt, + K_SADB_EALG_MAX); + SENDERR(EINVAL); + } + #endif + + 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); + } + + #ifdef COMB_PACKETS + 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, + k_pfkey_comb->sadb_x_comb_soft_packets, + k_pfkey_comb->sadb_x_comb_hard_packets); + SENDERR(EINVAL); + } + #endif + + 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 K_SADB_EXT_SUPPORTED_AUTH: + if(pfkey_alg->sadb_alg_id > K_SADB_AALG_MAX) { + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + "pfkey_supported_parse: " + "alg[%d], alg_id=%d > K_SADB_AALG_MAX=%d, fatal.\n", + i, + pfkey_alg->sadb_alg_id, + K_SADB_AALG_MAX); + SENDERR(EINVAL); + } + break; + case SADB_EXT_SUPPORTED_ENCRYPT: + #if K_SADB_EALG_MAX < 255 + if(pfkey_alg->sadb_alg_id > K_SADB_EALG_MAX) { + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + "pfkey_supported_parse: " + "alg[%d], alg_id=%d > K_SADB_EALG_MAX=%d, fatal.\n", + i, + pfkey_alg->sadb_alg_id, + K_SADB_EALG_MAX); + SENDERR(EINVAL); + } + #endif + break; + default: + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + "pfkey_supported_parse: " + "alg[%d], alg_id=%d > K_SADB_EALG_MAX=%d, fatal.\n", + i, + pfkey_alg->sadb_alg_id, + K_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 > K_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, K_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 + + DEBUG_NO_STATIC int + pfkey_x_ext_outif_parse(struct sadb_ext *pfkey_ext) + { + int error = 0; + struct sadb_x_plumbif *p = (struct sadb_x_plumbif *)pfkey_ext; + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_outif_parse:\n"); + /* sanity checks... */ + + if (p->sadb_x_outif_len != IPSEC_PFKEYv2_WORDS(sizeof(*p))) { + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + "pfkey_x_outif_parse: size wrong ext_len=%d, key_ext_len=%d.\n", + p->sadb_x_outif_len, (int)sizeof(*p)); + SENDERR(EINVAL); + } + + errlab: + return error; + } + + DEBUG_NO_STATIC int + pfkey_x_ext_saref_parse(struct sadb_ext *pfkey_ext) + { + int error = 0; + struct sadb_x_saref *p = (struct sadb_x_saref *)pfkey_ext; + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_saref_parse:\n"); + /* sanity checks... */ + + if (p->sadb_x_saref_len != IPSEC_PFKEYv2_WORDS(sizeof(*p))) { + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + "pfkey_x_saref_parse: size wrong ext_len=%d, key_ext_len=%d.\n", + p->sadb_x_saref_len, (int)sizeof(*p)); + SENDERR(EINVAL); + } + + errlab: + return error; + } + + + #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 + DEFINEPARSER(pfkey_x_ext_outif_parse); + DEFINEPARSER(pfkey_x_ext_saref_parse); + + 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, + #else + NULL,NULL,NULL,NULL, + #endif + &pfkey_x_ext_outif_parse_def, + &pfkey_x_ext_saref_parse_def, + }; + + 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; + pfkey_ext_track 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 -= IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg)); + + 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 > K_SADB_MAX) { + ERROR("pfkey_msg_parse: " + "msg type=%d > max=%d.\n", + pfkey_msg->sadb_msg_type, + K_SADB_MAX); + SENDERR(EINVAL); + } + + switch(pfkey_msg->sadb_msg_type) { + case K_SADB_GETSPI: + case K_SADB_UPDATE: + case K_SADB_ADD: + case K_SADB_DELETE: + case K_SADB_GET: + case K_SADB_X_GRPSA: + case K_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 K_SADB_ACQUIRE: + case K_SADB_REGISTER: + case K_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 != K_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\n", + remain + ); + + 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) { + ERROR("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 > K_SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) { + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + "pfkey_msg_parse: " + "ext type %d(%s) invalid, K_SADB_EXT_MAX=%d.\n", + pfkey_ext->sadb_ext_type, + pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), + K_SADB_EXT_MAX); + SENDERR(EINVAL); + } + + /* Have we already seen this type of extension? */ + if(extensions[pfkey_ext->sadb_ext_type] != NULL) + { + ERROR("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) { + ERROR("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(!pfkey_permitted_extension(dir,pfkey_msg->sadb_msg_type,pfkey_ext->sadb_ext_type)) { + ERROR("ext type %d(%s) not permitted (parse)\n", + pfkey_ext->sadb_ext_type, + pfkey_v2_sadb_ext_string(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))) { + ERROR("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[pfkey_ext->sadb_ext_type] = pfkey_ext; + pfkey_mark_extension(pfkey_ext->sadb_ext_type,&extensions_seen); + + 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); + } + + /* 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(pfkey_extensions_missing(dir,pfkey_msg->sadb_msg_type,extensions_seen)) { + ERROR("required extensions missing.seen=%08llx.\n",(unsigned long long)extensions_seen); + SENDERR(EINVAL); + } + + if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type == K_SADB_X_DELFLOW) + && ((extensions_seen & K_SADB_X_EXT_ADDRESS_DELFLOW) + != K_SADB_X_EXT_ADDRESS_DELFLOW) + && (((extensions_seen & (1<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 %16llx must be present or %16llx must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n", + (unsigned long long)K_SADB_X_EXT_ADDRESS_DELFLOW + - (extensions_seen & K_SADB_X_EXT_ADDRESS_DELFLOW), + (unsigned long long)(1<sadb_msg_type) { + case K_SADB_ADD: + case K_SADB_UPDATE: + /* check maturity */ + if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != + K_SADB_SASTATE_MATURE) { + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + "pfkey_msg_parse: " + "state=%d for add or update should be MATURE=%d.\n", + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, + K_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 k_sadb_sa*)extensions[SADB_EXT_SA]) && + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_auth != + SADB_AALG_NONE)) { + ERROR("pfkey_msg_parse: " + "auth alg is zero, must be non-zero for AH SAs.\n"); + SENDERR(EINVAL); + } + if(((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt != + SADB_EALG_NONE) { + ERROR("pfkey_msg_parse: " + "AH handed encalg=%d, must be zero.\n", + ((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt); + SENDERR(EINVAL); + } + break; + case SADB_SATYPE_ESP: + if(!(((struct k_sadb_sa*)extensions[SADB_EXT_SA]) && + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != + SADB_EALG_NONE)) { + ERROR("pfkey_msg_parse: " + "encrypt alg=%d is zero, must be non-zero for ESP=%d SAs.\n", + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, + ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); + SENDERR(EINVAL); + } + if((((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt == + SADB_EALG_NULL) && + (((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth == + SADB_AALG_NONE) ) { + ERROR("pfkey_msg_parse: " + "ESP handed encNULL+authNONE, illegal combination.\n"); + SENDERR(EINVAL); + } + break; + case K_SADB_X_SATYPE_COMP: + if(!(((struct k_sadb_sa*)extensions[SADB_EXT_SA]) && + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != + SADB_EALG_NONE)) { + ERROR("pfkey_msg_parse: " + "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n", + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, + ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); + SENDERR(EINVAL); + } + if(((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth != + SADB_AALG_NONE) { + ERROR("pfkey_msg_parse: " + "COMP handed auth=%d, must be zero.\n", + ((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth); + SENDERR(EINVAL); + } + break; + default: + break; + } + if(ntohl(((struct k_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 k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi)); + SENDERR(EINVAL); + } + default: + break; + } + + errlab: + return error; + } + + /* + * Local variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_parser.c linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_parser.c *** linux-2.6.16-ng-natt/net/ipsec/pfkey_v2_parser.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/pfkey_v2_parser.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,3015 ---- + /* + * @(#) 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 . + * + * 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. + * + */ + + /* + * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. + */ + + + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + + #include + + #include + + #ifdef SPINLOCK + # ifdef SPINLOCK_23 + # include /* *lock* */ + # else /* SPINLOCK_23 */ + # include /* *lock* */ + # endif /* SPINLOCK_23 */ + #endif /* SPINLOCK */ + #ifdef NET_21 + # include /* inet_addr_type */ + # include + # define ip_chk_addr inet_addr_type + # define IS_MYADDR RTN_LOCAL + #endif + + #include + #ifdef NETLINK_SOCK + # include + #else + # include + #endif + + #include /* get_random_bytes() */ + + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/ipsec_sa.h" + + #include "libreswan/ipsec_radij.h" + #include "libreswan/ipsec_xform.h" + #include "libreswan/ipsec_ah.h" + #include "libreswan/ipsec_esp.h" + #include "libreswan/ipsec_tunnel.h" + #include "libreswan/ipsec_mast.h" + #include "libreswan/ipsec_rcv.h" + #include "libreswan/ipcomp.h" + + #include + #include + + #include "libreswan/ipsec_proto.h" + #include "libreswan/ipsec_alg.h" + + #include "libreswan/ipsec_kern24.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) + { + int rc; + KLIPS_PRINT(debug_pfkey, "Calling SA_INIT\n"); + rc = ipsec_sa_init(ipsp); + return rc; + } + + int + pfkey_safe_build(int error, struct sadb_ext *extensions[K_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[K_SADB_EXT_MAX+1]; + struct sadb_msg *pfkey_reply = NULL; + struct socket_list *pfkey_socketsp; + uint8_t satype = ((struct sadb_msg*)extensions[K_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[K_SADB_EXT_SPIRANGE]) { + minspi = ((struct sadb_spirange *)extensions[K_SADB_EXT_SPIRANGE])->sadb_spirange_min; + maxspi = ((struct sadb_spirange *)extensions[K_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 = KLIPS_SATOT(debug_pfkey, &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 = KLIPS_SATOT(debug_pfkey, &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 = K_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], + K_SADB_GETSPI, + satype, + 0, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + extensions_reply) + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + K_SADB_EXT_SA, + extr->ips->ips_said.spi, + 0, + K_SADB_SASTATE_LARVAL, + 0, + 0, + 0), + extensions_reply) + + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], + K_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[K_SADB_EXT_ADDRESS_DST], + K_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[K_SADB_EXT_MAX+1]; + struct sadb_msg *pfkey_reply = NULL; + struct socket_list *pfkey_socketsp; + uint8_t satype = ((struct sadb_msg*)extensions[K_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[K_SADB_EXT_SA])->sadb_sa_state != K_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[K_SADB_EXT_SA])->sadb_sa_state, + K_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 = KLIPS_SATOT(debug_pfkey, &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 K_SADB_GETSPI first or call K_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))) { + 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; + + /* this will call delchain-equivalent if refcount=>0 */ + ipsec_sa_put(ipsq); + } + + spin_unlock_bh(&tdb_lock); + + if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], + K_SADB_UPDATE, + satype, + 0, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + extensions_reply) + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + K_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), + extensions_reply) + /* The 3 lifetime extentions should only be sent if non-zero. */ + && (extensions[K_SADB_EXT_LIFETIME_HARD] + ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_HARD], + K_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[K_SADB_EXT_LIFETIME_SOFT] + ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_SOFT], + K_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[K_SADB_EXT_LIFETIME_CURRENT], + K_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[K_SADB_EXT_ADDRESS_SRC], + K_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[K_SADB_EXT_ADDRESS_DST], + K_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[K_SADB_EXT_IDENTITY_SRC], + K_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[K_SADB_EXT_IDENTITY_DST], + K_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[K_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[K_SADB_EXT_MAX+1]; + struct sadb_msg *pfkey_reply = NULL; + struct socket_list *pfkey_socketsp; + uint8_t satype = ((struct sadb_msg*)extensions[K_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[K_SADB_EXT_SA])->sadb_sa_state != K_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[K_SADB_EXT_SA])->sadb_sa_state, + K_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 = KLIPS_SATOT(debug_pfkey, &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 = ipsec_sa_init(extr->ips))) { + KLIPS_ERROR(debug_pfkey, + "pfkey_add_parse: " + "not successful for SA: %s, deleting.\n", + sa_len ? sa : " (error)"); + SENDERR(-error); + } + + if(extr->sarefme!=IPSEC_SAREF_NULL + && extr->ips->ips_ref==IPSEC_SAREF_NULL) { + extr->ips->ips_ref=extr->sarefme; + } + + if(extr->sarefhim!=IPSEC_SAREF_NULL + && extr->ips->ips_refhim==IPSEC_SAREF_NULL) { + extr->ips->ips_refhim=extr->sarefhim; + } + + /* attach it to the SAref table */ + if((error = ipsec_sa_intern(extr->ips)) != 0) { + KLIPS_ERROR(debug_pfkey, + "pfkey_add_parse: " + "failed to intern SA as SAref#%lu\n" + , (unsigned long)extr->ips->ips_ref); + 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], + K_SADB_ADD, + satype, + 0, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + extensions_reply) + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + K_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), + extensions_reply) + && pfkey_safe_build(error = pfkey_saref_build(&extensions_reply[K_SADB_X_EXT_SAREF], + extr->ips->ips_ref, + extr->ips->ips_refhim), + extensions_reply) + /* The 3 lifetime extentions should only be sent if non-zero. */ + && (extensions[K_SADB_EXT_LIFETIME_HARD] + ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_HARD], + K_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[K_SADB_EXT_LIFETIME_SOFT] + ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_SOFT], + K_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[K_SADB_EXT_ADDRESS_SRC], + K_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[K_SADB_EXT_ADDRESS_DST], + K_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[K_SADB_EXT_IDENTITY_SRC], + K_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[K_SADB_EXT_IDENTITY_DST], + K_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[K_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(extr->outif != 0 && extr->outif != -1) { + extr->ips->ips_out = ipsec_mast_get_device(extr->outif); + extr->ips->ips_transport_direct = ipsec_mast_is_transport(extr->outif); + } + + 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); + } + ipsec_sa_put(extr->ips); + 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[K_SADB_EXT_MAX+1]; + struct sadb_msg *pfkey_reply = NULL; + struct socket_list *pfkey_socketsp; + uint8_t satype = ((struct sadb_msg*)extensions[K_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 = KLIPS_SATOT(debug_pfkey, &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); + spin_unlock_bh(&tdb_lock); + + if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], + K_SADB_DELETE, + satype, + 0, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + extensions_reply) + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + K_SADB_EXT_SA, + extr->ips->ips_said.spi, + 0, + 0, + 0, + 0, + 0), + extensions_reply) + + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], + K_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[K_SADB_EXT_ADDRESS_DST], + K_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[K_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 = KLIPS_SATOT(debug_pfkey, &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], + K_SADB_GET, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype, + 0, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + extensions_reply) + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + K_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), + 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[K_SADB_EXT_LIFETIME_CURRENT], + K_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[K_SADB_EXT_LIFETIME_HARD], + K_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[K_SADB_EXT_LIFETIME_SOFT], + K_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[K_SADB_EXT_ADDRESS_SRC], + K_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[K_SADB_EXT_ADDRESS_DST], + K_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[K_SADB_EXT_ADDRESS_PROXY], + K_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[K_SADB_EXT_KEY_AUTH], + K_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[K_SADB_EXT_KEY_ENCRYPT], + K_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[K_SADB_EXT_IDENTITY_SRC], + K_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[K_SADB_EXT_IDENTITY_DST], + K_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[K_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->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[K_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 > K_SADB_SATYPE_MAX. */ + if((satype == 0) || (satype > K_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[K_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[K_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 > K_SADB_SATYPE_MAX. */ + if((satype == 0) || (satype > K_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->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[K_SADB_EXT_RESERVED]); + errlab: + return error; + } + + int + pfkey_register_reply(int satype, struct sadb_msg *sadb_msg) + { + struct sadb_ext *extensions_reply[K_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 > K_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->ias_exttype == K_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->ias_exttype == K_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->ias_exttype == K_SADB_EXT_SUPPORTED_AUTH) { + alg_ap->sadb_alg_id = pfkey_supported_listp->supportedp->ias_id; + alg_ap->sadb_alg_ivlen = pfkey_supported_listp->supportedp->ias_ivlen; + alg_ap->sadb_alg_minbits = pfkey_supported_listp->supportedp->ias_keyminbits; + alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->ias_keymaxbits; + 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->ias_exttype == K_SADB_EXT_SUPPORTED_ENCRYPT) { + alg_ep->sadb_alg_id = pfkey_supported_listp->supportedp->ias_id; + alg_ep->sadb_alg_ivlen = pfkey_supported_listp->supportedp->ias_ivlen; + alg_ep->sadb_alg_minbits = pfkey_supported_listp->supportedp->ias_keyminbits; + alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->ias_keymaxbits; + 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->ias_exttype, + pfkey_supported_listp->supportedp->ias_id, + pfkey_supported_listp->supportedp->ias_ivlen, + pfkey_supported_listp->supportedp->ias_keyminbits, + pfkey_supported_listp->supportedp->ias_keymaxbits); + pfkey_supported_listp = pfkey_supported_listp->next; + } + + if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], + K_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[K_SADB_EXT_SUPPORTED_AUTH], + K_SADB_EXT_SUPPORTED_AUTH, + alg_num_a, + alg_a), + extensions_reply) : 1) && + (alg_num_e ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[K_SADB_EXT_SUPPORTED_ENCRYPT], + K_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_KLIPS_DEBUG + uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; + #endif /* CONFIG_KLIPS_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[K_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; + } + + + /* + * + * flush all SAs from the table + */ + 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[K_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[K_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[K_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[K_SADB_EXT_MAX+1]; + struct sadb_msg *pfkey_reply = NULL; + struct socket_list *pfkey_socketsp; + uint8_t satype = ((struct sadb_msg*)extensions[K_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 = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa1, sizeof(sa1)); + if(extr->ips2 != NULL) { + sa_len2 = KLIPS_SATOT(debug_pfkey, &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_ERROR(debug_pfkey, + "klips_debug:pfkey_x_grpsa_parse: " + "reserved ipsec_sa for SA1: %s not found. Call K_SADB_ADD/UPDATE first.\n", + sa_len1 ? sa1 : " (error)"); + SENDERR(ENOENT); + } + + if(extr->ips2) { /* GRPSA */ + + /* group ips2p to be after ips1p */ + + 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 K_SADB_ADD/UPDATE first.\n", + sa_len2 ? sa2 : " (error)"); + SENDERR(ENOENT); + } + + /* userspace puts things in inner to outer order */ + if(ips2p->ips_flags & EMT_INBOUND) { + struct ipsec_sa *t; + + /* exchange ips and ips2 */ + t = ips1p; + ips1p = ips2p; + ips2p = t; + } + + /* Is ips1p already linked? */ + if(ips1p->ips_next) { + ipsec_sa_put(ips1p); + ipsec_sa_put(ips2p); + spin_unlock_bh(&tdb_lock); + KLIPS_ERROR(debug_pfkey, + "klips_debug:pfkey_x_grpsa_parse: " + "ipsec_sa for SA: %s is already linked.\n", + sa_len1 ? sa1 : " (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_ERROR(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_next; + } + + /* 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_next = ips2p; + } else { /* UNGRPSA */ + while(ips1p) { + struct ipsec_sa *ipsn; + + /* take the reference to next */ + ipsn = ips1p->ips_next; + ips1p->ips_next = NULL; + + /* drop reference to current */ + ipsec_sa_put(ips1p); + + ips1p = ipsn; + } + + /* note: we have dropped reference to ips1p, and + * it is now NULL + */ + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_x_grpsa_parse: " + "unlinking ipsec_sa SA: %s.\n", + sa_len1 ? sa1 : " (error)"); + } + + spin_unlock_bh(&tdb_lock); + + /* MCR: not only is this ugly to read, and impossible + * to debug through, but it's also really inefficient. + * XXX simplify me. + */ + if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], + K_SADB_X_GRPSA, + satype, + 0, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + extensions_reply) + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + K_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), + extensions_reply) + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], + K_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[K_SADB_X_EXT_SATYPE2], + ((struct sadb_x_satype*)extensions[K_SADB_X_EXT_SATYPE2])->sadb_x_satype_satype + /* proto2satype(extr->ips2->ips_said.proto) */), + extensions_reply) + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_X_EXT_SA2], + K_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), + extensions_reply) + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_X_EXT_ADDRESS_DST2], + K_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_KLIPS_DEBUG + char buf1[64], buf2[64]; + #endif /* CONFIG_KLIPS_DEBUG */ + struct sadb_ext *extensions_reply[K_SADB_EXT_MAX+1]; + struct sadb_msg *pfkey_reply = NULL; + struct socket_list *pfkey_socketsp; + uint8_t satype = ((struct sadb_msg*)extensions[K_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_KLIPS_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_KLIPS_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_next; + } + + 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 = KLIPS_SATOT(debug_pfkey, &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[K_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); + dst_output(first); + } + if(last != NULL) { + KLIPS_PRINT(debug_eroute, + "klips_debug:pfkey_x_addflow_parse: " + "last=0p%p HOLD packet re-injected.\n", + last); + dst_output(last); + } + } + + 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], + K_SADB_X_ADDFLOW, + satype, + 0, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + extensions_reply) + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + K_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), + extensions_reply) + && (extensions[K_SADB_EXT_ADDRESS_SRC] + ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], + K_SADB_EXT_ADDRESS_SRC, + 0, /*extr->ips->ips_said.proto,*/ + 0, + extr->ips->ips_addr_s), + extensions_reply) : 1) + && (extensions[K_SADB_EXT_ADDRESS_DST] + ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], + K_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[K_SADB_X_EXT_ADDRESS_SRC_FLOW], + K_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[K_SADB_X_EXT_ADDRESS_DST_FLOW], + K_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[K_SADB_X_EXT_ADDRESS_SRC_MASK], + K_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[K_SADB_X_EXT_ADDRESS_DST_MASK], + K_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_KLIPS_DEBUG + char buf1[64], buf2[64]; + #endif /* CONFIG_KLIPS_DEBUG */ + struct sadb_ext *extensions_reply[K_SADB_EXT_MAX+1]; + struct sadb_msg *pfkey_reply = NULL; + struct socket_list *pfkey_socketsp; + uint8_t satype = ((struct sadb_msg*)extensions[K_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_KLIPS_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_KLIPS_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], + K_SADB_X_DELFLOW, + satype, + 0, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + extensions_reply) + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + K_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), + extensions_reply) + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_X_EXT_ADDRESS_SRC_FLOW], + K_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[K_SADB_X_EXT_ADDRESS_DST_FLOW], + K_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[K_SADB_X_EXT_ADDRESS_SRC_MASK], + K_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[K_SADB_X_EXT_ADDRESS_DST_MASK], + K_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[K_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], + K_SADB_EXPIRE, + satype, + 0, + ++pfkey_msg_seq, + 0), + extensions) + && pfkey_safe_build(error = pfkey_sa_build(&extensions[K_SADB_EXT_SA], + K_SADB_EXT_SA, + ipsp->ips_said.spi, + ipsp->ips_replaywin, + ipsp->ips_state, + ipsp->ips_authalg, + ipsp->ips_encalg, + ipsp->ips_flags), + extensions) + && pfkey_safe_build(error = pfkey_lifetime_build(&extensions[K_SADB_EXT_LIFETIME_CURRENT], + K_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[K_SADB_EXT_LIFETIME_HARD], + K_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[K_SADB_EXT_LIFETIME_SOFT], + K_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[K_SADB_EXT_ADDRESS_SRC], + K_SADB_EXT_ADDRESS_SRC, + 0, /* ipsp->ips_said.proto, */ + 0, + ipsp->ips_addr_s), + extensions) + && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], + K_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[K_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; */ + { K_SADB_AALG_MD5HMAC, K_SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, + 128, 128, 168, 168, + 0, 0, 0, 0, 0, + 57600, 86400, 57600, 86400}, + { K_SADB_AALG_SHA1HMAC, K_SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, + 160, 160, 168, 168, + 0, 0, 0, 0, 0, + 57600, 86400, 57600, 86400}, + }; + + /* XXX This should not be hard-coded. It should be taken from the spdb */ + uint8_t satype = K_SADB_SATYPE_ESP; + + pfkey_extensions_init(extensions); + + if((satype == 0) || (satype > K_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], + K_SADB_ACQUIRE, + satype, + 0, + ++pfkey_msg_seq, + 0), + extensions) + && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_SRC], + K_SADB_EXT_ADDRESS_SRC, + ipsp->ips_transport_protocol, + 0, + ipsp->ips_addr_s), + extensions) + && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], + K_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[K_SADB_EXT_ADDRESS_PROXY], + K_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], + K_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[K_SADB_EXT_IDENTITY_DST], + K_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[K_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[K_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); + } + + #ifdef KLIPS_PFKEY_ACQUIRE_LOSSAGE + # if KLIPS_PFKEY_ACQUIRE_LOSSAGE > 0 + if(sysctl_ipsec_regress_pfkey_lossage) { + return(0); + } + # endif + #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[K_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) ? K_SADB_SATYPE_ESP : 0; + + /* Construct K_SADB_X_NAT_T_NEW_MAPPING message */ + + pfkey_extensions_init(extensions); + + if((satype == 0) || (satype > K_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], K_SADB_X_NAT_T_NEW_MAPPING, + satype, 0, ++pfkey_msg_seq, 0), extensions) + /* SA */ + && pfkey_safe_build + (error = pfkey_sa_build(&extensions[K_SADB_EXT_SA], + K_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[K_SADB_EXT_ADDRESS_SRC], + K_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[K_SADB_X_EXT_NAT_T_SPORT], + K_SADB_X_EXT_NAT_T_SPORT, ipsp->ips_natt_sport), extensions) + /* ADDRESS_DST = new addr */ + && pfkey_safe_build + (error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], + K_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[K_SADB_X_EXT_NAT_T_DPORT], + K_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) + { + /* K_SADB_X_NAT_T_NEW_MAPPING not used in kernel */ + return -EINVAL; + } + #endif + + /******************************* + * EXTENSION PARSERS FOR KLIPS + ********************************/ + + DEBUG_NO_STATIC int + pfkey_x_outif_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) + { + struct sadb_x_plumbif *oif; + + oif = (struct sadb_x_plumbif *)pfkey_ext; + + extr->outif = oif->sadb_x_outif_ifnum; + + return 0; + } + + DEBUG_NO_STATIC int + pfkey_x_saref_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) + { + struct sadb_x_saref *saf; + + saf = (struct sadb_x_saref *)pfkey_ext; + + extr->sarefme = saf->sadb_x_saref_me; + extr->sarefhim = saf->sadb_x_saref_him; + + return 0; + } + + DEBUG_NO_STATIC int (*ext_processors[K_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, + #else + NULL, NULL, NULL, NULL, + #endif + pfkey_x_outif_process, + pfkey_x_saref_process, + }; + + + /******************************* + * MESSAGE PARSERS FOR KLIPS + ********************************/ + + /* + * this is a request to create a new device. Figure out which kind, and call appropriate + * routine in mast or tunnel code. + */ + DEBUG_NO_STATIC int + pfkey_x_plumb_parse(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr) + { + unsigned int vifnum; + + vifnum = extr->outif; + if(vifnum > IPSECDEV_OFFSET) { + return ipsec_tunnel_createnum(vifnum-IPSECDEV_OFFSET); + } else { + return ipsec_mast_createnum(vifnum); + } + } + + /* + * this is a request to create a new device. Figure out which kind, and call appropriate + * routine in mast or tunnel code. + * */ + DEBUG_NO_STATIC int + pfkey_x_unplumb_parse(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr) + { + unsigned int vifnum; + + vifnum = extr->outif; + if(vifnum > IPSECDEV_OFFSET) { + return ipsec_tunnel_deletenum(vifnum-IPSECDEV_OFFSET); + } else { + return ipsec_mast_deletenum(vifnum); + } + } + + + DEBUG_NO_STATIC int (*msg_parsers[K_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, + #else + NULL, + #endif + pfkey_x_plumb_parse, + pfkey_x_unplumb_parse, + }; + + int + pfkey_build_reply(struct sadb_msg *pfkey_msg, + struct pfkey_extracted_data *extr, + struct sadb_msg **pfkey_reply) + { + struct sadb_ext *extensions[K_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; // TODO: should this not be negative? + } + 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); + + if(!error + && pfkey_required_extension(EXT_BITS_OUT, msg_type, K_SADB_EXT_SA)) { + + error = pfkey_sa_build(&extensions[K_SADB_EXT_SA], + K_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); + pfkey_safe_build(error, extensions); + } + + if(!error + && pfkey_required_extension(EXT_BITS_OUT, msg_type, K_SADB_X_EXT_SAREF)) { + error = pfkey_saref_build(&extensions[K_SADB_X_EXT_SAREF], + extr->ips->ips_ref, + extr->ips->ips_refhim); + pfkey_safe_build(error, extensions); + } + + if(!error + && pfkey_required_extension(EXT_BITS_OUT,msg_type,K_SADB_EXT_LIFETIME_CURRENT)) { + error = pfkey_lifetime_build(&extensions + [K_SADB_EXT_LIFETIME_CURRENT], + K_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); + pfkey_safe_build(error, extensions); + } + + if(!error + && pfkey_required_extension(EXT_BITS_OUT,msg_type,K_SADB_EXT_ADDRESS_SRC)) { + error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_SRC], + K_SADB_EXT_ADDRESS_SRC, + extr->ips->ips_said.proto, + 0, + extr->ips->ips_addr_s); + pfkey_safe_build(error, extensions); + } + + if(!error + && pfkey_required_extension(EXT_BITS_OUT,msg_type,K_SADB_EXT_ADDRESS_DST)) { + error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], + K_SADB_EXT_ADDRESS_DST, + extr->ips->ips_said.proto, + 0, + extr->ips->ips_addr_d); + pfkey_safe_build(error, 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; + } + + /* + * interpret a pfkey message for klips usage. + * it used to be that we provided a reply in a seperate buffer, + * but now we overwrite the request buffer and return it. + */ + int + pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg) + { + int error = 0; + int i; + struct sadb_ext *extensions[K_SADB_EXT_MAX+1]; /* should be kalloc */ + struct pfkey_extracted_data extr; + + memset(&extr, 0, sizeof(extr)); + + 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 > K_SADB_SATYPE_MAX) { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_msg_interp: " + "satype %d > max %d\n", + pfkey_msg->sadb_msg_satype, + K_SADB_SATYPE_MAX); + SENDERR(EINVAL); + } + + switch(pfkey_msg->sadb_msg_type) { + case K_SADB_GETSPI: + case K_SADB_UPDATE: + case K_SADB_ADD: + case K_SADB_DELETE: + case K_SADB_X_GRPSA: + case K_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 <= K_SADB_EXT_MAX;i++) { + if(extensions[i] != NULL && ext_processors[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); + } + + errlab: + if(extr.ips != NULL) { + ipsec_sa_put(extr.ips); + } + if(extr.ips2 != NULL) { + ipsec_sa_put(extr.ips2); + } + if (extr.eroute != NULL) { + kfree(extr.eroute); + } + return(error); + } + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/prng.c linux-2.6.16-ng-natt-klips/net/ipsec/prng.c *** linux-2.6.16-ng-natt/net/ipsec/prng.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/prng.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,202 ---- + /* + * 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 . + * + * 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.8 2005/08/25 01:20:21 paul Exp $ + */ + #include "libreswan.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 MAXCOUNT 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 < MAXCOUNT - dstlen) + prng->count += dstlen; + else + prng->count = MAXCOUNT; + } + + /* + - 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 + #include + + 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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/radij.c linux-2.6.16-ng-natt-klips/net/ipsec/radij.c *** linux-2.6.16-ng-natt/net/ipsec/radij.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/radij.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,1013 ---- + char radij_c_version[] = "RCSID $Id: radij.c,v 1.48 2005/04/29 05:10:22 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. + */ + + #ifndef AUTOCONF_INCLUDED + #include + #endif + #include + #include /* printk() */ + + #include "libreswan/ipsec_param.h" + + #ifdef MALLOC_SLAB + # include /* kmalloc() */ + #else /* MALLOC_SLAB */ + # include /* kmalloc() */ + #endif /* MALLOC_SLAB */ + #include /* error codes */ + #include /* size_t */ + #include /* mark_bh */ + + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include /* struct iphdr */ + #include + #ifdef NET_21 + # include + #endif /* NET_21 */ + + #include + + #include + + #include "libreswan/radij.h" + #include "libreswan/ipsec_encap.h" + #include "libreswan/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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_DEBUG */ + /* Process leaves */ + while ((rn = base)) { + base = rn->rj_dupedkey; + #ifdef CONFIG_KLIPS_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_KLIPS_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; irj_off); + } else { + printk("klips_debug:"); + for (i=0; irj_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; + } + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/rangetoa.c linux-2.6.16-ng-natt-klips/net/ipsec/rangetoa.c *** linux-2.6.16-ng-natt/net/ipsec/rangetoa.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/rangetoa.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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.9 2004/07/10 07:48:37 mcr Exp $ + */ + #include "libreswan.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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/README-zlib linux-2.6.16-ng-natt-klips/net/ipsec/README-zlib *** linux-2.6.16-ng-natt/net/ipsec/README-zlib 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/README-zlib 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 , or to + Gilles Vollant 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 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 + 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 + 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 + 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 , 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 . 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 + + + 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. diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/README-zlib.freeswan linux-2.6.16-ng-natt-klips/net/ipsec/README-zlib.freeswan *** linux-2.6.16-ng-natt/net/ipsec/README-zlib.freeswan 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/README-zlib.freeswan 2008-06-01 17:37:11.000000000 -0400 *************** *** 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. diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/satot.c linux-2.6.16-ng-natt-klips/net/ipsec/satot.c *** linux-2.6.16-ng-natt/net/ipsec/satot.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/satot.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,134 ---- + /* + * 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 . + * + * 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.13 2004/07/10 07:48:37 mcr Exp $ + */ + #include "libreswan.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) { + char intunk[10]; + 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: snprintf(intunk, 10, "%%unk-%d", ntohl(sa->spi)); p = intunk; 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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/subnetof.c linux-2.6.16-ng-natt-klips/net/ipsec/subnetof.c *** linux-2.6.16-ng-natt/net/ipsec/subnetof.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/subnetof.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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.8 2004/07/10 07:48:37 mcr Exp $ + */ + #include "libreswan.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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/subnettoa.c linux-2.6.16-ng-natt-klips/net/ipsec/subnettoa.c *** linux-2.6.16-ng-natt/net/ipsec/subnettoa.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/subnettoa.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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.11 2004/07/10 07:48:37 mcr Exp $ + */ + #include "libreswan.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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/sysctl_net_ipsec.c linux-2.6.16-ng-natt-klips/net/ipsec/sysctl_net_ipsec.c *** linux-2.6.16-ng-natt/net/ipsec/sysctl_net_ipsec.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/sysctl_net_ipsec.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,363 ---- + /* + * 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 . + * + * 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.17.10.2 2007/10/30 21:42:25 paul Exp $ + */ + + /* -*- linux-c -*- + * + * Initiated April 3, 1998, Richard Guy Briggs + */ + + #include + #include + #include + + #include "libreswan/ipsec_param.h" + + #ifdef CONFIG_SYSCTL + + #define NET_IPSEC 2112 /* Random number */ + #ifdef CONFIG_KLIPS_DEBUG + extern int debug_ah; + extern int debug_esp; + extern int debug_mast; + extern int debug_tunnel; + extern int debug_xmit; + 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_KLIPS_IPCOMP + extern int sysctl_ipsec_debug_ipcomp; + #endif /* CONFIG_KLIPS_IPCOMP */ + #endif /* CONFIG_KLIPS_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_KLIPS_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_KLIPS_DEBUG */ + NET_IPSEC_ICMP=13, + NET_IPSEC_INBOUND_POLICY_CHECK=14, + NET_IPSEC_TOS=15, + NET_IPSEC_REGRESS_PFKEY_LOSSAGE=16, + NET_IPSEC_DEBUG_MAST=17, + NET_IPSEC_DEBUG_XMIT=18, + }; + + static ctl_table ipsec_table[] = { + #ifdef CONFIG_KLIPS_DEBUG + #ifdef CTL_TABLE_PARENT + { .ctl_name = NET_IPSEC_DEBUG_AH, + .procname = "debug_ah", + .data = &debug_ah, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_ESP, + .procname = "debug_esp", + .data = &debug_esp, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_MAST, + .procname = "debug_mast", + .data = &debug_mast, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_TUNNEL, + .procname = "debug_tunnel", + .data = &debug_tunnel, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_XMIT, + .procname = "debug_xmit", + .data = &debug_xmit, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_EROUTE, + .procname = "debug_eroute", + .data = &debug_eroute, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_SPI, + .procname = "debug_spi", + .data = &debug_spi, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_RADIJ, + .procname = "debug_radij", + .data = &debug_radij, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_NETLINK, + .procname = "debug_netlink", + .data = &debug_netlink, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_XFORM, + .procname = "debug_xform", + .data = &debug_xform, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_RCV, + .procname = "debug_rcv", + .data = &debug_rcv, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_PFKEY, + .procname = "debug_pfkey", + .data = &debug_pfkey, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_DEBUG_VERBOSE, + .procname = "debug_verbose", + .data = &sysctl_ipsec_debug_verbose, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + #else + { NET_IPSEC_DEBUG_AH, "debug_ah", &debug_ah, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_ESP, "debug_esp", &debug_esp, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_MAST, "debug_mast", &debug_mast, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_TUNNEL, "debug_tunnel", &debug_tunnel, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_TUNNEL, "debug_xmit", &debug_xmit, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_EROUTE, "debug_eroute", &debug_eroute, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_SPI, "debug_spi", &debug_spi, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_RADIJ, "debug_radij", &debug_radij, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_NETLINK, "debug_netlink", &debug_netlink, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_XFORM, "debug_xform", &debug_xform, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_RCV, "debug_rcv", &debug_rcv, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_PFKEY, "debug_pfkey", &debug_pfkey, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_DEBUG_VERBOSE, "debug_verbose",&sysctl_ipsec_debug_verbose, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + #endif /* CTL_TABLE_PARENT */ + #endif /* CONFIG_KLIPS_DEBUG */ + + #ifdef CONFIG_KLIPS_IPCOMP + #ifdef CTL_TABLE_PARENT + { .ctl_name = NET_IPSEC_DEBUG_IPCOMP, + .procname = "debug_ipcomp", + .data = &sysctl_ipsec_debug_ipcomp, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + #else + { NET_IPSEC_DEBUG_IPCOMP, "debug_ipcomp", &sysctl_ipsec_debug_ipcomp, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + #endif + #endif /* CONFIG_KLIPS_IPCOMP */ + + #ifdef CONFIG_KLIPS_REGRESS + #ifdef CTL_TABLE_PARENT + { + .ctl_name = NET_IPSEC_REGRESS_PFKEY_LOSSAGE, + .procname = "pfkey_lossage", + .data = &sysctl_ipsec_regress_pfkey_lossage, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + #else + { NET_IPSEC_REGRESS_PFKEY_LOSSAGE, "pfkey_lossage", + &sysctl_ipsec_regress_pfkey_lossage, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + #endif /* CTL_TABLE_PARENT */ + #endif /* CONFIG_KLIPS_REGRESS */ + + #ifdef CTL_TABLE_PARENT + { .ctl_name = NET_IPSEC_ICMP, + .procname = "icmp", + .data = &sysctl_ipsec_icmp, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_INBOUND_POLICY_CHECK, + .procname = "inbound_policy_check", + .data = &sysctl_ipsec_inbound_policy_check, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = NET_IPSEC_TOS, + .procname = "tos", + .data = &sysctl_ipsec_tos, + .maxlen = sizeof(int), + .mode = 0644, + .child = NULL, + .proc_handler = &proc_dointvec, + }, + {0} + #else + { NET_IPSEC_ICMP, "icmp", &sysctl_ipsec_icmp, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_INBOUND_POLICY_CHECK, "inbound_policy_check", &sysctl_ipsec_inbound_policy_check, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + { NET_IPSEC_TOS, "tos", &sysctl_ipsec_tos, + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + {0} + #endif + }; + + static ctl_table ipsec_net_table[] = { + #ifdef CTL_TABLE_PARENT + { .ctl_name = NET_IPSEC, + .procname = "ipsec", + .data = NULL, + .maxlen = 0, + .mode = 0555, + .child = ipsec_table, + .proc_handler = NULL, + }, + { 0 } + #else + { NET_IPSEC, "ipsec", NULL, 0, 0555, ipsec_table }, + { 0 } + #endif + }; + + static ctl_table ipsec_root_table[] = { + #ifdef CTL_TABLE_PARENT + { .ctl_name = CTL_NET, + .procname = "net", + .data = NULL, + .maxlen = 0, + .mode = 0555, + .child = ipsec_net_table, + .proc_handler = NULL, + }, + { 0 } + #else + { CTL_NET, "net", NULL, 0, 0555, ipsec_net_table }, + { 0 } + #endif + }; + + static struct ctl_table_header *ipsec_table_header; + + int ipsec_sysctl_register(void) + { + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + ipsec_table_header = register_sysctl_table(ipsec_root_table); + #else + ipsec_table_header = register_sysctl_table(ipsec_root_table, 0); + #endif + if (!ipsec_table_header) { + return -ENOMEM; + } + return 0; + } + + void ipsec_sysctl_unregister(void) + { + unregister_sysctl_table(ipsec_table_header); + } + + #endif /* CONFIG_SYSCTL */ + + /* + * + * Local Variables: + * c-file-style: "linux" + * End: + * + */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/trees.c linux-2.6.16-ng-natt-klips/net/ipsec/trees.c *** linux-2.6.16-ng-natt/net/ipsec/trees.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/trees.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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.4 2004/07/10 07:48:39 mcr Exp $ */ + + /* #define GEN_TREES_H */ + + #include "deflate.h" + + #ifdef DEBUG + # include + #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< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 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 + # 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<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++); + } + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/trees.h linux-2.6.16-ng-natt-klips/net/ipsec/trees.h *** linux-2.6.16-ng-natt/net/ipsec/trees.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/trees.h 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 + }; + diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ultoa.c linux-2.6.16-ng-natt-klips/net/ipsec/ultoa.c *** linux-2.6.16-ng-natt/net/ipsec/ultoa.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ultoa.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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.10 2004/07/10 07:48:37 mcr Exp $ + */ + #include "libreswan.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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/ultot.c linux-2.6.16-ng-natt-klips/net/ipsec/ultot.c *** linux-2.6.16-ng-natt/net/ipsec/ultot.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/ultot.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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.5 2004/07/10 07:48:37 mcr Exp $ + */ + #include "libreswan.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; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/version.c linux-2.6.16-ng-natt-klips/net/ipsec/version.c *** linux-2.6.16-ng-natt/net/ipsec/version.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/version.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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 . + * + * 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 + #endif + + #include "libreswan.h" + + #define V "2.5.51s" /* substituted in by Makefile */ + static const char libreswan_number[] = V; + static const char libreswan_string[] = "Libreswan " V; + + /* + - ipsec_version_code - return IPsec version number/code, as string + */ + const char * + ipsec_version_code() + { + return libreswan_number; + } + + /* + - ipsec_version_string - return full version string + */ + const char * + ipsec_version_string() + { + return libreswan_string; + } diff -c -w -r -N linux-2.6.16-ng-natt/net/ipsec/zutil.c linux-2.6.16-ng-natt-klips/net/ipsec/zutil.c *** linux-2.6.16-ng-natt/net/ipsec/zutil.c 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipsec/zutil.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 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.5 2004/07/10 07:48:40 mcr Exp $ */ + + #include + + #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 */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipv4/af_inet.c linux-2.6.16-ng-natt-klips/net/ipv4/af_inet.c *** linux-2.6.16-ng-natt/net/ipv4/af_inet.c 2006-03-20 00:53:29.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipv4/af_inet.c 2008-06-01 17:37:11.000000000 -0400 *************** *** 1222,1227 **** --- 1222,1239 ---- #if defined(CONFIG_IP_MROUTE) ip_mr_init(); #endif + + #if defined(CONFIG_KLIPS) + { + extern int ipsec_klips_init(void); + /* + * Initialise AF_INET ESP and AH protocol support including + * e-routing and SA tables + */ + ipsec_klips_init(); + } + #endif /* CONFIG_IPSEC */ + /* * Initialise per-cpu ipv4 mibs */ diff -c -w -r -N linux-2.6.16-ng-natt/net/ipv4/af_inet.c.preipsec linux-2.6.16-ng-natt-klips/net/ipv4/af_inet.c.preipsec *** linux-2.6.16-ng-natt/net/ipv4/af_inet.c.preipsec 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/ipv4/af_inet.c.preipsec 2006-03-20 00:53:29.000000000 -0500 *************** *** 0 **** --- 1,1307 ---- + /* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * PF_INET protocol family socket handler. + * + * Version: $Id: af_inet.c,v 1.137 2002/02/01 22:01:03 davem Exp $ + * + * Authors: Ross Biro + * Fred N. van Kempen, + * Florian La Roche, + * Alan Cox, + * + * Changes (see also sock.c) + * + * piggy, + * Karl Knutson : Socket protocol table + * A.N.Kuznetsov : Socket death error in accept(). + * John Richardson : Fix non blocking error in connect() + * so sockets that fail to connect + * don't return -EINPROGRESS. + * Alan Cox : Asynchronous I/O support + * Alan Cox : Keep correct socket pointer on sock + * structures + * when accept() ed + * Alan Cox : Semantics of SO_LINGER aren't state + * moved to close when you look carefully. + * With this fixed and the accept bug fixed + * some RPC stuff seems happier. + * Niibe Yutaka : 4.4BSD style write async I/O + * Alan Cox, + * Tony Gale : Fixed reuse semantics. + * Alan Cox : bind() shouldn't abort existing but dead + * sockets. Stops FTP netin:.. I hope. + * Alan Cox : bind() works correctly for RAW sockets. + * Note that FreeBSD at least was broken + * in this respect so be careful with + * compatibility tests... + * Alan Cox : routing cache support + * Alan Cox : memzero the socket structure for + * compactness. + * Matt Day : nonblock connect error handler + * Alan Cox : Allow large numbers of pending sockets + * (eg for big web sites), but only if + * specifically application requested. + * Alan Cox : New buffering throughout IP. Used + * dumbly. + * Alan Cox : New buffering now used smartly. + * Alan Cox : BSD rather than common sense + * interpretation of listen. + * Germano Caronni : Assorted small races. + * Alan Cox : sendmsg/recvmsg basic support. + * Alan Cox : Only sendmsg/recvmsg now supported. + * Alan Cox : Locked down bind (see security list). + * Alan Cox : Loosened bind a little. + * Mike McLagan : ADD/DEL DLCI Ioctls + * Willy Konynenberg : Transparent proxying support. + * David S. Miller : New socket lookup architecture. + * Some other random speedups. + * Cyrus Durgin : Cleaned up file for kmod hacks. + * Andi Kleen : Fix inet_stream_connect TCP race. + * + * 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. + */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #ifdef CONFIG_IP_MROUTE + #include + #endif + + DEFINE_SNMP_STAT(struct linux_mib, net_statistics) __read_mostly; + + extern void ip_mc_drop_socket(struct sock *sk); + + /* The inetsw table contains everything that inet_create needs to + * build a new socket. + */ + static struct list_head inetsw[SOCK_MAX]; + static DEFINE_SPINLOCK(inetsw_lock); + + /* New destruction routine */ + + void inet_sock_destruct(struct sock *sk) + { + struct inet_sock *inet = inet_sk(sk); + + __skb_queue_purge(&sk->sk_receive_queue); + __skb_queue_purge(&sk->sk_error_queue); + + if (sk->sk_type == SOCK_STREAM && sk->sk_state != TCP_CLOSE) { + printk("Attempt to release TCP socket in state %d %p\n", + sk->sk_state, sk); + return; + } + if (!sock_flag(sk, SOCK_DEAD)) { + printk("Attempt to release alive inet socket %p\n", sk); + return; + } + + BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc)); + BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc)); + BUG_TRAP(!sk->sk_wmem_queued); + BUG_TRAP(!sk->sk_forward_alloc); + + kfree(inet->opt); + dst_release(sk->sk_dst_cache); + sk_refcnt_debug_dec(sk); + } + + /* + * The routines beyond this point handle the behaviour of an AF_INET + * socket object. Mostly it punts to the subprotocols of IP to do + * the work. + */ + + /* + * Automatically bind an unbound socket. + */ + + static int inet_autobind(struct sock *sk) + { + struct inet_sock *inet; + /* We may need to bind the socket. */ + lock_sock(sk); + inet = inet_sk(sk); + if (!inet->num) { + if (sk->sk_prot->get_port(sk, 0)) { + release_sock(sk); + return -EAGAIN; + } + inet->sport = htons(inet->num); + } + release_sock(sk); + return 0; + } + + /* + * Move a socket into listening state. + */ + int inet_listen(struct socket *sock, int backlog) + { + struct sock *sk = sock->sk; + unsigned char old_state; + int err; + + lock_sock(sk); + + err = -EINVAL; + if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM) + goto out; + + old_state = sk->sk_state; + if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN))) + goto out; + + /* Really, if the socket is already in listen state + * we can only allow the backlog to be adjusted. + */ + if (old_state != TCP_LISTEN) { + err = inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); + if (err) + goto out; + } + sk->sk_max_ack_backlog = backlog; + err = 0; + + out: + release_sock(sk); + return err; + } + + /* + * Create an inet socket. + */ + + static int inet_create(struct socket *sock, int protocol) + { + struct sock *sk; + struct list_head *p; + struct inet_protosw *answer; + struct inet_sock *inet; + struct proto *answer_prot; + unsigned char answer_flags; + char answer_no_check; + int try_loading_module = 0; + int err; + + sock->state = SS_UNCONNECTED; + + /* Look for the requested type/protocol pair. */ + answer = NULL; + lookup_protocol: + err = -ESOCKTNOSUPPORT; + rcu_read_lock(); + list_for_each_rcu(p, &inetsw[sock->type]) { + answer = list_entry(p, struct inet_protosw, list); + + /* Check the non-wild match. */ + if (protocol == answer->protocol) { + if (protocol != IPPROTO_IP) + break; + } else { + /* Check for the two wild cases. */ + if (IPPROTO_IP == protocol) { + protocol = answer->protocol; + break; + } + if (IPPROTO_IP == answer->protocol) + break; + } + err = -EPROTONOSUPPORT; + answer = NULL; + } + + if (unlikely(answer == NULL)) { + if (try_loading_module < 2) { + rcu_read_unlock(); + /* + * Be more specific, e.g. net-pf-2-proto-132-type-1 + * (net-pf-PF_INET-proto-IPPROTO_SCTP-type-SOCK_STREAM) + */ + if (++try_loading_module == 1) + request_module("net-pf-%d-proto-%d-type-%d", + PF_INET, protocol, sock->type); + /* + * Fall back to generic, e.g. net-pf-2-proto-132 + * (net-pf-PF_INET-proto-IPPROTO_SCTP) + */ + else + request_module("net-pf-%d-proto-%d", + PF_INET, protocol); + goto lookup_protocol; + } else + goto out_rcu_unlock; + } + + err = -EPERM; + if (answer->capability > 0 && !capable(answer->capability)) + goto out_rcu_unlock; + + sock->ops = answer->ops; + answer_prot = answer->prot; + answer_no_check = answer->no_check; + answer_flags = answer->flags; + rcu_read_unlock(); + + BUG_TRAP(answer_prot->slab != NULL); + + err = -ENOBUFS; + sk = sk_alloc(PF_INET, GFP_KERNEL, answer_prot, 1); + if (sk == NULL) + goto out; + + err = 0; + sk->sk_no_check = answer_no_check; + if (INET_PROTOSW_REUSE & answer_flags) + sk->sk_reuse = 1; + + inet = inet_sk(sk); + inet->is_icsk = INET_PROTOSW_ICSK & answer_flags; + + if (SOCK_RAW == sock->type) { + inet->num = protocol; + if (IPPROTO_RAW == protocol) + inet->hdrincl = 1; + } + + if (ipv4_config.no_pmtu_disc) + inet->pmtudisc = IP_PMTUDISC_DONT; + else + inet->pmtudisc = IP_PMTUDISC_WANT; + + inet->id = 0; + + sock_init_data(sock, sk); + + sk->sk_destruct = inet_sock_destruct; + sk->sk_family = PF_INET; + sk->sk_protocol = protocol; + sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; + + inet->uc_ttl = -1; + inet->mc_loop = 1; + inet->mc_ttl = 1; + inet->mc_index = 0; + inet->mc_list = NULL; + + sk_refcnt_debug_inc(sk); + + if (inet->num) { + /* It assumes that any protocol which allows + * the user to assign a number at socket + * creation time automatically + * shares. + */ + inet->sport = htons(inet->num); + /* Add to protocol hash chains. */ + sk->sk_prot->hash(sk); + } + + if (sk->sk_prot->init) { + err = sk->sk_prot->init(sk); + if (err) + sk_common_release(sk); + } + out: + return err; + out_rcu_unlock: + rcu_read_unlock(); + goto out; + } + + + /* + * The peer socket should always be NULL (or else). When we call this + * function we are destroying the object and from then on nobody + * should refer to it. + */ + int inet_release(struct socket *sock) + { + struct sock *sk = sock->sk; + + if (sk) { + long timeout; + + /* Applications forget to leave groups before exiting */ + ip_mc_drop_socket(sk); + + /* If linger is set, we don't return until the close + * is complete. Otherwise we return immediately. The + * actually closing is done the same either way. + * + * If the close is due to the process exiting, we never + * linger.. + */ + timeout = 0; + if (sock_flag(sk, SOCK_LINGER) && + !(current->flags & PF_EXITING)) + timeout = sk->sk_lingertime; + sock->sk = NULL; + sk->sk_prot->close(sk, timeout); + } + return 0; + } + + /* It is off by default, see below. */ + int sysctl_ip_nonlocal_bind; + + int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) + { + struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; + struct sock *sk = sock->sk; + struct inet_sock *inet = inet_sk(sk); + unsigned short snum; + int chk_addr_ret; + int err; + + /* If the socket has its own bind function then use it. (RAW) */ + if (sk->sk_prot->bind) { + err = sk->sk_prot->bind(sk, uaddr, addr_len); + goto out; + } + err = -EINVAL; + if (addr_len < sizeof(struct sockaddr_in)) + goto out; + + chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr); + + /* Not specified by any standard per-se, however it breaks too + * many applications when removed. It is unfortunate since + * allowing applications to make a non-local bind solves + * several problems with systems using dynamic addressing. + * (ie. your servers still start up even if your ISDN link + * is temporarily down) + */ + err = -EADDRNOTAVAIL; + if (!sysctl_ip_nonlocal_bind && + !inet->freebind && + addr->sin_addr.s_addr != INADDR_ANY && + chk_addr_ret != RTN_LOCAL && + chk_addr_ret != RTN_MULTICAST && + chk_addr_ret != RTN_BROADCAST) + goto out; + + snum = ntohs(addr->sin_port); + err = -EACCES; + if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + goto out; + + /* We keep a pair of addresses. rcv_saddr is the one + * used by hash lookups, and saddr is used for transmit. + * + * In the BSD API these are the same except where it + * would be illegal to use them (multicast/broadcast) in + * which case the sending device address is used. + */ + lock_sock(sk); + + /* Check these errors (active socket, double bind). */ + err = -EINVAL; + if (sk->sk_state != TCP_CLOSE || inet->num) + goto out_release_sock; + + inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr; + if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) + inet->saddr = 0; /* Use device */ + + /* Make sure we are allowed to bind here. */ + if (sk->sk_prot->get_port(sk, snum)) { + inet->saddr = inet->rcv_saddr = 0; + err = -EADDRINUSE; + goto out_release_sock; + } + + if (inet->rcv_saddr) + sk->sk_userlocks |= SOCK_BINDADDR_LOCK; + if (snum) + sk->sk_userlocks |= SOCK_BINDPORT_LOCK; + inet->sport = htons(inet->num); + inet->daddr = 0; + inet->dport = 0; + sk_dst_reset(sk); + err = 0; + out_release_sock: + release_sock(sk); + out: + return err; + } + + int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr, + int addr_len, int flags) + { + struct sock *sk = sock->sk; + + if (uaddr->sa_family == AF_UNSPEC) + return sk->sk_prot->disconnect(sk, flags); + + if (!inet_sk(sk)->num && inet_autobind(sk)) + return -EAGAIN; + return sk->sk_prot->connect(sk, (struct sockaddr *)uaddr, addr_len); + } + + static long inet_wait_for_connect(struct sock *sk, long timeo) + { + DEFINE_WAIT(wait); + + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + + /* Basic assumption: if someone sets sk->sk_err, he _must_ + * change state of the socket from TCP_SYN_*. + * Connect() does not allow to get error notifications + * without closing the socket. + */ + while ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + if (signal_pending(current) || !timeo) + break; + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + } + finish_wait(sk->sk_sleep, &wait); + return timeo; + } + + /* + * Connect to a remote host. There is regrettably still a little + * TCP 'magic' in here. + */ + int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags) + { + struct sock *sk = sock->sk; + int err; + long timeo; + + lock_sock(sk); + + if (uaddr->sa_family == AF_UNSPEC) { + err = sk->sk_prot->disconnect(sk, flags); + sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED; + goto out; + } + + switch (sock->state) { + default: + err = -EINVAL; + goto out; + case SS_CONNECTED: + err = -EISCONN; + goto out; + case SS_CONNECTING: + err = -EALREADY; + /* Fall out of switch with err, set for this state */ + break; + case SS_UNCONNECTED: + err = -EISCONN; + if (sk->sk_state != TCP_CLOSE) + goto out; + + err = sk->sk_prot->connect(sk, uaddr, addr_len); + if (err < 0) + goto out; + + sock->state = SS_CONNECTING; + + /* Just entered SS_CONNECTING state; the only + * difference is that return value in non-blocking + * case is EINPROGRESS, rather than EALREADY. + */ + err = -EINPROGRESS; + break; + } + + timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); + + if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { + /* Error code is set above */ + if (!timeo || !inet_wait_for_connect(sk, timeo)) + goto out; + + err = sock_intr_errno(timeo); + if (signal_pending(current)) + goto out; + } + + /* Connection was closed by RST, timeout, ICMP error + * or another process disconnected us. + */ + if (sk->sk_state == TCP_CLOSE) + goto sock_error; + + /* sk->sk_err may be not zero now, if RECVERR was ordered by user + * and error was received after socket entered established state. + * Hence, it is handled normally after connect() return successfully. + */ + + sock->state = SS_CONNECTED; + err = 0; + out: + release_sock(sk); + return err; + + sock_error: + err = sock_error(sk) ? : -ECONNABORTED; + sock->state = SS_UNCONNECTED; + if (sk->sk_prot->disconnect(sk, flags)) + sock->state = SS_DISCONNECTING; + goto out; + } + + /* + * Accept a pending connection. The TCP layer now gives BSD semantics. + */ + + int inet_accept(struct socket *sock, struct socket *newsock, int flags) + { + struct sock *sk1 = sock->sk; + int err = -EINVAL; + struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err); + + if (!sk2) + goto do_err; + + lock_sock(sk2); + + BUG_TRAP((1 << sk2->sk_state) & + (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE)); + + sock_graft(sk2, newsock); + + newsock->state = SS_CONNECTED; + err = 0; + release_sock(sk2); + do_err: + return err; + } + + + /* + * This does both peername and sockname. + */ + int inet_getname(struct socket *sock, struct sockaddr *uaddr, + int *uaddr_len, int peer) + { + struct sock *sk = sock->sk; + struct inet_sock *inet = inet_sk(sk); + struct sockaddr_in *sin = (struct sockaddr_in *)uaddr; + + sin->sin_family = AF_INET; + if (peer) { + if (!inet->dport || + (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && + peer == 1)) + return -ENOTCONN; + sin->sin_port = inet->dport; + sin->sin_addr.s_addr = inet->daddr; + } else { + __u32 addr = inet->rcv_saddr; + if (!addr) + addr = inet->saddr; + sin->sin_port = inet->sport; + sin->sin_addr.s_addr = addr; + } + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + *uaddr_len = sizeof(*sin); + return 0; + } + + int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + size_t size) + { + struct sock *sk = sock->sk; + + /* We may need to bind the socket. */ + if (!inet_sk(sk)->num && inet_autobind(sk)) + return -EAGAIN; + + return sk->sk_prot->sendmsg(iocb, sk, msg, size); + } + + + static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags) + { + struct sock *sk = sock->sk; + + /* We may need to bind the socket. */ + if (!inet_sk(sk)->num && inet_autobind(sk)) + return -EAGAIN; + + if (sk->sk_prot->sendpage) + return sk->sk_prot->sendpage(sk, page, offset, size, flags); + return sock_no_sendpage(sock, page, offset, size, flags); + } + + + int inet_shutdown(struct socket *sock, int how) + { + struct sock *sk = sock->sk; + int err = 0; + + /* This should really check to make sure + * the socket is a TCP socket. (WHY AC...) + */ + how++; /* maps 0->1 has the advantage of making bit 1 rcvs and + 1->2 bit 2 snds. + 2->3 */ + if ((how & ~SHUTDOWN_MASK) || !how) /* MAXINT->0 */ + return -EINVAL; + + lock_sock(sk); + if (sock->state == SS_CONNECTING) { + if ((1 << sk->sk_state) & + (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE)) + sock->state = SS_DISCONNECTING; + else + sock->state = SS_CONNECTED; + } + + switch (sk->sk_state) { + case TCP_CLOSE: + err = -ENOTCONN; + /* Hack to wake up other listeners, who can poll for + POLLHUP, even on eg. unconnected UDP sockets -- RR */ + default: + sk->sk_shutdown |= how; + if (sk->sk_prot->shutdown) + sk->sk_prot->shutdown(sk, how); + break; + + /* Remaining two branches are temporary solution for missing + * close() in multithreaded environment. It is _not_ a good idea, + * but we have no choice until close() is repaired at VFS level. + */ + case TCP_LISTEN: + if (!(how & RCV_SHUTDOWN)) + break; + /* Fall through */ + case TCP_SYN_SENT: + err = sk->sk_prot->disconnect(sk, O_NONBLOCK); + sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED; + break; + } + + /* Wake up anyone sleeping in poll. */ + sk->sk_state_change(sk); + release_sock(sk); + return err; + } + + /* + * ioctl() calls you can issue on an INET socket. Most of these are + * device configuration and stuff and very rarely used. Some ioctls + * pass on to the socket itself. + * + * NOTE: I like the idea of a module for the config stuff. ie ifconfig + * loads the devconfigure module does its configuring and unloads it. + * There's a good 20K of config code hanging around the kernel. + */ + + int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) + { + struct sock *sk = sock->sk; + int err = 0; + + switch (cmd) { + case SIOCGSTAMP: + err = sock_get_timestamp(sk, (struct timeval __user *)arg); + break; + case SIOCADDRT: + case SIOCDELRT: + case SIOCRTMSG: + err = ip_rt_ioctl(cmd, (void __user *)arg); + break; + case SIOCDARP: + case SIOCGARP: + case SIOCSARP: + err = arp_ioctl(cmd, (void __user *)arg); + break; + case SIOCGIFADDR: + case SIOCSIFADDR: + case SIOCGIFBRDADDR: + case SIOCSIFBRDADDR: + case SIOCGIFNETMASK: + case SIOCSIFNETMASK: + case SIOCGIFDSTADDR: + case SIOCSIFDSTADDR: + case SIOCSIFPFLAGS: + case SIOCGIFPFLAGS: + case SIOCSIFFLAGS: + err = devinet_ioctl(cmd, (void __user *)arg); + break; + default: + if (sk->sk_prot->ioctl) + err = sk->sk_prot->ioctl(sk, cmd, arg); + else + err = -ENOIOCTLCMD; + break; + } + return err; + } + + const struct proto_ops inet_stream_ops = { + .family = PF_INET, + .owner = THIS_MODULE, + .release = inet_release, + .bind = inet_bind, + .connect = inet_stream_connect, + .socketpair = sock_no_socketpair, + .accept = inet_accept, + .getname = inet_getname, + .poll = tcp_poll, + .ioctl = inet_ioctl, + .listen = inet_listen, + .shutdown = inet_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = inet_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = tcp_sendpage + }; + + const struct proto_ops inet_dgram_ops = { + .family = PF_INET, + .owner = THIS_MODULE, + .release = inet_release, + .bind = inet_bind, + .connect = inet_dgram_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = inet_getname, + .poll = udp_poll, + .ioctl = inet_ioctl, + .listen = sock_no_listen, + .shutdown = inet_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = inet_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = inet_sendpage, + }; + + /* + * For SOCK_RAW sockets; should be the same as inet_dgram_ops but without + * udp_poll + */ + static const struct proto_ops inet_sockraw_ops = { + .family = PF_INET, + .owner = THIS_MODULE, + .release = inet_release, + .bind = inet_bind, + .connect = inet_dgram_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = inet_getname, + .poll = datagram_poll, + .ioctl = inet_ioctl, + .listen = sock_no_listen, + .shutdown = inet_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = inet_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = inet_sendpage, + }; + + static struct net_proto_family inet_family_ops = { + .family = PF_INET, + .create = inet_create, + .owner = THIS_MODULE, + }; + + /* Upon startup we insert all the elements in inetsw_array[] into + * the linked list inetsw. + */ + static struct inet_protosw inetsw_array[] = + { + { + .type = SOCK_STREAM, + .protocol = IPPROTO_TCP, + .prot = &tcp_prot, + .ops = &inet_stream_ops, + .capability = -1, + .no_check = 0, + .flags = INET_PROTOSW_PERMANENT | + INET_PROTOSW_ICSK, + }, + + { + .type = SOCK_DGRAM, + .protocol = IPPROTO_UDP, + .prot = &udp_prot, + .ops = &inet_dgram_ops, + .capability = -1, + .no_check = UDP_CSUM_DEFAULT, + .flags = INET_PROTOSW_PERMANENT, + }, + + + { + .type = SOCK_RAW, + .protocol = IPPROTO_IP, /* wild card */ + .prot = &raw_prot, + .ops = &inet_sockraw_ops, + .capability = CAP_NET_RAW, + .no_check = UDP_CSUM_DEFAULT, + .flags = INET_PROTOSW_REUSE, + } + }; + + #define INETSW_ARRAY_LEN (sizeof(inetsw_array) / sizeof(struct inet_protosw)) + + void inet_register_protosw(struct inet_protosw *p) + { + struct list_head *lh; + struct inet_protosw *answer; + int protocol = p->protocol; + struct list_head *last_perm; + + spin_lock_bh(&inetsw_lock); + + if (p->type >= SOCK_MAX) + goto out_illegal; + + /* If we are trying to override a permanent protocol, bail. */ + answer = NULL; + last_perm = &inetsw[p->type]; + list_for_each(lh, &inetsw[p->type]) { + answer = list_entry(lh, struct inet_protosw, list); + + /* Check only the non-wild match. */ + if (INET_PROTOSW_PERMANENT & answer->flags) { + if (protocol == answer->protocol) + break; + last_perm = lh; + } + + answer = NULL; + } + if (answer) + goto out_permanent; + + /* Add the new entry after the last permanent entry if any, so that + * the new entry does not override a permanent entry when matched with + * a wild-card protocol. But it is allowed to override any existing + * non-permanent entry. This means that when we remove this entry, the + * system automatically returns to the old behavior. + */ + list_add_rcu(&p->list, last_perm); + out: + spin_unlock_bh(&inetsw_lock); + + synchronize_net(); + + return; + + out_permanent: + printk(KERN_ERR "Attempt to override permanent protocol %d.\n", + protocol); + goto out; + + out_illegal: + printk(KERN_ERR + "Ignoring attempt to register invalid socket type %d.\n", + p->type); + goto out; + } + + void inet_unregister_protosw(struct inet_protosw *p) + { + if (INET_PROTOSW_PERMANENT & p->flags) { + printk(KERN_ERR + "Attempt to unregister permanent protocol %d.\n", + p->protocol); + } else { + spin_lock_bh(&inetsw_lock); + list_del_rcu(&p->list); + spin_unlock_bh(&inetsw_lock); + + synchronize_net(); + } + } + + /* + * Shall we try to damage output packets if routing dev changes? + */ + + int sysctl_ip_dynaddr; + + static int inet_sk_reselect_saddr(struct sock *sk) + { + struct inet_sock *inet = inet_sk(sk); + int err; + struct rtable *rt; + __u32 old_saddr = inet->saddr; + __u32 new_saddr; + __u32 daddr = inet->daddr; + + if (inet->opt && inet->opt->srr) + daddr = inet->opt->faddr; + + /* Query new route. */ + err = ip_route_connect(&rt, daddr, 0, + RT_CONN_FLAGS(sk), + sk->sk_bound_dev_if, + sk->sk_protocol, + inet->sport, inet->dport, sk); + if (err) + return err; + + sk_setup_caps(sk, &rt->u.dst); + + new_saddr = rt->rt_src; + + if (new_saddr == old_saddr) + return 0; + + if (sysctl_ip_dynaddr > 1) { + printk(KERN_INFO "%s(): shifting inet->" + "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n", + __FUNCTION__, + NIPQUAD(old_saddr), + NIPQUAD(new_saddr)); + } + + inet->saddr = inet->rcv_saddr = new_saddr; + + /* + * XXX The only one ugly spot where we need to + * XXX really change the sockets identity after + * XXX it has entered the hashes. -DaveM + * + * Besides that, it does not check for connection + * uniqueness. Wait for troubles. + */ + __sk_prot_rehash(sk); + return 0; + } + + int inet_sk_rebuild_header(struct sock *sk) + { + struct inet_sock *inet = inet_sk(sk); + struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); + u32 daddr; + int err; + + /* Route is OK, nothing to do. */ + if (rt) + return 0; + + /* Reroute. */ + daddr = inet->daddr; + if (inet->opt && inet->opt->srr) + daddr = inet->opt->faddr; + { + struct flowi fl = { + .oif = sk->sk_bound_dev_if, + .nl_u = { + .ip4_u = { + .daddr = daddr, + .saddr = inet->saddr, + .tos = RT_CONN_FLAGS(sk), + }, + }, + .proto = sk->sk_protocol, + .uli_u = { + .ports = { + .sport = inet->sport, + .dport = inet->dport, + }, + }, + }; + + err = ip_route_output_flow(&rt, &fl, sk, 0); + } + if (!err) + sk_setup_caps(sk, &rt->u.dst); + else { + /* Routing failed... */ + sk->sk_route_caps = 0; + /* + * Other protocols have to map its equivalent state to TCP_SYN_SENT. + * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme + */ + if (!sysctl_ip_dynaddr || + sk->sk_state != TCP_SYN_SENT || + (sk->sk_userlocks & SOCK_BINDADDR_LOCK) || + (err = inet_sk_reselect_saddr(sk)) != 0) + sk->sk_err_soft = -err; + } + + return err; + } + + EXPORT_SYMBOL(inet_sk_rebuild_header); + + #ifdef CONFIG_IP_MULTICAST + static struct net_protocol igmp_protocol = { + .handler = igmp_rcv, + }; + #endif + + static struct net_protocol tcp_protocol = { + .handler = tcp_v4_rcv, + .err_handler = tcp_v4_err, + .no_policy = 1, + }; + + static struct net_protocol udp_protocol = { + .handler = udp_rcv, + .err_handler = udp_err, + .no_policy = 1, + }; + + static struct net_protocol icmp_protocol = { + .handler = icmp_rcv, + }; + + static int __init init_ipv4_mibs(void) + { + net_statistics[0] = alloc_percpu(struct linux_mib); + net_statistics[1] = alloc_percpu(struct linux_mib); + ip_statistics[0] = alloc_percpu(struct ipstats_mib); + ip_statistics[1] = alloc_percpu(struct ipstats_mib); + icmp_statistics[0] = alloc_percpu(struct icmp_mib); + icmp_statistics[1] = alloc_percpu(struct icmp_mib); + tcp_statistics[0] = alloc_percpu(struct tcp_mib); + tcp_statistics[1] = alloc_percpu(struct tcp_mib); + udp_statistics[0] = alloc_percpu(struct udp_mib); + udp_statistics[1] = alloc_percpu(struct udp_mib); + if (! + (net_statistics[0] && net_statistics[1] && ip_statistics[0] + && ip_statistics[1] && tcp_statistics[0] && tcp_statistics[1] + && udp_statistics[0] && udp_statistics[1])) + return -ENOMEM; + + (void) tcp_mib_init(); + + return 0; + } + + static int ipv4_proc_init(void); + + /* + * IP protocol layer initialiser + */ + + static struct packet_type ip_packet_type = { + .type = __constant_htons(ETH_P_IP), + .func = ip_rcv, + }; + + static int __init inet_init(void) + { + struct sk_buff *dummy_skb; + struct inet_protosw *q; + struct list_head *r; + int rc = -EINVAL; + + if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) { + printk(KERN_CRIT "%s: panic\n", __FUNCTION__); + goto out; + } + + rc = proto_register(&tcp_prot, 1); + if (rc) + goto out; + + rc = proto_register(&udp_prot, 1); + if (rc) + goto out_unregister_tcp_proto; + + rc = proto_register(&raw_prot, 1); + if (rc) + goto out_unregister_udp_proto; + + /* + * Tell SOCKET that we are alive... + */ + + (void)sock_register(&inet_family_ops); + + /* + * Add all the base protocols. + */ + + if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0) + printk(KERN_CRIT "inet_init: Cannot add ICMP protocol\n"); + if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0) + printk(KERN_CRIT "inet_init: Cannot add UDP protocol\n"); + if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0) + printk(KERN_CRIT "inet_init: Cannot add TCP protocol\n"); + #ifdef CONFIG_IP_MULTICAST + if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0) + printk(KERN_CRIT "inet_init: Cannot add IGMP protocol\n"); + #endif + + /* Register the socket-side information for inet_create. */ + for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r) + INIT_LIST_HEAD(r); + + for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q) + inet_register_protosw(q); + + /* + * Set the ARP module up + */ + + arp_init(); + + /* + * Set the IP module up + */ + + ip_init(); + + tcp_v4_init(&inet_family_ops); + + /* Setup TCP slab cache for open requests. */ + tcp_init(); + + + /* + * Set the ICMP layer up + */ + + icmp_init(&inet_family_ops); + + /* + * Initialise the multicast router + */ + #if defined(CONFIG_IP_MROUTE) + ip_mr_init(); + #endif + /* + * Initialise per-cpu ipv4 mibs + */ + + if(init_ipv4_mibs()) + printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ; + + ipv4_proc_init(); + + ipfrag_init(); + + dev_add_pack(&ip_packet_type); + + rc = 0; + out: + return rc; + out_unregister_tcp_proto: + proto_unregister(&tcp_prot); + out_unregister_udp_proto: + proto_unregister(&udp_prot); + goto out; + } + + module_init(inet_init); + + /* ------------------------------------------------------------------------ */ + + #ifdef CONFIG_PROC_FS + static int __init ipv4_proc_init(void) + { + int rc = 0; + + if (raw_proc_init()) + goto out_raw; + if (tcp4_proc_init()) + goto out_tcp; + if (udp4_proc_init()) + goto out_udp; + if (fib_proc_init()) + goto out_fib; + if (ip_misc_proc_init()) + goto out_misc; + out: + return rc; + out_misc: + fib_proc_exit(); + out_fib: + udp4_proc_exit(); + out_udp: + tcp4_proc_exit(); + out_tcp: + raw_proc_exit(); + out_raw: + rc = -ENOMEM; + goto out; + } + + #else /* CONFIG_PROC_FS */ + static int __init ipv4_proc_init(void) + { + return 0; + } + #endif /* CONFIG_PROC_FS */ + + MODULE_ALIAS_NETPROTO(PF_INET); + + EXPORT_SYMBOL(inet_accept); + EXPORT_SYMBOL(inet_bind); + EXPORT_SYMBOL(inet_dgram_connect); + EXPORT_SYMBOL(inet_dgram_ops); + EXPORT_SYMBOL(inet_getname); + EXPORT_SYMBOL(inet_ioctl); + EXPORT_SYMBOL(inet_listen); + EXPORT_SYMBOL(inet_register_protosw); + EXPORT_SYMBOL(inet_release); + EXPORT_SYMBOL(inet_sendmsg); + EXPORT_SYMBOL(inet_shutdown); + EXPORT_SYMBOL(inet_sock_destruct); + EXPORT_SYMBOL(inet_stream_connect); + EXPORT_SYMBOL(inet_stream_ops); + EXPORT_SYMBOL(inet_unregister_protosw); + EXPORT_SYMBOL(net_statistics); + EXPORT_SYMBOL(sysctl_ip_nonlocal_bind); diff -c -w -r -N linux-2.6.16-ng-natt/net/Kconfig linux-2.6.16-ng-natt-klips/net/Kconfig *** linux-2.6.16-ng-natt/net/Kconfig 2006-03-20 00:53:29.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/Kconfig 2008-06-01 17:37:11.000000000 -0400 *************** *** 224,229 **** --- 224,233 ---- source "net/bluetooth/Kconfig" source "net/ieee80211/Kconfig" + if INET + source "net/ipsec/Kconfig" + endif # if INET + endif # if NET endmenu # Networking diff -c -w -r -N linux-2.6.16-ng-natt/net/Kconfig.preipsec linux-2.6.16-ng-natt-klips/net/Kconfig.preipsec *** linux-2.6.16-ng-natt/net/Kconfig.preipsec 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/Kconfig.preipsec 2006-03-20 00:53:29.000000000 -0500 *************** *** 0 **** --- 1,229 ---- + # + # Network configuration + # + + menu "Networking" + + config NET + bool "Networking support" + ---help--- + Unless you really know what you are doing, you should say Y here. + The reason is that some programs need kernel networking support even + when running on a stand-alone machine that isn't connected to any + other computer. + + If you are upgrading from an older kernel, you + should consider updating your networking tools too because changes + in the kernel and the tools often go hand in hand. The tools are + contained in the package net-tools, the location and version number + of which are given in . + + For a general introduction to Linux networking, it is highly + recommended to read the NET-HOWTO, available from + . + + # Make sure that all config symbols are dependent on NET + if NET + + menu "Networking options" + + config NETDEBUG + bool "Network packet debugging" + help + You can say Y here if you want to get additional messages useful in + debugging bad packets, but can overwhelm logs under denial of service + attacks. + + source "net/packet/Kconfig" + source "net/unix/Kconfig" + source "net/xfrm/Kconfig" + + config INET + bool "TCP/IP networking" + ---help--- + These are the protocols used on the Internet and on most local + Ethernets. It is highly recommended to say Y here (this will enlarge + your kernel by about 144 KB), since some programs (e.g. the X window + system) use TCP/IP even if your machine is not connected to any + other computer. You will get the so-called loopback device which + allows you to ping yourself (great fun, that!). + + For an excellent introduction to Linux networking, please read the + Linux Networking HOWTO, available from + . + + If you say Y here and also to "/proc file system support" and + "Sysctl support" below, you can change various aspects of the + behavior of the TCP/IP code by writing to the (virtual) files in + /proc/sys/net/ipv4/*; the options are explained in the file + . + + Short answer: say Y. + + if INET + source "net/ipv4/Kconfig" + source "net/ipv6/Kconfig" + + endif # if INET + + menuconfig NETFILTER + bool "Network packet filtering (replaces ipchains)" + ---help--- + Netfilter is a framework for filtering and mangling network packets + that pass through your Linux box. + + The most common use of packet filtering is to run your Linux box as + a firewall protecting a local network from the Internet. The type of + firewall provided by this kernel support is called a "packet + filter", which means that it can reject individual network packets + based on type, source, destination etc. The other kind of firewall, + a "proxy-based" one, is more secure but more intrusive and more + bothersome to set up; it inspects the network traffic much more + closely, modifies it and has knowledge about the higher level + protocols, which a packet filter lacks. Moreover, proxy-based + firewalls often require changes to the programs running on the local + clients. Proxy-based firewalls don't need support by the kernel, but + they are often combined with a packet filter, which only works if + you say Y here. + + You should also say Y here if you intend to use your Linux box as + the gateway to the Internet for a local network of machines without + globally valid IP addresses. This is called "masquerading": if one + of the computers on your local network wants to send something to + the outside, your box can "masquerade" as that computer, i.e. it + forwards the traffic to the intended outside destination, but + modifies the packets to make it look like they came from the + firewall box itself. It works both ways: if the outside host + replies, the Linux box will silently forward the traffic to the + correct local computer. This way, the computers on your local net + are completely invisible to the outside world, even though they can + reach the outside and can receive replies. It is even possible to + run globally visible servers from within a masqueraded local network + using a mechanism called portforwarding. Masquerading is also often + called NAT (Network Address Translation). + + Another use of Netfilter is in transparent proxying: if a machine on + the local network tries to connect to an outside host, your Linux + box can transparently forward the traffic to a local server, + typically a caching proxy server. + + Yet another use of Netfilter is building a bridging firewall. Using + a bridge with Network packet filtering enabled makes iptables "see" + the bridged traffic. For filtering on the lower network and Ethernet + protocols over the bridge, use ebtables (under bridge netfilter + configuration). + + Various modules exist for netfilter which replace the previous + masquerading (ipmasqadm), packet filtering (ipchains), transparent + proxying, and portforwarding mechanisms. Please see + under "iptables" for the location of + these packages. + + Make sure to say N to "Fast switching" below if you intend to say Y + here, as Fast switching currently bypasses netfilter. + + Chances are that you should say Y here if you compile a kernel which + will run as a router and N for regular hosts. If unsure, say N. + + if NETFILTER + + config NETFILTER_DEBUG + bool "Network packet filtering debugging" + depends on NETFILTER + help + You can say Y here if you want to get additional messages useful in + debugging the netfilter code. + + config BRIDGE_NETFILTER + bool "Bridged IP/ARP packets filtering" + depends on BRIDGE && NETFILTER && INET + default y + ---help--- + Enabling this option will let arptables resp. iptables see bridged + ARP resp. IP traffic. If you want a bridging firewall, you probably + want this option enabled. + Enabling or disabling this option doesn't enable or disable + ebtables. + + If unsure, say N. + + source "net/netfilter/Kconfig" + source "net/ipv4/netfilter/Kconfig" + source "net/ipv6/netfilter/Kconfig" + source "net/decnet/netfilter/Kconfig" + source "net/bridge/netfilter/Kconfig" + + endif + + source "net/dccp/Kconfig" + source "net/sctp/Kconfig" + source "net/tipc/Kconfig" + source "net/atm/Kconfig" + source "net/bridge/Kconfig" + source "net/8021q/Kconfig" + source "net/decnet/Kconfig" + source "net/llc/Kconfig" + source "net/ipx/Kconfig" + source "drivers/net/appletalk/Kconfig" + source "net/x25/Kconfig" + source "net/lapb/Kconfig" + + config NET_DIVERT + bool "Frame Diverter (EXPERIMENTAL)" + depends on EXPERIMENTAL + ---help--- + The Frame Diverter allows you to divert packets from the + network, that are not aimed at the interface receiving it (in + promisc. mode). Typically, a Linux box setup as an Ethernet bridge + with the Frames Diverter on, can do some *really* transparent www + caching using a Squid proxy for example. + + This is very useful when you don't want to change your router's + config (or if you simply don't have access to it). + + The other possible usages of diverting Ethernet Frames are + numberous: + - reroute smtp traffic to another interface + - traffic-shape certain network streams + - transparently proxy smtp connections + - etc... + + For more informations, please refer to: + + + + If unsure, say N. + + source "net/econet/Kconfig" + source "net/wanrouter/Kconfig" + source "net/sched/Kconfig" + + menu "Network testing" + + config NET_PKTGEN + tristate "Packet Generator (USE WITH CAUTION)" + depends on PROC_FS + ---help--- + This module will inject preconfigured packets, at a configurable + rate, out of a given interface. It is used for network interface + stress testing and performance analysis. If you don't understand + what was just said, you don't need it: say N. + + Documentation on how to use the packet generator can be found + at . + + To compile this code as a module, choose M here: the + module will be called pktgen. + + endmenu + + endmenu + + source "net/ax25/Kconfig" + source "net/irda/Kconfig" + source "net/bluetooth/Kconfig" + source "net/ieee80211/Kconfig" + + endif # if NET + endmenu # Networking + diff -c -w -r -N linux-2.6.16-ng-natt/net/Makefile linux-2.6.16-ng-natt-klips/net/Makefile *** linux-2.6.16-ng-natt/net/Makefile 2006-03-20 00:53:29.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/Makefile 2008-06-01 17:37:11.000000000 -0400 *************** *** 50,52 **** --- 50,55 ---- ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o endif + + obj-$(CONFIG_KLIPS) += ipsec/ + diff -c -w -r -N linux-2.6.16-ng-natt/net/Makefile.preipsec linux-2.6.16-ng-natt-klips/net/Makefile.preipsec *** linux-2.6.16-ng-natt/net/Makefile.preipsec 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/net/Makefile.preipsec 2006-03-20 00:53:29.000000000 -0500 *************** *** 0 **** --- 1,52 ---- + # + # Makefile for the linux networking. + # + # 2 Sep 2000, Christoph Hellwig + # Rewritten to use lists instead of if-statements. + # + + obj-y := nonet.o + + obj-$(CONFIG_NET) := socket.o core/ + + tmp-$(CONFIG_COMPAT) := compat.o + obj-$(CONFIG_NET) += $(tmp-y) + + # LLC has to be linked before the files in net/802/ + obj-$(CONFIG_LLC) += llc/ + obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/ + obj-$(CONFIG_NETFILTER) += netfilter/ + obj-$(CONFIG_INET) += ipv4/ + obj-$(CONFIG_XFRM) += xfrm/ + obj-$(CONFIG_UNIX) += unix/ + ifneq ($(CONFIG_IPV6),) + obj-y += ipv6/ + endif + obj-$(CONFIG_PACKET) += packet/ + obj-$(CONFIG_NET_KEY) += key/ + obj-$(CONFIG_NET_SCHED) += sched/ + obj-$(CONFIG_BRIDGE) += bridge/ + obj-$(CONFIG_IPX) += ipx/ + obj-$(CONFIG_ATALK) += appletalk/ + obj-$(CONFIG_WAN_ROUTER) += wanrouter/ + obj-$(CONFIG_X25) += x25/ + obj-$(CONFIG_LAPB) += lapb/ + obj-$(CONFIG_NETROM) += netrom/ + obj-$(CONFIG_ROSE) += rose/ + obj-$(CONFIG_AX25) += ax25/ + obj-$(CONFIG_IRDA) += irda/ + obj-$(CONFIG_BT) += bluetooth/ + obj-$(CONFIG_SUNRPC) += sunrpc/ + obj-$(CONFIG_RXRPC) += rxrpc/ + obj-$(CONFIG_ATM) += atm/ + obj-$(CONFIG_DECNET) += decnet/ + obj-$(CONFIG_ECONET) += econet/ + obj-$(CONFIG_VLAN_8021Q) += 8021q/ + obj-$(CONFIG_IP_DCCP) += dccp/ + obj-$(CONFIG_IP_SCTP) += sctp/ + obj-$(CONFIG_IEEE80211) += ieee80211/ + obj-$(CONFIG_TIPC) += tipc/ + + ifeq ($(CONFIG_NET),y) + obj-$(CONFIG_SYSCTL) += sysctl_net.o + endif diff -c -w -r -N linux-2.6.16-ng-natt/libreswan.patch linux-2.6.16-ng-natt-klips/libreswan.patch *** linux-2.6.16-ng-natt/libreswan.patch 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/libreswan.patch 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,53705 ---- + make[1]: Entering directory `/vol/git/libreswan.sony' + packaging/utils/kernelpatch 2.6 + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/README.libreswan-2 Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,112 @@ + +* + +* RCSID $Id: README.libreswan-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.libreswan-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/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 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 + +#else + +# include + +#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 + + * + + * 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 . + + * + + * 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=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=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,286 @@ + +/* 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 + +#else + +#include + +#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); + + + +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 */ + +/* 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 */ + +/* 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/crypto/ocf_assist.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,63 @@ + +#ifndef _OCF_ASSIST_H + +#define _OCF_ASSIST_H 1 + +/****************************************************************************/ + +/* The various hw_assist functions return these bits */ + + + +#define OCF_PROVIDES_AES 0x0001 + +#define OCF_PROVIDES_DES_3DES 0x0002 + + + +/****************************************************************************/ + +#if !defined(OCF_ASSIST) + +/****************************************************************************/ + +/* + + * stub it all out just in case + + */ + + + +#define ocf_aes_assist() (0) + +#define ocf_aes_set_key(a1,a2,a3,a4) + +#define ocf_aes_cbc_encrypt(a1,a2,a3,a4,a5,a6) + + + +#define ocf_des_assist() (0) + +#define ocf_des_set_key(a, b) + +#define ocf_des_cbc_encrypt(a1,a2,a3,a4,a5,a6) + +#define ocf_des_encrypt(a1,a2,a3) + +#define ocf_des_ede3_cbc_encrypt(a1,a2,a3,a4,a5,a6,a7,a8) + +#define ocf_des_ncbc_encrypt(a1,a2,a3,a4,a5,a6) + +#define ocf_des_ecb_encrypt(a1,a2,a3,a4) + + + +/****************************************************************************/ + +#else + +/****************************************************************************/ + + + +#include + +#include "aes.h" + +#include "des.h" + + + +extern int ocf_aes_assist(void); + +extern void ocf_aes_set_key(aes_context *cx, const unsigned char in_key[], + + int n_bytes, const int f); + +extern int ocf_aes_cbc_encrypt(aes_context *ctx, u8 *input, + + u8 *output, + + long length, + + u8 *ivec, int enc); + + + +extern int ocf_des_assist(void); + +extern int ocf_des_set_key(des_cblock *key, des_key_schedule schedule); + +extern void ocf_des_cbc_encrypt(des_cblock *input, des_cblock *output, + + long length, des_key_schedule schedule, + + des_cblock *ivec, int enc); + +extern void ocf_des_encrypt(DES_LONG *data, des_key_schedule ks, int enc); + +extern void ocf_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); + +extern void ocf_des_ncbc_encrypt(des_cblock *input, des_cblock *output, + + long length, des_key_schedule schedule, + + des_cblock *ivec, int enc); + +extern void ocf_des_ecb_encrypt(des_cblock *input, des_cblock *output, + + des_key_schedule ks, int enc); + + + +/****************************************************************************/ + +#endif /* !defined(OCF_ASSIST) */ + +/****************************************************************************/ + +#endif /* _OCF_ASSIST_H */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/des/des_locl.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,506 @@ + +/* 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 + + * 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 + +#include + +#include + +#include + +#ifndef RAND + +#define RAND + +#endif + +#undef NOPROTO + +#endif + + + +#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) + +#ifndef __KERNEL__ + +#include + +#else + +#include + +#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 + + + +#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); \ + + } \ + + } + + + +#define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) + + + +/* 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 + + * 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<>(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/include/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/include/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/include/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/include/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/libreswan.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,563 @@ + +#ifndef _LIBRESWAN_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 . + + * + + * 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: libreswan.h,v 1.95 2005/08/25 01:24:40 paul Exp $ + + */ + +#define _LIBRESWAN_H /* seen it, no need to see it again */ + + + +/* you'd think this should be builtin to compiler... */ + +#ifndef TRUE + +#define TRUE 1 + +#endif + + + +#ifndef FALSE + +#define FALSE 0 + +#endif + + + + + + + +/* + + * 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 */ + +#if defined(linux) + +#if defined(__KERNEL__) + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#define user_assert(foo) /*nothing*/ + + + +#else /* NOT in kernel */ + +#include + +#include + +#include + +#include + +#include + +#define user_assert(foo) assert(foo) + +#include + + + +# define uint8_t u_int8_t + +# define uint16_t u_int16_t + +# define uint32_t u_int32_t + +# define uint64_t u_int64_t + + + + + + + +#endif /* __KERNEL__ */ + + + +#endif /* linux */ + + + +#define DEBUG_NO_STATIC static + + + +/* + + * Yes Virginia, we have started a windows port. + + */ + +#if defined(__CYGWIN32__) + +#if !defined(WIN32_KERNEL) + +/* get windows equivalents */ + +#include + +#include + +#include + +#include + +#include + +#include + +#define user_assert(foo) assert(foo) + +#endif /* _KERNEL */ + +#endif /* WIN32 */ + + + +/* + + * Kovacs? A macosx port? + + */ + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#define user_assert(foo) assert(foo) + +#define __u32 unsigned int + +#define __u8 unsigned char + +#define s6_addr16 __u6_addr.__u6_addr16 + +#define DEBUG_NO_STATIC static + +#endif + + + +/* + + * FreeBSD + + */ + +#if defined(__FreeBSD__) + +# define DEBUG_NO_STATIC static + +#include + +#include + +#include + +#include + +#include + +#include + +#define user_assert(foo) assert(foo) + +/* apparently this way to deal with an IPv6 address is not standard. */ + +#define s6_addr16 __u6_addr.__u6_addr16 + +#endif + + + + + +#ifndef IPPROTO_COMP + +# define IPPROTO_COMP 108 + +#endif /* !IPPROTO_COMP */ + + + +#ifndef IPPROTO_INT + +# define IPPROTO_INT 61 + +#endif /* !IPPROTO_INT */ + + + +#if !defined(ESPINUDP_WITH_NON_IKE) + +#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 */ + +#if !defined(s6_addr16) && defined(__CYGWIN32__) + +struct in6_addr { + + union + + { + + u_int8_t u6_addr8[16]; + + u_int16_t u6_addr16[8]; + + u_int32_t 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; + + + +/* Translation to/from nfmark. + + * + + * use bits 16-31. Leave bit 32 as a indicate that IPsec processing + + * has already been done. + + */ + +#define IPSEC_SA_REF_TABLE_IDX_WIDTH 15 + +#define IPSEC_SA_REF_TABLE_OFFSET 16 + +#define IPSEC_SA_REF_MAASK ((1<> IPSEC_SA_REF_TABLE_OFFSET)&IPSEC_SA_REF_MASK) + + + +#define IPSEC_SAREF_NULL ((IPsecSAref_t)0) + +#define IPSEC_SAREF_NA ((IPsecSAref_t)0xffff0001) + + + +/* 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 + + + + + +/* + + * function to log stuff from libraries that may be used in multiple + + * places. + + */ + +typedef int (*libreswan_keying_debug_func_t)(const char *message, ...); + + + + + + + +/* + + * 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 */ + + + +/* looks up names in DNS */ + +err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst); + + + +/* does not look up names in DNS */ + +err_t ttoaddr_num(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 unsigned 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 add_port(int af, ip_address *addr, unsigned short port); + +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 isvalidsubnet(const ip_subnet *a); + +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 unsigned 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 unsigned 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 + +); + + + + + + + +/* + + * 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, + + KDF_NATT = 13, + +}; + + + + + +/* + + * 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 /* _LIBRESWAN_H */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/ipcomp.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,58 @@ + +/* + + * IPCOMP zlib interface code. + + * Copyright (C) 2000 Svenning Soerensen + + * Copyright (C) 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 . + + * + + * 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.14 2004/07/10 19:08:41 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 */ + + + +#include "libreswan/ipsec_sysctl.h" + + + +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; + + + +#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/libreswan/ipsec_ah.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,201 @@ + +/* + + * 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 . + + * + + * 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.26 2004/09/13 02:22:10 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__ + + + +#ifndef CONFIG_XFRM_ALTERNATE_STACK + +extern struct inet_protocol ah_protocol; + +#endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + + +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[]; + + + +#include "libreswan/ipsec_sysctl.h" + + + +#endif /* __KERNEL__ */ + + + +/* + + * $Log: ipsec_ah.h,v $ + + * Revision 1.26 2004/09/13 02:22:10 mcr + + * #define inet_protocol if necessary. + + * + + * Revision 1.25 2004/09/06 18:35:41 mcr + + * 2.6.8.1 gets rid of inet_protocol->net_protocol compatibility, + + * so adjust for that. + + * + + * Revision 1.24 2004/07/10 19:08:41 mcr + + * CONFIG_IPSEC -> CONFIG_KLIPS. + + * + + * 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/libreswan/ipsec_alg.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,248 @@ + +/* + + * Modular extensions service and registration functions interface + + * + + * Author: JuanJo Ciarlante + + * + + * 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 . + + * + + * 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 + +#include + +#include + +#include + + + +/* + + * 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 + + * + + ***************************************************************/ + + + +#define ixt_alg_type ixt_support.ias_exttype + +#define ixt_alg_id ixt_support.ias_id + + + +#define IPSEC_ALG_ST_SUPP 0x01 + +#define IPSEC_ALG_ST_REGISTERED 0x02 + +#define IPSEC_ALG_ST_EXCL 0x04 + +struct ipsec_alg { + + 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 */ \ + + + + struct ipsec_alg_supported ixt_support; + +}; + +/* + + * 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 { + + struct ipsec_alg ixt_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 { + + struct ipsec_alg ixt_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/libreswan/ipsec_alg_3des.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,12 @@ + +struct TripleDES_context { + + des_key_schedule s1; + + des_key_schedule s2; + + des_key_schedule s3; + +}; + +typedef struct TripleDES_context TripleDES_context; + + + +#define ESP_3DES_KEY_SZ 3*(sizeof(des_cblock)) + +#define ESP_3DES_CBC_BLK_LEN 8 + + + + + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/ipsec_auth.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,100 @@ + +/* + + * Authentication Header declarations + + * Copyright (C) 2003 Michael Richardson + + * + + * 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 . + + * + + * 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/libreswan/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 . + + * + + * 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/libreswan/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 + + * Copyright (C) 2001 Michael Richardson + + * + + * 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 . + + * + + * 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/libreswan/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 + + * and Michael Richardson + + * + + * 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 . + + * + + * 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/libreswan/ipsec_esp.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,159 @@ + +/* + + * 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 . + + * + + * 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.28 2004/09/13 02:22:10 mcr Exp $ + + */ + + + +#include "libreswan/ipsec_md5h.h" + +#include "libreswan/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; + +}; + + + +#ifndef CONFIG_XFRM_ALTERNATE_STACK + +extern struct inet_protocol esp_protocol; + +#endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + + +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_KLIPS_DEBUG + +extern int debug_esp; + +#endif /* CONFIG_KLIPS_DEBUG */ + +#endif /* __KERNEL__ */ + + + +/* + + * $Log: ipsec_esp.h,v $ + + * Revision 1.28 2004/09/13 02:22:10 mcr + + * #define inet_protocol if necessary. + + * + + * Revision 1.27 2004/09/06 18:35:41 mcr + + * 2.6.8.1 gets rid of inet_protocol->net_protocol compatibility, + + * so adjust for that. + + * + + * Revision 1.26 2004/07/10 19:08:41 mcr + + * CONFIG_IPSEC -> CONFIG_KLIPS. + + * + + * 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/libreswan/ipsec_ipcomp.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,97 @@ + +/* + + * IP compression header declations + + * + + * Copyright (C) 2003 Michael Richardson + + * + + * 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 . + + * + + * 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.4 2004/07/10 19:08:41 mcr Exp $ + + */ + + + +#ifndef IPSEC_IPCOMP_H + +#define IPSEC_IPCOMP_H + + + +#include "libreswan/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_KLIPS_DEBUG + +extern int sysctl_ipsec_debug_ipcomp; + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +struct ipcomphdr { /* IPCOMP header */ + + __u8 ipcomp_nh; /* Next header (protocol) */ + + __u8 ipcomp_flags; /* Reserved, must be 0 */ + + __u16 ipcomp_cpi; /* Compression Parameter Index */ + +}; + + + +#ifndef CONFIG_XFRM_ALTERNATE_STACK + +extern struct inet_protocol comp_protocol; + +#endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + + +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.4 2004/07/10 19:08:41 mcr + + * CONFIG_IPSEC -> CONFIG_KLIPS. + + * + + * 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/libreswan/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 . + + * + + * 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/libreswan/ipsec_ipip.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,45 @@ + +/* + + * Copyright (C) 2003 Michael Richardson + + * + + * 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 . + + * + + * 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/libreswan/ipsec_kern24.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,152 @@ + +/* + + * @(#) routines to makes kernel 2.4 compatible with 2.6 usage. + + * + + * Copyright (C) 2004 Michael Richardson + + * + + * 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 . + + * + + * 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_kern24.h,v 1.5 2005/08/05 08:48:38 mcr Exp $ + + */ + + + +#ifndef _IPSEC_KERN24_H + + + +#ifdef NET_21 + +# include + +#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 + +#if 0 + +#ifndef NETDEV_25 + +#define device net_device + +#endif + +#endif + +# 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 + + /* 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 + + + +#ifndef NET_26 + +#define sk_receive_queue receive_queue + +#define sk_destruct destruct + +#define sk_reuse reuse + +#define sk_zapped zapped + +#define sk_family family + +#define sk_protocol protocol + +#define sk_protinfo protinfo + +#define sk_sleep sleep + +#define sk_state_change state_change + +#define sk_shutdown shutdown + +#define sk_err err + +#define sk_stamp stamp + +#define sk_socket socket + +#define sk_sndbuf sndbuf + +#define sock_flag(sk, flag) sk->dead + +#define sk_for_each(sk, node, plist) for(sk=*plist; sk!=NULL; sk = sk->next) + +#endif + + + +/* deal with 2.4 vs 2.6 issues with module counts */ + + + +/* in 2.6, all refcounts are maintained *outside* of the + + * module to deal with race conditions. + + */ + + + +#ifdef NET_26 + +#define KLIPS_INC_USE /* nothing */ + +#define KLIPS_DEC_USE /* nothing */ + + + +#else + +#define KLIPS_INC_USE MOD_INC_USE_COUNT + +#define KLIPS_DEC_USE MOD_DEC_USE_COUNT + +#endif + + + +extern int printk_ratelimit(void); + + + + + +#define _IPSEC_KERN24_H 1 + + + +#endif /* _IPSEC_KERN24_H */ + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/ipsec_kversion.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,241 @@ + +#ifndef _LIBRESWAN_KVERSIONS_H + +/* + + * header file for Libreswan library functions + + * Copyright (C) 1998, 1999, 2000 Henry Spencer. + + * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs + + * Copyright (C) 2003 - 2008 Paul Wouters + + * + + * 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 . + + * + + * 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. + + * + + */ + +#define _LIBRESWAN_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 + +#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 + +#error "KLIPS is no longer supported on Linux 2.0. Sorry" + +#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 + +#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) + +# if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) && defined(CONFIG_NETFILTER)) + +# define SKB_RESET_NFCT + +# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + +# if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + +# define SKB_RESET_NFCT + +# endif + +# endif + +#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 + +#define NET_26 + +#define NETDEV_25 + +#endif + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8) + +#define NEED_INET_PROTOCOL + +#endif + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) + +#define HAVE_SOCK_ZAPPED + +#define NET_26_12_SKALLOC + +#endif + + + +/* see */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + +#define HAVE_SOCK_SECURITY + +/* skb->nf_debug disappared completely in 2.6.13 */ + +#define HAVE_SKB_NF_DEBUG + +#endif + + + +/* skb->stamp changed to skb->tstamp in 2.6.14 */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) + +#define HAVE_TSTAMP + +#define HAVE_INET_SK_SPORT + +#else + +#define HAVE_SKB_LIST + +#endif + + + +#define SYSCTL_IPSEC_DEFAULT_TTL sysctl_ip_default_ttl + +/* it seems 2.6.14 accidentally removed sysctl_ip_default_ttl */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) + +#undef SYSCTL_IPSEC_DEFAULT_TTL + +#define SYSCTL_IPSEC_DEFAULT_TTL IPSEC_DEFAULT_TTL + +#endif + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + +#define HAVE_NEW_SKB_LINEARIZE + +#endif + + + +/* this is the best we can do to detect XEN, which makes + + * patches to linux/skbuff.h, making it look like 2.6.18 version + + */ + +#ifdef CONFIG_XEN + +# HAVE_NEW_SKB_LINEARIZE + +#endif + + + +/* And the same for SuSe kernels who have it before it got into the + + * linus kernel. + + */ + +#ifdef SLE_VERSION_CODE + +# if SLE_VERSION_CODE >= 655616 + +# define HAVE_NEW_SKB_LINEARIZE + +# else + +# warning "A Suse kernel was detected, but we are unsure if it requires HAVE_NEW_SKB_LINEARIZE" + +# endif + +#endif + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) + +#define VOID_SOCK_UNREGISTER + +#endif + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + +/* skb->nfmark changed to skb->mark in 2.6.20 */ + +#define nfmark mark + +#endif + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + +#define ipsec_register_sysctl_table(a,b) register_sysctl_table(a) + +#define CTL_TABLE_PARENT + +#else + +#define ipsec_register_sysctl_table(a,b) register_sysctl_table(a,b) + +#endif + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + +/* need to include ip.h early, no longer pick it up in skbuff.h */ + +#include + +# define HAVE_KERNEL_TSTAMP + +# define HAVE_KMEM_CACHE_MACRO + +/* type of sock.sk_stamp changed from timeval to ktime */ + +# define grab_socket_timeval(tv, sock) { (tv) = ktime_to_timeval((sock).sk_stamp); } + +#else + +# define grab_socket_timeval(tv, sock) { (tv) = (sock).sk_stamp; } + +/* internals of struct skbuff changed */ + +# define HAVE_DEV_NEXT + +# define ip_hdr(skb) ((skb)->nh.iph) + +# define skb_tail_pointer(skb) ((skb)->tail) + +# define skb_end_pointer(skb) ((skb)->end) + +# define skb_network_header(skb) ((skb)->nh.raw) + +# define skb_set_network_header(skb,off) ((skb)->nh.raw = (skb)->data + (off)) + +# define tcp_hdr(skb) ((skb)->h.th) + +# define udp_hdr(skb) ((skb)->h.uh) + +# define skb_transport_header(skb) ((skb)->h.raw) + +# define skb_set_transport_header(skb,off) ((skb)->h.raw = (skb)->data + (off)) + +# define skb_mac_header(skb) ((skb)->mac.raw) + +# define skb_set_mac_header(skb,off) ((skb)->mac.raw = (skb)->data + (off)) + +#endif + +/* turn a pointer into an offset for above macros */ + +#define ipsec_skb_offset(skb, ptr) (((unsigned char *)(ptr)) - (skb)->data) + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + +/* Try using the new kernel encaps hook for nat-t, instead of udp.c */ + +#ifdef NOT_YET_FINISHED + +# define HAVE_UDP_ENCAP_CONVERT + +# endif + +#endif + + + +#ifdef NET_21 + +# include + +#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 + + + +#if __KERNEL__ + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + +#include "libreswan/ipsec_kern24.h" + +#else + +#error "kernels before 2.4 are not supported at this time" + +#endif + +#endif + +#endif + + + +#endif /* _LIBRESWAN_KVERSIONS_H */ + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/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 + + * and Michael Richardson + + * + + * 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 . + + * + + * 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/libreswan/ipsec_mast.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,59 @@ + +#ifndef _IPSEC_MAST_H + +#define _IPSEC_MAST_H + + + +#ifdef CONFIG_KLIPS_DEBUG + +#define DB_MAST_INIT 0x0001 + +#define DB_MAST_PROCFS 0x0002 + +#define DB_MAST_XMIT 0x0010 + +#define DB_MAST_OHDR 0x0020 + +#define DB_MAST_CROUT 0x0040 + +#define DB_MAST_OXFS 0x0080 + +#define DB_MAST_REVEC 0x0100 + +#define DB_MAST_ENCAP 0x0200 + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +struct ipsecmastconf { + + __u32 cf_cmd; + + union + + { + + char cfu_name[12]; + + } cf_u; + +#define cf_name cf_u.cfu_name + +}; + + + +struct mastpriv + +{ + + struct sk_buff_head sendq; + + struct wait_queue *wait_queue; + + int (*hard_header) (struct sk_buff *skb, + + struct net_device *dev, + + unsigned short type, + + void *daddr, + + void *saddr, + + unsigned len); + +#if 0 + + char locked; + + int (*hard_start_xmit) (struct sk_buff *skb, + + struct net_device *dev); + + int (*rebuild_header)(struct sk_buff *skb); + + int (*set_mac_address)(struct net_device *dev, void *addr); + + void (*header_cache_bind)(struct hh_cache **hhp, struct net_device *dev, + + unsigned short htype, __u32 daddr); + + void (*header_cache_update)(struct hh_cache *hh, + + struct net_device *dev, + + unsigned char * haddr); + + struct net_device_stats *(*get_stats)(struct net_device *dev); + +#endif + + struct net_device_stats mystats; + + int mtu; /* What is the desired MTU? */ + +}; + + + +extern int ipsec_mast_init_devices(void); + +extern int ipsec_mast_deletenum(int vifnum); + +extern int ipsec_mast_createnum(int vifnum); + +extern struct net_device *ipsec_mast_get_device(int vifnum); + +extern unsigned int ipsec_mast_is_transport(int vifnum); + + + + + + + +#endif + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/ipsec_md5h.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,143 @@ + +/* + + * RCSID $Id: ipsec_md5h.h,v 1.10 2004/09/08 17:21:35 ken 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 osMD5Init PROTO_LIST ((void *)); + +void osMD5Update PROTO_LIST + + ((void *, unsigned char *, __u32)); + +void osMD5Final PROTO_LIST ((unsigned char [16], void *)); + + + +#endif /* _IPSEC_MD5H_H_ */ + + + +/* + + * $Log: ipsec_md5h.h,v $ + + * Revision 1.10 2004/09/08 17:21:35 ken + + * Rename MD5* -> osMD5 functions to prevent clashes with other symbols exported by kernel modules (CIFS in 2.6 initiated this) + + * + + * 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/libreswan/ipsec_param.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,268 @@ + +/* + + * @(#) Libreswan tunable paramaters + + * + + * Copyright (C) 2001 Richard Guy Briggs + + * and Michael Richardson + + * Copyright (C) 2004 Michael Richardson + + * + + * 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 . + + * + + * 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. + + * + + * + + */ + + + +/* + + * 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 "libreswan/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. */ + +#ifdef CONFIG_KLIPS_IF_MAX + +#define IPSEC_NUM_IFMAX CONFIG_KLIPS_IF_MAX + +#endif + +#ifndef IPSEC_NUM_IFMAX + +#define IPSEC_NUM_IFMAX 64 + +#endif + + + +/* default number of ipsecX devices to create */ + +#define IPSEC_NUM_IF 2 + + + +/* 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" + +#define MAST_DEV_FORMAT "mast%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_KLIPS_DYNDEV + +#define CONFIG_KLIPS_DYNDEV 1 + +#endif /* CONFIG_KLIPS_DYNDEV */ + + + + + +#ifdef CONFIG_KLIPS_BIGGATE + +# define SADB_HASHMOD 8069 + +#else /* CONFIG_KLIPS_BIGGATE */ + +# define SADB_HASHMOD 257 + +#endif /* CONFIG_KLIPS_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_IDX_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_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 + + + +/* always turn on IPIP mode */ + +#ifndef CONFIG_KLIPS_IPIP + +#define CONFIG_KLIPS_IPIP 1 + +#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 /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *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_KLIPS_REGRESS + + + +/* + + * should pfkey_acquire() become 100% lossy? + + * + + */ + +extern int sysctl_ipsec_regress_pfkey_lossage; + +#ifndef KLIPS_PFKEY_ACQUIRE_LOSSAGE + +# ifdef CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE + +# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 100 + +# else /* CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE */ + +/* not by default! */ + +# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0 + +# endif /* CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE */ + +#endif /* KLIPS_PFKEY_ACQUIRE_LOSSAGE */ + + + +#endif /* CONFIG_KLIPS_REGRESS */ + + + + + +/* + + * debugging routines. + + */ + +#ifdef CONFIG_KLIPS_DEBUG + + #define KLIPS_ERROR(flag, format, args...) if(printk_ratelimit() || flag) printk(KERN_ERR "KLIPS " format, ## args) + + #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) + + #define KLIPS_SATOT(flag, sa, format, dst, dstlen) \ + + ((flag) ? satot(sa, format, dst, dstlen) : 0) + +#else /* CONFIG_KLIPS_DEBUG */ + + #define KLIPS_ERROR(flag, format, args...) if(printk_ratelimit()) printk(KERN_ERR "KLIPS " format, ## args) + + #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) + + #define KLIPS_SATOT(flag, sa, format, dst, dstlen) (0) + +#endif /* CONFIG_KLIPS_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__ */ + + + +#ifdef NEED_INET_PROTOCOL + +#define inet_protocol net_protocol + +#endif + + + +#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && CONFIG_IPSEC_NAT_TRAVERSAL + +#define NAT_TRAVERSAL 1 + +#else + +/* let people either #undef, or #define = 0 it */ + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + +#undef CONFIG_IPSEC_NAT_TRAVERSAL + +#endif + +#endif + + + +#ifndef IPSEC_DEFAULT_TTL + +#define IPSEC_DEFAULT_TTL 64 + +#endif + + + +#define _IPSEC_PARAM_H_ + +#endif /* _IPSEC_PARAM_H_ */ + + + +/* + + * Local variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/ipsec_policy.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,217 @@ + +#ifndef _IPSEC_POLICY_H + +/* + + * policy interface file between pluto and applications + + * Copyright (C) 2003 Michael Richardson + + * + + * 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 . + + * + + * 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.8 2005/07/26 01:12:38 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, /* 128 bit AES */ + +}; + + + +/* 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_LZJH= 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_int8_t proto; /* TCP, ICMP, etc. */ + + 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/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/libreswan/ipsec_proto.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,148 @@ + +/* + + * @(#) prototypes for FreeSWAN functions + + * + + * Copyright (C) 2001 Richard Guy Briggs + + * and Michael Richardson + + * + + * 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 . + + * + + * 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.14 2005/04/29 04:50:03 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. + + * + + */ + + + +/* forward references */ + +enum ipsec_direction; + +enum ipsec_life_type; + +struct ipsec_lifetime64; + +struct ident; + +struct sockaddr_encap; + +struct ipsec_sa; + + + +/* 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 int ipsec_sadb_cleanup(__u8); + + + +extern struct ipsec_sa *ipsec_sa_alloc(int*error); + + + + + +extern struct ipsec_sa *ipsec_sa_getbyid(ip_said *); + +extern int ipsec_sa_put(struct ipsec_sa *); + +extern /* void */ int ipsec_sa_add(struct ipsec_sa *); + + + +extern int ipsec_sa_init(struct ipsec_sa *ipsp); + +extern int ipsec_sa_wipe(struct ipsec_sa *ipsp); + + + +/* debug declarations */ + + + +/* ipsec_proc.c */ + +extern int ipsec_proc_init(void); + +extern void ipsec_proc_cleanup(void); + + + +/* ipsec_rcv.c */ + +extern int ipsec_rcv(struct sk_buff *skb); + +extern int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type); + + + +/* ipsec_xmit.c */ + +struct ipsec_xmit_state; + +extern enum ipsec_xmit_value ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs); + +extern enum ipsec_xmit_value ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs); + +extern void ipsec_print_ip(struct iphdr *ip); + + + + + + + +/* 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); + + + +/* ipsec_snprintf.c */ + +extern int ipsec_snprintf(char * buf, ssize_t size, const char *fmt, ...); + +extern void ipsec_dmp_block(char *s, caddr_t bb, int len); + + + + + +/* ipsec_alg.c */ + +extern int ipsec_alg_init(void); + + + + + +#ifdef CONFIG_KLIPS_DEBUG + + + +extern int debug_xform; + +extern int debug_eroute; + +extern int debug_spi; + +extern int debug_netlink; + + + +#endif /* CONFIG_KLIPS_DEBUG */ + + + + + + + + + +#define _IPSEC_PROTO_H + +#endif /* _IPSEC_PROTO_H_ */ + + + +/* + + * + + * Local variables: + + * c-file-style: "linux" + + * End: + + * + + */ + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/ipsec_radij.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,179 @@ + +/* + + * @(#) 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 . + + * + + * 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.22 2004/07/10 19:08:41 mcr Exp $ + + */ + + + +#ifndef _IPSEC_RADIJ_H + + + +#include + + + +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_KLIPS_DEBUG + +extern int debug_radij; + +void rj_dumptrees(void); + + + +#define DB_RJ_DUMPTREES 0x0001 + +#define DB_RJ_FINDROUTE 0x0002 + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +#define _IPSEC_RADIJ_H + +#endif + + + +/* + + * $Log: ipsec_radij.h,v $ + + * Revision 1.22 2004/07/10 19:08:41 mcr + + * CONFIG_IPSEC -> CONFIG_KLIPS. + + * + + * 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 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/libreswan/ipsec_rcv.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,157 @@ + +/* + + * + + * 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 . + + * + + * 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_RCV_H + +#define IPSEC_RCV_H + + + +#include "libreswan/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__ + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif /* for CONFIG_IP_FORWARD */ + +#ifdef CONFIG_MODULES + +#include + +#endif + +#include + +#include + + + +#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; /* the IP header */ + + struct ipsec_sa *ipsp; /* current SA being processed */ + + int len; /* length of packet */ + + int ilen; /* length of inner payload (-authlen) */ + + int authlen; /* how big is the auth data at end */ + + int hard_header_len; /* layer 2 size */ + + int iphlen; /* how big is IP header */ + + unsigned int transport_direct:1; + + 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, + + unsigned short xlen); + +#endif /* PROTO_HANDLER_SINGLE_PARM */ + + + +#ifdef CONFIG_KLIPS_DEBUG + +extern int debug_rcv; + +#define ipsec_rcv_dmp(_x,_y, _z) if (debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z) + +#else + +#define ipsec_rcv_dmp(_x,_y, _z) do {} while(0) + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +extern int sysctl_ipsec_inbound_policy_check; + +#endif /* __KERNEL__ */ + + + +extern int klips26_udp_encap_rcv(struct sock *sk, struct sk_buff *skb); + +extern int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type); + + + +// manage ipsec rcv state objects + +extern int ipsec_rcv_state_cache_init (void); + +extern void ipsec_rcv_state_cache_cleanup (void); + + + +#endif /* IPSEC_RCV_H */ + + + +/* + + * Local Variables: + + * c-basic-offset:8 + + * c-style:linux + + * End: + + * + + */ + + + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/ipsec_sa.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,274 @@ + +/* + + * @(#) Definitions of IPsec Security Association (ipsec_sa) + + * + + * Copyright (C) 2001, 2002, 2003 + + * Richard Guy Briggs + + * and Michael Richardson + + * + + * 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 . + + * + + * 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.23.2.1 2007/09/05 02:31:15 paul 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 "libreswan/ipsec_stats.h" + +#include "libreswan/ipsec_life.h" + +#include "libreswan/ipsec_eroute.h" + +#endif /* __KERNEL__ */ + +#include "libreswan/ipsec_param.h" + + + +#include "libreswan/pfkeyv2.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_MAX (~IPSEC_SAREF_NULL) + +#define IPSEC_SAREF_FIRST 1 + +#define IPSEC_SA_REF_MASK (IPSEC_SA_REF_MAX >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) + +#define IPSEC_SA_REF_TABLE_MASK ((IPSEC_SA_REF_MAX >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) + +#define IPSEC_SA_REF_ENTRY_MASK (IPSEC_SA_REF_MAX >> (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 + +{ + + atomic_t ips_refcount; /* reference count for this struct */ + + int ips_marked_deleted; /* used with reference counting */ + + IPsecSAref_t ips_ref; /* reference table entry number */ + + IPsecSAref_t ips_refhim; /* ref of paired SA, if any */ + + struct ipsec_sa *ips_next; /* pointer to next xform */ + + + + struct ipsec_sa *ips_hnext; /* next in hash chain */ + + + + struct ifnet *ips_rcvif; /* related rcv encap interface */ + + + + struct xform_functions *ips_xformfuncs; /* pointer to routines to process this SA */ + + + + struct net_device *ips_out; /* what interface to emerge on */ + + __u8 ips_transport_direct; /* if true, punt directly to + + * the protocol layer */ + + struct socket *ips_sock; /* cache of transport socket */ + + + + 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 */ + + enum sadb_sastate 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 */ + + + + /* these are included even if CONFIG_KLIPS_IPCOMP is off */ + + __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 */ + + + + /* these are included even if CONFIG_IPSEC_NAT_TRAVERSAL is off */ + + __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; + + + +#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; + +}; + + + +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); + + + +#define ipsec_sa_get(ips) __ipsec_sa_get(ips, __FUNCTION__, __LINE__) + +extern int __ipsec_sa_get(struct ipsec_sa *ips, const char *func, int line); + +extern int ipsec_sa_put(struct ipsec_sa *ips); + +extern int ipsec_sa_add(struct ipsec_sa *ips); + +extern void ipsec_sa_rm(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); + +extern int ipsec_sa_intern(struct ipsec_sa *ips); + +extern struct ipsec_sa *ipsec_sa_getbyref(IPsecSAref_t ref); + + + +#endif /* __KERNEL__ */ + + + +enum ipsec_direction { + + ipsec_incoming = 1, + + ipsec_outgoing = 2 + +}; + + + +#define _IPSEC_SA_H_ + +#endif /* _IPSEC_SA_H_ */ + + + +/* + + * Local variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/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 + +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/libreswan/ipsec_stats.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,76 @@ + +/* + + * @(#) definition of ipsec_stats structure + + * + + * Copyright (C) 2001 Richard Guy Briggs + + * and Michael Richardson + + * + + * 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 . + + * + + * 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.7 2005/04/14 01:17:45 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 */ + +}; + + + +#define _IPSEC_STATS_H_ + +#endif /* _IPSEC_STATS_H_ */ + + + +/* + + * $Log: ipsec_stats.h,v $ + + * Revision 1.7 2005/04/14 01:17:45 mcr + + * add prototypes for snprintf. + + * + + * 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 libreswan + + * + + * 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/libreswan/ipsec_sysctl.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,20 @@ + +#ifndef LIBRESWAN_SYSCTL_H + +#define LIBRESWAN_SYSCTL_H + + + +extern int debug_ah; + +extern int debug_esp; + +extern int debug_xform; + +extern int debug_eroute; + +extern int debug_spi; + +extern int debug_netlink; + +extern int debug_radij; + +extern int debug_rcv; + +extern int debug_tunnel; + +extern int debug_xmit; + +extern int debug_mast; + + + +extern int sysctl_ip_default_ttl; + +extern int sysctl_ipsec_inbound_policy_check; + +extern int sysctl_ipsec_debug_ipcomp; + +extern int sysctl_ipsec_debug_verbose; + +#endif + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/ipsec_tunnel.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,280 @@ + +/* + + * IPSEC tunneling code + + * Copyright (C) 1996, 1997 John Ioannidis. + + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. + + * Copyright (C) 2006 Michael Richardson + + * + + * 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 . + + * + + * 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.33 2005/06/04 16:06:05 mcr Exp $ + + */ + + + + + +# 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); + + + + + +#if defined(KLIPS) + +/* + + * 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 + +{ + + uint32_t 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) + +#define IPSEC_UDP_ENCAP_CONVERT (SIOCDEVPRIVATE + 3) + +#endif + + + +#ifdef __KERNEL__ + +#include + +#ifndef KERNEL_VERSION + +# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) + +#endif + +struct ipsecpriv + +{ + + struct sk_buff_head sendq; + + struct net_device *dev; + + struct wait_queue *wait_queue; + + int vifnum; + + char locked; + + int (*hard_start_xmit) (struct sk_buff *skb, + + struct net_device *dev); + + int (*hard_header) (struct sk_buff *skb, + + struct net_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 net_device *dev, + + unsigned long raddr, struct sk_buff *skb); + +#endif /* NET_21 */ + + int (*set_mac_address)(struct net_device *dev, void *addr); + +#ifndef NET_21 + + void (*header_cache_bind)(struct hh_cache **hhp, struct net_device *dev, + + unsigned short htype, __u32 daddr); + +#endif /* !NET_21 */ + + void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr); + + struct net_device_stats *(*get_stats)(struct net_device *dev); + + struct net_device_stats mystats; + + int mtu; /* What is the desired MTU? */ + +}; + + + +extern char ipsec_tunnel_c_version[]; + + + +extern struct net_device *ipsecdevices[IPSEC_NUM_IFMAX]; + +extern int ipsecdevices_max; + + + +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 net_device *dev); + +extern struct net_device *ipsec_get_device(int inst); + + + +#ifdef CONFIG_KLIPS_DEBUG + +extern int debug_tunnel; + +extern int sysctl_ipsec_debug_verbose; + +#endif /* CONFIG_KLIPS_DEBUG */ + +#endif /* __KERNEL__ */ + + + +#ifdef CONFIG_KLIPS_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 + +#define DB_TN_ENCAP 0x0200 + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +extern int ipsec_tunnel_deletenum(int vifnum); + +extern int ipsec_tunnel_createnum(int vifnum); + +extern struct net_device *ipsec_tunnel_get_device(int vifnum); + + + + + +/* manage ipsec xmit state objects */ + +extern int ipsec_xmit_state_cache_init (void); + +extern void ipsec_xmit_state_cache_cleanup (void); + + + +/* + + * $Log: ipsec_tunnel.h,v $ + + * Revision 1.33 2005/06/04 16:06:05 mcr + + * better patch for nat-t rcv-device code. + + * + + * Revision 1.32 2005/05/21 03:18:35 mcr + + * added additional debug flag tunnelling. + + * + + * Revision 1.31 2004/08/03 18:18:02 mcr + + * in 2.6, use "net_device" instead of #define device->net_device. + + * this probably breaks 2.0 compiles. + + * + + * Revision 1.30 2004/07/10 19:08:41 mcr + + * CONFIG_IPSEC -> CONFIG_KLIPS. + + * + + * 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 + + * 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 . + + * + + * 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/libreswan/ipsec_xform.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,264 @@ + +/* + + * 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 + + * + + * 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 . + + * + + * 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.42 2005/08/05 08:50:45 mcr Exp $ + + */ + + + +#ifndef _IPSEC_XFORM_H_ + + + +#include + + + +#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_LZJH 4 + + + +#define XFT_AUTH 0x0001 + +#define XFT_CONF 0x0100 + + + +/* available if CONFIG_KLIPS_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__ + +#include + + + +struct ipsec_rcv_state; + +struct ipsec_xmit_state; + + + +struct xform_functions { + + u8 protocol; + + 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_KLIPS_DEBUG + +extern void ipsec_dmp(char *s, caddr_t bb, int len); + +#else /* CONFIG_KLIPS_DEBUG */ + +#define ipsec_dmp(_x, _y, _z) + +#endif /* CONFIG_KLIPS_DEBUG */ + + + + + +#define _IPSEC_XFORM_H_ + +#endif /* _IPSEC_XFORM_H_ */ + + + +/* + + * $Log: ipsec_xform.h,v $ + + * Revision 1.42 2005/08/05 08:50:45 mcr + + * move #include of skbuff.h to a place where + + * we know it will be kernel only code. + + * + + * Revision 1.41 2004/07/10 19:08:41 mcr + + * CONFIG_IPSEC -> CONFIG_KLIPS. + + * + + * 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/libreswan/ipsec_xmit.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,211 @@ + +/* + + * 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 . + + * + + * 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.14 2005/05/11 01:00:26 mcr Exp $ + + */ + + + +#include "libreswan/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 net_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; /* ipsec_sa pointers */ + + //struct ipsec_sa *ipsp_outer; /* last SA applied by encap_bundle */ + + 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 net_device *physdev; + +/* struct device *virtdev; */ + + short physmtu; + + short cur_mtu; /* copy of prv->mtu, cause prv may == NULL */ + + short mtudiff; + +#ifdef NET_21 + + struct rtable *route; + +#endif /* NET_21 */ + + ip_said outgoing_said; + +#ifdef NET_21 + + int pass; + +#endif /* NET_21 */ + + 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); + + + +enum ipsec_xmit_value + +ipsec_xmit_encap_bundle_2(struct ipsec_xmit_state *ixs); + + + +extern void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er); + + + +extern enum ipsec_xmit_value + +ipsec_xmit_send(struct ipsec_xmit_state*ixs, struct flowi *fl); + + + +extern enum ipsec_xmit_value + +ipsec_nat_encap(struct ipsec_xmit_state*ixs); + + + +extern enum ipsec_xmit_value + +ipsec_tunnel_send(struct ipsec_xmit_state *ixs); + + + +extern void ipsec_xmit_cleanup(struct ipsec_xmit_state*ixs); + + + + + +extern int ipsec_xmit_trap_count; + +extern int ipsec_xmit_trap_sendcount; + + + +#ifdef CONFIG_KLIPS_DEBUG + +extern int debug_xmit; + +extern int debug_mast; + + + +#define ipsec_xmit_dmp(_x,_y, _z) if (debug_xmit && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z) + +#else + +#define ipsec_xmit_dmp(_x,_y, _z) do {} while(0) + + + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +extern int sysctl_ipsec_debug_verbose; + +extern int sysctl_ipsec_icmp; + +extern int sysctl_ipsec_tos; + + + + + +/* + + * $Log: ipsec_xmit.h,v $ + + * Revision 1.14 2005/05/11 01:00:26 mcr + + * do not call debug routines if !defined KLIPS_DEBUG. + + * + + * Revision 1.13 2005/04/29 05:01:38 mcr + + * use ipsec_dmp_block. + + * added cur_mtu to ixs instead of using ixs->dev. + + * + + * Revision 1.12 2004/08/20 21:45:37 mcr + + * CONFIG_KLIPS_NAT_TRAVERSAL is not used in an attempt to + + * be 26sec compatible. But, some defines where changed. + + * + + * Revision 1.11 2004/08/03 18:18:21 mcr + + * in 2.6, use "net_device" instead of #define device->net_device. + + * this probably breaks 2.0 compiles. + + * + + * Revision 1.10 2004/07/10 19:08:41 mcr + + * CONFIG_IPSEC -> CONFIG_KLIPS. + + * + + * 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/libreswan/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/libreswan/passert.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,75 @@ + +/* + + * sanitize a string into a printable format. + + * + + * Copyright (C) 1998-2002 D. Hugh Redelmeier. + + * Copyright (C) 2003 Michael Richardson + + * + + * 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 . + + * + + * 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.7.8.1 2007/09/05 02:32:24 paul Exp $ + + */ + + + +#include "libreswan.h" + + + +#ifndef _LIBRESWAN_PASSERT_H + +#define _LIBRESWAN_PASSERT_H + +/* our versions of assert: log result */ + + + +#ifdef DEBUG + + + +typedef void (*libreswan_passert_fail_t)(const char *pred_str, + + const char *file_str, + + unsigned long line_no) NEVER_RETURNS; + + + +extern libreswan_passert_fail_t libreswan_passert_fail; + + + +extern void pexpect_log(const char *pred_str + + , const char *file_str, unsigned long line_no); + + + +# define impossible() do { \ + + if(libreswan_passert_fail) { \ + + (*libreswan_passert_fail)("impossible", __FILE__, __LINE__); \ + + }} while(0) + + + +extern void libreswan_switch_fail(int n + + , const char *file_str, unsigned long line_no) NEVER_RETURNS; + + + +# define bad_case(n) libreswan_switch_fail((int) n, __FILE__, __LINE__) + + + +# define passert(pred) do { \ + + if (!(pred)) \ + + if(libreswan_passert_fail) { \ + + (*libreswan_passert_fail)(#pred, __FILE__, __LINE__); \ + + } \ + + } while(0) + + + +# define pexpect(pred) do { \ + + if (!(pred)) \ + + pexpect_log(#pred, __FILE__, __LINE__); \ + + } while(0) + + + +/* assert that an err_t is NULL; evaluate exactly once */ + +# define happy(x) { \ + + err_t ugh = x; \ + + if (ugh != NULL) \ + + if(libreswan_passert_fail) { (*libreswan_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*/ + + + +#endif /* _LIBRESWAN_PASSERT_H */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/pfkey.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,383 @@ + +/* + + * Libreswan specific PF_KEY headers + + * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. + + * Copyright (C) 2006-2007 Michael Richardson + + * + + * 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 . + + * + + * 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.52 2005/11/09 00:30:37 mcr Exp $ + + */ + + + +#ifndef __NET_IPSEC_PF_KEY_H + +#define __NET_IPSEC_PF_KEY_H + + + +#include "pfkeyv2.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); + + + +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[]; + + + +struct ipsec_alg_supported + +{ + + uint16_t ias_exttype; + + uint8_t ias_id; + + uint8_t ias_ivlen; + + uint16_t ias_keyminbits; + + uint16_t ias_keymaxbits; + + char *ias_name; + +}; + + + +extern struct supported_list *pfkey_supported_list[]; + +struct supported_list + +{ + + struct ipsec_alg_supported *supportedp; + + struct supported_list *next; + +}; + +extern int pfkey_list_insert_supported(struct ipsec_alg_supported*, struct supported_list**); + +extern int pfkey_list_remove_supported(struct ipsec_alg_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; + + int outif; + + IPsecSAref_t sarefme; + + IPsecSAref_t sarefhim; + +}; + + + +/* forward reference */ + +struct sadb_ext; + +struct sadb_msg; + +struct sockaddr; + +struct sadb_comb; + +struct sadb_sadb; + +struct sadb_alg; + + + +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 libreswan_keying_debug_func_t pfkey_debug_func; + +extern libreswan_keying_debug_func_t pfkey_error_func; + +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)->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) (DIVUP(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; + +}; + + + +enum pfkey_ext_required { + + EXT_BITS_IN=0, + + EXT_BITS_OUT=1 + +}; + + + +enum pfkey_ext_perm { + + EXT_BITS_PERM=0, + + EXT_BITS_REQ=1 + +}; + + + + + +typedef uint64_t pfkey_ext_track; + +static inline void pfkey_mark_extension(enum sadb_extension_t exttype, + + pfkey_ext_track *exten_track) + +{ + + *exten_track |= (1 << exttype); + +} + + + +extern int pfkey_extensions_missing(enum pfkey_ext_required inout, + + enum sadb_msg_t sadb_operation, + + pfkey_ext_track extensions_seen); + +extern int pfkey_required_extension(enum pfkey_ext_required inout, + + enum sadb_msg_t sadb_operation, + + enum sadb_extension_t exttype); + +extern int pfkey_permitted_extension(enum pfkey_ext_required inout, + + enum sadb_msg_t sadb_operation, + + enum sadb_extension_t exttype); + + + + + +extern void pfkey_extensions_init(struct sadb_ext *extensions[]); + +extern void pfkey_extensions_free(struct sadb_ext *extensions[]); + +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); + + + +extern int + +pfkey_saref_build(struct sadb_ext **pfkey_ext, + + IPsecSAref_t in, IPsecSAref_t out); + + + +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, + + unsigned 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 __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); + + + +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); + + + +struct sadb_builds { + + struct k_sadb_sa sa_base; + +}; + + + +int + +pfkey_sa_builds(struct sadb_ext **pfkey_ext, + + struct sadb_builds sab); + + + +extern int + +pfkey_outif_build(struct sadb_ext **pfkey_ext, + + uint16_t outif); + + + +#endif /* __NET_IPSEC_PF_KEY_H */ + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/include/libreswan/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 + + * + + * 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 . + + * + + * 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 int (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); + +extern int (*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/libreswan/pfkeyv2.h Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,331 @@ + +/* + + * RCSID $Id: pfkeyv2.h,v 1.31 2005/04/14 01:14:54 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 + + + +#include + + + +#define PF_KEY_V2 2 + +#define PFKEYV2_REVISION 199806L + + + +enum sadb_msg_t { + + K_SADB_RESERVED=SADB_RESERVED, + + K_SADB_GETSPI=SADB_GETSPI, + + K_SADB_UPDATE=SADB_UPDATE, + + K_SADB_ADD=SADB_ADD, + + K_SADB_DELETE=SADB_DELETE, + + K_SADB_GET=SADB_GET, + + K_SADB_ACQUIRE=SADB_ACQUIRE, + + K_SADB_REGISTER=SADB_REGISTER, + + K_SADB_EXPIRE=SADB_EXPIRE, + + K_SADB_FLUSH=SADB_FLUSH, + + K_SADB_DUMP=SADB_DUMP, + + K_SADB_X_PROMISC=SADB_X_PROMISC, + + K_SADB_X_PCHANGE=SADB_X_PCHANGE, + + K_SADB_X_GRPSA=13, + + K_SADB_X_ADDFLOW=14, + + K_SADB_X_DELFLOW=15, + + K_SADB_X_DEBUG=16, + + K_SADB_X_NAT_T_NEW_MAPPING=17, + + K_SADB_X_PLUMBIF=18, + + K_SADB_X_UNPLUMBIF=19, + + K_SADB_MAX=19 + +}; + + + +#define SADB_X_GRPSA K_SADB_X_GRPSA + +#define SADB_X_ADDFLOW K_SADB_X_ADDFLOW + +#define SADB_X_DELFLOW K_SADB_X_DELFLOW + +#define SADB_X_DEBUG K_SADB_X_DEBUG + +#define SADB_X_PLUMBIF K_SADB_X_PLUMBIF + +#define SADB_X_UNPLUMBIF K_SADB_X_UNPLUMBIF + + + +struct k_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]; + +} __attribute__((packed)); + + + +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; + +} __attribute__((packed)); + + + +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]; + +} __attribute__((packed)); + + + +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]; + +} __attribute__((packed)); + + + +/* + + * a plumbif extension can appear in + + * - a plumbif message to create the interface. + + * - a unplumbif message to delete the interface. + + * - a sadb add/replace to indicate which interface + + * a decrypted packet should emerge on. + + * + + * the create/delete part could/should be replaced with netlink equivalents, + + * or better yet, FORCES versions of same. + + * + + */ + +struct sadb_x_plumbif { + + uint16_t sadb_x_outif_len; + + uint16_t sadb_x_outif_exttype; + + uint16_t sadb_x_outif_ifnum; + +} __attribute__((packed)); + + + +/* + + * the ifnum describes a device that you wish to create refer to. + + * + + * devices 0-40959 are mastXXX devices. + + * devices 40960-49141 are mastXXX devices with transport set. + + * devices 49152-65536 are deprecated ipsecXXX devices. + + */ + +#define IPSECDEV_OFFSET (48*1024) + +#define MASTTRANSPORT_OFFSET (40*1024) + + + +/* + + * an saref extension sets the SA's reference number, and + + * may also set the paired SA's reference number. + + * + + */ + +struct sadb_x_saref { + + uint16_t sadb_x_saref_len; + + uint16_t sadb_x_saref_exttype; + + uint32_t sadb_x_saref_me; + + uint32_t sadb_x_saref_him; + +} __attribute__((packed)); + + + +/* + + * 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; + +} __attribute__((packed)); + + + +/* + + * NOTE that there is a limit of 31 extensions due to current implementation + + * in pfkeyv2_ext_bits.c + + */ + +enum sadb_extension_t { + + K_SADB_EXT_RESERVED=SADB_RESERVED, + + K_SADB_EXT_SA= SADB_EXT_SA, + + K_SADB_EXT_LIFETIME_CURRENT=SADB_EXT_LIFETIME_CURRENT, + + K_SADB_EXT_LIFETIME_HARD= SADB_EXT_LIFETIME_HARD, + + K_SADB_EXT_LIFETIME_SOFT= SADB_EXT_LIFETIME_SOFT, + + K_SADB_EXT_ADDRESS_SRC= SADB_EXT_ADDRESS_SRC, + + K_SADB_EXT_ADDRESS_DST= SADB_EXT_ADDRESS_DST, + + K_SADB_EXT_ADDRESS_PROXY= SADB_EXT_ADDRESS_PROXY, + + K_SADB_EXT_KEY_AUTH= SADB_EXT_KEY_AUTH, + + K_SADB_EXT_KEY_ENCRYPT= SADB_EXT_KEY_ENCRYPT, + + K_SADB_EXT_IDENTITY_SRC= SADB_EXT_IDENTITY_SRC, + + K_SADB_EXT_IDENTITY_DST= SADB_EXT_IDENTITY_DST, + + K_SADB_EXT_SENSITIVITY= SADB_EXT_SENSITIVITY, + + K_SADB_EXT_PROPOSAL= SADB_EXT_PROPOSAL, + + K_SADB_EXT_SUPPORTED_AUTH= SADB_EXT_SUPPORTED_AUTH, + + K_SADB_EXT_SUPPORTED_ENCRYPT=SADB_EXT_SUPPORTED_ENCRYPT, + + K_SADB_EXT_SPIRANGE= SADB_EXT_SPIRANGE, + + K_SADB_X_EXT_KMPRIVATE= SADB_X_EXT_KMPRIVATE, + + K_SADB_X_EXT_SATYPE2= 18, + + K_SADB_X_EXT_POLICY= SADB_X_EXT_POLICY, + + K_SADB_X_EXT_SA2= SADB_X_EXT_SA2, + + K_SADB_X_EXT_ADDRESS_DST2= 20, + + K_SADB_X_EXT_ADDRESS_SRC_FLOW=21, + + K_SADB_X_EXT_ADDRESS_DST_FLOW=22, + + K_SADB_X_EXT_ADDRESS_SRC_MASK=23, + + K_SADB_X_EXT_ADDRESS_DST_MASK=24, + + K_SADB_X_EXT_DEBUG= 25, + + K_SADB_X_EXT_PROTOCOL= 26, + + K_SADB_X_EXT_NAT_T_TYPE= 27, + + K_SADB_X_EXT_NAT_T_SPORT= 28, + + K_SADB_X_EXT_NAT_T_DPORT= 29, + + K_SADB_X_EXT_NAT_T_OA= 30, + + K_SADB_X_EXT_PLUMBIF= 31, + + K_SADB_X_EXT_SAREF= 32, + + K_SADB_EXT_MAX= 32, + +}; + + + + + +#define SADB_X_EXT_SATYPE2 K_SADB_X_EXT_SATYPE2 + +#define SADB_X_EXT_ADDRESS_DST2 K_SADB_X_EXT_ADDRESS_DST2 + +#define SADB_X_EXT_ADDRESS_SRC_FLOW K_SADB_X_EXT_ADDRESS_SRC_FLOW + +#define SADB_X_EXT_ADDRESS_DST_FLOW K_SADB_X_EXT_ADDRESS_DST_FLOW + +#define SADB_X_EXT_ADDRESS_SRC_MASK K_SADB_X_EXT_ADDRESS_SRC_MASK + +#define SADB_X_EXT_ADDRESS_DST_MASK K_SADB_X_EXT_ADDRESS_DST_MASK + +#define SADB_X_EXT_DEBUG K_SADB_X_EXT_DEBUG + +#define SADB_X_EXT_PROTOCOL K_SADB_X_EXT_PROTOCOL + + + +#undef SADB_X_EXT_NAT_T_TYPE + +#undef SADB_X_EXT_NAT_T_SPORT + +#undef SADB_X_EXT_NAT_T_DPORT + +#undef SADB_X_EXT_NAT_T_OA + +#define SADB_X_EXT_PLUMBIF K_SADB_X_EXT_PLUMBIF + + + + + + + +/* K_SADB_X_DELFLOW required over and above K_SADB_X_SAFLAGS_CLEARFLOW */ + +#define K_SADB_X_EXT_ADDRESS_DELFLOW \ + + ( (1<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 . + + * + + * 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/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.4 2004/07/10 07:48:40 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 + +# 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 + +# 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 /* for off_t */ + +# include /* 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/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 + +#define HAVE_MEMCPY + + + +#if 0 // #ifdef STDC + +# include + +# include + +# include + +#endif + +#ifndef __KERNEL__ + +#ifdef NO_ERRNO_H + + extern int errno; + +#else + +# include + +#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 + +# endif + +# else /* MSC or DJGPP */ + +# include + +# 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 /* 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 + + 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 */ + --- swan26/net/Kconfig.preipsec 2005-09-01 18:15:19.000000000 -0400 + +++ swan26/net/Kconfig 2005-09-03 16:51:17.000000000 -0400 + @@ -215,2 +215,6 @@ + + +if INET + +source "net/ipsec/Kconfig" + +endif # if INET + + + endif # if NET + --- /distros/kernel/linux-2.6.3-rc4/net/Makefile Mon Feb 16 21:22:12 2004 + +++ ref26/net/Makefile Thu Feb 19 21:02:25 2004 + @@ -42,3 +42,6 @@ + ifeq ($(CONFIG_NET),y) + obj-$(CONFIG_SYSCTL) += sysctl_net.o + endif + + + +obj-$(CONFIG_KLIPS) += ipsec/ + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/Kconfig Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,161 @@ + +# + +# IPSEC configuration + +# Copyright (C) 2004 Michael Richardson + +# + +# 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 . + +# + +# 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: Kconfig,v 1.6.2.1 2006/04/20 16:33:06 mcr Exp $ + + + +config KLIPS + + tristate "Libreswan IPsec (KLIPS)" + + default n + + select NF_CONNTRACK && NETFILTER + + help + + KLIPS is the Libreswan (www.libreswan.org) Kernel Level IP Security + + system. It is extensively tested, and has interoperated with + + many other systems. + + It provides "ipsecX" devices on which one can do firewalling. + + The Libreswan userland, is compatible with both KLIPS and NETKEY + + You cannot build KLIPS and NETKEY inline into the kernel. + + + +menu "KLIPS options" + + depends on KLIPS + + + +config KLIPS_ESP + + bool 'Encapsulating Security Payload - ESP ("VPN")' + + default y + + help + + This option provides support for the IPSEC Encapsulation Security + + Payload (IP protocol 50) which provides packet layer content + + hiding, and content authentication. + + It is recommended to enable this. RFC2406 + + + +config KLIPS_AH + + bool 'Authentication Header - AH' + + default n + + help + + This option provides support for the IPSEC Authentication Header + + (IP protocol 51) which provides packet layer sender and content + + authentication. It does not provide for confidentiality. + + It is not recommended to enable this. RFC2402 + + + +config KLIPS_AUTH_HMAC_MD5 + + bool 'HMAC-MD5 authentication algorithm' + + default y + + help + + The HMAC-MD5 algorithm is used by ESP (and AH) to guarantee packet + + integrity. There is little reason not to include it. + + + +config KLIPS_AUTH_HMAC_SHA1 + + bool 'HMAC-SHA1 authentication algorithm' + + default y + + help + + The HMAC-SHA1 algorithm is used by ESP (and AH) to guarantee packet + + integrity. SHA1 is a little slower than MD5, but is said to be + + a bit more secure. There is little reason not to include it. + + + +config KLIPS_ENC_CRYPTOAPI + + bool 'CryptoAPI algorithm interface' + + default n + + help + + Enable the algorithm interface to make all CryptoAPI 1.0 algorithms + + available to KLIPS. + + + +config KLIPS_ENC_1DES + + bool 'Include 1DES with CryptoAPI' + + default n + + depends on KLIPS_ENC_CRYPTOAPI + + help + + The CryptoAPI interface does not include support for every algorithm + + yet, and one that it doesn't support by default is the VERY WEAK + + 1DES. Select this if you are terminally stupid. + + + +config KLIPS_ENC_3DES + + bool '3DES encryption algorithm' + + default y + + help + + The 3DES algorithm is used by ESP to provide for packet privacy. + + 3DES is 3-repeats of the DES algorithm. 3DES is widely supported, + + and analyzed and is considered very secure. 1DES is not supported. + + + +config KLIPS_ENC_AES + + bool 'AES encryption algorithm' + + default y + + help + + The AES algorithm is used by ESP to provide for packet privacy. + + AES the NIST replacement for DES. AES is being widely analyzed, + + and is very fast. + + + +config KLIPS_IPCOMP + + bool 'IP compression' + + default y + + help + + The IPcomp protocol is used prior to ESP to make the packet + + smaller. Once encrypted, compression will fail, so any link + + layer efforts (e.g. PPP) will not work. + + + +config KLIPS_DEBUG + + bool 'IPsec debugging' + + default y + + help + + KLIPS includes a lot of debugging code. Unless there is a real + + tangible benefit to removing this code, it should be left in place. + + Debugging connections without access to kernel level debugging is + + essentially impossible. Leave this on. + + + +config KLIPS_IF_MAX + + int 'Maximum number of virtual interfaces' + + default 64 + + range 4 256 + + help + + KLIPS creates virtual interfaces for tunnel purposes. At present + + it keeps track of certain items in an array (FIX ME), and needs + + to preallocate this array. Only a pointer is used per item. + + + +endmenu + + + +# + +# + +# $Log: Kconfig,v $ + +# Revision 1.6.2.1 2006/04/20 16:33:06 mcr + +# remove all of CONFIG_KLIPS_ALG --- one can no longer build without it. + +# Fix in-kernel module compilation. Sub-makefiles do not work. + +# + +# Revision 1.6 2005/05/18 20:55:27 mcr + +# default cryptoapi to n. + +# + +# Revision 1.5 2005/05/11 01:23:25 mcr + +# added 1DES option to cryptoapi. + +# + +# Revision 1.4 2005/04/29 05:29:54 mcr + +# add option to include cryptoapi algorithms. + +# + +# Revision 1.3 2004/08/17 03:27:23 mcr + +# klips 2.6 edits. + +# + +# Revision 1.2 2004/08/14 03:27:39 mcr + +# 2.6 kernel build/configuration files. + +# + +# Revision 1.1 2004/08/14 02:47:55 mcr + +# kernel build/config patches + +# + +# Revision 1.3 2004/02/24 17:17:04 mcr + +# s/CONFIG_IPSEC/CONFIG_KLIPS/ as 26sec uses "CONFIG_IPSEC" to + +# turn it on/off as well. + +# + +# Revision 1.2 2004/02/22 06:50:42 mcr + +# kernel 2.6 port - merged with 2.4 code. + +# + +# Revision 1.1.2.1 2004/02/20 02:07:53 mcr + +# module configuration for KLIPS 2.6 + +# + +# + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/Makefile Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,190 @@ + +# Makefile for KLIPS kernel code as a module for 2.6 kernels + +# + +# Makefile for KLIPS kernel code as a module + +# Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. + +# Copyright (C) 2002-2004 Michael Richardson + +# + +# 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 . + +# + +# 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.fs2_6,v 1.8.2.1 2006/04/20 16:33:06 mcr 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). + +# + + + +LIBRESWANSRCDIR?=. + +KLIPS_TOP?=. + + + +-include ${LIBRESWANSRCDIR}/Makefile.ver + + + +base-klips-objs := + + + +base-klips-objs+= ipsec_init.o ipsec_sa.o ipsec_radij.o radij.o + +base-klips-objs+= ipsec_life.o ipsec_proc.o + +base-klips-objs+= ipsec_tunnel.o ipsec_xmit.o ipsec_rcv.o ipsec_ipip.o + +base-klips-objs+= ipsec_snprintf.o + +base-klips-objs+= ipsec_mast.o + +base-klips-objs+= sysctl_net_ipsec.o + +base-klips-objs+= pfkey_v2.o pfkey_v2_parser.o pfkey_v2_ext_process.o + +base-klips-objs+= version.o + + + +base-klips-objs+= satot.o + +base-klips-objs+= addrtot.o + +base-klips-objs+= ultot.o + +base-klips-objs+= addrtypeof.o + +base-klips-objs+= anyaddr.o + +base-klips-objs+= initaddr.o + +base-klips-objs+= ultoa.o + +base-klips-objs+= addrtoa.o + +base-klips-objs+= subnettoa.o + +base-klips-objs+= subnetof.o + +base-klips-objs+= goodmask.o + +base-klips-objs+= datatot.o + +base-klips-objs+= rangetoa.o + +base-klips-objs+= prng.o + +base-klips-objs+= pfkey_v2_parse.o + +base-klips-objs+= pfkey_v2_build.o + +base-klips-objs+= pfkey_v2_debug.o + +base-klips-objs+= pfkey_v2_ext_bits.o + +base-klips-objs+= version.o + + + +obj-${CONFIG_KLIPS} += ipsec.o + + + +ipsec-objs += ${base-klips-objs} + + + +ipsec-$(CONFIG_KLIPS_ESP) += ipsec_esp.o + +ipsec-$(CONFIG_KLIPS_IPCOMP) += ipsec_ipcomp.o + +ipsec-$(CONFIG_KLIPS_AUTH_HMAC_MD5) += ipsec_md5c.o + +ipsec-$(CONFIG_KLIPS_AUTH_HMAC_SHA1) += ipsec_sha1.o + + + +# AH, if you really think you need it. + +ipsec-$(CONFIG_KLIPS_AH) += ipsec_ah.o + + + +ipsec-y += ipsec_alg.o + + + +# include code from DES subdir + +crypto-$(CONFIG_KLIPS_ENC_3DES) += des/ipsec_alg_3des.o + +crypto-$(CONFIG_KLIPS_ENC_3DES) += des/cbc_enc.o + +crypto-$(CONFIG_KLIPS_ENC_3DES) += des/ecb_enc.o + +crypto-$(CONFIG_KLIPS_ENC_3DES) += des/set_key.o + + + +ifeq ($(strip ${SUBARCH}),) + +SUBARCH:=${ARCH} + +endif + + + +# the assembly version expects frame pointers, which are + +# optional in many kernel builds. If you want speed, you should + +# probably use cryptoapi code instead. + +USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} + +ifeq (${USEASSEMBLY},i386y) + +crypto-$(CONFIG_KLIPS_ENC_3DES) += des/dx86unix.o + +else + +crypto-$(CONFIG_KLIPS_ENC_3DES) += des/des_enc.o + +endif + + + +# include code from AES subdir + +crypto-$(CONFIG_KLIPS_ENC_AES) += aes/ipsec_alg_aes.o + +crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes_xcbc_mac.o + +crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes_cbc.o + + + +ifeq ($(strip ${SUBARCH}),) + +SUBARCH:=${ARCH} + +endif + + + +USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} + +ifeq (${USEASSEMBLY},i386y) + +crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes-i586.o + +else + +crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes.o + +endif + + + +ipsec-y += ${crypto-y} + + + +ipsec-$(CONFIG_KLIPS_ENC_CRYPTOAPI) += ipsec_alg_cryptoapi.o + + + +# IPcomp stuff + +base-ipcomp-objs := ipcomp.o + +base-ipcomp-objs += adler32.o + +base-ipcomp-objs += deflate.o + +base-ipcomp-objs += infblock.o + +base-ipcomp-objs += infcodes.o + +base-ipcomp-objs += inffast.o + +base-ipcomp-objs += inflate.o + +base-ipcomp-objs += inftrees.o + +base-ipcomp-objs += infutil.o + +base-ipcomp-objs += trees.o + +base-ipcomp-objs += zutil.o + +asm-ipcomp-obj-$(CONFIG_M586) += match586.o + +asm-ipcomp-obj-$(CONFIG_M586TSC) += match586.o + +asm-ipcomp-obj-$(CONFIG_M586MMX) += match586.o + +asm-ipcomp-obj-$(CONFIG_M686) += match686.o + +asm-ipcomp-obj-$(CONFIG_MPENTIUMIII) += match686.o + +asm-ipcomp-obj-$(CONFIG_MPENTIUM4) += match686.o + +asm-ipcomp-obj-$(CONFIG_MK6) += match586.o + +asm-ipcomp-obj-$(CONFIG_MK7) += match686.o + +asm-ipcomp-obj-$(CONFIG_MCRUSOE) += match586.o + +asm-ipcomp-obj-$(CONFIG_MWINCHIPC6) += match586.o + +asm-ipcomp-obj-$(CONFIG_MWINCHIP2) += match686.o + +asm-ipcomp-obj-$(CONFIG_MWINCHIP3D) += match686.o + +base-ipcomp-objs += ${asm-ipcomp-obj-y} + + + +ipsec-$(CONFIG_KLIPS_IPCOMP) += ${base-ipcomp-objs} + + + +EXTRA_CFLAGS += -DIPCOMP_PREFIX -DKLIPS + + + +# + +# $Log: Makefile.fs2_6,v $ + +# Revision 1.8.2.1 2006/04/20 16:33:06 mcr + +# remove all of CONFIG_KLIPS_ALG --- one can no longer build without it. + +# Fix in-kernel module compilation. Sub-makefiles do not work. + +# + +# Revision 1.8 2005/05/11 03:15:42 mcr + +# adjusted makefiles to sanely build modules properly. + +# + +# Revision 1.7 2005/04/13 22:52:12 mcr + +# moved KLIPS specific snprintf() wrapper to seperate file. + +# + +# Revision 1.6 2004/08/22 05:02:03 mcr + +# organized symbols such that it is easier to build modules. + +# + +# Revision 1.5 2004/08/18 01:43:56 mcr + +# adjusted makefile enumation so that it can be used by module + +# wrapper. + +# + +# Revision 1.4 2004/08/17 03:27:23 mcr + +# klips 2.6 edits. + +# + +# Revision 1.3 2004/08/04 16:50:13 mcr + +# removed duplicate definition of dx86unix.o + +# + +# Revision 1.2 2004/08/03 18:21:09 mcr + +# only set KLIPS_TOP and LIBRESWANSRCDIR if not already set. + +# + +# Revision 1.1 2004/07/26 15:02:22 mcr + +# makefile for KLIPS module for 2.6. + +# + +# Revision 1.3 2004/02/24 17:17:04 mcr + +# s/CONFIG_IPSEC/CONFIG_KLIPS/ as 26sec uses "CONFIG_IPSEC" to + +# turn it on/off as well. + +# + +# Revision 1.2 2004/02/22 06:50:42 mcr + +# kernel 2.6 port - merged with 2.4 code. + +# + +# Revision 1.1.2.1 2004/02/20 02:07:53 mcr + +# module configuration for KLIPS 2.6 + +# + +# + +# 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/README-zlib 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 , or to + +Gilles Vollant 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 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 + +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 + +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 + +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 , 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 . 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 + + + + + +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/net/ipsec/README-zlib.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/net/ipsec/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 . + + * + + * 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.10 2004/07/10 07:43:47 mcr Exp $ + + */ + +#include "libreswan.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 libreswan.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/net/ipsec/addrtot.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,348 @@ + +/* + + * 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 . + + * + + * 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. + + * + + */ + + + +#if defined(__KERNEL__) && defined(__HAVE_ARCH_STRSTR) + +#include + +#endif + + + +#include "libreswan.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); + + + +#if defined(__KERNEL__) && !defined(__HAVE_ARCH_STRSTR) + +#define strstr ipsec_strstr + +/* + + * Find the first occurrence of find in s. + + * (from NetBSD 1.6's /src/lib/libc/string/strstr.c) + + */ + +static char *strstr(const char *s, const char *find); + + + +static char * + +strstr(s, find) + + const char *s, *find; + +{ + + char c, sc; + + size_t len; + + + + if ((c = *find++) != 0) { + + len = strlen(find); + + do { + + do { + + if ((sc = *s++) == 0) + + return (NULL); + + } while (sc != c); + + } while (strncmp(s, find, len) != 0); + + s--; + + } + + /* LINTED interface specification */ + + return ((char *)s); + +} + +#endif + + + +/* + + - 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, "", dstlen); + + return sizeof(""); + + } + + + + 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 + +#include + +#include + +#include + +#include + + + +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 */ + + + +/* + + * Local variables: + + * c-file-style: "linux" + + * End: + + */ + + + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/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 . + + * + + * 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.10 2004/07/10 07:43:47 mcr Exp $ + + */ + +#include "libreswan.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/net/ipsec/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.6 2004/07/10 19:11:18 mcr Exp $ */ + + + +#include + +#include + + + +#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/net/ipsec/aes/Makefile Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,56 @@ + +# Makefile for KLIPS 3DES kernel code as a module for 2.6 kernels + +# + +# Makefile for KLIPS kernel code as a module + +# Copyright (C) 2002-2004 Michael Richardson + +# + +# 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 . + +# + +# 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.fs2_6,v 1.2 2005/08/12 14:13:58 mcr 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). + +# + + + +obj-$(CONFIG_KLIPS_ENC_AES) += ipsec_alg_aes.o + +obj-$(CONFIG_KLIPS_ENC_AES) += aes_xcbc_mac.o + +obj-$(CONFIG_KLIPS_ENC_AES) += aes_cbc.o + + + +ifeq ($(strip ${SUBARCH}),) + +SUBARCH:=${ARCH} + +endif + + + +# the assembly version expects frame pointers, which are + +# optional in many kernel builds. If you want speed, you should + +# probably use cryptoapi code instead. + +USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} + +ifeq (${USEASSEMBLY},i386y) + +obj-$(CONFIG_KLIPS_ENC_AES) += aes-i586.o + +else + +obj-$(CONFIG_KLIPS_ENC_AES) += aes.o + +endif + + + + + +# + +# $Log: Makefile.fs2_6,v $ + +# Revision 1.2 2005/08/12 14:13:58 mcr + +# do not use assembly code with there are no frame pointers, + +# as it does not have the right linkages. + +# + +# Revision 1.1 2004/08/17 03:31:34 mcr + +# klips 2.6 edits. + +# + +# + +# 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/aes/aes-i586.S Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,892 @@ + +// + +// Copyright (c) 2001, Dr Brian Gladman , 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/net/ipsec/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 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/net/ipsec/aes/aes_cbc.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,46 @@ + +/* + +// 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 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 + +#else + +#include + +#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.2 2004/07/10 07:48:40 mcr + + * Moved from linux/crypto/ciphers/aes/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/net/ipsec/aes/aes_xcbc_mac.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,67 @@ + +#ifdef __KERNEL__ + +#include + +#include + +#define AES_DEBUG(x) + +#else + +#include + +#include + +#define AES_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) { + + AES_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) { + + AES_DEBUG(printf("using k3\n")); + + xor_block(out, ctxm->k3); + + } + + else + + { + + AES_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/net/ipsec/aes/ipsec_alg_aes.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,300 @@ + +/* + + * ipsec_alg AES cipher stubs + + * + + * Author: JuanJo Ciarlante + + * + + * 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 . + + * + + * 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 + + * Fixes list: + + * PK: make XCBC comply with latest draft (keylength) + + * + + */ + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +/* + + * special case: ipsec core modular with this static algo inside: + + * must avoid MODULE magic for this file + + */ + +#if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_AES) + +#undef MODULE + +#endif + + + +#include + +#include + + + +#include /* printk() */ + +#include /* error codes */ + +#include /* size_t */ + +#include + + + +/* Check if __exit is defined, if not null it */ + +#ifndef __exit + +#define __exit + +#endif + + + +/* Low freeswan header coupling */ + +#include + +#include "libreswan/ipsec_alg.h" + +#include "crypto/aes_cbc.h" + + + +#define CONFIG_KLIPS_ENC_AES_MAC 1 + + + +#define AES_CONTEXT_T aes_context + +static int debug_aes=0; + +static int test_aes=0; + +static int excl_aes=0; + +static int keyminbits=0; + +static int keymaxbits=0; + +#if defined(CONFIG_KLIPS_ENC_AES_MODULE) + +MODULE_AUTHOR("JuanJo Ciarlante "); + +#ifdef module_param + +module_param(debug_aes,int,0664); + +module_param(test_aes,int,0664); + +module_param(excl_aes,int,0664); + +module_param(keyminbits,int,0664); + +module_param(keymaxbits,int,0664); + +#else + +MODULE_PARM(debug_aes, "i"); + +MODULE_PARM(test_aes, "i"); + +MODULE_PARM(excl_aes, "i"); + +MODULE_PARM(keyminbits, "i"); + +MODULE_PARM(keymaxbits, "i"); + +#endif + +#endif + + + +#if CONFIG_KLIPS_ENC_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 + +#if 0 + +#ifdef MODULE_PARM + +MODULE_PARM(auth_id, "i"); + +#else + +module_param(auth_id,int,0664); + +#endif + +#endif + +#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_aes > 0) + + printk(KERN_DEBUG "klips_debug:_aes_set_key:" + + "ret=%d key_e=%p key=%p keysize=%ld\n", + + ret, key_e, key, (unsigned long int) 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_aes > 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_KLIPS_ENC_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_common: { ixt_version: IPSEC_ALG_VERSION, + + ixt_refcnt: ATOMIC_INIT(0), + + ixt_name: "aes_mac", + + ixt_blocksize: ESP_AES_MAC_BLK_LEN, + + ixt_support: { + + ias_exttype: IPSEC_ALG_TYPE_AUTH, + + ias_id: 0, + + ias_keyminbits: ESP_AES_MAC_KEY_SZ*8, + + ias_keymaxbits: ESP_AES_MAC_KEY_SZ*8, + + }, + + }, + +#if defined(CONFIG_KLIPS_ENC_AES_MODULE) + + ixt_module: THIS_MODULE, + +#endif + + 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_KLIPS_ENC_AES_MAC */ + +static struct ipsec_alg_enc ipsec_alg_AES = { + + ixt_common: { ixt_version: IPSEC_ALG_VERSION, + + ixt_refcnt: ATOMIC_INIT(0), + + ixt_name: "aes", + + ixt_blocksize: ESP_AES_CBC_BLK_LEN, + + ixt_support: { + + ias_exttype: IPSEC_ALG_TYPE_ENCRYPT, + + //ias_ivlen: 128, + + ias_id: ESP_AES, + + ias_keyminbits: ESP_AES_KEY_SZ_MIN*8, + + ias_keymaxbits: ESP_AES_KEY_SZ_MAX*8, + + }, + + }, + +#if defined(CONFIG_KLIPS_ENC_AES_MODULE) + + ixt_module: THIS_MODULE, + +#endif + + 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_KLIPS_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_common.ixt_support.ias_keyminbits=keyminbits; + + if (keymaxbits) { + + ipsec_alg_AES.ixt_common.ixt_support.ias_keymaxbits=keymaxbits; + + if (keymaxbits*8>ipsec_alg_AES.ixt_common.ixt_support.ias_keymaxbits) + + ipsec_alg_AES.ixt_e_keylen=keymaxbits*8; + + } + + if (excl_aes) ipsec_alg_AES.ixt_common.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_common.ixt_support.ias_exttype, + + ipsec_alg_AES.ixt_common.ixt_support.ias_id, + + ipsec_alg_AES.ixt_common.ixt_name, + + ret); + + if (ret==0 && test_aes) { + + test_ret=ipsec_alg_test( + + ipsec_alg_AES.ixt_common.ixt_support.ias_exttype , + + ipsec_alg_AES.ixt_common.ixt_support.ias_id, + + test_aes); + + printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", + + ipsec_alg_AES.ixt_common.ixt_support.ias_exttype , + + ipsec_alg_AES.ixt_common.ixt_support.ias_id, + + test_ret); + + } + +#if CONFIG_KLIPS_ENC_AES_MAC + + if (auth_id!=0){ + + int ret; + + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_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_common.ixt_support.ias_exttype, + + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, + + ipsec_alg_AES_MAC.ixt_common.ixt_name, + + ret); + + if (ret==0 && test_aes) { + + test_ret=ipsec_alg_test( + + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype, + + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, + + test_aes); + + printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", + + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype, + + ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_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_KLIPS_ENC_AES_MAC */ + + return ret; + +} + + + +#if defined(CONFIG_KLIPS_ENC_AES_MODULE) + +IPSEC_ALG_MODULE_EXIT_MOD( ipsec_aes_fini ) + +#else + +IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_aes_fini ) + +#endif + +{ + +#if CONFIG_KLIPS_ENC_AES_MAC + + if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC); + +#endif /* CONFIG_KLIPS_ENC_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 + + + --- /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_ENC_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.alg_aes Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,18 @@ + +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 $(LIBCRYPTO)/libaes/libaes.a + + + + + +$(MOD_AES): $(AES_OBJS) + + $(LD) $(EXTRA_LDFLAGS) -r $(AES_OBJS) -o $@ + + + +$(LIBCRYPTO)/libaes/libaes.a: + + $(MAKE) -C $(LIBCRYPTO)/libaes 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_cryptoapi.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,442 @@ + +/* + + * ipsec_alg to linux cryptoapi GLUE + + * + + * Authors: CODE.ar TEAM + + * Harpo MAxx + + * JuanJo Ciarlante + + * Luciano Ruete + + * + + * 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 . + + * + + * 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) + + */ + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +/* + + * 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 + +#include + + + +#include /* printk() */ + +#include /* error codes */ + +#include /* size_t */ + +#include + + + +/* 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 "libreswan/ipsec_alg.h" + + + +#include + +#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 + +#include + +#include + + + +#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; + +static int test=0; + +static int excl=0; + +#ifdef module_param + +module_param(debug, int, 0664); + +module_param(test, int, 0664); + +module_param(excl, int, 0664); + +#else + +MODULE_PARM(debug, "i"); + +MODULE_PARM(test, "i"); + +MODULE_PARM(excl, "i"); + +#endif + + + +static int noauto = 0; + +#ifdef module_param + +module_param(noauto,int, 0664); + +#else + +MODULE_PARM(noauto,"i"); + +#endif + +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}; + + + +#ifdef module_param_array + +module_param_array(des_ede3,int,NULL,0); + +module_param_array(aes,int,NULL,0); + +module_param_array(blowfish,int,NULL,0); + +module_param_array(cast,int,NULL,0); + +module_param_array(serpent,int,NULL,0); + +module_param_array(twofish,int,NULL,0); + +#else + +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"); + +#endif + +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 + +#include + +#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/anyaddr.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,150 @@ + +/* + + * 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 . + + * + + * 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.10 2004/07/10 07:43:47 mcr Exp $ + + */ + +#include "libreswan.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; + + + + case 0: + + /* a zeroed structure is considered any address */ + + return 1; + + + + 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/net/ipsec/datatot.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,234 @@ + +/* + + * 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 . + + * + + * 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.9 2005/08/30 21:15:26 mcr Exp $ + + */ + +#include "libreswan.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 unsigned 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 */ + + unsigned 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; + + } + + + + user_assert(inblocksize < sizeof(inblock)); + + user_assert(outblocksize < sizeof(outblock)); + + user_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; + + } + + + + user_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((const char *)src, nreal, format, out); + + needed += outblocksize; + + sincebreak += outblocksize; + + if (dst < stop) { + + if (out != dst) { + + user_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; + + } + + } + + + + user_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; + + + + user_assert(nreal > 0); + + switch (format) { + + case 'x': + + user_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: + + user_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 unsigned 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 unsigned 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/net/ipsec/defconfig Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,147 @@ + + + +# + +# RCSID $Id: defconfig,v 1.30 2005/09/15 02:31:12 paul Exp $ + +# + + + +# + +# Libreswan 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_KLIPS=m + + + +# To do tunnel mode IPSec, this must be enabled. + +CONFIG_KLIPS_IPIP=y + + + +# To enable authentication, say 'y'. (Highly recommended) + +CONFIG_KLIPS_AH=y + + + +# Authentication algorithm(s): + +CONFIG_KLIPS_AUTH_HMAC_MD5=y + +CONFIG_KLIPS_AUTH_HMAC_SHA1=y + + + +# To enable encryption, say 'y'. (Highly recommended) + +CONFIG_KLIPS_ESP=y + + + +# modular algo extensions (and new ALGOs) + +CONFIG_KLIPS_ALG=y + + + +# Encryption algorithm(s): + +CONFIG_KLIPS_ENC_3DES=y + +CONFIG_KLIPS_ENC_AES=y + + + +# Use CryptoAPI for ALG? - by default, no. + +CONFIG_KLIPS_ENC_CRYPTOAPI=n + + + +# IP Compression: new, probably still has minor bugs. + +CONFIG_KLIPS_IPCOMP=y + + + +# To enable userspace-switchable KLIPS debugging, say 'y'. + +CONFIG_KLIPS_DEBUG=y + + + +# + +# + +# $Log: defconfig,v $ + +# Revision 1.30 2005/09/15 02:31:12 paul + +# Changed a FreeS/WAN occurance to Libreswan + +# + +# Revision 1.29 2005/08/24 22:10:05 mcr + +# do not list NAT_TRAVERSAL as a default for KLIPS, + +# let it live in the packaging "MODULE_DEF_CONFIG" files. + +# + +# Revision 1.28 2005/05/11 03:15:42 mcr + +# adjusted makefiles to sanely build modules properly. + +# + +# Revision 1.27 2005/03/20 03:00:05 mcr + +# default configuration should enable NAT_TRAVERSAL. + +# + +# Revision 1.26 2004/07/10 19:11:18 mcr + +# CONFIG_IPSEC -> CONFIG_KLIPS. + +# + +# 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 libreswan + +# + +# 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 + +# 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/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.4 2004/07/10 07:48:37 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)<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/net/ipsec/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.5 2004/07/10 07:48:38 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/net/ipsec/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/net/ipsec/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/net/ipsec/des/Makefile Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,60 @@ + +# Makefile for KLIPS kernel code as a module for 2.6 kernels + +# + +# Makefile for KLIPS kernel code as a module + +# Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. + +# Copyright (C) 2002-2004 Michael Richardson + +# + +# 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 . + +# + +# 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.fs2_6,v 1.3 2005/08/12 14:13:59 mcr 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). + +# + + + +obj-$(CONFIG_KLIPS_ENC_3DES) += ipsec_alg_3des.o + +obj-$(CONFIG_KLIPS_ENC_3DES) += cbc_enc.o + +obj-$(CONFIG_KLIPS_ENC_3DES) += ecb_enc.o + +obj-$(CONFIG_KLIPS_ENC_3DES) += set_key.o + + + +ifeq ($(strip ${SUBARCH}),) + +SUBARCH:=${ARCH} + +endif + + + +# the assembly version expects frame pointers, which are + +# optional in many kernel builds. If you want speed, you should + +# probably use cryptoapi code instead. + +USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} + +ifeq (${USEASSEMBLY},i386y) + +obj-$(CONFIG_KLIPS_ENC_3DES) += dx86unix.o + +else + +obj-$(CONFIG_KLIPS_ENC_3DES) += des_enc.o + +endif + + + +# + +# $Log: Makefile.fs2_6,v $ + +# Revision 1.3 2005/08/12 14:13:59 mcr + +# do not use assembly code with there are no frame pointers, + +# as it does not have the right linkages. + +# + +# Revision 1.2 2005/04/29 05:13:07 mcr + +# 3DES algorithm code. + +# + +# Revision 1.1 2004/08/17 03:27:30 mcr + +# klips 2.6 edits. + +# + +# + +# 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/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/net/ipsec/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 and , 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.12 2004/07/10 08:06:51 mcr Exp $ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/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 + + The 'n' bit ofb code was wrong, it was not shifting the shift + + register. It worked correctly for n == 64. Thanks to + + Gigi Ankeny 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 . + + + +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 . 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 . */ + + + + 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 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 + + + +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 + + for the patch. + + + +Version 3.21 22/11/95 + + After some emailing back and forth with + + Colin Plumb , 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 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 + + 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 for pointing this + + one out. + + + +Version 3.12 08/05/95 + + As pointed out by The Crypt Keeper , + + 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 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 . + + + +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 + + + +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 + + + +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 + + 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 , 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/net/ipsec/des/asm/des-586.pl Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,251 @@ + +#!/usr/local/bin/perl + +# + +# The inner loop instruction sequence and the IP/FP modifications are from + +# Svend Olaf Mikkelsen + +# + + + +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/net/ipsec/des/asm/des686.pl Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,230 @@ + +#!/usr/local/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 "); + +&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/net/ipsec/des/asm/desboth.pl Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,79 @@ + +#!/usr/local/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/net/ipsec/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 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/net/ipsec/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/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/net/ipsec/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/net/ipsec/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/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/net/ipsec/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 + +#ifndef MSDOS + +#include + +#else + +#include + +extern void exit(); + +#endif + +#include + +#ifndef VMS + +#ifndef _IRIX + +#include + +#endif + +#ifdef TIMES + +#include + +#include + +#endif + +#else /* VMS */ + +#include + +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 + +#endif + + + +#ifdef sun + +#include + +#include + +#endif + + + +#include "des/des_locl.h" + +#include "des/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/net/ipsec/des/dx86unix.S Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,3160 @@ + +/* + + * This file was originally generated by Michael Richardson + + * 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/net/ipsec/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/des_locl.h" + +#include "des/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.8 2004/08/04 15:57:22 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/net/ipsec/des/ipsec_alg_3des.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,182 @@ + +/* + + * ipsec_alg 3DES cipher stubs + + * + + * Copyright (C) 2005 Michael Richardson + + * + + * Adapted from ipsec_alg_aes.c by JuanJo Ciarlante + + * + + * 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 . + + * + + * 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 AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +/* + + * special case: ipsec core modular with this static algo inside: + + * must avoid MODULE magic for this file + + */ + +#if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_3DES) + +#undef MODULE + +#endif + + + +#include + +#include + + + +#include /* printk() */ + +#include /* error codes */ + +#include /* size_t */ + +#include + + + +/* Low freeswan header coupling */ + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_alg.h" + +#include "crypto/des.h" + +#include "libreswan/ipsec_alg_3des.h" + + + +#define AES_CONTEXT_T aes_context + +static int debug_3des=0; + +static int test_3des=0; + +static int excl_3des=0; + + + +#if defined(CONFIG_KLIPS_ENC_3DES_MODULE) + +MODULE_AUTHOR("Michael Richardson "); + +#ifdef module_param + +module_param(debug_3des, int, 0664); + +module_param(test_des, int, 0664); + +module_param(excl_des, int, 0664); + +#else + +MODULE_PARM(debug_3des, "i"); + +MODULE_PARM(test_des, "i"); + +MODULE_PARM(excl_des, "i"); + +#endif + +#endif + + + +#define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ + +#define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ + + + +static int _3des_set_key(struct ipsec_alg_enc *alg, + + __u8 * key_e, const __u8 * key, + + size_t keysize) + +{ + + int ret = 0; + + TripleDES_context *ctx = (TripleDES_context*)key_e; + + + + if(keysize != 192/8) { + + return EINVAL; + + } + + + + des_set_key((des_cblock *)(key + DES_KEY_SZ*0), ctx->s1); + + des_set_key((des_cblock *)(key + DES_KEY_SZ*1), ctx->s2); + + des_set_key((des_cblock *)(key + DES_KEY_SZ*2), ctx->s3); + + + + if (debug_3des > 0) + + printk(KERN_DEBUG "klips_debug:_3des_set_key:" + + "ret=%d key_e=%p key=%p keysize=%ld\n", + + ret, key_e, key, (unsigned long int) keysize); + + return ret; + +} + + + +static int _3des_cbc_encrypt(struct ipsec_alg_enc *alg, + + __u8 * key_e, + + __u8 * in, + + int ilen, const __u8 * iv, + + int encrypt) + +{ + + TripleDES_context *ctx=(TripleDES_context*)key_e; + + des_cblock miv; + + + + memcpy(&miv, iv, sizeof(miv)); + + + + if (debug_3des > 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); + + + + des_ede3_cbc_encrypt((des_cblock *)in, + + (des_cblock *)in, + + ilen, + + ctx->s1, + + ctx->s2, + + ctx->s3, + + &miv, encrypt); + + return 1; + +} + + + +static struct ipsec_alg_enc ipsec_alg_3DES = { + + ixt_common: { ixt_version: IPSEC_ALG_VERSION, + + ixt_refcnt: ATOMIC_INIT(0), + + ixt_name: "3des", + + ixt_blocksize: ESP_3DES_CBC_BLK_LEN, + + ixt_support: { + + ias_exttype: IPSEC_ALG_TYPE_ENCRYPT, + + ias_id: ESP_3DES, + + //ias_ivlen: 64, + + ias_keyminbits: ESP_3DES_KEY_SZ*8, + + ias_keymaxbits: ESP_3DES_KEY_SZ*8, + + }, + + }, + +#if defined(MODULE_KLIPS_ENC_3DES_MODULE) + + ixt_module: THIS_MODULE, + +#endif + + ixt_e_keylen: ESP_3DES_KEY_SZ*8, + + ixt_e_ctx_size: sizeof(TripleDES_context), + + ixt_e_set_key: _3des_set_key, + + ixt_e_cbc_encrypt:_3des_cbc_encrypt, + +}; + + + +#if defined(CONFIG_KLIPS_ENC_3DES_MODULE) + +IPSEC_ALG_MODULE_INIT_MOD( ipsec_3des_init ) + +#else + +IPSEC_ALG_MODULE_INIT_STATIC( ipsec_3des_init ) + +#endif + +{ + + int ret, test_ret; + + + + if (excl_3des) ipsec_alg_3DES.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL; + + ret=register_ipsec_alg_enc(&ipsec_alg_3DES); + + printk("ipsec_3des_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", + + ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, + + ipsec_alg_3DES.ixt_common.ixt_support.ias_id, + + ipsec_alg_3DES.ixt_common.ixt_name, + + ret); + + if (ret==0 && test_3des) { + + test_ret=ipsec_alg_test( + + ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, + + ipsec_alg_3DES.ixt_common.ixt_support.ias_id, + + test_3des); + + printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", + + ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, + + ipsec_alg_3DES.ixt_common.ixt_support.ias_id, + + test_ret); + + } + + return ret; + +} + + + +#if defined(CONFIG_KLIPS_ENC_3DES_MODULE) + +IPSEC_ALG_MODULE_EXIT_MOD( ipsec_3des_fini ) + +#else + +IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_3des_fini ) + +#endif + +{ + + unregister_ipsec_alg_enc(&ipsec_alg_3DES); + + return; + +} + + + +/* Dual, because 3des code is 4-clause BSD licensed */ + +#ifdef MODULE_LICENSE + +MODULE_LICENSE("Dual BSD/GPL"); + +#endif + + + + + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/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/des_locl.h" + +#include "des/podd.h" + +#include "des/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>(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>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/net/ipsec/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 . + + * + + * 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.12 2004/07/10 07:43:47 mcr Exp $ + + */ + +#include "libreswan.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/net/ipsec/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 + +#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/net/ipsec/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/net/ipsec/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 + +#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/net/ipsec/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/net/ipsec/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 + +#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)<avail_in-n;c=(k>>3)>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/net/ipsec/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/net/ipsec/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/net/ipsec/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 + +#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<state->wbits)) + + { + + length = (1<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/net/ipsec/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 + +#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/net/ipsec/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/net/ipsec/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 + +#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/net/ipsec/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)<>=(j);k-=(j);} + +/* output bytes */ + +#define WAVAIL (uInt)(qread?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/net/ipsec/initaddr.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,85 @@ + +/* + + * 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 . + + * + + * 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.6 2004/07/10 07:43:47 mcr Exp $ + + */ + +#include "libreswan.h" + + + +err_t + +add_port(af, addr, port) + +int af; + +ip_address *addr; + +unsigned short port; + +{ + + switch (af) { + + case AF_INET: + + addr->u.v4.sin_port = port; + + break; + + case AF_INET6: + + addr->u.v6.sin6_port = port; + + break; + + default: + + return "unknown address family in add_port"; + + break; + + } + + return NULL; + +} + + + +/* + + - 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"; + +#if !defined(__KERNEL__) + + /* On BSD, the kernel compares the entire struct sockaddr when + + * using bind(). However, this is as large as the largest + + * address family, so the 'remainder' has to be 0. Linux + + * compares interface addresses with the length of sa_len, + + * instead of sizeof(struct sockaddr), so in that case padding + + * is not needed. + + * + + * Patch by Stefan Arentz + + */ + + bzero(&dst->u.v4, sizeof(dst->u.v4)); + +#endif + + dst->u.v4.sin_family = af; + + dst->u.v4.sin_port = 0; + + 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"; + +#if !defined(__KERNEL__) + + bzero(&dst->u.v6, sizeof(dst->u.v6)); + +#endif + + dst->u.v6.sin6_family = af; + + dst->u.v6.sin6_flowinfo = 0; /* unused */ + + dst->u.v6.sin6_port = 0; + + 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/net/ipsec/ipcomp.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,694 @@ + +/* + + * IPCOMP zlib interface code. + + * implementation of RFC 3173. + + * + + * Copyright (C) 2000 Svenning Soerensen + + * Copyright (C) 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 . + + * + + * 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. + + */ + + + +/* SSS */ + + + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +#define __NO_VERSION__ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include + +#include + +#include + +#include + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + +#include + + + +#include + + + +#include + + + +#include "libreswan/ipsec_kern24.h" + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */ + +#include "libreswan/ipsec_proto.h" + +#include "libreswan/ipcomp.h" + +#include "zlib/zlib.h" + +#include "zlib/zutil.h" + + + +#include /* SADB_X_CALG_DEFLATE */ + + + +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); + +} + + + +/* + + * We use this function because sometimes we want to pass a negative offset + + * into skb_put(), this does not work on 64bit platforms because long to + + * unsigned int casting. + + */ + +static inline unsigned char * + +safe_skb_put(struct sk_buff *skb, int extend) + +{ + + unsigned char *ptr; + + + + if (extend>0) { + + // increase the size of the packet + + ptr = skb_put(skb, extend); + + } else { + + // shrink the size of the packet + + ptr = skb_tail_pointer(skb); + + skb_trim (skb, skb->len + extend); + + } + + + + return ptr; + +} + + + +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 = ip_hdr(skb); + +#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_KLIPS_DEBUG + + if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { + + __u8 *c; + + + + c = (__u8*)iph + iphlen; + + ipsec_dmp_block("compress before", c, pyldsz); + + } + +#endif /* CONFIG_KLIPS_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 */ + + safe_skb_put (skb, cpyldsz + sizeof(struct ipcomphdr) - pyldsz); + + + +#ifdef CONFIG_KLIPS_DEBUG + + if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { + + __u8 *c; + + + + c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr); + + ipsec_dmp_block("compress result", c, cpyldsz); + + } + +#endif /* CONFIG_KLIPS_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 = ip_hdr(skb); + +#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_KLIPS_DEBUG + + if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { + + __u8 *c; + + + + c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr); + + ipsec_dmp_block("decompress before", c, cpyldsz); + + } + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +#ifdef NET_21 + + iph = ip_hdr(nskb); + +#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 */ + + safe_skb_put(nskb, -zs.avail_out); + + + + ipsec_kfree_skb(skb); + + + + if (iph->protocol == IPPROTO_COMP) + + { + +#ifdef CONFIG_KLIPS_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_KLIPS_DEBUG */ + + + + ipsec_kfree_skb(nskb); + + return NULL; + + } + + + +#ifdef CONFIG_KLIPS_DEBUG + + if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { + + __u8 *c; + + + + c = (__u8*)iph + iphlen; + + ipsec_dmp_block("decompress result", c, pyldsz); + + } + +#endif /* CONFIG_KLIPS_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 = ip_hdr(skb); + +#else /* NET_21 */ + + iph = skb->ip_hdr; + +#endif /* NET_21 */ + + if (!iph) return NULL; + + iphlen = iph->ihl << 2; + + + + n=alloc_skb(skb_end_pointer(skb) - 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 */ + + safe_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); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + + n->list=NULL; + +#endif + + n->next=NULL; + + n->prev=NULL; + + n->sk=NULL; + + n->dev=skb->dev; + + if (skb_transport_header(skb)) + + skb_set_transport_header(n, offset); + + n->protocol=skb->protocol; + +#ifdef NET_21 + + n->csum = 0; + + n->priority=skb->priority; + + n->dst=dst_clone(skb->dst); + + skb_set_network_header(n, offset); + +#ifndef NETDEV_23 + + n->is_clone=0; + +#endif /* NETDEV_23 */ + + atomic_set(&n->users, 1); + + n->destructor = NULL; + +#ifdef HAVE_SOCK_SECURITY + + n->security=skb->security; + +#endif + + 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_header(skb)) + + skb_set_mac_header(n, offset); + +#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; + +#ifdef HAVE_TSTAMP + + n->tstamp = skb->tstamp; + +#else + + n->stamp=skb->stamp; + +#endif + +#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 */ + + + + 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,360 @@ + +/* + + * processing code for AH + + * Copyright (C) 2003-2004 Michael Richardson + + * + + * 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 . + + * + + * 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 AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +#define __NO_VERSION__ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *lock* */ + +# endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + + + +#include + +#include + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_rcv.h" + +#include "libreswan/ipsec_xmit.h" + + + +#include "libreswan/ipsec_auth.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_proto.h" + + + +__u32 zeroes[AH_AMAX]; + + + +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_transport_header(skb); + + + + 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_transport_header(skb) + ahhlen, + + skb->len - 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_network_header(skb) + ahhlen), + + (void *)(skb_network_header(skb)), 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); + + + + skb_set_network_header(skb, ahhlen); + + irs->ipp = ip_hdr(skb); + + + + ipsec_rcv_dmp("ah postpull", (void *)ip_hdr(skb), 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_KLIPS_AUTH_HMAC_MD5 + + MD5_CTX md5; + +#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + + SHA1_CTX sha1; + +#endif /* CONFIG_KLIPS_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_KLIPS_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)); + + osMD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); + + ipsec_xmit_dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Update(&tctx.md5, (unsigned char *)ahp, + + sizeof(struct ahhdr) - sizeof(ahp->ah_data)); + + ipsec_xmit_dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); + + ipsec_xmit_dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Update(&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)); + + osMD5Final(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)); + + osMD5Update(&tctx.md5, hash, AHMD596_ALEN); + + ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Final(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_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_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_KLIPS_AUTH_HMAC_SHA1 */ + + default: + + ixs->stats->tx_errors++; + + return IPSEC_XMIT_AH_BADALG; + + } + +#ifdef NET_21 + + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ahp)); + +#endif /* NET_21 */ + + + + return IPSEC_XMIT_OK; + +} + + + +struct xform_functions ah_xform_funcs[]={ + + { + + protocol: IPPROTO_AH, + + 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, + + }, + +}; + + + + + +#ifndef CONFIG_XFRM_ALTERNATE_STACK + +#ifdef NET_26 + +struct inet_protocol ah_protocol = { + + .handler = ipsec_rcv, + + .no_policy = 1, + +}; + +#else + +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 /* NET_26 */ + +#endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + + +/* + + * Local variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /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,1045 @@ + +/* + + * Modular extensions service and registration functions + + * + + * Author: JuanJo Ciarlante + + * + + * 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 . + + * + + * 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 AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +#define __NO_VERSION__ + +#include + +#include /* printk() */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + +#include + +#include + +#include /* memcmp() */ + +#include /* get_random_bytes() */ + +#include /* error codes */ + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *lock* */ + +# endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + + + +#include "libreswan/ipsec_param.h" + +#include + +#include "libreswan/ipsec_sa.h" + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_rcv.h" + +#if defined(CONFIG_KLIPS_ESP) || defined(CONFIG_KLIPS_AH) + +# include "libreswan/ipsec_ah.h" + +#endif /* defined(CONFIG_KLIPS_ESP) || defined(CONFIG_KLIPS_AH) */ + +#ifdef CONFIG_KLIPS_ESP + +# include "libreswan/ipsec_esp.h" + +#endif /* !CONFIG_KLIPS_ESP */ + +#ifdef CONFIG_KLIPS_IPCOMP + +# include "libreswan/ipcomp.h" + +#endif /* CONFIG_KLIPS_COMP */ + + + +#include + +#include + + + +#include "libreswan/ipsec_alg.h" + +#include "libreswan/ipsec_proto.h" + + + +#if K_SADB_EALG_MAX < 255 + +#warning Compiling with limited ESP support ( K_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 { struct ipsec_alg *ixtc = (struct ipsec_alg *)ixt; printk(KERN_ERR "%s: (%s) " fmt, __FUNCTION__, ixtc->ixt_name , ## args) \ + + ; goto out; } while(0) + + + +#ifdef NET_26 + +/* + + * Must be already protected by lock + + */ + +static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) + +{ + +#ifdef MODULE + + if (ixt->ixt_module) + + try_module_get(ixt->ixt_module); + +#endif + + atomic_inc(&ixt->ixt_refcnt); + +} + +static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) { + + atomic_dec(&ixt->ixt_refcnt); + +#ifdef MODULE + + if (ixt->ixt_module) + + module_put(ixt->ixt_module); + +#endif + +} + + + +#else + + + +/* + + * Must be already protected by lock + + */ + +static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) { + +#ifdef MODULE + + if (ixt->ixt_module) { + + __MOD_INC_USE_COUNT(ixt->ixt_module); + + } + +#endif + + atomic_inc(&ixt->ixt_refcnt); + +} + +static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) { + + atomic_dec(&ixt->ixt_refcnt); + +#ifdef MODULE + + if (ixt->ixt_module) + + __MOD_DEC_USE_COUNT(ixt->ixt_module); + +#endif + +} + +#endif + + + +/* + + * 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; + +#ifdef CONFIG_KLIPS_DEBUG + + int debug_flag = (encrypt==IPSEC_ALG_ENCRYPT ? + + debug_tunnel : debug_rcv); + +#endif + + + + KLIPS_PRINT(debug_flag, + + "klips_debug:ipsec_alg_esp_encrypt: " + + "entering with encalg=%d, ixt_e=%p\n", + + sa_p->ips_encalg, ixt_e); + + if (ixt_e == NULL) { + + KLIPS_ERROR(debug_flag, + + "klips_debug:ipsec_alg_esp_encrypt: " + + "NULL ipsec_alg_enc object\n"); + + return -1; + + } + + KLIPS_PRINT(debug_flag, + + "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_flag, + + "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_common.ixt_support.ias_id) { + + case ESP_3DES: + + keyminbits=keymaxbits=192;break; + + case ESP_DES: + + keyminbits=keymaxbits=64;break; + + default: + + keyminbits=ixt_e->ixt_common.ixt_support.ias_keyminbits; + + keymaxbits=ixt_e->ixt_common.ixt_support.ias_keymaxbits; + + } + + if(sa_p->ips_key_bits_eips_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_common.ixt_support.ias_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_common.ixt_support.ias_keyminbits; + + keymaxbits=ixt_a->ixt_common.ixt_support.ias_keymaxbits; + + if(sa_p->ips_key_bits_aips_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_common.ixt_blocksize==0) /* || ixt->ixt_common.ixt_blocksize%2) need for ESP_NULL */ + + barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_common.ixt_blocksize); + + if (ixt->ixt_common.ixt_support.ias_keyminbits==0 + + && ixt->ixt_common.ixt_support.ias_keymaxbits==0 + + && ixt->ixt_e_keylen==0) + + goto zero_key_ok; + + + + if (ixt->ixt_common.ixt_support.ias_keyminbits==0) + + barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits); + + + + if (ixt->ixt_common.ixt_support.ias_keymaxbits==0) + + barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_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_common.ixt_support.ias_id==0 || ixt->ixt_common.ixt_support.ias_id > K_SADB_AALG_MAX) + + barf_out("invalid alg_id=%d > %d (K_SADB_AALG_MAX)\n", + + ixt->ixt_common.ixt_support.ias_id, K_SADB_AALG_MAX); + + + + if (ixt->ixt_common.ixt_blocksize==0 + + || ixt->ixt_common.ixt_blocksize%2) + + barf_out(KERN_ERR "invalid blocksize=%d\n", + + ixt->ixt_common.ixt_blocksize); + + + + if (ixt->ixt_common.ixt_blocksize>AH_BLKLEN_MAX) + + barf_out(KERN_ERR "sorry blocksize=%d > %d. " + + "Please increase AH_BLKLEN_MAX and recompile\n", + + ixt->ixt_common.ixt_blocksize, + + AH_BLKLEN_MAX); + + if (ixt->ixt_common.ixt_support.ias_keyminbits==0 && ixt->ixt_common.ixt_support.ias_keymaxbits==0 && ixt->ixt_a_keylen==0) + + goto zero_key_ok; + + if (ixt->ixt_common.ixt_support.ias_keyminbits==0) + + barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits); + + if (ixt->ixt_common.ixt_support.ias_keymaxbits==0) + + barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_keymaxbits); + + if (ixt->ixt_common.ixt_support.ias_keymaxbits!=ixt->ixt_common.ixt_support.ias_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 + + */ + + if (ixt->ixt_support.ias_ivlen == 0 + + && ixt->ixt_blocksize > 1) { + + ixt->ixt_support.ias_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_support.ias_id, ret); + + + + + + ret = pfkey_list_insert_supported((struct ipsec_alg_supported *)&ixt->ixt_support + + , &(pfkey_supported_list[K_SADB_SATYPE_ESP])); + + + + if (ret==0) { + + ixt->ixt_state |= IPSEC_ALG_ST_SUPP; + + /* send register event to userspace */ + + pfkey_register_reply(K_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 ipsec_alg_supported *)&ixt->ixt_support + + , &(pfkey_supported_list[K_SADB_SATYPE_ESP])); + + + + /* send register event to userspace */ + + pfkey_register_reply(K_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_common.ixt_support.ias_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_common.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_common.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_common.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), + + K_SADB_EALG_MAX, K_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_KLIPS_ENC_AES) && CONFIG_KLIPS_ENC_AES && !defined(CONFIG_KLIPS_ENC_AES_MODULE) + +#if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI + +#warning "Using built-in AES rather than CryptoAPI AES" + +#endif + + { + + extern int ipsec_aes_init(void); + + ipsec_aes_init(); + + } + +#endif + + + +#if defined(CONFIG_KLIPS_ENC_3DES) && !defined(CONFIG_KLIPS_ENC_3DES_MODULE) + +#if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI + +#warning "Using built-in 3des rather than CryptoAPI 3des" + +#endif + + { + + extern int ipsec_3des_init(void); + + ipsec_3des_init(); + + } + +#endif + + + + /* If we are doing CryptoAPI, then init */ + +#if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI && !defined(CONFIG_KLIPS_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_support.ias_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_support.ias_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; + + inext; 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_support.ias_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_support.ias_ivlen, ixt->ixt_support.ias_keyminbits, ixt->ixt_support.ias_keymaxbits); + + + + len += ipsec_snprintf(buffer+len, length-len, + + "IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", + + ixt->ixt_support.ias_ivlen, ixt->ixt_support.ias_keyminbits, ixt->ixt_support.ias_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. + + */ + + + +#ifdef CONFIG_MODULES + +#ifndef NET_26 + +#if 0 + +#ifndef EXPORT_SYMBOL_GPL + +#undef EXPORT_SYMBOL_GPL + +#define EXPORT_SYMBOL_GPL EXPORT_SYMBOL + +#endif + +#endif + +EXPORT_SYMBOL(register_ipsec_alg); + +EXPORT_SYMBOL(unregister_ipsec_alg); + +EXPORT_SYMBOL(ipsec_alg_test); + +#endif + +#endif + --- /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,450 @@ + +/* + + * ipsec_alg to linux cryptoapi GLUE + + * + + * Authors: CODE.ar TEAM + + * Harpo MAxx + + * JuanJo Ciarlante + + * Luciano Ruete + + * + + * 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 . + + * + + * 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) + + */ + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +/* + + * special case: ipsec core modular with this static algo inside: + + * must avoid MODULE magic for this file + + */ + +#if CONFIG_KLIPS_MODULE && CONFIG_KLIPS_ENC_CRYPTOAPI + +#undef MODULE + +#endif + + + +#include + +#include + + + +#include /* printk() */ + +#include /* error codes */ + +#include /* size_t */ + +#include + + + +/* 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 + + + +#include "libreswan.h" + +#include "libreswan/ipsec_alg.h" + +#include "libreswan/ipsec_policy.h" + + + +#include + +#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 + +#include + +#include + + + +#define CIPHERNAME_AES "aes" + +#define CIPHERNAME_1DES "des" + +#define CIPHERNAME_3DES "des3_ede" + +#define CIPHERNAME_BLOWFISH "blowfish" + +#define CIPHERNAME_CAST "cast5" + +#define CIPHERNAME_SERPENT "serpent" + +#define CIPHERNAME_TWOFISH "twofish" + + + +#define ESP_SERPENT 252 /* from ipsec drafts */ + +#define ESP_TWOFISH 253 /* from ipsec drafts */ + + + +#define DIGESTNAME_MD5 "md5" + +#define DIGESTNAME_SHA1 "sha1" + + + +MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); + +static int debug_crypto=0; + +static int test_crypto=0; + +static int excl_crypto=0; + +#ifdef module_param + +module_param(debug_crypto, int, 0664); + +module_param(test_crypto, int, 0664); + +module_param(excl_crypto, int, 0664); + +#else + +MODULE_PARM(debug_crypto, "i"); + +MODULE_PARM(test_crypto, "i"); + +MODULE_PARM(excl_crypto, "i"); + +#endif + + + +static int noauto = 0; + +MODULE_PARM(noauto,"i"); + +MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones"); + + + +#ifdef CONFIG_KLIPS_ENC_1DES + +static int des_ede1[] = {-1, -1}; + +#endif + +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}; + + + +#ifdef module_param_array + +#ifdef CONFIG_KLIPS_ENC_1DES + +module_param_array(des_ede1,int,NULL,0); + +#endif + +module_param_array(des_ede3,int,NULL,0); + +module_param_array(aes,int,NULL,0); + +module_param_array(blowfish,int,NULL,0); + +module_param_array(cast,int,NULL,0); + +module_param_array(serpent,int,NULL,0); + +module_param_array(twofish,int,NULL,0); + +#else + +#ifdef CONFIG_KLIPS_ENC_1DES + +MODULE_PARM(des_ede1,"1-2i"); + +#endif + +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"); + +#endif + +MODULE_PARM_DESC(des_ede1, "0: disable | 1: force_enable | min,max: dontuse"); + +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_common:{ ixt_support:{ ias_id: ESP_AES}}}}, + + { CIPHERNAME_TWOFISH, 16, 128, 256, twofish, { ixt_common:{ ixt_support:{ ias_id: ESP_TWOFISH,}}}}, + + { CIPHERNAME_SERPENT, 16, 128, 256, serpent, { ixt_common:{ ixt_support:{ ias_id: ESP_SERPENT,}}}}, + + { CIPHERNAME_CAST, 8, 128, 128, cast , { ixt_common:{ ixt_support:{ ias_id: ESP_CAST,}}}}, + + { CIPHERNAME_BLOWFISH, 8, 96, 448, blowfish, { ixt_common:{ ixt_support:{ ias_id: ESP_BLOWFISH,}}}}, + + { CIPHERNAME_3DES, 8, 192, 192, des_ede3, { ixt_common:{ ixt_support:{ ias_id: ESP_3DES,}}}}, + +#ifdef CONFIG_KLIPS_ENC_1DES + + { CIPHERNAME_1DES, 8, 64, 64, des_ede1, { ixt_common:{ ixt_support:{ ias_id: ESP_DES,}}}}, + +#endif + + { 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_common.ixt_version = IPSEC_ALG_VERSION; + + cptr->alg.ixt_common.ixt_module = THIS_MODULE; + + atomic_set (& cptr->alg.ixt_common.ixt_refcnt, 0); + + strncpy (cptr->alg.ixt_common.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_common.ixt_name)); + + + + cptr->alg.ixt_common.ixt_blocksize=cptr->blocksize; + + cptr->alg.ixt_common.ixt_support.ias_keyminbits=cptr->minbits; + + cptr->alg.ixt_common.ixt_support.ias_keymaxbits=cptr->maxbits; + + cptr->alg.ixt_common.ixt_state = 0; + + if (excl_crypto) cptr->alg.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL; + + cptr->alg.ixt_e_keylen=cptr->alg.ixt_common.ixt_support.ias_keymaxbits/8; + + cptr->alg.ixt_e_ctx_size = 0; + + cptr->alg.ixt_common.ixt_support.ias_exttype = 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_common.ixt_data = cptr; + + + + ret=register_ipsec_alg_enc(&cptr->alg); + + printk(KERN_INFO "KLIPS cryptoapi interface: " + + "alg_type=%d alg_id=%d name=%s " + + "keyminbits=%d keymaxbits=%d, %s(%d)\n", + + cptr->alg.ixt_common.ixt_support.ias_exttype, + + cptr->alg.ixt_common.ixt_support.ias_id, + + cptr->alg.ixt_common.ixt_name, + + cptr->alg.ixt_common.ixt_support.ias_keyminbits, + + cptr->alg.ixt_common.ixt_support.ias_keymaxbits, + + ret ? "not found" : "found", 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_crypto > 0) + + printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" + + "name=%s key_e=%p \n", + + alg->ixt_common.ixt_name, key_e); + + if (!key_e) { + + printk(KERN_ERR "klips_debug: _capi_destroy_key:" + + "name=%s NULL key_e!\n", + + alg->ixt_common.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_common.ixt_data; + + if (!cptr) { + + printk(KERN_ERR "_capi_new_key(): " + + "NULL ixt_data (?!) for \"%s\" algo\n" + + , alg->ixt_common.ixt_name); + + goto err; + + } + + if (debug_crypto > 0) + + printk(KERN_DEBUG "klips_debug:_capi_new_key:" + + "name=%s cptr=%p key=%p keysize=%d\n", + + alg->ixt_common.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_common.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_common.ixt_name, keylen); + + crypto_free_tfm(tfm); + + tfm=NULL; + + } + +err: + + if (debug_crypto > 0) + + printk(KERN_DEBUG "klips_debug:_capi_new_key:" + + "name=%s key=%p keylen=%d tfm=%p\n", + + alg->ixt_common.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_crypto > 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_crypto > 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_crypto>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(cptr->alg.ixt_common.ixt_support.ias_name == NULL) { + + cptr->alg.ixt_common.ixt_support.ias_name = cptr->ciphername; + + } + + + + if( setup_cipher(cptr->ciphername) ) { + + if (debug_crypto > 0) + + printk(KERN_DEBUG "klips_debug:" + + "setup_cipher_list():" + + "ciphername=%s found\n" + + , cptr->ciphername); + + + + if (setup_ipsec_alg_capi_cipher(cptr) != 0) { + + printk(KERN_ERR "klips_debug:" + + "setup_cipher_list():" + + "ciphername=%s failed ipsec_alg_register\n" + + , cptr->ciphername); + + } + + } else { + + printk(KERN_INFO "KLIPS: 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_common.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_common.ixt_state & IPSEC_ALG_ST_REGISTERED) { + + test_ret=ipsec_alg_test( + + cptr->alg.ixt_common.ixt_support.ias_exttype, + + cptr->alg.ixt_common.ixt_support.ias_id, + + test_crypto); + + printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", + + cptr->alg.ixt_common.ixt_support.ias_exttype, + + cptr->alg.ixt_common.ixt_support.ias_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_crypto) { + + 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 + + + +#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,547 @@ + +/* + + * processing code for ESP + + * Copyright (C) 2003 Michael Richardson + + * + + * 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 . + + * + + * 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 AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +#define __NO_VERSION__ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *lock* */ + +# endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + + + +#include + +#include + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_rcv.h" + +#include "libreswan/ipsec_xmit.h" + + + +#include "libreswan/ipsec_auth.h" + + + +#ifdef CONFIG_KLIPS_ESP + +#include "libreswan/ipsec_esp.h" + +#endif /* CONFIG_KLIPS_ESP */ + + + +#include "libreswan/ipsec_proto.h" + +#include "libreswan/ipsec_alg.h" + + + +#ifdef CONFIG_KLIPS_DEBUG + +#define ESP_DMP(_x,_y,_z) if(debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z) + +#else + +#define ESP_DMP(_x,_y,_z) + +#endif + + + +#ifdef CONFIG_KLIPS_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_transport_header(skb); + + 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; + + //unsigned char *idat = (unsigned char *)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_transport_header(skb)[irs->ilen]); + + + + 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; + + + + 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; + + } + + aa = irs->authfuncs; + + + + /* copy the initialized keying material */ + + memcpy(&tctx, irs->ictx, irs->ictx_len); + + + +#ifdef HASH_DEBUG + + ESP_DMP("ictx", irs->ictx, irs->ictx_len); + + + + ESP_DMP("mac_esp", (caddr_t)espp, irs->ilen); + +#endif + + (*aa->update)((void *)&tctx, (caddr_t)espp, irs->ilen); + + + + (*aa->final)(irs->hash, (void *)&tctx); + + + +#ifdef HASH_DEBUG + + ESP_DMP("hash1", irs->hash, aa->hashlen); + +#endif + + + + memcpy(&tctx, irs->octx, irs->octx_len); + + + +#ifdef HASH_DEBUG + + ESP_DMP("octx", irs->octx, irs->octx_len); + +#endif + + + + (*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 i; + + int pad = 0, padlen; + + int badpad = 0; + + int esphlen = 0; + + __u8 *idat; /* pointer to content to be decrypted/authenticated */ + + int encaplen = 0; + + struct sk_buff *skb; + + struct ipsec_alg_enc *ixt_e=NULL; + + + + skb=irs->skb; + + + + idat = skb_transport_header(skb); + + + + /* encaplen is the distance between the end of the IP + + * header and the beginning of the ESP header. + + * on ESP headers it is zero, but on UDP-encap ESP + + * it includes the space for the UDP header. + + * + + * Note: UDP-encap code has already moved the + + * skb->data forward to accomodate this. + + */ + + encaplen = skb_transport_header(skb) - (skb_network_header(skb) + irs->iphlen); + + + + ixt_e=ipsp->ips_alg_enc; + + esphlen = ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8; + + KLIPS_PRINT(debug_rcv, + + "klips_debug:ipsec_rcv: " + + "encalg=%d esphlen=%d\n", + + ipsp->ips_encalg, esphlen); + + + + idat += esphlen; + + irs->ilen -= esphlen; + + + + if (ipsec_alg_esp_encrypt(ipsp, + + idat, irs->ilen, espp->esp_iv, + + IPSEC_ALG_DECRYPT) <= 0) { + + KLIPS_ERROR(debug_rcv, "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; + + } + + + + ESP_DMP("postdecrypt", idat, irs->ilen); + + + + 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: 0x 0x ...\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. + + * + + * XXX this is really unnecessary, since odds we are in tunnel + + * mode, and we will be *removing* this IP header. + + * + + */ + + memmove((void *)(idat - irs->iphlen), + + (void *)(skb_network_header(skb)), irs->iphlen); + + + + ESP_DMP("esp postmove", (idat - irs->iphlen), + + irs->iphlen + irs->ilen); + + + + /* 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); + + skb_set_network_header(skb, ipsec_skb_offset(skb, idat - irs->iphlen)); + + irs->ipp = ip_hdr(skb); + + + + ESP_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) + +{ + +#ifdef CONFIG_KLIPS_ENC_3DES + + __u32 iv[2]; + +#endif + + struct esphdr *espp; + + int ilen = 0; + + int padlen = 0, i; + + unsigned char *dat; + + unsigned char *idat, *pad; + + __u8 hash[AH_AMAX]; + + union { + +#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + + MD5_CTX md5; + +#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + + SHA1_CTX sha1; + +#endif /* CONFIG_KLIPS_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_KLIPS_ENC_3DES) + +#ifdef CONFIG_KLIPS_ENC_3DES + + case ESP_3DES: + +#endif /* CONFIG_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_ENC_3DES */ + + default: + + ixs->stats->tx_errors++; + + return IPSEC_XMIT_ESP_BADALG; + + } + + + + switch(ixs->ipsp->ips_encalg) { + +#if defined(CONFIG_KLIPS_ENC_3DES) + +#ifdef CONFIG_KLIPS_ENC_3DES + + case ESP_3DES: + +#endif /* CONFIG_KLIPS_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_KLIPS_ENC_3DES) */ + + default: + + ixs->stats->tx_errors++; + + return IPSEC_XMIT_ESP_BADALG; + + } + + + + switch(ixs->ipsp->ips_authalg) { + +#ifdef CONFIG_KLIPS_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)); + + osMD5Update(&tctx.md5, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); + + ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Final(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)); + + osMD5Update(&tctx.md5, hash, AHMD596_ALEN); + + ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Final(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_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_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_KLIPS_AUTH_HMAC_SHA1 */ + + case AH_NONE: + + break; + + default: + + ixs->stats->tx_errors++; + + return IPSEC_XMIT_AH_BADALG; + + } + + + + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, espp)); + + + + return IPSEC_XMIT_OK; + +} + + + + + +struct xform_functions esp_xform_funcs[]={ + + { + + protocol: IPPROTO_ESP, + + 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, + + }, + +}; + + + +#ifndef CONFIG_XFRM_ALTERNATE_STACK + +#ifdef NET_26 + +struct inet_protocol esp_protocol = { + + .handler = ipsec_rcv, + + .no_policy = 1, + +}; + +#else + +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 /* NET_26 */ + +#endif /* CONFIG_XFRM_ALTERNATE_STACK */ + + + +#endif /* !CONFIG_KLIPS_ESP */ + + + +/* + + * Local variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /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,454 @@ + +/* + + * @(#) Initialization code. + + * Copyright (C) 1996, 1997 John Ioannidis. + + * Copyright (C) 1998 - 2002 Richard Guy Briggs + + * 2001 - 2004 Michael Richardson + + * + + * 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 . + + * + + * 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. + + * + + */ + + + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include /* struct sockaddr_in */ + +#include + +#include /* get_random_bytes() */ + +#include + + + +#include + + + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* 23_SPINLOCK */ + +# include /* *lock* */ + +# endif /* 23_SPINLOCK */ + +#endif /* SPINLOCK */ + + + +#include + + + +#ifdef CONFIG_PROC_FS + +# include + +#endif /* CONFIG_PROC_FS */ + + + +#ifdef NETLINK_SOCK + +# include + +#else + +# include + +#endif + + + +#include "libreswan/radij.h" + + + +#include "libreswan/ipsec_life.h" + +#include "libreswan/ipsec_stats.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_mast.h" + + + +#include "libreswan/ipsec_rcv.h" + +#include "libreswan/ipsec_xmit.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + + + +#ifdef CONFIG_KLIPS_IPCOMP + +# include "libreswan/ipcomp.h" + +#endif /* CONFIG_KLIPS_IPCOMP */ + + + +#include "libreswan/ipsec_proto.h" + +#include "libreswan/ipsec_alg.h" + + + +#include + +#include + + + +#if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + +#include + +#endif + + + +#ifndef HAVE_UDP_ENCAP_CONVERT + +# if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(HAVE_XFRM4_UDP_REGISTER) + +# warning "You are trying to build KLIPS2.6 with NAT-T support, but you did not" + +# error "properly apply the NAT-T patch to your 2.6 kernel source tree." + +# endif + +#endif + + + +#if !defined(CONFIG_KLIPS_ESP) && !defined(CONFIG_KLIPS_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 + + + +struct prng ipsec_prng; + + + + + +#if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + +xfrm4_rcv_encap_t klips_old_encap = NULL; + +#endif + + + +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 + + + +/* + + * inet_*_protocol returns void on 2.4.x, int on 2.6.x + + * So we need our own wrapper + +*/ + +#ifdef NET_26 + +static inline int + +libreswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol, char *protstr) + +{ + + int err = inet_add_protocol(prot, protocol); + + if (err) + + printk(KERN_ERR "KLIPS: can not register %s protocol - recompile with CONFIG_INET_%s disabled or as module\n", protstr,protstr); + + return err; + +} + + + +static inline int + +libreswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol) + +{ + + return inet_del_protocol(prot, protocol); + +} + + + +#else + +static inline int + +libreswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol) + +{ + + inet_add_protocol(prot); + + return 0; + +} + + + +static inline int + +libreswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol) + +{ + + inet_del_protocol(prot); + + return 0; + +} + + + +#endif + + + +/* void */ + +int + +ipsec_klips_init(void) + +{ + + int error = 0; + + unsigned char seed[256]; + +#ifdef CONFIG_KLIPS_ENC_3DES + + extern int des_check_key; + + + + /* turn off checking of keys */ + + des_check_key=0; + +#endif /* CONFIG_KLIPS_ENC_3DES */ + + + + KLIPS_PRINT(1, "klips_info:ipsec_init: " + + "KLIPS startup, Libreswan KLIPS IPsec stack version: %s\n", + + ipsec_version_code()); + + + + error = ipsec_xmit_state_cache_init (); + + if (error) + + goto error_xmit_state_cache; + + + + error = ipsec_rcv_state_cache_init (); + + if (error) + + goto error_rcv_state_cache; + + + + error |= ipsec_proc_init(); + + if (error) + + goto error_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(); + + if (error) + + goto error_sadb_init; + + + + error |= ipsec_radijinit(); + + if (error) + + goto error_radijinit; + + + + error |= pfkey_init(); + + if (error) + + goto error_pfkey_init; + + + + error |= register_netdevice_notifier(&ipsec_dev_notifier); + + if (error) + + goto error_netdev_notifier; + + + +#ifdef CONFIG_XFRM_ALTERNATE_STACK + + error = xfrm_register_alternate_rcv (ipsec_rcv); + + if (error) + + goto error_xfrm_register; + + + +#else // CONFIG_XFRM_ALTERNATE_STACK + + + +#ifdef CONFIG_KLIPS_ESP + + error |= libreswan_inet_add_protocol(&esp_protocol, IPPROTO_ESP,"ESP"); + + if (error) + + goto error_libreswan_inet_add_protocol_esp; + + + +#endif /* CONFIG_KLIPS_ESP */ + + + +#ifdef CONFIG_KLIPS_AH + + error |= libreswan_inet_add_protocol(&ah_protocol, IPPROTO_AH,"AH"); + + if (error) + + goto error_libreswan_inet_add_protocol_ah; + +#endif /* CONFIG_KLIPS_AH */ + + + +/* we never actually link IPCOMP to the stack */ + +#ifdef IPCOMP_USED_ALONE + +#ifdef CONFIG_KLIPS_IPCOMP + + error |= libreswan_inet_add_protocol(&comp_protocol, IPPROTO_COMP,"IPCOMP"); + + if (error) + + goto error_libreswan_inet_add_protocol_comp; + +#endif /* CONFIG_KLIPS_IPCOMP */ + +#endif + + + +#endif // CONFIG_XFRM_ALTERNATE_STACK + + + + error |= ipsec_tunnel_init_devices(); + + if (error) + + goto error_tunnel_init_devices; + + + + error |= ipsec_mast_init_devices(); + + + +#if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + + /* register our ESP-UDP handler */ + + if(udp4_register_esp_rcvencap(klips26_rcv_encap + + , &klips_old_encap)!=0) { + + printk(KERN_ERR "KLIPS: can not register klips_rcv_encap function\n"); + + } + +#endif + + + + + +#ifdef CONFIG_SYSCTL + + error |= ipsec_sysctl_register(); + + if (error) + + goto error_sysctl_register; + +#endif + + + + ipsec_alg_init(); + + + + get_random_bytes((void *)seed, sizeof(seed)); + + prng_init(&ipsec_prng, seed, sizeof(seed)); + + + + return error; + + + + // undo ipsec_sysctl_register + +error_sysctl_register: + + ipsec_tunnel_cleanup_devices(); + +error_tunnel_init_devices: + +#ifdef CONFIG_XFRM_ALTERNATE_STACK + + xfrm_deregister_alternate_rcv(ipsec_rcv); + +error_xfrm_register: + +#else // CONFIG_XFRM_ALTERNATE_STACK + +#ifdef IPCOMP_USED_ALONE + +#ifdef CONFIG_KLIPS_IPCOMP + +error_libreswan_inet_add_protocol_comp: + + libreswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP); + +#endif /* CONFIG_KLIPS_IPCOMP */ + +#endif + +#ifdef CONFIG_KLIPS_AH + +error_libreswan_inet_add_protocol_ah: + + libreswan_inet_del_protocol(&ah_protocol, IPPROTO_AH); + +#endif + +#ifdef CONFIG_KLIPS_ESP + +error_libreswan_inet_add_protocol_esp: + + libreswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP); + +#endif + +#endif + + unregister_netdevice_notifier(&ipsec_dev_notifier); + +error_netdev_notifier: + + pfkey_cleanup(); + +error_pfkey_init: + + ipsec_radijcleanup(); + +error_radijinit: + + ipsec_sadb_cleanup(0); + + ipsec_sadb_free(); + +error_sadb_init: + +error_proc_init: + + // ipsec_proc_init() does not cleanup after itself, so we have to do it here + + // TODO: ipsec_proc_init() should roll back what it chaned on failure + + ipsec_proc_cleanup(); + + ipsec_rcv_state_cache_cleanup (); + +error_rcv_state_cache: + + ipsec_xmit_state_cache_cleanup (); + +error_xmit_state_cache: + + return error; + +} + + + + + +/* void */ + +int + +ipsec_cleanup(void) + +{ + + int error = 0; + + + +#ifdef CONFIG_SYSCTL + + ipsec_sysctl_unregister(); + +#endif + +#if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + + if(udp4_unregister_esp_rcvencap(klips_old_encap) < 0) { + + printk(KERN_ERR "KLIPS: can not unregister klips_rcv_encap function\n"); + + } + +#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"); + + + +#ifdef CONFIG_XFRM_ALTERNATE_STACK + + + + xfrm_deregister_alternate_rcv(ipsec_rcv); + + + +#else // CONFIG_XFRM_ALTERNATE_STACK + + + +/* we never actually link IPCOMP to the stack */ + +#ifdef IPCOMP_USED_ALONE + +#ifdef CONFIG_KLIPS_IPCOMP + + if (libreswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP) < 0) + + printk(KERN_INFO "klips_debug:ipsec_cleanup: " + + "comp close: can't remove protocol\n"); + +#endif /* CONFIG_KLIPS_IPCOMP */ + +#endif /* IPCOMP_USED_ALONE */ + + + +#ifdef CONFIG_KLIPS_AH + + if (libreswan_inet_del_protocol(&ah_protocol, IPPROTO_AH) < 0) + + printk(KERN_INFO "klips_debug:ipsec_cleanup: " + + "ah close: can't remove protocol\n"); + +#endif /* CONFIG_KLIPS_AH */ + + + +#ifdef CONFIG_KLIPS_ESP + + if (libreswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP) < 0) + + printk(KERN_INFO "klips_debug:ipsec_cleanup: " + + "esp close: can't remove protocol\n"); + +#endif /* CONFIG_KLIPS_ESP */ + + + +#endif // CONFIG_XFRM_ALTERNATE_STACK + + + + 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_rcv_state_cache_cleanup (); + + ipsec_xmit_state_cache_cleanup (); + + + + ipsec_rcv_state_cache_cleanup (); + + ipsec_xmit_state_cache_cleanup (); + + + + ipsec_proc_cleanup(); + + + + prng_final(&ipsec_prng); + + + + return error; + +} + + + +#ifdef MODULE + +int + +init_module(void) + +{ + + int error = 0; + + + + error |= ipsec_klips_init(); + + + + return error; + +} + + + +#ifndef NET_26 + +void + +cleanup_module(void) + +{ + + KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ + + "klips_debug:cleanup_module: " + + "calling ipsec_cleanup.\n"); + + + + ipsec_cleanup(); + + + + KLIPS_PRINT(1, "klips_info:cleanup_module: " + + "ipsec module unloaded.\n"); + +} + +#endif + +#endif /* MODULE */ + + + +/* + + * + + * 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,254 @@ + +/* + + * processing code for IPCOMP + + * Copyright (C) 2003 Michael Richardson + + * + + * 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 . + + * + + * 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 AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +#define __NO_VERSION__ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *lock* */ + +# endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + + + +#include + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_rcv.h" + +#include "libreswan/ipsec_xmit.h" + + + +#include "libreswan/ipsec_auth.h" + + + +#ifdef CONFIG_KLIPS_IPCOMP + +#include "libreswan/ipsec_ipcomp.h" + +#endif /* CONFIG_KLIPS_IPCOMP */ + + + +#include "libreswan/ipsec_proto.h" + + + +#ifdef CONFIG_KLIPS_IPCOMP + +enum ipsec_rcv_value + +ipsec_rcv_ipcomp_checks(struct ipsec_rcv_state *irs, + + struct sk_buff *skb) + +{ + + int ipcompminlen; + + + + ipcompminlen = 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_transport_header(skb); + + 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_transport_header(skb), skb->len); + + + + if(ipsp == NULL) { + + return IPSEC_RCV_SAIDNOTFOUND; + + } + + + + if(sysctl_ipsec_inbound_policy_check && + + ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) != (ntohl(irs->said.spi) & 0x0000ffff)) && + + (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 = KLIPS_SATOT(debug_rcv, &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 = ip_hdr(skb); + +#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_KLIPS_DEBUG + + unsigned int old_tot_len = ntohs(ixs->iph->tot_len); + +#endif /* CONFIG_KLIPS_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 = ip_hdr(ixs->skb); + +#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_KLIPS_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_KLIPS_DEBUG */ + + + + return IPSEC_XMIT_OK; + +} + + + +struct xform_functions ipcomp_xform_funcs[]={ + + { + + protocol: IPPROTO_COMP, + + 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) */ + +#ifndef CONFIG_XFRM_ALTERNATE_STACK + +#ifdef CONFIG_KLIPS_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_KLIPS_IPCOMP */ + +#endif /* CONFIG_XFRM_ALTERNATE_STACK */ + +#endif + + + +#endif /* CONFIG_KLIPS_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,123 @@ + +/* + + * processing code for IPIP + + * Copyright (C) 2003 Michael Richardson + + * + + * 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 . + + * + + * 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 AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +#define __NO_VERSION__ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *lock* */ + +# endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + + + +#include + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_rcv.h" + +#include "libreswan/ipsec_xmit.h" + + + +#include "libreswan/ipsec_auth.h" + +#include "libreswan/ipsec_ipip.h" + +#include "libreswan/ipsec_param.h" + + + +#include "libreswan/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 = ip_hdr(ixs->skb)->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; + + } + + ixs->iph->ttl = SYSCTL_IPSEC_DEFAULT_TTL; + + 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 + + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ip_hdr(ixs->skb))); + +#endif /* NET_21 */ + + return IPSEC_XMIT_OK; + +} + + + +struct xform_functions ipip_xform_funcs[]={ + + { + + protocol: IPPROTO_IPIP, + + 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_kern24.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,74 @@ + +/* + + * Copyright 2005 (C) Michael Richardson + + * + + * This is a file of functions which are present in 2.6 kernels, + + * but are not available by default in the 2.4 series. + + * + + * As such this code is usually from the Linux kernel, and is covered by + + * GPL. + + * + + * 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 . + + * + + * 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. + + * + + * $Id: ipsec_kern24.c,v 1.2 2005/05/20 03:19:18 mcr Exp $ + + * + + */ + + + +#include + +#include + +#include + + + +/* + + * printk rate limiting, lifted from the networking subsystem. + + * + + * This enforces a rate limit: not more than one kernel message + + * every printk_ratelimit_jiffies to make a denial-of-service + + * attack impossible. + + */ + +static spinlock_t ratelimit_lock = SPIN_LOCK_UNLOCKED; + + + +int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst) + +{ + + static unsigned long toks = 10*5*HZ; + + static unsigned long last_msg; + + static int missed; + + unsigned long flags; + + unsigned long now = jiffies; + + + + spin_lock_irqsave(&ratelimit_lock, flags); + + toks += now - last_msg; + + last_msg = now; + + if (toks > (ratelimit_burst * ratelimit_jiffies)) + + toks = ratelimit_burst * ratelimit_jiffies; + + if (toks >= ratelimit_jiffies) { + + int lost = missed; + + missed = 0; + + toks -= ratelimit_jiffies; + + spin_unlock_irqrestore(&ratelimit_lock, flags); + + if (lost) + + printk(KERN_WARNING "printk: %d messages suppressed.\n", lost); + + return 1; + + } + + missed++; + + spin_unlock_irqrestore(&ratelimit_lock, flags); + + return 0; + +} + + + +/* minimum time in jiffies between messages */ + +int printk_ratelimit_jiffies = 5*HZ; + + + +/* number of messages we send before ratelimiting */ + +int printk_ratelimit_burst = 10; + + + +int printk_ratelimit(void) + +{ + + return __printk_ratelimit(printk_ratelimit_jiffies, + + printk_ratelimit_burst); + +} + --- /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,221 @@ + +/* + + * @(#) lifetime structure utilities + + * + + * Copyright (C) 2001 Richard Guy Briggs + + * and Michael Richardson + + * + + * 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 . + + * + + * 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. + + * + + * + + */ + + + +/* + + * 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 + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif /* for CONFIG_IP_FORWARD */ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#include /* struct device, struct net_device_stats and other headers */ + +#include /* eth_type_trans */ + +#include + +#include + +#include + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_life.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_eroute.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + + + +#include "libreswan/ipsec_sa.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_ipe4.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + + + +#ifdef CONFIG_KLIPS_IPCOMP + +#include "libreswan/ipcomp.h" + +#endif /* CONFIG_KLIPS_IPCOMP */ + + + +#include + +#include + + + +#include "libreswan/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 != K_SADB_SASTATE_DYING) { + + pfkey_expire(ips, 0); + + } + + ips->ips_state = K_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; + + } + + } + +} + + + + + +/* + + * + + * 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,841 @@ + +/* + + * IPSEC MAST code. + + * Copyright (C) 2005 Michael Richardson + + * + + * 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 . + + * + + * 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.7 2005/04/29 05:10:22 mcr Exp $"; + + + +#define __NO_VERSION__ + +#include + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif /* for CONFIG_IP_FORWARD */ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include + +#include + +#include + +#include + + + +#include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + + + +#include + + + +#include /* icmp_send() */ + +#include + +#ifdef NETDEV_23 + +# include + +#endif /* NETDEV_23 */ + + + +#include + + + +#include "libreswan/ipsec_kversion.h" + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_life.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_eroute.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_sa.h" + +#include "libreswan/ipsec_xmit.h" + +#include "libreswan/ipsec_mast.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_ipe4.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + +#include "libreswan/ipsec_kern24.h" + + + +#include + +#include + + + +#include "libreswan/ipsec_proto.h" + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + +#include + +#endif + + + +int ipsec_mastdevice_count = -1; + +int debug_mast; + + + +static __u32 zeroes[64]; + + + +DEBUG_NO_STATIC int + +ipsec_mast_open(struct net_device *dev) + +{ + + struct mastpriv *prv = dev->priv; + + + + prv = prv; + + + + /* + + * Can't open until attached. + + */ + + + + KLIPS_PRINT(debug_mast & DB_MAST_INIT, + + "klips_debug:ipsec_mast_open: " + + "dev = %s\n", + + dev->name); + + + + return 0; + +} + + + +DEBUG_NO_STATIC int + +ipsec_mast_close(struct net_device *dev) + +{ + + return 0; + +} + + + +static inline int ipsec_mast_xmit2(struct sk_buff *skb) + +{ + + return dst_output(skb); + +} + + + +int ip_cmsg_send_ipsec(struct cmsghdr *cmsg, struct ipcm_cookie *ipc) + +{ + + struct ipsec_sa *sa1; + + xfrm_sec_unique_t *ref; + + struct sec_path *sp; + + + + if(cmsg->cmsg_len != CMSG_LEN(sizeof(xfrm_sec_unique_t))) { + + return -EINVAL; + + } + + + + ref = (xfrm_sec_unique_t *)CMSG_DATA(cmsg); + + + + sp = secpath_dup(NULL); + + if(!sp) { + + return -EINVAL; + + } + + + + sp->ref = *ref; + + KLIPS_PRINT(debug_mast, "sending with saref=%u\n", sp->ref); + + + + sa1 = ipsec_sa_getbyref(sp->ref); + + if(sa1 && sa1->ips_out) { + + ipc->oif = sa1->ips_out->ifindex; + + KLIPS_PRINT(debug_mast, "setting oif: %d\n", ipc->oif); + + } + + ipsec_sa_put(sa1); + + + + ipc->sp = sp; + + + + return 0; + +} + + + +#if 0 + +/* Paul: This seems to be unused dead code */ + +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->ifindex /* 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 < skb_network_header(ixs->skb) - 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)(skb_network_header(ixs->skb) - ixs->skb->data), + + ixs->skb->len); + + return IPSEC_XMIT_PUSHPULLERR; + + } + + __skb_pull(ixs->skb, skb_network_header(ixs->skb)- 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; + +} + +#endif + + + +/* + + * 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 net_device *dev) + +{ + + struct ipsec_xmit_state ixs_mem; + + struct ipsec_xmit_state *ixs = &ixs_mem; + + enum ipsec_xmit_value stat = IPSEC_XMIT_OK; + + IPsecSAref_t SAref; + + + + if(skb == NULL) { + + printk("mast start_xmit passed NULL\n"); + + return 0; + + } + + + + memset(&ixs_mem, 0, sizeof(struct ipsec_xmit_state)); + + + + ixs->skb = skb; + + SAref = 0; + + if(skb->nfmark & 0x80000000) { + + SAref = NFmark2IPsecSAref(skb->nfmark); + + KLIPS_PRINT(debug_mast, "getting SAref=%d from nfmark\n", + + SAref); + + } + + + + if(skb->sp && skb->sp->ref != IPSEC_SAREF_NULL) { + + SAref = skb->sp->ref; + + KLIPS_PRINT(debug_mast, "getting SAref=%d from sec_path\n", + + SAref); + + } + + + + KLIPS_PRINT(debug_mast, "skb=%p\n", skb); + + + + ipsec_xmit_sanity_check_skb(ixs); + + + + ixs->ipsp = ipsec_sa_getbyref(SAref); + + if(ixs->ipsp == NULL) { + + KLIPS_ERROR(debug_mast, "%s: no SA for saref=%d (sp=%p)\n", + + dev->name, SAref, skb->sp); + + ipsec_kfree_skb(skb); + + return 0; + + } + + + + /* + + * we should be calculating the MTU by looking up a route + + * based upon the destination in the SA, and then cache + + * it into the SA, but we don't do that right now. + + */ + + ixs->cur_mtu = 1460; + + ixs->physmtu = 1460; + + + + stat = ipsec_xmit_encap_bundle_2(ixs); + + + + if(stat != IPSEC_XMIT_OK) { + + /* SA processing failed */ + + /* log it somehow */ + + goto failed; + + } + + + + /* do any final NAT-encapsulation */ + + stat = ipsec_nat_encap(ixs); + + if(stat != IPSEC_XMIT_OK) { + + goto failed; + + } + + + + /* now send the packet again */ + + { + + struct flowi fl; + + + + memset(&fl, 0, sizeof(fl)); + + ipsec_xmit_send(ixs, &fl); + + } + + + +failed: + + ipsec_xmit_cleanup(ixs); + + + + if(ixs->ipsp) { + + ipsec_sa_put(ixs->ipsp); + + ixs->ipsp=NULL; + + } + + if(ixs->skb) { + + ipsec_kfree_skb(ixs->skb); + + ixs->skb=NULL; + + } + + return 0; + +} + + + +DEBUG_NO_STATIC struct net_device_stats * + +ipsec_mast_get_stats(struct net_device *dev) + +{ + + return &(((struct mastpriv *)(dev->priv))->mystats); + +} + + + +#if 0 + +/* + + * 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 net_device *dev, + + unsigned short type, void *daddr, void *saddr, unsigned len) + +{ + + struct mastpriv *prv = dev->priv; + + struct net_device_stats *stats; /* This device's statistics */ + + int ret = 0; + + + + 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\n", + + 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); + + + + /* 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; + + } + + } else { + + KLIPS_PRINT(debug_mast, + + "klips_debug:ipsec_mast_hard_header: " + + "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); + + } + + + + return ret; + +} + + + +DEBUG_NO_STATIC int + +ipsec_mast_rebuild_header(struct sk_buff *skb) + +{ + + struct mastpriv *prv = skb->dev->priv; + + + + prv = prv; + + return 0; + +} + + + +DEBUG_NO_STATIC int + +ipsec_mast_set_mac_address(struct net_device *dev, void *addr) + +{ + + struct mastpriv *prv = dev->priv; + + + + prv = prv; + + return 0; + + + +} + + + +DEBUG_NO_STATIC void + +ipsec_mast_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr) + +{ + + struct mastpriv *prv = dev->priv; + + + + 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; + + } + + + + KLIPS_PRINT(debug_mast & DB_MAST_REVEC, + + "klips_debug:ipsec_mast: " + + "Revectored cache_update\n"); + + return; + +} + +#endif + + + +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 net_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; + +} + + + +DEBUG_NO_STATIC int + +ipsec_mast_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + +{ + + struct ipsecmastconf *cf = (struct ipsecmastconf *)&ifr->ifr_data; + + struct ipsecpriv *prv = dev->priv; + + + + cf = cf; + + prv=prv; + + + + 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) { + + 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 net_device *dev = ptr; + + struct mastpriv *priv = dev->priv; + + + + priv = priv; + + + + 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; + + } + + 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_probe(struct net_device *dev) + +{ + + int i; + + + + KLIPS_PRINT(debug_mast, + + "klips_debug:ipsec_mast_init: " + + "allocating %lu bytes initialising device: %s\n", + + (unsigned long) sizeof(struct mastpriv), + + 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 mastpriv), GFP_KERNEL); + + if (dev->priv == NULL) + + return -ENOMEM; + + memset((caddr_t)(dev->priv), 0, sizeof(struct mastpriv)); + + + + 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 = 8+20+20+8; + + dev->mtu = 0; + + dev->addr_len = 0; + + dev->type = ARPHRD_NONE; + + dev->tx_queue_len = 10; + + memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ + + + + /* New-style flags. */ + + dev->flags = IFF_NOARP; + + + + /* We're done. Have I forgotten anything? */ + + return 0; + +} + + + +struct net_device *mastdevices[IPSEC_NUM_IFMAX]; + +int mastdevices_max=-1; + + + +int ipsec_mast_createnum(int vifnum) + +{ + + struct net_device *im; + + int vifentry; + + + + if(vifnum > IPSEC_NUM_IFMAX) { + + return -ENOENT; + + } + + + + if(mastdevices[vifnum]!=NULL) { + + return -EEXIST; + + } + + + + /* no identical device */ + + if(vifnum > mastdevices_max) { + + mastdevices_max=vifnum; + + } + + vifentry = vifnum; + + + + im = (struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL); + + if(im == NULL) { + + printk(KERN_ERR "failed to allocate space for mast%d device\n", vifnum); + + return -ENOMEM; + + } + + + + memset((caddr_t)im, 0, sizeof(struct net_device)); + + snprintf(im->name, IFNAMSIZ, MAST_DEV_FORMAT, vifnum); + + + +#ifdef HAVE_NEXT_DEV + + im->next = NULL; + +#endif + + im->init = ipsec_mast_probe; + + + + if(register_netdev(im) != 0) { + + printk(KERN_ERR "ipsec_mast: failed to register %s\n", + + im->name); + + return -EIO; + + } + + + + dev_hold(im); + + mastdevices[vifentry]=im; + + + + return 0; + +} + + + + + +int + +ipsec_mast_deletenum(int vifnum) + +{ + + struct net_device *dev_ipsec; + + + + if(vifnum > IPSEC_NUM_IFMAX) { + + return -ENOENT; + + } + + + + dev_ipsec = mastdevices[vifnum]; + + if(dev_ipsec == NULL) { + + return -ENOENT; + + } + + + + /* release reference */ + + mastdevices[vifnum]=NULL; + + ipsec_dev_put(dev_ipsec); + + + + KLIPS_PRINT(debug_tunnel, "Unregistering %s (refcnt=%d)\n", + + dev_ipsec->name, + + atomic_read(&dev_ipsec->refcnt)); + + unregister_netdev(dev_ipsec); + + KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", dev_ipsec->name); + +#ifndef NETDEV_23 + + kfree(dev_ipsec->name); + + dev_ipsec->name=NULL; + +#endif /* !NETDEV_23 */ + + kfree(dev_ipsec->priv); + + dev_ipsec->priv=NULL; + + + + return 0; + +} + + + + + +struct net_device * + +ipsec_mast_get_device(int vifnum) + +{ + + int ovifnum = vifnum; + + + + if(vifnum > IPSECDEV_OFFSET) { + + return ipsec_tunnel_get_device(vifnum-IPSECDEV_OFFSET); + + } else { + + struct net_device *nd; + + + + if(vifnum >= MASTTRANSPORT_OFFSET) { + + vifnum -= MASTTRANSPORT_OFFSET; + + } + + + + if(vifnum <= mastdevices_max) { + + nd = mastdevices[vifnum]; + + + + if(nd) dev_hold(nd); + + return nd; + + } else { + + KLIPS_ERROR(debug_tunnel, + + "no such vif %d (ovif=%d)\n", vifnum, ovifnum); + + return NULL; + + } + + } + +} + + + +unsigned int + +ipsec_mast_is_transport(int vifnum) + +{ + + if(vifnum > MASTTRANSPORT_OFFSET && vifnum priv); + + dev_mast->priv=NULL; + + dev_put(mastdevices[i]); + + mastdevices[i]=NULL; + + } + + } + + return error; + +} + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + + + + + --- /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,406 @@ + +/* + + * RCSID $Id: ipsec_md5c.c,v 1.10 2005/04/15 01:25:57 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 + +#include + + + +#include "libreswan/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 here; 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 osMD5Init(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 osMD5Update (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 osMD5Final (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); + + osMD5Update (context, PADDING, padLen); + + + + /* Append length (before padding) */ + + osMD5Update (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 + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /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,1042 @@ + +/* + + * @(#) /proc file system interface code. + + * + + * Copyright (C) 1996, 1997 John Ioannidis. + + * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs + + * 2001 Michael Richardson + + * + + * 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 . + + * + + * 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. + + */ + + + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + +#define __NO_VERSION__ + +#include + +#include /* printk() */ + +#include /* struct iphdr */ + + + +#include "libreswan/ipsec_kversion.h" + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct sockaddr_in */ + +#include + +#include /* copy_from_user */ + +#include + +#ifdef SPINLOCK + +#ifdef SPINLOCK_23 + +#include /* *lock* */ + +#else /* SPINLOCK_23 */ + +#include /* *lock* */ + +#endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + + + +#include + +#ifdef CONFIG_PROC_FS + +#include + +#endif /* CONFIG_PROC_FS */ + +#ifdef NETLINK_SOCK + +#include + +#else + +#include + +#endif + + + +#include "libreswan/radij.h" + + + +#include "libreswan/ipsec_life.h" + +#include "libreswan/ipsec_stats.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_xmit.h" + + + +#include "libreswan/ipsec_rcv.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + +#include "libreswan/ipsec_kern24.h" + + + +#ifdef CONFIG_KLIPS_IPCOMP + +#include "libreswan/ipcomp.h" + +#endif /* CONFIG_KLIPS_IPCOMP */ + + + +#include "libreswan/ipsec_proto.h" + + + +#include + +#include + + + +#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; + + + +#ifdef CONFIG_KLIPS_DEBUG + +int debug_esp = 0; + +int debug_ah = 0; + +int sysctl_ipsec_inbound_policy_check = 1; + +int debug_tunnel = 0; + +int debug_xmit = 0; + +int debug_xform = 0; + +int debug_eroute = 0; + +int debug_spi = 0; + +int debug_radij = 0; + +int debug_pfkey = 0; + +int debug_rcv = 0; + +int debug_netlink = 0; + +int sysctl_ipsec_debug_verbose = 0; + +int sysctl_ipsec_debug_ipcomp =0; + +int sysctl_ipsec_icmp = 0; + +int sysctl_ipsec_tos = 0; + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +#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_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_KLIPS_DEBUG + + if (debug_radij & DB_RJ_DUMPTREES) + + rj_dumptrees(); /* XXXXXXXXX */ + +#endif /* CONFIG_KLIPS_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) { + + ipsec_sa_get(sa_p); + + 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_KLIPS_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_KLIPS_IPCOMP */ + + + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + + { + + char *natttype_name; + + + + switch(sa_p->ips_natt_type) + + { + + case 0: + + natttype_name="none"; + + break; + + 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); + + } + +#else + + len += ipsec_snprintf(buffer + len, length-len, " natencap=na"); + +#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ + + + + /* we decrement by one, because this SA has been referenced in order to dump this info */ + + len += ipsec_snprintf(buffer + len,length-len, " refcount=%d", + + atomic_read(&sa_p->ips_refcount)-1); + + + + len += ipsec_snprintf(buffer+len, length-len, " ref=%d", + + sa_p->ips_ref); + + len += ipsec_snprintf(buffer+len, length-len, " refhim=%d", + + sa_p->ips_refhim); + + + + if(sa_p->ips_out) { + + len += ipsec_snprintf(buffer+len, length-len, " outif=%s:%d", + + sa_p->ips_out->name, + + sa_p->ips_transport_direct); + + } + +#ifdef CONFIG_KLIPS_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_KLIPS_DEBUG */ + + + + len += ipsec_snprintf(buffer+len, length-len, "\n"); + + + + ipsec_sa_put(sa_p); + + + + 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) + + { + + sa_p2 = sa_p; + + while(sa_p2 != NULL) { + + struct ipsec_sa *sa2n; + + sa_len = satot(&sa_p2->ips_said, + + 'x', sa, sizeof(sa)); + + + + len += ipsec_snprintf(buffer+len, length-len, "%s ", + + sa_len ? sa : " (error)"); + + + + sa2n = sa_p2->ips_next; + + sa_p2 = sa2n; + + } + + len += ipsec_snprintf(buffer+len, length-len, "\n"); + + + + 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 net_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 net_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, "Libreswan 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; + +} + + + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + +unsigned int natt_available = 1; + +#else + +unsigned int natt_available = 0; + +#endif + +#ifdef module_param + +module_param(natt_available, int, 0444); + +#else + +MODULE_PARM("natt_available","i"); + +#endif + + + +IPSEC_PROCFS_DEBUG_NO_STATIC + +int + +ipsec_natt_get_info(char *buffer, + + char **start, + + off_t offset, + + int length IPSEC_PROC_LAST_ARG) + +{ + + int len = 0; + + off_t begin = 0; + + + + len += ipsec_snprintf(buffer + len, + + length-len, "%d\n", + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + + 1 + +#else + + 0 + +#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; + + + + KLIPS_INC_USE; + + if(count > IPSEC_BIRTH_TEMPLATE_MAXLEN) { + + len = IPSEC_BIRTH_TEMPLATE_MAXLEN; + + } else { + + len = count; + + } + + + + if(copy_from_user(ibr->packet_template, buffer, len)) { + + KLIPS_DEC_USE; + + return -EFAULT; + + } + + ibr->packet_template_len = len; + + + + KLIPS_DEC_USE; + + + + return len; + +} + + + + + +#ifdef CONFIG_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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}, + + {"natt", &proc_net_ipsec_dir, NULL, ipsec_natt_get_info, NULL, NULL}, + + {"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_KLIPS_DEBUG + + error |= proc_register_dynamic(&proc_net, &ipsec_klipsdebug); + +#endif /* CONFIG_KLIPS_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_KLIPS_DEBUG + + error |= proc_register(proc_net, &ipsec_klipsdebug); + +#endif /* CONFIG_KLIPS_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_KLIPS_DEBUG + + if (proc_net_unregister(ipsec_klipsdebug.low_ino) != 0) + + printk("klips_debug:ipsec_cleanup: " + + "cannot unregister /proc/net/ipsec_klipsdebug\n"); + +#endif /* CONFIG_KLIPS_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_KLIPS_DEBUG + + remove_proc_entry("ipsec_klipsdebug", proc_net); + +#endif /* CONFIG_KLIPS_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 */ + +} + + + +/* + + * + + * 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,554 @@ + +/* + + * 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 . + + * + + * 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 AUTOCONF_INCLUDED + +#include + +#endif + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, struct net_device_stats and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* 23_SPINLOCK */ + +# include /* *lock* */ + +# endif /* 23_SPINLOCK */ + +#endif /* SPINLOCK */ + + + +#include + + + +#include "libreswan/ipsec_eroute.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_tunnel.h" /* struct ipsecpriv */ + +#include "libreswan/ipsec_xform.h" + + + +#include + +#include + + + +#include "libreswan/ipsec_proto.h" + + + +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 = 0; + + + + 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_KLIPS_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_KLIPS_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 0; + + } + + + + 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_KLIPS_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; ier_eaddr = *eaddr; + + retrt->er_emask = *emask; + + retrt->er_said = said; + + retrt->er_pid = pid; + + retrt->er_count = 0; + + retrt->er_lasttime = jiffies/HZ; + + + + { + + /* this is because gcc 3. doesn't like cast's as lvalues */ + + struct rjtentry *rje = (struct rjtentry *)&(retrt->er_rjt); + + caddr_t er = (caddr_t)&(retrt->er_eaddr); + + + + rje->rd_nodes->rj_key= er; + + } + + + + 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 = KLIPS_SATOT(debug_eroute, &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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_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; + +} + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /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,1859 @@ + +/* + + * receive code + + * Copyright (C) 1996, 1997 John Ioannidis. + + * Copyright (C) 1998-2003 Richard Guy Briggs. + + * Copyright (C) 2004-2007 Michael Richardson + + * Copyright (C) 2007-2008 Paul Wouters + + * + + * 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 . + + * + + * 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 AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +#define __NO_VERSION__ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + + + +#include + +#include + +#include + +#include + +#include + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *lock* */ + +# endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + + + +#include + + + +#include "libreswan/ipsec_kern24.h" + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_mast.h" + +#include "libreswan/ipsec_rcv.h" + + + +#include "libreswan/ipsec_auth.h" + + + +#include "libreswan/ipsec_esp.h" + + + +#ifdef CONFIG_KLIPS_AH + +#include "libreswan/ipsec_ah.h" + +#endif /* CONFIG_KLIPS_AH */ + + + +#ifdef CONFIG_KLIPS_IPCOMP + +#include "libreswan/ipsec_ipcomp.h" + +#endif /* CONFIG_KLIPS_COMP */ + + + +#include + +#include + + + +#include "libreswan/ipsec_proto.h" + +#include "libreswan/ipsec_alg.h" + +#include "libreswan/ipsec_kern24.h" + + + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + +#include + +#endif + + + +/* 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 + + + +/* + + * 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_KLIPS_AUTH_HMAC_MD5 + +struct auth_alg ipsec_rcv_md5[]={ + + {osMD5Init, osMD5Update, osMD5Final, AHMD596_ALEN} + +}; + + + +#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + + + +#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + +struct auth_alg ipsec_rcv_sha1[]={ + + {SHA1Init, SHA1Update, SHA1Final, AHSHA196_ALEN} + +}; + +#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + + + +static inline void ipsec_rcv_redodebug(struct ipsec_rcv_state *irs) + +{ + + struct iphdr * ipp = irs->ipp; + + struct in_addr ipsaddr, ipdaddr; + + + + 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)); + +} + + + +/* + + * look up the SA from the said in the header. + + * + + */ + +enum ipsec_rcv_value + +ipsec_rcv_decap_lookup(struct ipsec_rcv_state *irs + + , struct xform_functions *proto_funcs + + , struct ipsec_sa **pnewipsp) + +{ + + __u8 proto; + + struct ipsec_sa *newipsp; + + struct iphdr *ipp; + + struct sk_buff *skb; + + + + skb = irs->skb; + + ipp = irs->ipp; + + proto = ipp->protocol; + + + + 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; + + + + /* note: rcv_checks set up the said.spi value, if appropriate */ + + 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; + + } + + + + /* If it is in larval state, drop the packet, we cannot process yet. */ + + if(newipsp->ips_state == K_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 == K_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_ERROR(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_next != newipsp) { + + KLIPS_ERROR(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)"); + + } + + + + + + + + + + + + + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + + if (proto == IPPROTO_ESP) { + + 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 + + } + + + + *pnewipsp = newipsp; + + return IPSEC_RCV_OK; + +} + + + +void ip_cmsg_recv_ipsec(struct msghdr *msg, struct sk_buff *skb) + +{ + + struct ipsec_sa *sa1; + + struct sec_path *sp; + + xfrm_sec_unique_t refs[2]; + + + + sp = skb->sp; + + + + if(sp==NULL) return; + + + + KLIPS_PRINT(debug_rcv, "retrieving saref=%u from skb=%p\n", + + sp->ref, skb); + + + + sa1 = ipsec_sa_getbyref(sp->ref); + + if(sa1) { + + refs[1]= sa1->ips_refhim; + + } + + refs[0]=sp->ref; + + + + put_cmsg(msg, SOL_IP, IP_IPSEC_REFINFO, + + sizeof(xfrm_sec_unique_t)*2, &refs); + +} + + + + + +/* + + * decapsulate a single layer of ESP/AH/IPCOMP. + + * + + * the following things should be setup to enter this function. + + * + + * irs->stats == stats structure (or NULL) + + * irs->ipp = IP header. + + * irs->len = total length of packet + + * skb->nh.iph = ipp; + + * skb->h.raw = start of payload + + * irs->ipsp = NULL. + + * irs->iphlen = N/A = is recalculated. + + * irs->ilen = 0; + + * irs->authlen = 0; + + * irs->authfuncs = NULL; + + * irs->skb = the skb; + + * + + * proto_funcs should be from ipsec_esp.c, ipsec_ah.c or ipsec_ipcomp.c. + + * + + */ + +enum ipsec_rcv_value + +ipsec_rcv_decap_once(struct ipsec_rcv_state *irs + + , struct xform_functions *proto_funcs) + +{ + + int iphlen; + + __u8 proto; + + struct ipsec_sa* ipsnext = NULL; /* next SA towards inside of packet */ + + int replay = 0; /* replay value in AH or ESP packet */ + + struct iphdr *ipp; + + struct sk_buff *skb; + + struct ipsec_alg_auth *ixt_a=NULL; + + + + skb = irs->skb; + + irs->len = skb->len; + + ipp = irs->ipp; + + proto = ipp->protocol; + + ipsec_rcv_redodebug(irs); + + + + iphlen = ipp->ihl << 2; + + irs->iphlen=iphlen; + + ipp->check= 0; /* we know the sum is good */ + + + + /* note: rcv_checks set up the said.spi value, if appropriate */ + + if(proto_funcs->rcv_checks) { + + enum ipsec_rcv_value retval = + + (*proto_funcs->rcv_checks)(irs, skb); + + + + if(retval < 0) { + + return retval; + + } + + } + + + + /* 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) { + + + + /* + + * disconnect SA from the hash table, so it can not be + + * found again. + + */ + + ipsec_sa_rm(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; + + } + + + +#if 0 + + /* + + * This is removed for some reasons: + + * 1) it needs to happen *after* authentication. + + * 2) do we really care, if it authenticates, if it came + + * from the wrong location? + + * 3) the NAT_KA messages in IKE will also get to pluto + + * and it will figure out that stuff has moved. + + * 4) the 2.6 udp-esp encap function does not pass us + + * the originating port number, and I can't tell + + * if skb->sk is guaranteed to be valid here. + + * 2005-04-16: mcr@xelerance.com + + */ + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + + /* + + * + + * XXX we should ONLY update pluto if the SA passes all checks, + + * which we clearly do not now. + + */ + + 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; + + struct sockaddr_in *psin = (struct sockaddr_in*)(newipsp->ips_addr_s); + + + + /** 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 [%08x:%u] (notifying pluto of change).\n", + + irs->sa_len ? irs->sa : " (error)", + + irs->ipsaddr_txt, irs->natt_sport, + + psin->sin_addr.s_addr, + + newipsp->ips_natt_sport); + + if(irs->stats) { + + irs->stats->rx_dropped++; + + } + + ipsec_sa_put(newipsp); + + return IPSEC_RCV_FAILEDINBOUND; + + } + + } + +#endif + +#endif + + + + irs->authfuncs=NULL; + + + + /* authenticate, if required */ + + 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 + + switch(irs->ipsp->ips_authalg) { + +#ifdef CONFIG_KLIPS_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_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_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_KLIPS_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; + + } + + + + /* ilen counts number of bytes in ESP portion */ + + irs->ilen = ((irs->skb->data + irs->skb->len) - skb_transport_header(irs->skb)) - 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; + + } + + + + if(irs->authfuncs || ixt_a) { + + 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_ERROR(debug_rcv & DB_RX_INAU, + + "klips_debug:ipsec_rcv: " + + "auth failed on incoming packet from %s (replay=%d): calculated hash=%08x%08x%08x received hash=%08x%08x%08x, dropped\n", + + irs->ipsaddr_txt, + + replay, + + 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 */) { + + + + /* we need to remove it from the sadb hash, so that it can't be found again */ + + ipsec_sa_rm(irs->ipsp); + + + + KLIPS_ERROR(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_ERROR(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; + + ipp = irs->ipp = ip_hdr(skb); + + irs->iphlen = ipp->ihl<<2; + + skb_set_transport_header(skb, ipsec_skb_offset(skb, skb_network_header(skb) + irs->iphlen)); + + + + /* zero any options that there might be */ + + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); + + ipsec_rcv_redodebug(irs); + + + + /* + + * 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 *)ip_hdr(skb), irs->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_next; + + if(sysctl_ipsec_inbound_policy_check) { + + if(ipsnext) { + + if( + + ipp->protocol != IPPROTO_AH + + && ipp->protocol != IPPROTO_ESP + +#ifdef CONFIG_KLIPS_IPCOMP + + && ipp->protocol != IPPROTO_COMP + + && (ipsnext->ips_said.proto != IPPROTO_COMP + + || ipsnext->ips_next) + +#endif /* CONFIG_KLIPS_IPCOMP */ + + && ipp->protocol != IPPROTO_IPIP + + && ipp->protocol != IPPROTO_ATT_HEARTBEAT /* 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_KLIPS_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_KLIPS_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; + +} + + + +void ipsec_rcv_setoutif(struct ipsec_rcv_state *irs) + +{ + + struct sk_buff *skb = irs->skb; + + + + if(skb!=NULL && irs->ipsp->ips_out) { + + if(skb->dev != irs->ipsp->ips_out) { + + KLIPS_PRINT(debug_rcv, + + "changing originating interface from %s to %s\n", + + skb->dev->name, + + irs->ipsp->ips_out->name); + + } + + skb->dev = irs->ipsp->ips_out; + + + + if(skb->dev && skb->dev->get_stats) { + + struct net_device_stats *stats = skb->dev->get_stats(skb->dev); + + irs->stats = stats; + + } + + } + +} + + + +static enum ipsec_rcv_value + +ipsec_rcv_decap_ipip(struct ipsec_rcv_state *irs) + +{ + + struct ipsec_sa *ipsp = NULL; + + struct ipsec_sa* ipsnext = NULL; + + struct iphdr *ipp; + + struct sk_buff *skb; + + enum ipsec_rcv_value result = IPSEC_RCV_DECAPFAIL; + + + + ipp = irs->ipp; + + ipsp = irs->ipsp; + + skb = irs->skb; + + irs->sa_len = satot(&irs->said, 0, irs->sa, sizeof(irs->sa)); + + if((ipp->protocol != IPPROTO_IPIP) && + + (ipp->protocol != IPPROTO_ATT_HEARTBEAT)) { /* AT&T heartbeats to SIG/GIG */ + + 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(irs->stats) { + + irs->stats->rx_dropped++; + + } + + goto rcvleave; + + } + + if(sysctl_ipsec_inbound_policy_check) { + + struct sockaddr_in *psin = (struct sockaddr_in*)(ipsp->ips_addr_s); + + if((ipsnext = ipsp->ips_next)) { + + char sa2[SATOT_BUF]; + + size_t sa_len2; + + sa_len2 = satot(&ipsnext->ips_said, 0, sa2, sizeof(sa2)); + + 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(irs->stats) { + + irs->stats->rx_dropped++; + + } + + goto rcvleave; + + } + + if(ipp->saddr != psin->sin_addr.s_addr) { + + KLIPS_PRINT(debug_rcv, + + "klips_debug:ipsec_rcv: " + + "SA:%s, src=%s(%08x) does match expected 0x%08x.\n", + + irs->sa_len ? irs->sa : " (error)", + + irs->ipsaddr_txt, + + ipp->saddr, psin->sin_addr.s_addr); + + if(irs->stats) { + + irs->stats->rx_dropped++; + + } + + goto rcvleave; + + } + + } + + + + ipsec_rcv_setoutif(irs); + + + + 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) { + + 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; + + } + + + + /* + + * we need to pull up by size of IP header, + + * options, but also by any UDP/ESP encap there might + + * have been, and this deals with all cases. + + */ + + skb_pull(skb, (skb_transport_header(skb) - skb_network_header(skb))); + + + + /* new L3 header is where L4 payload was */ + + skb_set_network_header(skb, ipsec_skb_offset(skb, skb_transport_header(skb))); + + + + /* now setup new L4 payload location */ + + ipp = (struct iphdr *)skb_network_header(skb); + + skb_set_transport_header(skb, ipsec_skb_offset(skb, skb_network_header(skb) + (ipp->ihl << 2))); + + + + + + /* remove any saved options that we might have, + + * since we have a new IP header. + + */ + + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); + + + +#if 0 + + KLIPS_PRINT(debug_rcv, "csum: %d\n", ip_fast_csum((u8 *)ipp, ipp->ihl)); + +#endif + + + + /* re-do any strings for debugging */ + + irs->ipp = ipp; + + ipsec_rcv_redodebug(irs); + + + + 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)); + + 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(irs->stats) { + + irs->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 */ + + + + result = IPSEC_RCV_OK; + + + +rcvleave: + + return result; + +} + + + + + +/* + + * core decapsulation loop for all protocols. + + * + + * the following things should be setup to enter this function. + + * + + * irs->stats == stats structure (or NULL) + + * irs->ipp = IP header. + + * irs->ipsp = NULL. + + * irs->ilen = 0; + + * irs->authlen = 0; + + * irs->authfuncs = NULL; + + * irs->skb = skb; + + * skb->nh.iph = ipp; + + * skb->h.raw = start of payload + + * + + */ + +enum ipsec_rcv_value + +ipsec_rcv_decap(struct ipsec_rcv_state *irs) + +{ + + struct iphdr *ipp; + + struct sk_buff *skb = NULL; + + struct ipsec_sa *lastipsp; + + enum ipsec_rcv_value irv; + + struct xform_functions *proto_funcs; + + int decap_stat; + + + + lastipsp=NULL; + + + + /* 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. + + */ + + + + /* probably can go away now */ + + spin_lock(&tdb_lock); + + + + switch(irs->ipp->protocol) { + + case IPPROTO_ESP: + + proto_funcs = esp_xform_funcs; + + break; + + + +#ifdef CONFIG_KLIPS_AH + + case IPPROTO_AH: + + proto_funcs = ah_xform_funcs; + + break; + +#endif /* !CONFIG_KLIPS_AH */ + + + +#ifdef CONFIG_KLIPS_IPCOMP + + case IPPROTO_COMP: + + proto_funcs = ipcomp_xform_funcs; + + break; + +#endif /* !CONFIG_KLIPS_IPCOMP */ + + default: + + if(irs->stats) { + + irs->stats->rx_errors++; + + } + + decap_stat = IPSEC_RCV_BADPROTO; + + goto rcvleave; + + } + + + + /* look up the first SA -- we need the protocol functions to figure + + * out how to do that. + + */ + + { + + struct ipsec_sa *newipsp; + + /* look up the first SA */ + + irv = ipsec_rcv_decap_lookup(irs, proto_funcs, &newipsp); + + if(irv != IPSEC_RCV_OK) { + + return irv; + + } + + + + /* newipsp is already referenced by the get() function */ + + irs->ipsp=newipsp; + + } + + + + do { + + ipsec_rcv_setoutif(irs); + + + + proto_funcs = irs->ipsp->ips_xformfuncs; + + if(proto_funcs == NULL) { + + decap_stat = IPSEC_RCV_BADPROTO; + + goto rcvleave; + + } + + + + if(proto_funcs->protocol != irs->ipp->protocol) { + + if(proto_funcs->protocol == IPPROTO_COMP) { + + /* loops like an IPCOMP that we can skip */ + + goto skipipcomp; + + } + + + + if(irs->stats) { + + irs->stats->rx_errors++; + + } + + decap_stat = IPSEC_RCV_FAILEDINBOUND; + + 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; + + } + + + + /* okay, acted on this SA, so free any previous SA, and record a new one*/ + + skipipcomp: + + if(irs->ipsp) { + + struct ipsec_sa *newipsp = NULL; + + newipsp = irs->ipsp->ips_next; + + if(newipsp) { + + ipsec_sa_get(newipsp); + + } + + if(lastipsp) { + + ipsec_sa_put(lastipsp); + + } + + lastipsp = irs->ipsp; + + irs->ipsp=newipsp; + + } + + + + /* end decapsulation loop here */ + + } while((irs->ipp->protocol == IPPROTO_ESP + + || irs->ipp->protocol == IPPROTO_AH + + || irs->ipp->protocol == IPPROTO_COMP) + + && irs->ipsp != NULL); + + + + /* end of decap loop */ + + ipp =irs->ipp; + + skb = irs->skb; + + + + /* + + * if there is an IPCOMP, but we didn't process it, + + * then we can just skip it + + */ + +#ifdef CONFIG_KLIPS_IPCOMP + + if(irs->ipsp && irs->ipsp->ips_said.proto == IPPROTO_COMP) { + + struct ipsec_sa *newipsp = NULL; + + newipsp = irs->ipsp->ips_next; + + if(newipsp) { + + ipsec_sa_get(newipsp); + + } + + if(lastipsp) { + + ipsec_sa_put(lastipsp); + + } + + lastipsp = irs->ipsp; + + irs->ipsp=newipsp; + + } + +#endif /* CONFIG_KLIPS_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 = lastipsp->ips_natt_oa ? + + ((struct sockaddr_in*)(lastipsp->ips_natt_oa))->sin_addr.s_addr : 0; + + + + if(natt_oa != 0) { + + /* reset source address to what it was before NAT */ + + ipp->saddr = natt_oa; + + ipp->check = 0; + + ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); + + KLIPS_PRINT(debug_rcv, "csum: %04x\n", ipp->check); + + } + + } + +#endif + + + + /* + + * the SA is still locked from the loop + + */ + + if(irs->ipsp && irs->ipsp->ips_xformfuncs->protocol == IPPROTO_IPIP) { + + enum ipsec_rcv_value decap_stat; + + + + decap_stat = ipsec_rcv_decap_ipip(irs); + + if(decap_stat != IPSEC_RCV_OK) { + + spin_unlock(&tdb_lock); + + goto rcvleave; + + } + + } + + + + spin_unlock(&tdb_lock); + + + + if(irs->stats) { + + irs->stats->rx_bytes += skb->len; + + } + + + + /* + + * if we are supposed to return the packet directly to the transport + + * layer, then dump it out correctly. + + */ + + if(lastipsp->ips_transport_direct) { + + KLIPS_PRINT(debug_rcv, "receiving packet as transport direct\n"); + + skb->ip_summed=CHECKSUM_UNNECESSARY; + + /* STUFF */ + + } + + + + if(skb->sp) { + + secpath_put(skb->sp); + + } + + skb->sp = secpath_dup(NULL); + + skb->sp->ref = lastipsp->ips_ref; + + + + /* release the dst that was attached, since we have likely + + * changed the actual destination of the packet. + + */ + + if(skb->dst) { + + dst_release(skb->dst); + + skb->dst = NULL; + + } + + skb->pkt_type = PACKET_HOST; + + if(irs->hard_header_len && + + (skb_mac_header(skb) != (skb_network_header(skb) - irs->hard_header_len)) && + + (irs->hard_header_len <= skb_headroom(skb))) { + + /* copy back original MAC header */ + + memmove(skb_network_header(skb) - irs->hard_header_len, + + skb_mac_header(skb), irs->hard_header_len); + + skb_set_mac_header(skb, ipsec_skb_offset(skb, skb_network_header(skb) - irs->hard_header_len)); + + } + + + + /* + + * make sure that data now starts at IP header, since we are going + + * to pass this back to ip_input (aka netif_rx). Rules for what the + + * pointers wind up a different for 2.6 vs 2.4, so we just fudge it here. + + */ + +#ifdef NET_26 + + irs->skb->data = skb_push(irs->skb, skb_transport_header(irs->skb) - skb_network_header(irs->skb)); + +#else + + irs->skb->data = skb_network_header(irs->skb); + + { + + struct iphdr *iph = ip_hdr(irs->skb); + + int len = ntohs(iph->tot_len); + + irs->skb->len = len; + + } + +#endif + + + +#ifdef SKB_RESET_NFCT + + nf_conntrack_put(skb->nfct); + + skb->nfct = NULL; + +#if defined(CONFIG_NETFILTER_DEBUG) && defined(HAVE_SKB_NF_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(%s) called.\n", skb->dev->name); + + netif_rx(skb); + + skb=NULL; + + + + rcvleave: + + if(lastipsp) { + + ipsec_sa_put(lastipsp); + + lastipsp=NULL; + + } + + if(irs->ipsp) { + + ipsec_sa_put(irs->ipsp); + + } + + irs->ipsp=NULL; + + + + if(skb) { + + ipsec_kfree_skb(skb); + + } + + + + return(0); + +} + + + +struct sk_buff *ipsec_rcv_unclone(struct sk_buff *skb, + + struct ipsec_rcv_state *irs) + +{ + + /* 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); + + } + + return skb; + + + +rcvleave: + + ipsec_kfree_skb(skb); + + return NULL; + +} + + + + + +#if !defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) + +/* + + * decapsulate a UDP encapsulated ESP packet + + */ + +struct sk_buff *ipsec_rcv_natt_decap(struct sk_buff *skb + + , struct ipsec_rcv_state *irs + + , int *udp_decap_ret_p) + +{ + + *udp_decap_ret_p = 0; + + 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)); + + *udp_decap_ret_p = 0; + + return NULL; + + } + + 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"); + + *udp_decap_ret_p = -1; + + return NULL; + + } + + } + + else { + + return NULL; + + } + + } + + return skb; + +} + +#endif + + + +/* management of buffers */ + +static struct ipsec_rcv_state * ipsec_rcv_state_new (void); + +static void ipsec_rcv_state_delete (struct ipsec_rcv_state *irs); + + + +int + +ipsec_rcv(struct sk_buff *skb + +#ifndef PROTO_HANDLER_SINGLE_PARM + + unsigned short xlen + +#endif /* PROTO_HANDLER_SINGLE_PARM */ + + ) + +{ + +#ifdef CONFIG_KLIPS_DEBUG + + struct net_device *dev = skb->dev; + +#endif /* CONFIG_KLIPS_DEBUG */ + + unsigned char protoc; + + struct net_device_stats *stats = NULL; /* This device's statistics */ + + struct ipsec_rcv_state nirs, *irs = &nirs; + + struct iphdr *ipp; + + int i; + + + + /* Don't unlink in the middle of a turnaround */ + + KLIPS_INC_USE; + + + + memset(&nirs, 0, sizeof(struct ipsec_rcv_state)); + + + + if (skb == NULL) { + + KLIPS_PRINT(debug_rcv, + + "klips_debug:ipsec_rcv: " + + "NULL skb passed in.\n"); + + goto error_no_skb; + + } + + + + if (skb->data == NULL) { + + KLIPS_PRINT(debug_rcv, + + "klips_debug:ipsec_rcv: " + + "NULL skb->data passed in, packet is bogus, dropping.\n"); + + goto error_bad_skb; + + } + + + +#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26) + + { + + /* NET_26 NAT-T is handled by seperate function */ + + struct sk_buff *nskb; + + int udp_decap_ret = 0; + + + + nskb = ipsec_rcv_natt_decap(skb, irs, &udp_decap_ret); + + if(nskb == NULL) { + + /* return with non-zero, because UDP.c code + + * need to send it upstream. + + */ + + if(skb && udp_decap_ret == 0) { + + ipsec_kfree_skb(skb); + + } + + KLIPS_DEC_USE; + + return(udp_decap_ret); + + } + + skb = nskb; + + } + +#endif /* NAT_T */ + + + + /* dev->hard_header_len is unreliable and should not be used */ + + /* klips26_rcv_encap will have already set hard_header_len for us?? */ + + if (irs->hard_header_len == 0) { + + irs->hard_header_len = skb_mac_header(skb) ? (skb_network_header(skb) - skb_mac_header(skb)) : 0; + + if((irs->hard_header_len < 0) || (irs->hard_header_len > skb_headroom(skb))) + + irs->hard_header_len = 0; + + } + + + + skb = ipsec_rcv_unclone(skb, irs); + + if(skb == NULL) { + + goto rcvleave; + + } + + + +#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)) { + +#ifdef HAVE_NEW_SKB_LINEARIZE + + if (skb_linearize_cow(skb) != 0) + +#else + + if (skb_linearize(skb, GFP_ATOMIC) != 0) + +#endif + + { + + goto rcvleave; + + } + + } + +#endif /* IP_FRAGMENT_LINEARIZE */ + + + +#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26) + + if (irs->natt_len) { + + /** + + * Now, we are sure packet is ESPinUDP, and we have a private + + * copy that has been linearized, 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 = skb->nh.iph; + + 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; + + } + + + + /* advance payload pointer to point past the UDP header */ + + skb->h.raw = skb->h.raw + irs->natt_len; + + + + /* modify protocol */ + + ipp->protocol = IPPROTO_ESP; + + + + skb->sk = NULL; + + + + KLIPS_IP_PRINT(debug_rcv, skb->nh.iph); + + } + +#endif + + + + /* ipp = skb->nh.iph; */ + + ipp = ip_hdr(skb); + + + + irs->ipp = ipp; + + ipsec_rcv_redodebug(irs); + + + + 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_KLIPS_IPCOMP_disabled_until_we_register_IPCOMP_HANDLER + + (protoc != IPPROTO_COMP) && + +#endif /* CONFIG_KLIPS_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 there is an attached ipsec device, then use that device for + + * stats until we know better. + + */ + + if(skb->dev) { + + struct ipsecpriv *prvdev = NULL; + + struct net_device *ipsecdev = NULL; + + + + for(i = 0; i <= ipsecdevices_max; i++) { + + if(ipsecdevices[i] == NULL) continue; + + prvdev = ipsecdevices[i]->priv; + + + + if(prvdev == NULL) continue; + + + + if(prvdev->dev == skb->dev) { + + ipsecdev = ipsecdevices[i]; + + break; + + } + + } + + + + if(ipsecdev) { + + skb->dev = ipsecdev; + + } else { + + skb->dev = ipsec_mast_get_device(0); + + + + /* ipsec_mast_get takes the device */ + + if(skb->dev) dev_put(skb->dev); + + } + + + + if(prvdev) { + + stats = (struct net_device_stats *) &(prvdev->mystats); + + } + + } + + + + if(stats) { + + stats->rx_packets++; + + } + + + + KLIPS_IP_PRINT(debug_rcv, ipp); + + + + /* 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; + + + + (void)ipsec_rcv_decap(irs); + + + + ipsec_rcv_state_delete (irs); + + KLIPS_DEC_USE; + + return(0); + + + +rcvleave: + + ipsec_rcv_state_delete (irs); + + + +error_bad_skb: + + ipsec_kfree_skb(skb); + +error_no_skb: + + + + KLIPS_DEC_USE; + + return(0); + + + +} + + + +#ifdef NET_26 + +/* + + * this entry point is not a protocol entry point, so the entry + + * is a bit different. + + * + + * skb->iph->tot_len has been byte-swapped, and reduced by the size of + + * the IP header (and options). + + * + + * skb->h.raw has been pulled up the ESP header. + + * + + * skb->iph->protocol = 50 IPPROTO_ESP; + + * + + */ + +int klips26_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) + +{ + + return klips26_rcv_encap(skb, udp_sk(sk)->encap_type); + +} + + + +int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type) + +{ + + struct ipsec_rcv_state *irs = NULL; + + struct iphdr *ipp; + + + + /* Don't unlink in the middle of a turnaround */ + + KLIPS_INC_USE; + + + + irs = ipsec_rcv_state_new (); + + if (unlikely (! irs)) { + + KLIPS_PRINT(debug_rcv, + + "klips_debug:ipsec_rcv: " + + "failled to allocate a rcv state object\n"); + + goto error_alloc; + + } + + + + /* XXX fudge it so that all nat-t stuff comes from ipsec0 */ + + /* eventually, the SA itself will determine which device + + * it comes from + + */ + + { + + skb->dev = ipsec_get_device(0); + + } + + + + /* set up for decap loop */ + + irs->hard_header_len = skb->dev->hard_header_len; + + + + skb = ipsec_rcv_unclone(skb, irs); + + + +#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)) { + +#ifdef HAVE_NEW_SKB_LINEARIZE + + if (skb_linearize_cow(skb) != 0) + +#else + + if (skb_linearize(skb, GFP_ATOMIC) != 0) + +#endif + + { + + goto rcvleave; + + } + + } + +#endif /* IP_FRAGMENT_LINEARIZE */ + + + + /* ipp = skb->nh.iph; */ + + ipp =ip_hdr(skb); + + + + irs->ipp = ipp; + + ipsec_rcv_redodebug(irs); + + + + irs->iphlen = ipp->ihl << 2; + + + + KLIPS_IP_PRINT(debug_rcv, ipp); + + + + irs->stats= NULL; + + irs->ipp = ipp; + + irs->ipsp = NULL; + + irs->ilen = 0; + + irs->authlen=0; + + irs->authfuncs=NULL; + + irs->skb = skb; + + + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + + switch(encap_type) { + + case UDP_ENCAP_ESPINUDP: + + irs->natt_type = ESPINUDP_WITH_NON_ESP; + + break; + + + + case UDP_ENCAP_ESPINUDP_NON_IKE: + + irs->natt_type = ESPINUDP_WITH_NON_IKE; + + break; + + + + default: + + if(printk_ratelimit()) { + + printk(KERN_INFO "KLIPS received unknown UDP-ESP encap type %u\n", + + encap_type); + + } + + return -1; + + } + + + +#endif + + ipsec_rcv_decap(irs); + + + + KLIPS_DEC_USE; + + ipsec_rcv_state_delete (irs); + + return 0; + + + +rcvleave: + + if(skb) { + + ipsec_kfree_skb(skb); + + } + + ipsec_rcv_state_delete (irs); + +error_alloc: + + KLIPS_DEC_USE; + + return 0; + +} + +#endif + + + +// ------------------------------------------------------------------------ + +// this handles creating and managing state for recv path + + + +static spinlock_t irs_cache_lock = SPIN_LOCK_UNLOCKED; + +#ifdef HAVE_KMEM_CACHE_MACRO + +static struct kmem_cache *irs_cache_allocator = NULL; + +#else + +static kmem_cache_t *irs_cache_allocator = NULL; + +#endif + +static unsigned irs_cache_allocated_count = 0; + + + +int + +ipsec_rcv_state_cache_init (void) + +{ + + if (irs_cache_allocator) + + return -EBUSY; + + + + spin_lock_init(&irs_cache_lock); + +#ifdef HAVE_KMEM_CACHE_MACRO + + /* irs_cache_allocator = KMEM_CACHE(ipsec_irs,0); */ + + irs_cache_allocator = kmem_cache_create ("ipsec_irs", + + sizeof (struct ipsec_rcv_state), 0, + + 0, NULL); + +#else + + irs_cache_allocator = kmem_cache_create ("ipsec_irs", + + sizeof (struct ipsec_rcv_state), 0, + + 0, NULL, NULL); + +#endif + + if (! irs_cache_allocator) + + return -ENOMEM; + + + + return 0; + +} + + + +void + +ipsec_rcv_state_cache_cleanup (void) + +{ + + if (unlikely (irs_cache_allocated_count)) + + printk ("ipsec: deleting ipsec_irs kmem_cache while in use\n"); + + + + if (irs_cache_allocator) { + + kmem_cache_destroy (irs_cache_allocator); + + irs_cache_allocator = NULL; + + } + + irs_cache_allocated_count = 0; + +} + + + +static struct ipsec_rcv_state * + +ipsec_rcv_state_new (void) + +{ + + struct ipsec_rcv_state *irs; + + + + spin_lock_bh (&irs_cache_lock); + + + + irs = kmem_cache_alloc (irs_cache_allocator, GFP_ATOMIC); + + + + if (likely (irs != NULL)) + + irs_cache_allocated_count++; + + + + spin_unlock_bh (&irs_cache_lock); + + + + if (unlikely (NULL == irs)) + + goto bail; + + + + // initialize the object + + memset((caddr_t)irs, 0, sizeof(*irs)); + + + +bail: + + return irs; + +} + + + +static void + +ipsec_rcv_state_delete (struct ipsec_rcv_state *irs) + +{ + + if (unlikely (! irs)) + + return; + + + + spin_lock_bh (&irs_cache_lock); + + + + irs_cache_allocated_count--; + + kmem_cache_free (irs_cache_allocator, irs); + + + + spin_unlock_bh (&irs_cache_lock); + +} + + + +/* + + * + + * Local Variables: + + * c-set-style: linux + + * End: + + * + + */ + --- /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,1525 @@ + +/* + + * 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 . + + * + + * 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.31 2005/11/11 04:38:56 paul Exp $ + + * + + * This is the file formerly known as "ipsec_xform.h" + + * + + */ + + + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* vmalloc() */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + +#ifdef SPINLOCK + +#ifdef SPINLOCK_23 + +#include /* *lock* */ + +#else /* SPINLOCK_23 */ + +#include /* *lock* */ + +#endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + + + +#include + + + +#include "libreswan/radij.h" + + + +#include "libreswan/ipsec_stats.h" + +#include "libreswan/ipsec_life.h" + +#include "libreswan/ipsec_sa.h" + +#include "libreswan/ipsec_xform.h" + + + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_ipe4.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + +#include "libreswan/ipsec_ipip.h" + +#ifdef CONFIG_KLIPS_IPCOMP + +#include "libreswan/ipsec_ipcomp.h" + +#endif /* CONFIG_KLIPS_COMP */ + + + +#include + +#include + + + +#include "libreswan/ipsec_proto.h" + +#include "libreswan/ipsec_alg.h" + + + + + +#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; + + + +/* 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) + + + +int + +ipsec_SAref_recycle(void) + +{ + + int table, i; + + int error = 0; + + int entry; + + int addone; + + + + ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; + + ipsec_sadb.refFreeListTail = IPSEC_SAREF_NULL; + + + + 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 = IPSEC_SAREF_FIRST; + + } + + + + 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)); + + + + /* add one additional table entry */ + + addone = 0; + + + + ipsec_sadb.refFreeListHead = IPSEC_SAREF_FIRST; + + for(i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) { + + table = IPsecSAref2table(ipsec_sadb.refFreeListCont); + + if(addone == 0 && ipsec_sadb.refTable[table] == NULL) { + + addone = 1; + + 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 = IPSEC_SAREF_FIRST; + + ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; + + KLIPS_PRINT(debug_xform, + + "klips_debug:ipsec_SAref_recycle: " + + "SArefFreeList refilled.\n"); + + return 0; + + } + + } + + } + + ipsec_sadb.refFreeListCont++; + + ipsec_sadb.refFreeListTail=i; + + } + + + + if(ipsec_sadb.refFreeListTail == IPSEC_SAREF_NULL) { + + KLIPS_PRINT(debug_xform, + + "klips_debug:ipsec_SAref_recycle: " + + "out of room in the SArefTable.\n"); + + + + return(-ENOSPC); + + } + + + + ipsec_sadb.refFreeListHead = IPSEC_SAREF_FIRST; + + 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; + +} + + + +int + +ipsec_saref_verify_slot(IPsecSAref_t ref) + +{ + + int ref_table=IPsecSAref2table(ref); + + + + if(ipsec_sadb.refTable[ref_table] == NULL) { + + return ipsec_SArefSubTable_alloc(ref_table); + + } + + return 0; + +} + + + +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 = IPSEC_SAREF_NULL; + + ipsec_sadb.refFreeListCont = IPSEC_SAREF_FIRST; + + ipsec_sadb.refFreeListTail = IPSEC_SAREF_NULL; + + + + 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 */ + + + + + + /* 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(); + + return error; + +} + + + +IPsecSAref_t + +ipsec_SAref_alloc(int*error) /* pass in error var by pointer */ + +{ + + IPsecSAref_t SAref; + + + + KLIPS_PRINT(debug_xform, + + "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 == IPSEC_SAREF_NULL) { + + KLIPS_PRINT(debug_xform, + + "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_ERROR(debug_xform, + + "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, + + "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, + + "ipsec_SAref_alloc: " + + "last FreeList entry allocated, resetting list head to empty.\n"); + + ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; + + } + + + + return SAref; + +} + + + +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_next != NULL) { + + printk(" next=0p%p", ips->ips_next); + + } + + 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, + + "ipsec_sa_alloc: " + + "memory allocation error\n"); + + *error = -ENOMEM; + + return NULL; + + } + + memset((caddr_t)ips, 0, sizeof(*ips)); + + + + /* return with at least counter = 1 */ + + ipsec_sa_get(ips); + + + + *error = 0; + + return(ips); + +} + + + +void + +ipsec_sa_untern(struct ipsec_sa *ips) + +{ + + IPsecSAref_t ref = ips->ips_ref; + + int error; + + + + /* verify that we are removing correct item! */ + + error = ipsec_saref_verify_slot(ref); + + if(error) { + + return; + + } + + + + if(IPsecSAref2SA(ref) == ips) { + + IPsecSAref2SA(ref) = NULL; + + ipsec_sa_put(ips); + + } else { + + KLIPS_PRINT(debug_xform, + + "ipsec_sa_untern: " + + "ref=%u -> %p but untern'ing %p\n", ref, + + IPsecSAref2SA(ref), ips); + + } + + + +} + + + +int + +ipsec_sa_intern(struct ipsec_sa *ips) + +{ + + int error; + + IPsecSAref_t ref = ips->ips_ref; + + + + if(ref == IPSEC_SAREF_NULL) { + + ref = ipsec_SAref_alloc(&error); /* pass in error return by pointer */ + + KLIPS_PRINT(debug_xform, + + "ipsec_sa_intern: " + + "allocated ref=%u for sa %p\n", ref, ips); + + + + if(ref == IPSEC_SAREF_NULL) { + + KLIPS_PRINT(debug_xform, + + "ipsec_sa_intern: " + + "SAref allocation error\n"); + + return error; + + } + + + + ips->ips_ref = ref; + + } + + + + error = ipsec_saref_verify_slot(ref); + + if(error) { + + return error; + + } + + + + ipsec_sa_get(ips); + + /* + + * if there is an existing SA at this reference, then free it + + * note, that nsa might == ips!. That's okay, we just incremented + + * the reference count above. + + */ + + { + + struct ipsec_sa *nsa = IPsecSAref2SA(ref); + + if(nsa) { + + ipsec_sa_put(nsa); + + } + + } + + + + KLIPS_PRINT(debug_xform, + + "ipsec_sa_alloc: " + + "SAref[%d]=%p\n", + + ips->ips_ref, ips); + + IPsecSAref2SA(ips->ips_ref) = ips; + + + + /* return OK */ + + return 0; + +} + + + + + +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, + + "ipsec_sa_getbyid: " + + "null pointer passed in!\n"); + + return NULL; + + } + + + + hashval = IPS_HASH(said); + + + + sa_len = KLIPS_SATOT(debug_xform, said, 0, sa, sizeof(sa)); + + KLIPS_PRINT(debug_xform, + + "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, + + "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)) { + + ipsec_sa_get(ips); + + return ips; + + } + + } + + + + KLIPS_PRINT(debug_xform, + + "ipsec_sa_getbyid: " + + "no entry in linked list for hash=%d of SA:%s.\n", + + hashval, + + sa_len ? sa : " (error)"); + + return NULL; + +} + + + +struct ipsec_sa * + +ipsec_sa_getbyref(IPsecSAref_t ref) + +{ + + struct ipsec_sa *ips; + + struct IPsecSArefSubTable *st = ipsec_sadb.refTable[IPsecSAref2table(ref)]; + + + + if(st == NULL) { + + return NULL; + + } + + + + ips = st->entry[IPsecSAref2entry(ref)]; + + if(ips) { + + ipsec_sa_get(ips); + + } + + return ips; + +} + + + +int + +ipsec_sa_put(struct ipsec_sa *ips) + +{ + + char sa[SATOT_BUF]; + + size_t sa_len; + + + + if(ips == NULL) { + + KLIPS_PRINT(debug_xform, + + "ipsec_sa_put: " + + "null pointer passed in!\n"); + + return -1; + + } + + + + if(debug_xform) { + + sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); + + + + KLIPS_PRINT(debug_xform, + + "ipsec_sa_put: " + + "ipsec_sa %p SA:%s, ref:%d reference count (%d--) decremented.\n", + + ips, + + sa_len ? sa : " (error)", + + ips->ips_ref, + + atomic_read(&ips->ips_refcount)); + + } + + + + if(atomic_dec_and_test(&ips->ips_refcount)) { + + KLIPS_PRINT(debug_xform, + + "ipsec_sa_put: freeing %p\n", + + ips); + + /* it was zero */ + + ipsec_sa_wipe(ips); + + } + + + + return 0; + +} + + + +int + +__ipsec_sa_get(struct ipsec_sa *ips, const char *func, int line) + +{ + + char sa[SATOT_BUF]; + + size_t sa_len; + + + + if(debug_xform) { + + sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); + + + + KLIPS_PRINT(debug_xform, + + "ipsec_sa_get: " + + "ipsec_sa %p SA:%s, ref:%d reference count (%d++) incremented by %s:%d.\n", + + ips, + + sa_len ? sa : " (error)", + + ips->ips_ref, + + atomic_read(&ips->ips_refcount), + + func, line); + + } + + + + atomic_inc(&ips->ips_refcount); + + return atomic_read(&ips->ips_refcount); + +} + + + +/* + + 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); + + + + ipsec_sa_get(ips); + + spin_lock_bh(&tdb_lock); + + + + ips->ips_hnext = ipsec_sadb_hash[hashval]; + + ipsec_sadb_hash[hashval] = ips; + + + + spin_unlock_bh(&tdb_lock); + + + + return error; + +} + + + +/* + + * remove it from the hash chain, decrementing hash count + + */ + +void ipsec_sa_rm(struct ipsec_sa *ips) + +{ + + unsigned int hashval; + + char sa[SATOT_BUF]; + + size_t sa_len; + + + + + + if(ips == NULL) return; + + + + + + hashval = IPS_HASH(&ips->ips_said); + + + + sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); + + KLIPS_PRINT(debug_xform, + + "klips_debug:ipsec_sa_del: " + + "unhashing SA:%s (ref=%u), hashval=%d.\n", + + sa_len ? sa : " (error)", + + ips->ips_ref, + + hashval); + + + + if(ipsec_sadb_hash[hashval] == NULL) { + + return; + + } + + + + if (ips == ipsec_sadb_hash[hashval]) { + + ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; + + ips->ips_hnext = NULL; + + ipsec_sa_put(ips); + + KLIPS_PRINT(debug_xform, + + "klips_debug:ipsec_sa_del: " + + "successfully unhashed first ipsec_sa in chain.\n"); + + return; + + } else { + + struct ipsec_sa *ipstp; + + + + 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; + + ipsec_sa_put(ips); + + KLIPS_PRINT(debug_xform, + + "klips_debug:ipsec_sa_del: " + + "successfully unhashed link in ipsec_sa chain.\n"); + + return; + + } + + } + + } + +} + + + + + +#if 0 + +/* + + * The ipsec_sa table better be locked before it is handed in, + + * or races might happen. + + * + + * this routine assumes the SA has a refcount==0, and we free it. + + * we also assume that the pointers are already cleaned up. + + */ + +static 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_ERROR(debug_xform, + + "klips_error:ipsec_sa_del: " + + "null pointer passed in!\n"); + + return -ENODATA; + + } + + + + if(ips->ips_next) { + + struct ipsec_sa *in = ips->ips_next; + + + + ips->ips_next=NULL; + + ipsec_sa_put(in); + + } + + + + sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); + + hashval = IPS_HASH(&ips->ips_said); + + + + KLIPS_PRINT(debug_xform, + + "klips_debug:ipsec_sa_del: " + + "deleting SA:%s (ref=%u), hashval=%d.\n", + + sa_len ? sa : " (error)", + + ips->ips_ref, + + hashval); + + + + if(ipsec_sadb_hash[hashval] == NULL) { + + /* if this is NULL, then we can be sure that the SA was never + + * added to the SADB, so we just free it. + + */ + + KLIPS_PRINT(debug_xform, + + "klips_debug:ipsec_sa_del: " + + "no entries in ipsec_sa table for hash=%d (ref=%u) of SA:%s.\n", + + hashval, + + ips->ips_ref, + + 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; + + + + ipsec_sa_put(ips); + + 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; + + ipsec_sa_put(ips); + + 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; + +} + +#endif + + + +int + +ipsec_sadb_cleanup(__u8 proto) + +{ + + unsigned i; + + int error = 0; + + struct ipsec_sa *ips; + + //struct ipsec_sa *ipsnext, **ipsprev; + + //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++) { + + ips = ipsec_sadb_hash[i]; + + + + while(ips) { + + ipsec_sadb_hash[i]=ips->ips_hnext; + + ips->ips_hnext=NULL; + + ipsec_sa_put(ips); + + + + ips = ipsec_sadb_hash[i]; + + } + + } + + + +//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) { + + struct ipsec_sa *sa1 = ipsec_sadb.refTable[table]->entry[entry]; + + ipsec_sa_put(sa1); + + 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) { + + struct ipsec_sa *sa1 = ipsec_sadb.refTable[table]->entry[entry]; + + + + BUG_ON(atomic_read(&sa1->ips_refcount) == 1); + + ipsec_sa_put(sa1); + + 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 IPSEC_SA_REF_CODE + + /* remove me from the SArefTable */ + + if(debug_xform) + + { + + char sa[SATOT_BUF]; + + size_t sa_len; + + struct IPsecSArefSubTable *subtable = NULL; + + + + if(IPsecSAref2table(IPsecSA2SAref(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)), + + subtable, + + subtable ? IPsecSAref2entry(IPsecSA2SAref(ips)) : 0); + + } + + + + if(ips->ips_ref != IPSEC_SAREF_NULL) { + + struct IPsecSArefSubTable *subtable = NULL; + + int ref_table=IPsecSAref2table(IPsecSA2SAref(ips)); + + int ref_entry=IPsecSAref2entry(IPsecSA2SAref(ips)); + + + + if(ref_table < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { + + subtable = ipsec_sadb.refTable[ref_table]; + + if(subtable!=NULL && subtable->entry[ref_entry] == ips) { + + + + subtable->entry[ref_entry] = NULL; + + } + + } + + ips->ips_ref = IPSEC_SAREF_NULL; + + } + +#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) { + + 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 + + { + + memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); + + kfree(ips->ips_key_e); + + } + + } + + 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; + + + + if (ips->ips_alg_enc||ips->ips_alg_auth) { + + ipsec_alg_sa_wipe(ips); + + } + + + + BUG_ON(atomic_read(&ips->ips_refcount) != 0); + + + + memset((caddr_t)ips, 0, sizeof(*ips)); + + kfree(ips); + + ips = NULL; + + + + return 0; + +} + + + +extern int sysctl_ipsec_debug_verbose; + + + +int ipsec_sa_init(struct ipsec_sa *ipsp) + +{ + + 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_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) + + unsigned char kb[AHMD596_BLKLEN]; + +#endif + + struct ipsec_alg_enc *ixt_e = NULL; + + struct ipsec_alg_auth *ixt_a = NULL; + + + + if(ipsp == NULL) { + + KLIPS_PRINT(debug_pfkey, + + "ipsec_sa_init: " + + "ipsp is NULL, fatal\n"); + + SENDERR(EINVAL); + + } + + + + sa_len = KLIPS_SATOT(debug_pfkey, &ipsp->ips_said, 0, sa, sizeof(sa)); + + + + KLIPS_PRINT(debug_pfkey, + + "ipsec_sa_init: " + + "(pfkey defined) called for SA:%s\n", + + sa_len ? sa : " (error)"); + + + + KLIPS_PRINT(debug_pfkey, + + "ipsec_sa_init: " + + "calling init routine of %s%s%s\n", + + IPS_XFORM_NAME(ipsp)); + + + + switch(ipsp->ips_said.proto) { + +#ifdef CONFIG_KLIPS_IPIP + + case IPPROTO_IPIP: { + + ipsp->ips_xformfuncs = ipip_xform_funcs; + + 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, + + "ipsec_sa_init: " + + "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", + + ipaddr_txt, + + ipaddr2_txt); + + } + + break; + +#endif /* !CONFIG_KLIPS_IPIP */ + + + +#ifdef CONFIG_KLIPS_AH + + case IPPROTO_AH: + + ipsp->ips_xformfuncs = ah_xform_funcs; + + + + switch(ipsp->ips_authalg) { + +# ifdef CONFIG_KLIPS_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, + + "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, + + "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, + + "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); + + osMD5Init(ictx); + + osMD5Update(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); + + osMD5Init(octx); + + osMD5Update(octx, kb, AHMD596_BLKLEN); + + + +# if KLIPS_DIVULGE_HMAC_KEY + + KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, + + "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_KLIPS_AUTH_HMAC_MD5 */ + +# ifdef CONFIG_KLIPS_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, + + "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, + + "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, + + "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, + + "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_KLIPS_AUTH_HMAC_SHA1 */ + + default: + + KLIPS_PRINT(debug_pfkey, + + "ipsec_sa_init: " + + "authalg=%d support not available in the kernel", + + ipsp->ips_authalg); + + SENDERR(EINVAL); + + } + + break; + +#endif /* CONFIG_KLIPS_AH */ + + + +#ifdef CONFIG_KLIPS_ESP + + case IPPROTO_ESP: + + ipsp->ips_xformfuncs = esp_xform_funcs; + + { + +#if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) + + unsigned char *akp; + + unsigned int aks; + +#endif + + + + ipsec_alg_sa_init(ipsp); + + ixt_e=ipsp->ips_alg_enc; + + + + if (ixt_e == NULL) { + + if(printk_ratelimit()) { + + printk(KERN_ERR + + "ipsec_sa_init: " + + "encalg=%d support not available in the kernel", + + ipsp->ips_encalg); + + } + + SENDERR(ENOENT); + + } + + + + ipsp->ips_iv_size = ixt_e->ixt_common.ixt_support.ias_ivlen/8; + + + + /* 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; + + } + + + + if ((error=ipsec_alg_enc_key_create(ipsp)) < 0) + + SENDERR(-error); + + + + if ((ixt_a=ipsp->ips_alg_auth)) { + + if ((error=ipsec_alg_auth_key_create(ipsp)) < 0) + + SENDERR(-error); + + } else + + + + switch(ipsp->ips_authalg) { + +# ifdef CONFIG_KLIPS_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, + + "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, + + "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, + + "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); + + osMD5Init(ictx); + + osMD5Update(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); + + osMD5Init(octx); + + osMD5Update(octx, kb, AHMD596_BLKLEN); + + + +# if KLIPS_DIVULGE_HMAC_KEY + + KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, + + "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_KLIPS_AUTH_HMAC_MD5 */ + +# ifdef CONFIG_KLIPS_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, + + "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, + + "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, + + "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, + + "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_KLIPS_AUTH_HMAC_SHA1 */ + + case AH_NONE: + + break; + + default: + + KLIPS_PRINT(debug_pfkey, + + "ipsec_sa_init: " + + "authalg=%d support not available in the kernel.\n", + + ipsp->ips_authalg); + + SENDERR(EINVAL); + + } + + } + + break; + +#endif /* !CONFIG_KLIPS_ESP */ + +#ifdef CONFIG_KLIPS_IPCOMP + + case IPPROTO_COMP: + + ipsp->ips_xformfuncs = ipcomp_xform_funcs; + + 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_KLIPS_IPCOMP */ + + default: + + printk(KERN_ERR "KLIPS sa initialization: " + + "proto=%d unknown.\n", + + ipsp->ips_said.proto); + + SENDERR(EINVAL); + + } + + + + errlab: + + return(error); + +} + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + + + --- /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,177 @@ + +/* + + * 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 + +#include + + + +#include "libreswan/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 + +} + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/ipsec_snprintf.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,121 @@ + +/* + + * @(#) ipsec_snprintf() function + + * + + * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs + + * 2001 Michael Richardson + + * Copyright (C) 2005 Michael Richardson + + * + + * 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 . + + * + + * 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_proc.c. + + */ + + + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + +#define __NO_VERSION__ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_kversion.h" + +#include "libreswan/ipsec_param.h" + + + +#include + + + +#include "libreswan/radij.h" + + + +#include "libreswan/ipsec_life.h" + +#include "libreswan/ipsec_stats.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_xmit.h" + + + +#include "libreswan/ipsec_rcv.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + +#include "libreswan/ipsec_kern24.h" + + + +#ifdef CONFIG_KLIPS_IPCOMP + +#include "libreswan/ipcomp.h" + +#endif /* CONFIG_KLIPS_IPCOMP */ + + + +#include "libreswan/ipsec_proto.h" + + + +#include + +#include + + + +/* 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; + +} + + + + + +void ipsec_dmp_block(char *s, caddr_t bb, int len) + +{ + + int i; + + unsigned char *b = bb; + + + + printk(KERN_INFO "klips_dmp: " + + "at %s, len=%d:\n", s, len); + + + + for(i = 0; i < len; i++ /*, c++*/) { + + if(!(i % 16)) { + + printk(KERN_INFO + + "klips_debug: @%03x:", + + i); + + } + + printk(" %02x", b[i]); + + if(!((i + 1) % 16)) { + + printk("\n"); + + } + + } + + if(i % 16) { + + printk("\n"); + + } + +} + + + +/* + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + + + --- /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,1876 @@ + +/* + + * 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 . + + * + + * 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. + + */ + + + +#define __NO_VERSION__ + +#include + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif /* for CONFIG_IP_FORWARD */ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include + +#include + +#include + + + +#include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include + + + +#include + + + +#ifdef NET_21 + +# include + +# define ip_chk_addr inet_addr_type + +# define IS_MYADDR RTN_LOCAL + +# include + +# undef dev_kfree_skb + +# define dev_kfree_skb(a,b) kfree_skb(a) + +# define PHYSDEV_TYPE + +#endif /* NET_21 */ + + + +#include /* icmp_send() */ + +#include + +#ifdef NETDEV_23 + +# include + +#endif /* NETDEV_23 */ + + + +#include + +#include + + + +#include "libreswan/ipsec_kversion.h" + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_life.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_eroute.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_sa.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_xmit.h" + +#include "libreswan/ipsec_ipe4.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + +#include "libreswan/ipsec_kern24.h" + + + +#include + +#include + + + +#include "libreswan/ipsec_proto.h" + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + +#include + +#endif + + + +static __u32 zeroes[64]; + + + +DEBUG_NO_STATIC int + +ipsec_tunnel_open(struct net_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; + + + + KLIPS_INC_USE; + + return 0; + +} + + + +DEBUG_NO_STATIC int + +ipsec_tunnel_close(struct net_device *dev) + +{ + + KLIPS_DEC_USE; + + return 0; + +} + + + +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 + +} + + + +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 + + * . + + */ + + 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_KLIPS_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_KLIPS_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) + +{ + + unsigned int bypass; + + + + bypass = FALSE; + + + + /* + + * 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) { + + struct udphdr *t = NULL; + + + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + + "klips_debug:udp port check: " + + "fragoff: %d len: %d>%ld \n", + + ntohs(ixs->iph->frag_off) & IP_OFFSET, + + (ixs->skb->len - ixs->hard_header_len), + + (unsigned long int) ((ixs->iph->ihl << 2) + sizeof(struct udphdr))); + + + + if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 && + + ((ixs->skb->len - ixs->hard_header_len) >= + + ((ixs->iph->ihl << 2) + sizeof(struct udphdr)))) + + { + + t =((struct udphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2))); + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + + "klips_debug:udp port in packet: " + + "port %d -> %d\n", + + ntohs(t->source), ntohs(t->dest)); + + } + + + + ixs->sport=0; ixs->dport=0; + + + + if(ixs->skb->sk) { + +#ifdef NET_26 + +#ifdef HAVE_INET_SK_SPORT + + ixs->sport = ntohs(inet_sk(ixs->skb->sk)->sport); + + ixs->dport = ntohs(inet_sk(ixs->skb->sk)->dport); + +#else + + struct udp_sock *us; + + + + us = (struct udp_sock *)ixs->skb->sk; + + + + ixs->sport = ntohs(us->inet.sport); + + ixs->dport = ntohs(us->inet.dport); + +#endif + +#else + + ixs->sport = ntohs(ixs->skb->sk->sport); + + ixs->dport = ntohs(ixs->skb->sk->dport); + +#endif + + + + } + + + + if(t != NULL) { + + if(ixs->sport == 0) { + + ixs->sport = ntohs(t->source); + + } + + if(ixs->dport == 0) { + + ixs->dport = ntohs(t->dest); + + } + + } + + } + + + + /* + + * practically identical to above, but let's be careful about + + * tcp vs udp headers + + */ + + if(ixs->iph->protocol == IPPROTO_TCP) { + + struct tcphdr *t = NULL; + + + + if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 && + + ((ixs->skb->len - ixs->hard_header_len) >= + + ((ixs->iph->ihl << 2) + sizeof(struct tcphdr)))) { + + t =((struct tcphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2))); + + } + + + + ixs->sport=0; ixs->dport=0; + + + + if(ixs->skb->sk) { + +#ifdef NET_26 + +#ifdef HAVE_INET_SK_SPORT + + ixs->sport = ntohs(inet_sk(ixs->skb->sk)->sport); + + ixs->dport = ntohs(inet_sk(ixs->skb->sk)->dport); + +#else + + struct tcp_tw_bucket *tw; + + tw = (struct tcp_tw_bucket *)ixs->skb->sk; + + ixs->sport = ntohs(tw->tw_sport); + + ixs->dport = ntohs(tw->tw_dport); + +#endif + +#else + + ixs->sport = ntohs(ixs->skb->sk->sport); + + ixs->dport = ntohs(ixs->skb->sk->dport); + +#endif + + } + + + + if(t != NULL) { + + if(ixs->sport == 0) { + + ixs->sport = ntohs(t->source); + + } + + if(ixs->dport == 0) { + + ixs->dport = ntohs(t->dest); + + } + + } + + } + + + + /* 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); + + + + /* + + * 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==NULL + + || 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->iph->protocol == IPPROTO_UDP && + + (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"); + + } + + bypass = TRUE; + + } + + + +#ifdef KLIPS_EXCEPT_DNS53 + + /* + + * + + * if we are udp/53 or tcp/53, also let it through a %trap or %hold, + + * since it is DNS, but *also* follow the %trap. + + * + + * we do not do this for tunnels, only %trap's and %hold's. + + * + + */ + + + + if (ip_chk_addr((unsigned long)ixs->iph->saddr) == IS_MYADDR + + && (ixs->eroute==NULL + + || 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->iph->protocol == IPPROTO_UDP + + || ixs->iph->protocol == IPPROTO_TCP) + + && ixs->dport == 53)) { + + + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + + "klips_debug:ipsec_xmit_SAlookup: " + + "possible DNS packet\n"); + + + + if(ixs->eroute) + + { + + if(ixs->eroute->er_said.spi == htonl(SPI_TRAP) + + || ixs->eroute->er_said.spi == htonl(SPI_HOLD)) + + { + + ixs->outgoing_said.spi = htonl(SPI_PASSTRAP); + + bypass = TRUE; + + } + + } + + else + + { + + ixs->outgoing_said.spi = htonl(SPI_PASSTRAP); + + bypass = TRUE; + + } + + + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + + "klips_debug:ipsec_xmit_SAlookup: " + + "bypass = %d\n", bypass); + + + + if(bypass + + && !(ixs->skb->sk) + + && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0)) + + { + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + + "klips_debug:ipsec_xmit_SAlookup: " + + "local port 53 (probably DNS) passthrough:" + + "base fragment, rest of fragments will " + + "probably get filtered.\n"); + + } + + } + +#endif + + + + if (bypass==FALSE && 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]; + + } + + } + + } + + + + 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; + +} + + + +/* management of buffers */ + +static struct ipsec_xmit_state * ipsec_xmit_state_new (void); + +static void ipsec_xmit_state_delete (struct ipsec_xmit_state *ixs); + + + + + +/* + + * 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 net_device *dev) + +{ + + struct ipsec_xmit_state *ixs = NULL; + + enum ipsec_xmit_value stat; + + + + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + + "\n\nipsec_tunnel_start_xmit: STARTING"); + + + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + + ixs->natt_type = 0, ixs->natt_head = 0; + + ixs->natt_sport = 0, ixs->natt_dport = 0; + +#endif + + stat = IPSEC_XMIT_ERRMEMALLOC; + + ixs = ipsec_xmit_state_new (); + + if (! ixs) { + + goto alloc_error; + + } + + + + 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_nat_encap(ixs); + + if(stat != IPSEC_XMIT_OK) { + + goto cleanup; + + } + + + + stat = ipsec_tunnel_restore_hard_header(ixs); + + if(stat != IPSEC_XMIT_OK) { + + goto cleanup; + + } + + + + bypass: + + stat = ipsec_tunnel_send(ixs); + + + + cleanup: + + ipsec_xmit_cleanup(ixs); + + + + ipsec_xmit_state_delete (ixs); + +alloc_error: + + return 0; + +} + + + +DEBUG_NO_STATIC struct net_device_stats * + +ipsec_tunnel_get_stats(struct net_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 net_device *dev, + + unsigned short type, void *daddr, void *saddr, unsigned len) + +{ + + struct ipsecpriv *prv = dev->priv; + + struct net_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(ip_hdr(skb)->saddr), + + (__u32)ntohl(ip_hdr(skb)->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 net_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(ip_hdr(skb)->saddr), + + (__u32)ntohl(ip_hdr(skb)->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 net_device *dev, + + unsigned long raddr, struct sk_buff *skb) + +#endif /* NET_21 */ + +{ + + struct ipsecpriv *prv = skb->dev->priv; + + struct net_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(ip_hdr(skb)->saddr), + + (__u32)ntohl(ip_hdr(skb)->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(ip_hdr(skb)->saddr), + + (__u32)ntohl(ip_hdr(skb)->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 net_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 net_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 net_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 net_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 net_device *dev, struct net_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; iaddr_len; i++) { + + dev->dev_addr[i] = physdev->dev_addr[i]; + + } + +#ifdef CONFIG_KLIPS_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_KLIPS_DEBUG */ + + + + return 0; + +} + + + +/* + + * We call the detach routine to detach the ipsec tunnel from another device. + + */ + + + +DEBUG_NO_STATIC int + +ipsec_tunnel_detach(struct net_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; idev_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 net_device *ipsecdev = NULL, *prvdev; + + struct ipsecpriv *prv; + + 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 net_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", + + ipsecdev->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, ipsecdev->name, prvdev->name); + + return ret; + + } + + } + + } + + } + + } + + return 0; + +} + + + +DEBUG_NO_STATIC int + +ipsec_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + +{ + + struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data; + + struct ipsecpriv *prv = dev->priv; + + struct net_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); + + 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(); + + + +#ifdef HAVE_UDP_ENCAP_CONVERT + + case IPSEC_UDP_ENCAP_CONVERT: + + { + + unsigned int *socknum =(unsigned int *)&ifr->ifr_data; + + struct socket *sock; + + int err, fput_needed; + + + + /* that's a static function in socket.c + + * sock = sockfd_lookup_light(*socknum, &err, &fput_needed); */ + + sock = sockfd_lookup(*socknum, &err); + + if (!sock) + + goto encap_out; + + + + /* check that it's a UDP socket */ + + udp_sk(sk)->encap_type = UDP_ENCAP_ESPINUDP_NON_IKE; + + udp_sk(sk)->encap_rcv = klips26_udp_encap_rcv; + + + + KLIPS_PRINT(debug_tunnel + + , "UDP socket: %u set to NON-IKE encap mode\n" + + , socknum); + + + + err = 0; + + + + encap_output: + + fput_light(sock->file, fput_needed); + + encap_out: + + return err; + +#endif + + + + default: + + KLIPS_PRINT(debug_tunnel & DB_TN_INIT, + + "klips_debug:ipsec_tunnel_ioctl: " + + "unknown command %d.\n", + + cmd); + + return -EOPNOTSUPP; + + } + +} + + + +struct net_device *ipsec_get_device(int inst) + +{ + + struct net_device *ipsec_dev; + + + + ipsec_dev = NULL; + + + + if(inst < IPSEC_NUM_IF) { + + ipsec_dev = ipsecdevices[inst]; + + } + + + + return ipsec_dev; + +} + + + +int + +ipsec_device_event(struct notifier_block *unused, unsigned long event, void *ptr) + +{ + + struct net_device *dev = ptr; + + struct net_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 net_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 net_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 */; + + + + /* 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 net_device *dev) + +{ + + ipsec_tunnel_init(dev); + + return 0; + +} + + + +struct net_device *ipsecdevices[IPSEC_NUM_IFMAX]; + +int ipsecdevices_max=-1; + + + + + +int + +ipsec_tunnel_createnum(int ifnum) + +{ + + char name[IFNAMSIZ]; + + struct net_device *dev_ipsec; + + int vifentry; + + + + if(ifnum > IPSEC_NUM_IFMAX) { + + return -ENOENT; + + } + + + + if(ipsecdevices[ifnum]!=NULL) { + + return -EEXIST; + + } + + + + /* no identical device */ + + if(ifnum > ipsecdevices_max) { + + ipsecdevices_max=ifnum; + + } + + vifentry = ifnum; + + + + KLIPS_PRINT(debug_tunnel & DB_TN_INIT, + + "klips_debug:ipsec_tunnel_init_devices: " + + "creating and registering IPSEC_NUM_IF=%u device\n", + + ifnum); + + + + sprintf(name, IPSEC_DEV_FORMAT, ifnum); + + dev_ipsec = (struct net_device*)kmalloc(sizeof(struct net_device), GFP_KERNEL); + + if (dev_ipsec == NULL) { + + printk(KERN_ERR "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 net_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 */ + +#ifdef HAVE_DEV_NEXT + + dev_ipsec->next = NULL; + +#endif + + 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[vifentry]=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; + +} + + + + + +int + +ipsec_tunnel_init_devices(void) + +{ + + int i; + + int error; + + + + 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 net_device) + IFNAMSIZ), + + IFNAMSIZ); + + + + for(i = 0; i < IPSEC_NUM_IF; i++) { + + error = ipsec_tunnel_createnum(i); + + + + if(error) break; + + } + + return 0; + +} + + + +int + +ipsec_tunnel_deletenum(int vifnum) + +{ + + struct net_device *dev_ipsec; + + + + if(vifnum > IPSEC_NUM_IFMAX) { + + return -ENOENT; + + } + + + + dev_ipsec = ipsecdevices[vifnum]; + + if(dev_ipsec == NULL) { + + return -ENOENT; + + } + + + + /* release reference */ + + ipsecdevices[vifnum]=NULL; + + ipsec_dev_put(dev_ipsec); + + + + KLIPS_PRINT(debug_tunnel, "Unregistering %s (refcnt=%d)\n", + + dev_ipsec->name, + + atomic_read(&dev_ipsec->refcnt)); + + unregister_netdev(dev_ipsec); + + KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", dev_ipsec->name); + +#ifndef NETDEV_23 + + kfree(dev_ipsec->name); + + dev_ipsec->name=NULL; + +#endif /* !NETDEV_23 */ + + kfree(dev_ipsec->priv); + + dev_ipsec->priv=NULL; + + + + return 0; + +} + + + + + +struct net_device * + +ipsec_tunnel_get_device(int vifnum) + +{ + + struct net_device *nd; + + + + if(vifnum < ipsecdevices_max) { + + nd = ipsecdevices[vifnum]; + + + + if(nd) dev_hold(nd); + + return nd; + + } else { + + return NULL; + + } + +} + + + + + +/* void */ + +int + +ipsec_tunnel_cleanup_devices(void) + +{ + + int error = 0; + + int i; + + struct net_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", + + dev_ipsec->name, + + atomic_read(&dev_ipsec->refcnt)); + + unregister_netdev(dev_ipsec); + + KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", dev_ipsec->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; + +} + + + +// ------------------------------------------------------------------------ + +// this handles creating and managing state for xmit path + + + +static spinlock_t ixs_cache_lock = SPIN_LOCK_UNLOCKED; + +#ifdef HAVE_KMEM_CACHE_MACRO + +static struct kmem_cache *ixs_cache_allocator = NULL; + +#else + +static kmem_cache_t *ixs_cache_allocator = NULL; + +#endif + +static unsigned ixs_cache_allocated_count = 0; + + + +int + +ipsec_xmit_state_cache_init (void) + +{ + +#ifdef HAVE_KMEM_CACHE_MACRO + + struct ipsec_xmit_state ipsec_ixs; + +#endif + + if (ixs_cache_allocator) + + return -EBUSY; + + + + spin_lock_init(&ixs_cache_lock); + +#ifdef HAVE_KMEM_CACHE_MACRO + + /* ixs_cache_allocator = KMEM_CACHE(ipsec_ixs,0); */ + + ixs_cache_allocator = kmem_cache_create ("ipsec_ixs", + + sizeof (struct ipsec_xmit_state), 0, + + 0, NULL); + +#else + + ixs_cache_allocator = kmem_cache_create ("ipsec_ixs", + + sizeof (struct ipsec_xmit_state), 0, + + 0, NULL, NULL); + +#endif + + if (! ixs_cache_allocator) + + return -ENOMEM; + + + + return 0; + +} + + + +void + +ipsec_xmit_state_cache_cleanup (void) + +{ + + if (unlikely (ixs_cache_allocated_count)) + + printk ("ipsec: deleting ipsec_ixs kmem_cache while in use\n"); + + + + if (ixs_cache_allocator) { + + kmem_cache_destroy (ixs_cache_allocator); + + ixs_cache_allocator = NULL; + + } + + ixs_cache_allocated_count = 0; + +} + + + +static struct ipsec_xmit_state * + +ipsec_xmit_state_new (void) + +{ + + struct ipsec_xmit_state *ixs; + + + + spin_lock_bh (&ixs_cache_lock); + + + + ixs = kmem_cache_alloc (ixs_cache_allocator, GFP_ATOMIC); + + + + if (likely (ixs != NULL)) + + ixs_cache_allocated_count++; + + + + spin_unlock_bh (&ixs_cache_lock); + + + + if (unlikely (NULL == ixs)) + + goto bail; + + + + // initialize the object + + memset((caddr_t)ixs, 0, sizeof(*ixs)); + + + +bail: + + return ixs; + +} + + + +static void + +ipsec_xmit_state_delete (struct ipsec_xmit_state *ixs) + +{ + + if (unlikely (! ixs)) + + return; + + + + spin_lock_bh (&ixs_cache_lock); + + + + ixs_cache_allocated_count--; + + kmem_cache_free (ixs_cache_allocator, ixs); + + + + spin_unlock_bh (&ixs_cache_lock); + +} + + + +/* + + * + + * 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,75 @@ + +/* + + * 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 . + + * + + * 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.65 2005/04/29 05:10:22 mcr Exp $ + + */ + + + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + +#include /* printk() */ + + + +#include "freeswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#include /* get_random_bytes() */ + +#include + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *lock* */ + +# endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + + + +#include + + + +#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 + +#include + + + +#ifdef SPINLOCK + +spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED; + +#else /* SPINLOCK */ + +spinlock_t tdb_lock; + +#endif /* SPINLOCK */ + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /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,1940 @@ + +/* + + * IPSEC Transmit code. + + * Copyright (C) 1996, 1997 John Ioannidis. + + * Copyright (C) 1998-2003 Richard Guy Briggs. + + * Copyright (C) 2004-2005 Michael Richardson + + * + + * 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 . + + * + + * 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. + + */ + + + +#define __NO_VERSION__ + +#include + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif /* for CONFIG_IP_FORWARD */ + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + + + +#include + +#include + +#include + + + +#include + +#include + +#include + +#ifdef NET_21 + +# define MSS_HACK_ /* experimental */ + +# include + +# include + +# define proto_priv cb + +#endif /* NET_21 */ + + + +#include /* icmp_send() */ + +#include + +#ifdef NETDEV_23 + +# include + +#endif /* NETDEV_23 */ + + + +#include + +#ifdef MSS_HACK + +# include /* TCP options */ + +#endif /* MSS_HACK */ + + + +#include "libreswan/ipsec_kern24.h" + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_life.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_eroute.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xmit.h" + +#include "libreswan/ipsec_sa.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_ipe4.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + + + +#ifdef CONFIG_KLIPS_IPCOMP + +#include "libreswan/ipcomp.h" + +#endif /* CONFIG_KLIPS_IPCOMP */ + + + +#include + +#include + + + +#include "libreswan/ipsec_proto.h" + +#include "libreswan/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 */ + + + + + + + +#if defined(CONFIG_KLIPS_AH) + +static __u32 zeroes[64]; + +#endif + + + +int ipsec_xmit_trap_count = 0; + +int ipsec_xmit_trap_sendcount = 0; + + + +#ifdef CONFIG_KLIPS_DEBUG + +#define dmp(_x,_y,_z) if(debug_xmit && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z) + +#else /* CONFIG_KLIPS_DEBUG */ + +#define dmp(_x, _y, _z) + +#endif /* CONFIG_KLIPS_DEBUG */ + + + + + +#if !defined(SKB_COPY_EXPAND) || defined(KLIPS_UNIT_TESTS) + +/* + + * This is mostly skbuff.c:skb_copy(). + + */ + +struct sk_buff * + +skb_copy_expand(const 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; + +#ifdef HAVE_SOCK_SECURITY + + n->security=skb->security; + +#endif + +#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_KLIPS_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)"); + + if(ip->protocol == IPPROTO_ESP) + + printk(" (ESP)"); + + if(ip->protocol == IPPROTO_AH) + + printk(" (AH)"); + + if(ip->protocol == IPPROTO_COMP) + + printk(" (COMP)"); + + 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 len = ntohs(ip->tot_len) - ip->ihl*4; + + + + c = ((__u8*)ip) + ip->ihl*4; + + ipsec_dmp_block("ip_print", c, len); + + } + +} + +#endif /* CONFIG_KLIPS_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->cur_mtu = 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; + + } + + + + /* 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; + + } + + } + + + + ixs->iph = ip_hdr(ixs->skb); + + + + /* 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_KLIPS_ESP + + struct esphdr *espp; + + unsigned char *idat, *pad; + + int authlen = 0, padlen = 0, i; + +#endif /* !CONFIG_KLIPS_ESP */ + +#ifdef CONFIG_KLIPS_AH + + struct iphdr ipo; + + struct ahhdr *ahp; + +#endif /* CONFIG_KLIPS_AH */ + +#if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) + + union { + +#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + + MD5_CTX md5; + +#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + + SHA1_CTX sha1; + +#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + + } tctx; + + __u8 hash[AH_AMAX]; + +#endif /* defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMACn_SHA1) */ + + int headroom = 0, tailroom = 0, ilen = 0, len = 0; + + unsigned char *dat; + + int blocksize = 8; /* XXX: should be inside ixs --jjo */ + + struct ipsec_alg_enc *ixt_e = NULL; + + struct ipsec_alg_auth *ixt_a = NULL; + + + + ixs->iphlen = ixs->iph->ihl << 2; + + ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen; + + ixs->sa_len = KLIPS_SATOT(debug_tunnel, &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_KLIPS_AH + + case IPPROTO_AH: + + headroom += sizeof(struct ahhdr); + + break; + +#endif /* CONFIG_KLIPS_AH */ + + + +#ifdef CONFIG_KLIPS_ESP + + case IPPROTO_ESP: + + ixt_e=ixs->ipsp->ips_alg_enc; + + if (ixt_e) { + + blocksize = ixt_e->ixt_common.ixt_blocksize; + + headroom += ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8; + + } else { + + ixs->stats->tx_errors++; + + return IPSEC_XMIT_ESP_BADALG; + + } + + + + ixt_a=ixs->ipsp->ips_alg_auth; + + if (ixt_a) { + + tailroom += AHHMAC_HASHLEN; + + authlen = AHHMAC_HASHLEN; + + } else + + switch(ixs->ipsp->ips_authalg) { + +#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + + case AH_MD5: + + authlen = AHHMAC_HASHLEN; + + break; + +#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + + case AH_SHA: + + authlen = AHHMAC_HASHLEN; + + break; + +#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + + case AH_NONE: + + break; + + default: + + ixs->stats->tx_errors++; + + return IPSEC_XMIT_ESP_BADALG; + + } + + tailroom += blocksize != 1 ? + + ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : + + ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; + + tailroom += authlen; + + break; + +#endif /* CONFIG_KLIPS_ESP */ + + + +#ifdef CONFIG_KLIPS_IPIP + + case IPPROTO_IPIP: + + headroom += sizeof(struct iphdr); + + ixs->iphlen = sizeof(struct iphdr); + + break; + +#endif /* !CONFIG_KLIPS_IPIP */ + + + +#ifdef CONFIG_KLIPS_IPCOMP + + case IPPROTO_COMP: + + break; + +#endif /* CONFIG_KLIPS_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_KLIPS_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)); + + + + if (!ixt_e) { + + 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_KLIPS_DEBUG + + if(debug_tunnel & DB_TN_ENCAP) { + + dmp("pre-encrypt", dat, len); + + } + +#endif + + + + /* + + * Do all operations here: + + * copy IV->ESP, encrypt, update ips IV + + * + + */ + + { + + int ret; + + memcpy(espp->esp_iv, + + ixs->ipsp->ips_iv, + + ixs->ipsp->ips_iv_size); + + ret=ipsec_alg_esp_encrypt(ixs->ipsp, + + idat, ilen, espp->esp_iv, + + IPSEC_ALG_ENCRYPT); + + + + prng_bytes(&ipsec_prng, + + (char *)ixs->ipsp->ips_iv, + + ixs->ipsp->ips_iv_size); + + } + + + + if (ixt_a) { + + ipsec_alg_sa_esp_hash(ixs->ipsp, + + (caddr_t)espp, len - ixs->iphlen - authlen, + + &(dat[len - authlen]), authlen); + + + + } else + + switch(ixs->ipsp->ips_authalg) { + +#ifdef CONFIG_KLIPS_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)); + + osMD5Update(&tctx.md5, (caddr_t)espp, len - ixs->iphlen - authlen); + + dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Final(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)); + + osMD5Update(&tctx.md5, hash, AHMD596_ALEN); + + dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Final(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_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_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_KLIPS_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;*/ + + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, espp)); + +#endif /* NET_21 */ + + break; + +#endif /* !CONFIG_KLIPS_ESP */ + +#ifdef CONFIG_KLIPS_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_KLIPS_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)); + + osMD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); + + dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); + + dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); + + dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Update(&tctx.md5, dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom); + + dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Final(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)); + + osMD5Update(&tctx.md5, hash, AHMD596_ALEN); + + dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); + + osMD5Final(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_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_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_KLIPS_AUTH_HMAC_SHA1 */ + + default: + + ixs->stats->tx_errors++; + + return IPSEC_XMIT_AH_BADALG; + + } + +#ifdef NET_21 + + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ahp)); + +#endif /* NET_21 */ + + break; + +#endif /* CONFIG_KLIPS_AH */ + +#ifdef CONFIG_KLIPS_IPIP + + case IPPROTO_IPIP: + + ixs->iph->version = 4; + + switch(sysctl_ipsec_tos) { + + case 0: + +#ifdef NET_21 + + ixs->iph->tos = ip_hdr(ixs->skb)->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; + + } + + ixs->iph->ttl = SYSCTL_IPSEC_DEFAULT_TTL; + + 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 + + skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ip_hdr(ixs->skb))); + +#endif /* NET_21 */ + + break; + +#endif /* !CONFIG_KLIPS_IPIP */ + +#ifdef CONFIG_KLIPS_IPCOMP + + case IPPROTO_COMP: + + { + + unsigned int flags = 0; + +#ifdef CONFIG_KLIPS_DEBUG + + unsigned int old_tot_len = ntohs(ixs->iph->tot_len); + +#endif /* CONFIG_KLIPS_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 = ip_hdr(ixs->skb); + +#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_KLIPS_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_KLIPS_DEBUG */ + + } + + break; + +#endif /* CONFIG_KLIPS_IPCOMP */ + + default: + + ixs->stats->tx_errors++; + + return IPSEC_XMIT_BADPROTO; + + } + + + +#ifdef NET_21 + + skb_set_network_header(ixs->skb, ipsec_skb_offset(ixs->skb, 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_next; + + + + 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_KLIPS_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_KLIPS_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_2(struct ipsec_xmit_state *ixs) + +{ + + struct ipsec_alg_enc *ixt_e = NULL; + + struct ipsec_alg_auth *ixt_a = NULL; + + int blocksize = 8; + + enum ipsec_xmit_value bundle_stat = IPSEC_XMIT_OK; + + struct ipsec_sa *saved_ipsp; + + + + 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? + + */ + + saved_ipsp = ixs->ipsp; /* save the head of the ipsec_sa chain */ + + while (ixs->ipsp) { + + if (debug_tunnel & DB_TN_XMIT) { + + ixs->sa_len = KLIPS_SATOT(debug_tunnel, &ixs->ipsp->ips_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); + + if(ixs->sa_len == 0) { + + strcpy(ixs->sa_txt, "(error)"); + + } + + } else { + + *ixs->sa_txt = 0; + + ixs->sa_len = 0; + + } + + + + /* If it is in larval state, drop the packet, we cannot process yet. */ + + if(ixs->ipsp->ips_state == K_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)"); + + if(ixs->stats) { + + ixs->stats->tx_errors++; + + } + + bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; + + goto cleanup; + + } + + + + if(ixs->ipsp->ips_state == K_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_rm(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_rm(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_KLIPS_AH + + case IPPROTO_AH: + + ixs->headroom += sizeof(struct ahhdr); + + break; + +#endif /* CONFIG_KLIPS_AH */ + +#ifdef CONFIG_KLIPS_ESP + + case IPPROTO_ESP: + + ixt_e=ixs->ipsp->ips_alg_enc; + + if (ixt_e) { + + blocksize = ixt_e->ixt_common.ixt_blocksize; + + ixs->headroom += ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8; + + } + + else { + + ixs->stats->tx_errors++; + + bundle_stat = IPSEC_XMIT_ESP_BADALG; + + goto cleanup; + + } + + + + if ((ixt_a=ixs->ipsp->ips_alg_auth)) { + + ixs->tailroom += AHHMAC_HASHLEN; + + } else + + switch(ixs->ipsp->ips_authalg) { + +#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + + case AH_MD5: + + ixs->tailroom += AHHMAC_HASHLEN; + + break; + +#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + + case AH_SHA: + + ixs->tailroom += AHHMAC_HASHLEN; + + break; + +#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + + case AH_NONE: + + break; + + default: + + ixs->stats->tx_errors++; + + bundle_stat = IPSEC_XMIT_AH_BADALG; + + goto cleanup; + + } + + ixs->tailroom += blocksize != 1 ? + + ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : + + ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; + +#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_KLIPS_ESP */ + +#ifdef CONFIG_KLIPS_IPIP + + case IPPROTO_IPIP: + + ixs->headroom += sizeof(struct iphdr); + + break; + +#endif /* !CONFIG_KLIPS_IPIP */ + + case IPPROTO_COMP: + +#ifdef CONFIG_KLIPS_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_KLIPS_IPCOMP */ + + default: + + ixs->stats->tx_errors++; + + bundle_stat = IPSEC_XMIT_BADPROTO; + + goto cleanup; + + } + + ixs->ipsp = ixs->ipsp->ips_next; + + 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 = saved_ipsp; /* 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->cur_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->cur_mtu, ixs->physmtu, + + ixs->tot_headroom, ixs->tot_tailroom, ixs->mtudiff, ntohs(ixs->iph->tot_len)); + + if(ixs->cur_mtu == 0 || 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 ? ixs->dev->name : "ifX", + + ixs->cur_mtu, + + ixs->cur_mtu - newmtu, + + newmtu); + + ixs->cur_mtu = newmtu; + + + + /* this would seem to adjust the MTU of the route as well */ + +#if 0 + + ixs->skb->dst->pmtu = ixs->prv->mtu; /* RGB */ + +#endif /* 0 */ + + } + + + + /* + + 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->cur_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->cur_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->cur_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->cur_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 force destination address to sane value + + */ + + + + struct sockaddr_in *sv4=(struct sockaddr_in *)ixs->ipsp->ips_addr_d; + + __u32 natt_d = sv4->sin_addr.s_addr; + + struct iphdr *ipp = ixs->iph; + + + + /* set the destination address to what it needs to be for the + + * NAT encapsulation. + + */ + + KLIPS_PRINT(debug_tunnel, + + "xmit: setting ND=%08x\n", natt_d); + + ipp->daddr = natt_d; + + ipp->check = 0; + + ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); + + } + +#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ + + + + if(!ixs->hard_header_stripped && ixs->hard_header_len>0) { + + 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); + + + + if(tskb && ixs->skb->sk) { + + skb_set_owner_w(tskb, ixs->skb->sk); + + } + + + + 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)); + + } + + + +#ifdef CONFIG_KLIPS_DEBUG + + if(debug_tunnel & DB_TN_ENCAP) { + + ipsec_print_ip(ixs->iph); + + } + +#endif + + + + /* + + * Apply grouped transforms to packet + + */ + + while (ixs->ipsp) { + + enum ipsec_xmit_value encap_stat = IPSEC_XMIT_OK; + + + + encap_stat = ipsec_xmit_encap_once(ixs); + + + +#ifdef CONFIG_KLIPS_DEBUG + + if(debug_tunnel & DB_TN_ENCAP) { + + ipsec_print_ip(ixs->iph); + + } + +#endif + + + + 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: + + return bundle_stat; + +} + + + +/* + + * upon entry to this function, ixs->skb should be setup + + * as follows: + + * + + * data = beginning of IP packet <- differs from ipsec_rcv(). + + * nh.raw = beginning of IP packet. + + * h.raw = data after the IP packet. + + * + + */ + +enum ipsec_xmit_value + +ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs) + +{ + + 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_KLIPS_DEBUG + + char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF]; + +#endif /* CONFIG_KLIPS_DEBUG */ + + + + /* Signal all listening KMds with a PF_KEY ACQUIRE */ + + + + memset(&src, 0, sizeof(src)); + + memset(&dst, 0, sizeof(dst)); + + 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; + + + + 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: " + + "K_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) */ + + + + /* ipsec_sa_getbyid() takes a reference to the ixs */ + + 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)"); + + if(ixs->stats) { + + ixs->stats->tx_dropped++; + + } + + bundle_stat = IPSEC_XMIT_SAIDNOTFOUND; + + goto cleanup; + + } + + + + bundle_stat = ipsec_xmit_encap_bundle_2(ixs); + + + + /* we are done with this SA */ + + ipsec_sa_put(ixs->ipsp); + + + +cleanup: + + return bundle_stat; + +} + + + +void + +ipsec_xmit_cleanup(struct ipsec_xmit_state*ixs) + +{ + + if(ixs->dev) { + +#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); + + ixs->saved_header = NULL; + + } + + if(ixs->skb) { + + dev_kfree_skb(ixs->skb); + + ixs->skb=NULL; + + } + + if(ixs->oskb) { + + dev_kfree_skb(ixs->oskb); + + ixs->oskb=NULL; + + } + + if (ixs->ips.ips_ident_s.data) { + + kfree(ixs->ips.ips_ident_s.data); + + ixs->ips.ips_ident_s.data=NULL; + + } + + if (ixs->ips.ips_ident_d.data) { + + kfree(ixs->ips.ips_ident_d.data); + + ixs->ips.ips_ident_d.data=NULL; + + } + +} + + + +#ifdef NETDEV_23 + +static inline int ipsec_xmit_send2(struct sk_buff *skb) + +{ + +#ifdef NETDEV_25 /* 2.6 kernels */ + + return dst_output(skb); + +#else + + return ip_send(skb); + +#endif + +} + +#endif /* NETDEV_23 */ + + + +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + +enum ipsec_xmit_value ipsec_nat_encap(struct ipsec_xmit_state *ixs) + +{ + + if (ixs->natt_type && ixs->natt_head) { + +#if 0 + + struct iphdr *ipp = ixs->skb->nh.iph; + +#endif + + struct iphdr *ipp = ixs->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); + + + +#if 0 + + /* set IP destination address (matters in transport mode) */ + + { + + struct sockaddr_in *d = (struct sockaddr_in *)ixs->ipsp->ips_addr_d; + + ipp->daddr = d->sin_addr.s_addr; + + } + +#endif + + + + /* 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); + + } + + return IPSEC_XMIT_OK; + +} + +#endif + + + +/* avoid forward reference complain on <2.5 */ + +struct flowi; + + + +enum ipsec_xmit_value + +ipsec_xmit_send(struct ipsec_xmit_state*ixs, struct flowi *fl) + +{ + + int error; + + + +#ifdef NETDEV_25 + +#if 0 + + 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; + +#endif + + fl->nl_u.ip4_u.daddr = ixs->iph->daddr; + + fl->nl_u.ip4_u.saddr = ixs->pass ? 0 : ixs->iph->saddr; + + fl->nl_u.ip4_u.tos = RT_TOS(ixs->iph->tos); + + fl->proto = ixs->iph->protocol; + + + + if ((error = ip_route_output_key(&ixs->route, fl))) { + +#else + + /*skb_orphan(ixs->skb);*/ + + if((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", + + 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; + + if(ixs->stats) { + + ixs->stats->tx_bytes += ixs->skb->len; + + } + + + +#if 0 + + if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { + +#endif + + if(ixs->skb->len < skb_network_header(ixs->skb) - ixs->skb->data) { + + if(ixs->stats) { + + 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)(skb_network_header(ixs->skb) - ixs->skb->data), + + ixs->skb->len); + + return IPSEC_XMIT_PUSHPULLERR; + + } + + __skb_pull(ixs->skb, skb_network_header(ixs->skb) - ixs->skb->data); + +#ifdef SKB_RESET_NFCT + + if(!ixs->pass) { + + nf_conntrack_put(ixs->skb->nfct); + + ixs->skb->nfct = NULL; + + } + +#if defined(CONFIG_NETFILTER_DEBUG) && defined(HAVE_SKB_NF_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"); + +#if 0 + + KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->skb->nh.iph); + +#endif + + KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ip_hdr(ixs->skb)); + +#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_xmit_send2); + + 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); + + if(ixs->stats) { + + 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 */ + + if(ixs->stats) { + + ixs->stats->tx_packets++; + + } + + + + ixs->skb = NULL; + + + + return IPSEC_XMIT_OK; + +} + + + +#ifdef NETDEV_25 + +enum ipsec_xmit_value + +ipsec_tunnel_send(struct ipsec_xmit_state *ixs) + +{ + + struct flowi fl; + + + + memset(&fl, 0, sizeof(fl)); + + + + /* new route/dst cache code from James Morris */ + + ixs->skb->dev = ixs->physdev; + + fl.oif = ixs->physdev->iflink; + + + + return ipsec_xmit_send(ixs, &fl); + +} + +#else + +enum ipsec_xmit_value + +ipsec_tunnel_send(struct ipsec_xmit_state *ixs) + +{ + + return ipsec_xmit_send(ixs, NULL); + +} + +#endif + + + + + + + +/* + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/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 + + * + + * 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/net/ipsec/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 + + * + + * 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/net/ipsec/pfkey_v2.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,1555 @@ + +/* + + * @(#) 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 . + + * + + * 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. + + * + + */ + + + +/* + + * 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 + +#include + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + + + +#include "libreswan/ipsec_param.h" + + + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include /* struct socket */ + +#include + +#include + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include + +#include + +#include + +#include /* struct sock */ + +#include + +/* #include */ + +#include + +#ifdef CONFIG_PROC_FS + +# include + +#endif /* CONFIG_PROC_FS */ + + + +#include + + + +#include + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_sa.h" + + + +#include + +#include + + + +#include "libreswan/ipsec_proto.h" + +#include "libreswan/ipsec_kern24.h" + +#include "libreswan/ipsec_sysctl.h" + + + +#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) + + + +#ifndef SOCKOPS_WRAPPED + +#define SOCKOPS_WRAPPED(name) name + +#endif /* SOCKOPS_WRAPPED */ + + + + + +#ifdef NET_26 + +static rwlock_t pfkey_sock_lock = RW_LOCK_UNLOCKED; + +HLIST_HEAD(pfkey_sock_list); + +static DECLARE_WAIT_QUEUE_HEAD(pfkey_sock_wait); + +static atomic_t pfkey_sock_users = ATOMIC_INIT(0); + +#else + +struct sock *pfkey_sock_list = NULL; + +#endif + + + +struct supported_list *pfkey_supported_list[K_SADB_SATYPE_MAX+1]; + + + +struct socket_list *pfkey_open_sockets = NULL; + +struct socket_list *pfkey_registered_sockets[K_SADB_SATYPE_MAX+1]; + + + +int pfkey_msg_interp(struct sock *, struct sadb_msg *); + + + +DEBUG_NO_STATIC int pfkey_create(struct socket *sock, int protocol); + +DEBUG_NO_STATIC int pfkey_shutdown(struct socket *sock, int mode); + +DEBUG_NO_STATIC int pfkey_release(struct socket *sock); + + + +#ifdef NET_26 + +DEBUG_NO_STATIC int pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len); + +DEBUG_NO_STATIC int pfkey_recvmsg(struct kiocb *kiocb, struct socket *sock, struct msghdr *msg + + , size_t size, int flags); + +#else + +DEBUG_NO_STATIC int pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm); + +DEBUG_NO_STATIC int pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm); + +#endif + + + +struct net_proto_family pfkey_family_ops = { + + .owner = THIS_MODULE, + + .family = PF_KEY, + + .create = pfkey_create + +}; + + + +struct proto_ops SOCKOPS_WRAPPED(pfkey_ops) = { + +#ifdef NETDEV_23 + + owner: THIS_MODULE, + + 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 + +SOCKOPS_WRAP(pfkey, PF_KEY); + +#endif /* NETDEV_23 */ + + + +#ifdef NET_26 + +static void pfkey_sock_list_grab(void) + +{ + + write_lock_bh(&pfkey_sock_lock); + + + + if (atomic_read(&pfkey_sock_users)) { + + DECLARE_WAITQUEUE(wait, current); + + + + add_wait_queue_exclusive(&pfkey_sock_wait, &wait); + + for(;;) { + + set_current_state(TASK_UNINTERRUPTIBLE); + + if (atomic_read(&pfkey_sock_users) == 0) + + break; + + write_unlock_bh(&pfkey_sock_lock); + + schedule(); + + write_lock_bh(&pfkey_sock_lock); + + } + + + + __set_current_state(TASK_RUNNING); + + remove_wait_queue(&pfkey_sock_wait, &wait); + + } + +} + + + +static __inline__ void pfkey_sock_list_ungrab(void) + +{ + + write_unlock_bh(&pfkey_sock_lock); + + wake_up(&pfkey_sock_wait); + +} + + + +static __inline__ void pfkey_lock_sock_list(void) + +{ + + /* read_lock() synchronizes us to pfkey_table_grab */ + + + + read_lock(&pfkey_sock_lock); + + atomic_inc(&pfkey_sock_users); + + read_unlock(&pfkey_sock_lock); + +} + + + +static __inline__ void pfkey_unlock_sock_list(void) + +{ + + if (atomic_dec_and_test(&pfkey_sock_users)) + + wake_up(&pfkey_sock_wait); + +} + +#endif + + + +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 ipsec_alg_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 ipsec_alg_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; + +} + + + +#ifdef NET_26 + +DEBUG_NO_STATIC void + +pfkey_insert_socket(struct sock *sk) + +{ + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_insert_socket: " + + "sk=0p%p\n", + + sk); + + pfkey_sock_list_grab(); + + sk_add_node(sk, &pfkey_sock_list); + + pfkey_sock_list_ungrab(); + +} + + + +DEBUG_NO_STATIC void + +pfkey_remove_socket(struct sock *sk) + +{ + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_remove_socket: 0p%p\n", sk); + + pfkey_sock_list_grab(); + + sk_del_node_init(sk); + + pfkey_sock_list_ungrab(); + + return; + +} + +#else + + + +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; + + + + s = NULL; + + 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; + +} + +#endif + + + +DEBUG_NO_STATIC void + +pfkey_destroy_socket(struct sock *sk) + +{ + + struct sk_buff *skb; + + + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_destroy_socket: 0p%p\n",sk); + + pfkey_remove_socket(sk); + + + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_destroy_socket: " + + "pfkey_remove_socket called, sk=0p%p\n",sk); + + + + 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->sk_receive_queue), + + sk->sk_receive_queue.next, + + sk->sk_receive_queue.prev); + + + + while(sk && ((skb=skb_dequeue(&(sk->sk_receive_queue)))!=NULL)) { + +#ifdef CONFIG_KLIPS_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(" sk:0p%p", skb->sk); + + 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_transport_header(skb)); + + printk(" nh:0p%p", skb_network_header(skb)); + + printk(" mac:0p%p", skb_mac_header(skb)); + + 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); + +#ifdef HAVE_SOCK_SECURITY + + printk(" security:%d", skb->security); + +#endif + + printk(" truesize:%d", skb->truesize); + + printk(" head:0p%p", skb->head); + + printk(" data:0p%p", skb->data); + + printk(" tail:0p%p", skb_tail_pointer(skb)); + + printk(" end:0p%p", skb_end_pointer(skb)); + + if(sysctl_ipsec_debug_verbose) { + + unsigned char* i; + + printk(" data"); + + for(i = skb->head; i < skb_end_pointer(skb); i++) { + + printk(":%2x", (unsigned char)(*(i))); + + } + + } + + printk(" destructor:0p%p", skb->destructor); + + printk("\n"); + + } + +#endif /* CONFIG_KLIPS_DEBUG */ + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_destroy_socket: " + + "skb=0p%p freed.\n", + + skb); + + ipsec_kfree_skb(skb); + + } + + + +#ifdef NET_26 + + sock_set_flag(sk, SOCK_DEAD); + +#else + + sk->dead = 1; + +#endif + + 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; + + } + + + + sk = sock->sk; + + + + 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_set_transport_header(skb, ipsec_skb_offset(skb, skb_put(skb, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN))); + + memcpy(skb_transport_header(skb), pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); + + + + 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; + +} + + + +#ifdef NET_26_12_SKALLOC + +static struct proto key_proto = { + + .name = "KEY", + + .owner = THIS_MODULE, + + .obj_size = sizeof(struct sock), + + + +}; + +#endif + + + +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; + + } + + + + sock->state = SS_UNCONNECTED; + + + + KLIPS_INC_USE; + + + +#ifdef NET_26 + +#ifdef NET_26_12_SKALLOC + + sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, &key_proto, 1); + +#else + + sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL); + +#endif + +#else + + /* 2.4 interface */ + + sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1); + +#endif + + + + if(sk == NULL) + + { + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_create: " + + "Out of memory trying to allocate.\n"); + + KLIPS_DEC_USE; + + return -ENOMEM; + + } + + + + sock_init_data(sock, sk); + + + + sk->sk_destruct = NULL; + + sk->sk_reuse = 1; + + sock->ops = &pfkey_ops; + + + + sk->sk_family = PF_KEY; + +/* sk->num = protocol; */ + + sk->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->sk_sleep); + + + + 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; + +} + + + +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; */ + + } + + + + sk=sock->sk; + + + + /* 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); + + + + if(sock_flag(sk, SOCK_DEAD)) + + if(sk->sk_state_change) { + + sk->sk_state_change(sk); + + } + + + + sock->sk = NULL; + + + + /* 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 = K_SADB_SATYPE_UNSPEC; i <= K_SADB_SATYPE_MAX; i++) { + + pfkey_list_remove_socket(sock, &(pfkey_registered_sockets[i])); + + } + + + + KLIPS_DEC_USE; + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_release: " + + "succeeded.\n"); + + + + return 0; + +} + + + +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; + + } + + + + sk=sock->sk; + + + + 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->sk_shutdown|=SEND_SHUTDOWN; + + sk->sk_state_change(sk); + + } + + + + if(mode&RCV_SHUTDOWN) { + + sk->sk_shutdown|=RCV_SHUTDOWN; + + sk->sk_state_change(sk); + + } + + return 0; + +} + + + +/* + + * Send PF_KEY data down. + + */ + + + +DEBUG_NO_STATIC int + +#ifdef NET_26 + +pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) + +#else + +pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) + +#endif + +{ + + 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); + + } + + + + sk = sock->sk; + + + + 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->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); + + } + + + + if(msg->msg_control) + + { + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_sendmsg: " + + "can't set flags or set msg_control.\n"); + + SENDERR(EINVAL); + + } + + + + if(sk->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", (int)len); + + SENDERR(EMSGSIZE); + + } + + + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_sendmsg: " + + "allocating %d bytes for downward message.\n", + + (int)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", + + (int)len, (int)IPSEC_PFKEYv2_ALIGN); + + SENDERR(EMSGSIZE); + + } + + + + 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 > K_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))) { + + 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_26 + +pfkey_recvmsg(struct kiocb *kiocb + + , struct socket *sock + + , struct msghdr *msg + + , size_t size + + , int flags) + +#else + +pfkey_recvmsg(struct socket *sock + + , struct msghdr *msg + + , int size, int flags + + , struct scm_cookie *scm) + +#endif + +{ + + struct sock *sk; + + int noblock = flags & MSG_DONTWAIT; + + struct sk_buff *skb; + + int error; + + + + if(sock == NULL) { + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_recvmsg: " + + "Null socket passed in.\n"); + + return -EINVAL; + + } + + + + sk = sock->sk; + + + + 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, (int)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; + + } + + + + msg->msg_namelen = 0; /* sizeof(*ska); */ + + + + if(sk->sk_err) { + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_sendmsg: " + + "sk->sk_err=%d.\n", sk->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; + + } + + else if(size len) { + + msg->msg_flags |= MSG_TRUNC; + + } + + + + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size); + +#ifdef HAVE_KERNEL_TSTAMP + + sk->sk_stamp = skb->tstamp; + +#elif defined(HAVE_TSTAMP) + + sk->sk_stamp.tv_sec = skb->tstamp.off_sec; + + sk->sk_stamp.tv_usec = skb->tstamp.off_usec; + +#else + + sk->sk_stamp=skb->stamp; + +#endif + + + + skb_free_datagram(sk, skb); + + return size; + +} + + + +#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; /* limit of useful snprintf output */ + +#ifdef NET_26 + + struct hlist_node *node; + +#endif + + off_t begin=0; + + int len=0; + + struct sock *sk; + + + +#ifdef CONFIG_KLIPS_DEBUG + + if(!sysctl_ipsec_debug_verbose) { + +#endif /* CONFIG_KLIPS_DEBUG */ + + len += ipsec_snprintf(buffer, length, + + " sock pid socket next prev e n p sndbf Flags Type St\n"); + +#ifdef CONFIG_KLIPS_DEBUG + + } else { + + len += ipsec_snprintf(buffer, length, + + " sock pid d sleep socket next prev e r z n p sndbf stamp Flags Type St\n"); + + } + +#endif /* CONFIG_KLIPS_DEBUG */ + + + + sk_for_each(sk, node, &pfkey_sock_list) { + + + +#ifdef CONFIG_KLIPS_DEBUG + + if(!sysctl_ipsec_debug_verbose) { + +#endif /* CONFIG_KLIPS_DEBUG */ + + len += ipsec_snprintf(buffer+len, length-len, + + "%8p %5d %8p %d %d %5d %08lX %8X %2X\n", + + sk, + + key_pid(sk), + + sk->sk_socket, + + sk->sk_err, + + sk->sk_protocol, + + sk->sk_sndbuf, + + sk->sk_socket->flags, + + sk->sk_socket->type, + + sk->sk_socket->state); + +#ifdef CONFIG_KLIPS_DEBUG + + } else { + + struct timeval t; + + grab_socket_timeval(t, *sk); + + len += ipsec_snprintf(buffer+len, length-len, + + "%8p %5d %d %8p %8p %d %d %d %d %5d %d.%06d %08lX %8X %2X\n", + + sk, + + key_pid(sk), + + sock_flag(sk, SOCK_DEAD), + + sk->sk_sleep, + + sk->sk_socket, + + sk->sk_err, + + sk->sk_reuse, + +#ifdef HAVE_SOCK_ZAPPED + + sock_flag(sk, SOCK_ZAPPED), + +#else + + sk->sk_zapped, + +#endif + + sk->sk_protocol, + + sk->sk_sndbuf, + + (unsigned int)t.tv_sec, + + (unsigned int)t.tv_usec, + + sk->sk_socket->flags, + + sk->sk_socket->type, + + sk->sk_socket->state); + + } + +#endif /* CONFIG_KLIPS_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; + + } + + } + + } + + + + *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 */ + +) + +{ + + /* limit of useful snprintf output */ + + const int max_content = length > 0? length-1 : 0; + + off_t begin=0; + + int len=0; + + int satype; + + struct supported_list *ps; + + + + len += ipsec_snprintf(buffer, length, + + "satype exttype alg_id ivlen minbits maxbits name\n"); + + + + for(satype = K_SADB_SATYPE_UNSPEC; satype <= K_SADB_SATYPE_MAX; satype++) { + + ps = pfkey_supported_list[satype]; + + while(ps) { + + struct ipsec_alg_supported *alg = ps->supportedp; + + unsigned char *n = alg->ias_name; + + if(n == NULL) n = "unknown"; + + + + len += ipsec_snprintf(buffer+len, length-len, + + " %2d %2d %2d %3d %3d %3d %20s\n", + + satype, + + alg->ias_exttype, + + alg->ias_id, + + alg->ias_ivlen, + + alg->ias_keyminbits, + + alg->ias_keymaxbits, + + 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; /* 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; + + } + + } + + + + ps = ps->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; /* limit of useful snprintf output */ + + 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 = K_SADB_SATYPE_UNSPEC; satype <= K_SADB_SATYPE_MAX; satype++) { + + pfkey_sockets = pfkey_registered_sockets[satype]; + + while(pfkey_sockets) { + + 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); + + + + 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 ipsec_alg_supported supported[], int size) + +{ + + int i; + + int error = 0; + + + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:init_pfkey: " + + "sizeof(supported_init_)[%d]/sizeof(struct ipsec_alg_supported)[%d]=%d.\n", + + satype, + + size, + + (int)sizeof(struct ipsec_alg_supported), + + (int)(size/sizeof(struct ipsec_alg_supported))); + + + + for(i = 0; i < size / sizeof(struct ipsec_alg_supported); i++) { + + + + unsigned char *n = supported[i].ias_name; + + if(n == NULL) n="unknown"; + + + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:init_pfkey: " + + "i=%d inserting satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d name=%s.\n", + + i, + + satype, + + supported[i].ias_exttype, + + supported[i].ias_id, + + supported[i].ias_ivlen, + + supported[i].ias_keyminbits, + + supported[i].ias_keymaxbits, + + n); + + + + 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 ipsec_alg_supported*supportedp; + + + + while(pfkey_supported_list[satype]) { + + unsigned char *n; + + supportedp = pfkey_supported_list[satype]->supportedp; + + + + n = supportedp->ias_name; + + if(n == NULL) n="unknown"; + + + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:init_pfkey: " + + "removing satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d name=%s.\n", + + satype, + + supportedp->ias_exttype, + + supportedp->ias_id, + + supportedp->ias_ivlen, + + supportedp->ias_keyminbits, + + supportedp->ias_keymaxbits, n); + + + + error |= pfkey_list_remove_supported(supportedp, + + &(pfkey_supported_list[satype])); + + } + + return error; + +} + + + +int + +pfkey_init(void) + +{ + + int error = 0; + + int i; + + + + static struct ipsec_alg_supported supported_init_ah[] = { + +#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + + {K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_MD5HMAC, 0, 128, 128}, + +#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + + {K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_SHA1HMAC, 0, 160, 160} + +#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + + }; + + static struct ipsec_alg_supported supported_init_esp[] = { + +#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 + + {K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_MD5HMAC, 0, 128, 128}, + +#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ + +#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 + + {K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_SHA1HMAC, 0, 160, 160}, + +#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ + +#ifdef CONFIG_KLIPS_ENC_3DES + + {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_EALG_3DESCBC, 64, 168, 168}, + +#endif /* CONFIG_KLIPS_ENC_3DES */ + + }; + + static struct ipsec_alg_supported supported_init_ipip[] = { + + {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv4_in_IPv4, 0, 32, 32} + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + + , {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv6_in_IPv4, 0, 128, 32} + + , {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv4_in_IPv6, 0, 32, 128} + + , {K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv6_in_IPv6, 0, 128, 128} + +#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ + + }; + +#ifdef CONFIG_KLIPS_IPCOMP + + static struct ipsec_alg_supported supported_init_ipcomp[] = { + + {K_SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_CALG_DEFLATE, 0, 1, 1} + + }; + +#endif /* CONFIG_KLIPS_IPCOMP */ + + + +#if 0 + + printk(KERN_INFO + + "klips_info:pfkey_init: " + + "FreeS/WAN: initialising PF_KEYv2 domain sockets.\n"); + +#endif + + + + for(i = K_SADB_SATYPE_UNSPEC; i <= K_SADB_SATYPE_MAX; i++) { + + pfkey_registered_sockets[i] = NULL; + + pfkey_supported_list[i] = NULL; + + } + + + + error |= supported_add_all(K_SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah)); + + error |= supported_add_all(K_SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp)); + +#ifdef CONFIG_KLIPS_IPCOMP + + error |= supported_add_all(K_SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp)); + +#endif /* CONFIG_KLIPS_IPCOMP */ + + error |= supported_add_all(K_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 VOID_SOCK_UNREGISTER + + sock_unregister(PF_KEY); + +#else + + error |= sock_unregister(PF_KEY); + +#endif + + + + error |= supported_remove_all(K_SADB_SATYPE_AH); + + error |= supported_remove_all(K_SADB_SATYPE_ESP); + +#ifdef CONFIG_KLIPS_IPCOMP + + error |= supported_remove_all(K_SADB_X_SATYPE_COMP); + +#endif /* CONFIG_KLIPS_IPCOMP */ + + error |= supported_remove_all(K_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 */ + +struct net_protocol; + +void pfkey_proto_init(struct net_protocol *pro) + +{ + + pfkey_init(); + +} + +#endif /* MODULE */ + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/pfkey_v2_build.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,1448 @@ + +/* + + * 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 . + + * + + * 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.53 2005/11/09 00:30:37 mcr Exp $ + + */ + + + +/* + + * Template from klips/net/ipsec/ipsec/ipsec_parser.c. + + */ + + + +char pfkey_v2_build_c_version[] = "$Id: pfkey_v2_build.c,v 1.53 2005/11/09 00:30:37 mcr Exp $"; + + + +/* + + * Some ugly stuff to allow consistent debugging code for use in the + + * kernel and in user space + +*/ + + + +#if defined(__KERNEL__) && defined(linux) + + + +# include /* for printk */ + + + +# include "libreswan/ipsec_kversion.h" /* for malloc switch */ + +# ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +# else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +# endif /* MALLOC_SLAB */ + +# include /* error codes */ + +# include /* size_t */ + +# include /* mark_bh */ + + + +# include /* struct device, and other headers */ + +# include /* eth_type_trans */ + +# include /* struct iphdr */ + +# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + +# include /* struct ipv6hdr */ + +# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ + + + +# define MALLOC(size) kmalloc(size, GFP_ATOMIC) + +# define FREE(obj) kfree(obj) + +# include + +#else /* __KERNEL__ */ + + + +# include + +# include + +# include + +# include + +# include + +# include /* memset */ + + + +# include + + + +#endif /* __KERNEL__ */ + + + +#include + +#include + + + +#ifdef __KERNEL__ + +#include "libreswan/radij.h" /* rd_nodes */ + +#include "libreswan/ipsec_encap.h" /* sockaddr_encap */ + +#endif /* __KERNEL__ */ + + + + + +#include "libreswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ + +#include "libreswan/pfkey_debug.h" + + + + + +#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) + + + +void + +pfkey_extensions_init(struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]) + +{ + + int i; + + + + for (i = 0; i != K_SADB_EXT_MAX + 1; i++) { + + extensions[i] = NULL; + + } + +} + + + +void + +pfkey_extensions_free(struct sadb_ext *extensions[K_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 != K_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) { + + ERROR("pfkey_msg_hdr_build: " + + "why is pfkey_msg already pointing to something?\n"); + + SENDERR(EINVAL); + + } + + + + if(!msg_type) { + + ERROR("pfkey_msg_hdr_build: " + + "msg type not set, must be non-zero..\n"); + + SENDERR(EINVAL); + + } + + + + if(msg_type > K_SADB_MAX) { + + ERROR("pfkey_msg_hdr_build: " + + "msg type too large:%d.\n", + + msg_type); + + SENDERR(EINVAL); + + } + + + + if(satype > K_SADB_SATYPE_MAX) { + + ERROR("pfkey_msg_hdr_build: " + + "satype %d > max %d\n", + + satype, SADB_SATYPE_MAX); + + SENDERR(EINVAL); + + } + + + + pfkey_msg = (struct sadb_msg*)MALLOC(sizeof(struct sadb_msg)); + + *pfkey_ext = (struct sadb_ext*)pfkey_msg; + + + + if(pfkey_msg == NULL) { + + ERROR("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_builds(struct sadb_ext **pfkey_ext, + + struct sadb_builds sab) + +{ + + int error = 0; + + struct k_sadb_sa *pfkey_sa = (struct k_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(sab.sa_base.sadb_sa_spi), /* in network order */ + + sab.sa_base.sadb_sa_replay, + + sab.sa_base.sadb_sa_state, + + sab.sa_base.sadb_sa_auth, + + sab.sa_base.sadb_sa_encrypt, + + sab.sa_base.sadb_sa_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(sab.sa_base.sadb_sa_exttype != SADB_EXT_SA && + + sab.sa_base.sadb_sa_exttype != K_SADB_X_EXT_SA2) { + + DEBUGGING(PF_KEY_DEBUG_BUILD, + + "pfkey_sa_build: " + + "invalid exttype=%d.\n", + + sab.sa_base.sadb_sa_exttype); + + SENDERR(EINVAL); + + } + + + + if(sab.sa_base.sadb_sa_replay > 64) { + + DEBUGGING(PF_KEY_DEBUG_BUILD, + + "pfkey_sa_build: " + + "replay window size: %d -- must be 0 <= size <= 64\n", + + sab.sa_base.sadb_sa_replay); + + SENDERR(EINVAL); + + } + + + + if(sab.sa_base.sadb_sa_auth > SADB_AALG_MAX) { + + DEBUGGING(PF_KEY_DEBUG_BUILD, + + "pfkey_sa_build: " + + "auth=%d > SADB_AALG_MAX=%d.\n", + + sab.sa_base.sadb_sa_auth, + + SADB_AALG_MAX); + + SENDERR(EINVAL); + + } + + + +#if K_SADB_EALG_MAX < 255 + + if(sab.sa_base.sadb_sa_encrypt > K_SADB_EALG_MAX) { + + DEBUGGING(PF_KEY_DEBUG_BUILD, + + "pfkey_sa_build: " + + "encrypt=%d > K_SADB_EALG_MAX=%d.\n", + + sab.sa_base.sadb_sa_encrypt, + + K_SADB_EALG_MAX); + + SENDERR(EINVAL); + + } + +#endif + + + + if(sab.sa_base.sadb_sa_state > K_SADB_SASTATE_MAX) { + + DEBUGGING(PF_KEY_DEBUG_BUILD, + + "pfkey_sa_build: " + + "sa_state=%d exceeds MAX=%d.\n", + + sab.sa_base.sadb_sa_state, + + K_SADB_SASTATE_MAX); + + SENDERR(EINVAL); + + } + + + + if(sab.sa_base.sadb_sa_state == K_SADB_SASTATE_DEAD) { + + DEBUGGING(PF_KEY_DEBUG_BUILD, + + "pfkey_sa_build: " + + "sa_state=%d is DEAD=%d is not allowed.\n", + + sab.sa_base.sadb_sa_state, + + K_SADB_SASTATE_DEAD); + + SENDERR(EINVAL); + + } + + + + if((IPSEC_SAREF_NULL != sab.sa_base.sadb_x_sa_ref) && (sab.sa_base.sadb_x_sa_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", + + sab.sa_base.sadb_x_sa_ref, + + IPSEC_SAREF_NULL, + + IPSEC_SA_REF_TABLE_NUM_ENTRIES); + + SENDERR(EINVAL); + + } + + + + pfkey_sa = (struct k_sadb_sa*)MALLOC(sizeof(struct k_sadb_sa)); + + *pfkey_ext = (struct sadb_ext*)pfkey_sa; + + + + if(pfkey_sa == NULL) { + + DEBUGGING(PF_KEY_DEBUG_BUILD, + + "pfkey_sa_build: " + + "memory allocation failed\n"); + + SENDERR(ENOMEM); + + } + + memset(pfkey_sa, 0, sizeof(struct k_sadb_sa)); + + + + *pfkey_sa = sab.sa_base; + + pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN; + + + +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) + +{ + + struct sadb_builds sab; + + + + memset(&sab, 0, sizeof(sab)); + + sab.sa_base.sadb_sa_exttype = exttype; + + sab.sa_base.sadb_sa_spi = spi; + + sab.sa_base.sadb_sa_replay = replay_window; + + sab.sa_base.sadb_sa_state = sa_state; + + sab.sa_base.sadb_sa_auth = auth; + + sab.sa_base.sadb_sa_encrypt = encrypt; + + sab.sa_base.sadb_sa_flags = flags; + + sab.sa_base.sadb_x_sa_ref = IPSEC_SAREF_NULL; + + + + return pfkey_sa_builds(pfkey_ext, sab); + +} + + + +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); + + } + + + + pfkey_lifetime = (struct sadb_lifetime*)MALLOC(sizeof(struct sadb_lifetime)); + + *pfkey_ext = (struct sadb_ext*) pfkey_lifetime; + + + + if(pfkey_lifetime == NULL) { + + 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; + + + +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 K_SADB_X_EXT_ADDRESS_DST2: + + case K_SADB_X_EXT_ADDRESS_SRC_FLOW: + + case K_SADB_X_EXT_ADDRESS_DST_FLOW: + + case K_SADB_X_EXT_ADDRESS_SRC_MASK: + + case K_SADB_X_EXT_ADDRESS_DST_MASK: + +#ifdef NAT_TRAVERSAL + + case K_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, + + unsigned 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); + + } + + + + pfkey_key = (struct sadb_key*) + + MALLOC(sizeof(struct sadb_key) + + + DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_key; + + + + if(pfkey_key == NULL) { + + 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 + + + + pfkey_ident = (struct sadb_ident*) + + MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_ident; + + + + if(pfkey_ident == NULL) { + + 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 */ + + + + pfkey_sens = (struct sadb_sens*) + + MALLOC(sizeof(struct sadb_sens) + + + (sens_len + integ_len) * sizeof(uint64_t)); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_sens; + + + + if(pfkey_sens == NULL) { + + 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); + + } + + + + pfkey_prop = (struct sadb_prop*) + + MALLOC(sizeof(struct sadb_prop) + + + comb_num * sizeof(struct sadb_comb)); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_prop; + + + + if(pfkey_prop == NULL) { + + 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); + + } + + + + pfkey_supported = (struct sadb_supported*) + + MALLOC(sizeof(struct sadb_supported) + + + alg_num * + + sizeof(struct sadb_alg)); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_supported; + + + + if(pfkey_supported == NULL) { + + 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); + + } + + + + pfkey_spirange = (struct sadb_spirange*) + + MALLOC(sizeof(struct sadb_spirange)); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_spirange; + + + + if(pfkey_spirange == NULL) { + + 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 */ + + + + pfkey_x_kmprivate = (struct sadb_x_kmprivate*) + + MALLOC(sizeof(struct sadb_x_kmprivate)); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_x_kmprivate; + + + + if(pfkey_x_kmprivate == NULL) { + + 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 = K_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 > K_SADB_SATYPE_MAX) { + + ERROR("pfkey_x_satype_build: " + + "satype %d > max %d\n", + + satype, K_SADB_SATYPE_MAX); + + SENDERR(EINVAL); + + } + + + + pfkey_x_satype = (struct sadb_x_satype*) + + MALLOC(sizeof(struct sadb_x_satype)); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_x_satype; + + if(pfkey_x_satype == NULL) { + + 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 = K_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); + + + + pfkey_x_debug = (struct sadb_x_debug*) + + MALLOC(sizeof(struct sadb_x_debug)); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_x_debug; + + + + if(pfkey_x_debug == NULL) { + + 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 = K_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); + + + + pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*) + + MALLOC(sizeof(struct sadb_x_nat_t_type)); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type; + + + + if(pfkey_x_nat_t_type == NULL) { + + 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 = K_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 K_SADB_X_EXT_NAT_T_SPORT: + + case K_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); + + + + pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*) + + MALLOC(sizeof(struct sadb_x_nat_t_port)); + + + + *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port; + + + + if(pfkey_x_nat_t_port == NULL) { + + 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) / IPSEC_PFKEYv2_ALIGN; + + p->sadb_protocol_exttype = K_SADB_X_EXT_PROTOCOL; + + p->sadb_protocol_proto = protocol; + + p->sadb_protocol_flags = 0; + + p->sadb_protocol_reserved2 = 0; + + errlab: + + return error; + +} + + + +int pfkey_outif_build(struct sadb_ext **pfkey_ext, + + uint16_t outif) + +{ + + int error = 0; + + struct sadb_x_plumbif * p = (struct sadb_x_plumbif *)*pfkey_ext; + + + + if ((p = (struct sadb_x_plumbif*)MALLOC(sizeof(*p))) == 0) { + + ERROR("pfkey_build: memory allocation failed\n"); + + SENDERR(ENOMEM); + + } + + *pfkey_ext = (struct sadb_ext *)p; + + + + p->sadb_x_outif_len = IPSEC_PFKEYv2_WORDS(sizeof(*p)); + + p->sadb_x_outif_exttype = K_SADB_X_EXT_PLUMBIF; + + p->sadb_x_outif_ifnum = outif; + + + + errlab: + + return error; + +} + + + + + +int pfkey_saref_build(struct sadb_ext **pfkey_ext, + + IPsecSAref_t in, IPsecSAref_t out) + +{ + + int error = 0; + + struct sadb_x_saref* s; + + + + /* +4 because sadb_x_saref is not a multiple of 8 bytes */ + + + + if ((s = (struct sadb_x_saref*)MALLOC(sizeof(*s)+4)) == 0) { + + ERROR("pfkey_build: memory allocation failed\n"); + + SENDERR(ENOMEM); + + } + + *pfkey_ext = (struct sadb_ext *)s; + + + + s->sadb_x_saref_len = IPSEC_PFKEYv2_WORDS(sizeof(*s)); + + s->sadb_x_saref_exttype = K_SADB_X_EXT_SAREF; + + s->sadb_x_saref_me = in; + + s->sadb_x_saref_him = out; + + + + errlab: + + return error; + +} + + + + + +#if defined(I_DONT_THINK_THIS_WILL_BE_USEFUL) && I_DONT_THINK_THIS_WILL_BE_USEFUL + +int (*ext_default_builders[K_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; + + pfkey_ext_track extensions_seen = 0; + +#ifndef __KERNEL__ + + struct sadb_ext *extensions_check[K_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 <= K_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 <= K_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(!pfkey_permitted_extension(dir,(*pfkey_msg)->sadb_msg_type,ext)) { + + ERROR("ext type %d not permitted for %d/%d (build)\n", + + ext, + + dir,(*pfkey_msg)->sadb_msg_type); + + 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); + + + + { + + char *pfkey_ext_c = (char *)pfkey_ext; + + + + pfkey_ext_c += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN; + + + +#if 0 + + printf("memcpy(%p,%p,%d) -> %p %p:%p\n", pfkey_ext, + + extensions[ext], + + (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN, + + pfkey_ext_c, (*pfkey_msg), (char *)(*pfkey_msg)+(total_size*IPSEC_PFKEYv2_ALIGN)); + +#endif + + memcpy(pfkey_ext, + + extensions[ext], + + (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); + + pfkey_ext = (struct sadb_ext *)pfkey_ext_c; + + } + + + + /* Mark that we have seen this extension */ + + pfkey_mark_extension(ext,&extensions_seen); + + } + + } + + + + if(pfkey_extensions_missing(dir,(*pfkey_msg)->sadb_msg_type,extensions_seen)) { + + ERROR("required extensions missing. seen=%08llx\n", (unsigned long long)extensions_seen); + + 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; + +} + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/pfkey_v2_debug.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,144 @@ + +/* + + * @(#) pfkey version 2 debugging messages + + * + + * Copyright (C) 2001 Richard Guy Briggs + + * and Michael Richardson + + * + + * 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 . + + * + + * 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.11 2005/04/06 17:45:16 mcr Exp $ + + * + + */ + + + +#ifdef __KERNEL__ + + + +# include /* for printk */ + + + +# include "libreswan/ipsec_kversion.h" /* for malloc switch */ + +# ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +# else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +# endif /* MALLOC_SLAB */ + +# include /* error codes */ + +# include /* size_t */ + +# include /* mark_bh */ + + + +# include /* struct device, and other headers */ + +# include /* eth_type_trans */ + +extern int debug_pfkey; + + + +#else /* __KERNEL__ */ + + + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) + +# include + +#else + +# include + +# include + +# include + +#endif + + + +#endif /* __KERNEL__ */ + + + +#include "libreswan.h" + +#include "libreswan/pfkeyv2.h" + +#include "libreswan/pfkey.h" + + + +/* + + * This file provides ASCII translations of PF_KEY magic numbers. + + * + + */ + + + +static char *pfkey_sadb_ext_strings[]={ + + "reserved", /* K_SADB_EXT_RESERVED 0 */ + + "security-association", /* K_SADB_EXT_SA 1 */ + + "lifetime-current", /* K_SADB_EXT_LIFETIME_CURRENT 2 */ + + "lifetime-hard", /* K_SADB_EXT_LIFETIME_HARD 3 */ + + "lifetime-soft", /* K_SADB_EXT_LIFETIME_SOFT 4 */ + + "source-address", /* K_SADB_EXT_ADDRESS_SRC 5 */ + + "destination-address", /* K_SADB_EXT_ADDRESS_DST 6 */ + + "proxy-address", /* K_SADB_EXT_ADDRESS_PROXY 7 */ + + "authentication-key", /* K_SADB_EXT_KEY_AUTH 8 */ + + "cipher-key", /* K_SADB_EXT_KEY_ENCRYPT 9 */ + + "source-identity", /* K_SADB_EXT_IDENTITY_SRC 10 */ + + "destination-identity", /* K_SADB_EXT_IDENTITY_DST 11 */ + + "sensitivity-label", /* K_SADB_EXT_SENSITIVITY 12 */ + + "proposal", /* K_SADB_EXT_PROPOSAL 13 */ + + "supported-auth", /* K_SADB_EXT_SUPPORTED_AUTH 14 */ + + "supported-cipher", /* K_SADB_EXT_SUPPORTED_ENCRYPT 15 */ + + "spi-range", /* K_SADB_EXT_SPIRANGE 16 */ + + "X-kmpprivate", /* K_SADB_X_EXT_KMPRIVATE 17 */ + + "X-satype2", /* K_SADB_X_EXT_SATYPE2 18 */ + + "X-security-association", /* K_SADB_X_EXT_SA2 19 */ + + "X-destination-address2", /* K_SADB_X_EXT_ADDRESS_DST2 20 */ + + "X-source-flow-address", /* K_SADB_X_EXT_ADDRESS_SRC_FLOW 21 */ + + "X-dest-flow-address", /* K_SADB_X_EXT_ADDRESS_DST_FLOW 22 */ + + "X-source-mask", /* K_SADB_X_EXT_ADDRESS_SRC_MASK 23 */ + + "X-dest-mask", /* K_SADB_X_EXT_ADDRESS_DST_MASK 24 */ + + "X-set-debug", /* K_SADB_X_EXT_DEBUG 25 */ + + /* NAT_TRAVERSAL */ + + "X-ext-protocol", /* K_SADB_X_EXT_PROTOCOL 26 */ + + "X-NAT-T-type", /* K_SADB_X_EXT_NAT_T_TYPE 27 */ + + "X-NAT-T-sport", /* K_SADB_X_EXT_NAT_T_SPORT 28 */ + + "X-NAT-T-dport", /* K_SADB_X_EXT_NAT_T_DPORT 29 */ + + "X-NAT-T-OA", /* K_SADB_X_EXT_NAT_T_OA 30 */ + + "X-plumbif", /* K_SADB_X_EXT_PLUMBIF 31 */ + + "X-saref", /* K_SADB_X_EXT_SAREF 32 */ + +}; + + + +const char * + +pfkey_v2_sadb_ext_string(int ext) + +{ + + if(ext <= K_SADB_EXT_MAX) { + + return pfkey_sadb_ext_strings[ext]; + + } else { + + return "unknown-ext"; + + } + +} + + + + + +static char *pfkey_sadb_type_strings[]={ + + "reserved", /* K_SADB_RESERVED */ + + "getspi", /* K_SADB_GETSPI */ + + "update", /* K_SADB_UPDATE */ + + "add", /* K_SADB_ADD */ + + "delete", /* K_SADB_DELETE */ + + "get", /* K_SADB_GET */ + + "acquire", /* K_SADB_ACQUIRE */ + + "register", /* K_SADB_REGISTER */ + + "expire", /* K_SADB_EXPIRE */ + + "flush", /* K_SADB_FLUSH */ + + "dump", /* K_SADB_DUMP */ + + "x-promisc", /* K_SADB_X_PROMISC */ + + "x-pchange", /* K_SADB_X_PCHANGE */ + + "x-groupsa", /* K_SADB_X_GRPSA */ + + "x-addflow(eroute)", /* K_SADB_X_ADDFLOW */ + + "x-delflow(eroute)", /* K_SADB_X_DELFLOW */ + + "x-debug", /* K_SADB_X_DEBUG */ + +}; + + + +const char * + +pfkey_v2_sadb_type_string(int sadb_type) + +{ + + if(sadb_type <= K_SADB_MAX) { + + return pfkey_sadb_type_strings[sadb_type]; + + } else { + + return "unknown-sadb-type"; + + } + +} + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/pfkey_v2_ext_bits.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,814 @@ + +/* + + * 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 . + + * + + * 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.22 2005/05/11 01:45:31 mcr 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.22 2005/05/11 01:45:31 mcr Exp $"; + + + +/* + + * Some ugly stuff to allow consistent debugging code for use in the + + * kernel and in user space + +*/ + + + +#if defined(__KERNEL__) && defined(linux) + + + +# include /* for printk */ + + + +# include "libreswan/ipsec_kversion.h" /* for malloc switch */ + +# ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +# else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +# endif /* MALLOC_SLAB */ + +# include /* error codes */ + +# include /* size_t */ + +# include /* mark_bh */ + + + +# include /* struct device, and other headers */ + +# include /* eth_type_trans */ + +# include /* struct iphdr */ + +# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + +# include + +# endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ + + + +#else /* __KERNEL__ */ + + + +# include + +# include + +# include + +#endif + + + +#include + +#include + +#include + + + +#include "libreswan/pfkey_debug.h" + + + + + +pfkey_ext_track extensions_bitmaps[2/*in/out*/][2/*perm/req*/][K_SADB_MAX+1]={ + + + +/* INBOUND EXTENSIONS */ + +{ + + + +/* PERMITTED IN */ + +{ + +/* K_SADB_RESERVED */ + +0 + +, + +/* SADB_GETSPI */ + +1ULL< + + * + + * 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 . + + * + + * 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. + + * + + */ + + + +/* + + * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. + + */ + + + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + + + +#include + + + +#include + + + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *lock* */ + +# endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + +#ifdef NET_21 + +# include + +# define ip_chk_addr inet_addr_type + +# define IS_MYADDR RTN_LOCAL + +#endif + + + +#include + +#ifdef NETLINK_SOCK + +# include + +#else + +# include + +#endif + + + +#include /* get_random_bytes() */ + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_rcv.h" + +#include "libreswan/ipcomp.h" + + + +#include + +#include + + + +#include "libreswan/ipsec_proto.h" + +#include "libreswan/ipsec_alg.h" + + + +#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) + + + +/* returns 0 on success */ + +int + +pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) + +{ + + struct k_sadb_sa *k_pfkey_sa = (struct k_sadb_sa *)pfkey_ext; + + 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 K_SADB_EXT_SA: + + ipsp = extr->ips; + + break; + + case K_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; + + + + if(k_pfkey_sa->sadb_sa_len > sizeof(struct sadb_sa)/IPSEC_PFKEYv2_ALIGN) { + + ipsp->ips_ref = k_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 = K_SADB_EALG_NONE; + + break; + + case IPPROTO_ESP: + + ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; + + ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; + + ipsec_alg_sa_init(ipsp); + + break; + + case IPPROTO_IPIP: + + ipsp->ips_authalg = AH_NONE; + + ipsp->ips_encalg = ESP_NONE; + + break; + +#ifdef CONFIG_KLIPS_IPCOMP + + case IPPROTO_COMP: + + ipsp->ips_authalg = AH_NONE; + + ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; + + break; + +#endif /* CONFIG_KLIPS_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 K_SADB_EXT_LIFETIME_CURRENT: + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_lifetime_process: " + + "lifetime_current not supported yet.\n"); + + SENDERR(EINVAL); + + break; + + case K_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 K_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); + + if (debug_pfkey) + + 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 K_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 K_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 K_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 K_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 K_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 K_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 K_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 K_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 K_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 K_SADB_EXT_ADDRESS_SRC: + + case K_SADB_EXT_ADDRESS_DST: + + case K_SADB_EXT_ADDRESS_PROXY: + + case K_SADB_X_EXT_ADDRESS_DST2: + +#ifdef NAT_TRAVERSAL + + case K_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); + + } + + { + + *(struct in_addr *)sap = ((struct sockaddr_in *)s)->sin_addr; + + } + + + + if (portp != 0) + + *portp = ((struct sockaddr_in*)s)->sin_port; + +#ifdef CONFIG_KLIPS_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_KLIPS_DEBUG */ + + } + + + + ipsp = extr->ips; + + switch(pfkey_address->sadb_address_exttype) { + + case K_SADB_X_EXT_ADDRESS_DST2: + + ipsp = extr->ips2; + + case K_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; + + if (debug_pfkey) + + 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 K_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 K_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 K_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 K_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, + + "pfkey_x_satype_process: .\n"); + + + + if(!extr || !extr->ips) { + + KLIPS_PRINT(debug_pfkey, + + "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_ERROR(debug_pfkey, + + "pfkey_x_satype_process: " + + "proto lookup from satype=%d failed.\n", + + pfkey_x_satype->sadb_x_satype_satype); + + SENDERR(EINVAL); + + } + + KLIPS_PRINT(debug_pfkey, + + "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 K_SADB_X_EXT_NAT_T_SPORT: + + extr->ips->ips_natt_sport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; + + break; + + case K_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_KLIPS_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_KLIPS_IPCOMP + + sysctl_ipsec_debug_ipcomp |= pfkey_x_debug->sadb_x_debug_ipcomp; + +#endif /* CONFIG_KLIPS_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_KLIPS_IPCOMP + + sysctl_ipsec_debug_ipcomp &= pfkey_x_debug->sadb_x_debug_ipcomp; + +#endif /* CONFIG_KLIPS_IPCOMP */ + + sysctl_ipsec_debug_verbose &= pfkey_x_debug->sadb_x_debug_verbose; + + } + +#else /* CONFIG_KLIPS_DEBUG */ + + printk("klips_debug:pfkey_x_debug_process: " + + "debugging not enabled\n"); + + SENDERR(EINVAL); + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +errlab: + + return error; + +} + + + +/* + + * Local variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/pfkey_v2_parse.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,1597 @@ + +/* + + * 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 . + + * + + * 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.65 2005/04/06 17:46:05 mcr Exp $ + + */ + + + +/* + + * Template from klips/net/ipsec/ipsec/ipsec_parser.c. + + */ + + + +char pfkey_v2_parse_c_version[] = "$Id: pfkey_v2_parse.c,v 1.65 2005/04/06 17:46:05 mcr Exp $"; + + + +/* + + * Some ugly stuff to allow consistent debugging code for use in the + + * kernel and in user space + +*/ + + + +#ifdef __KERNEL__ + + + +# include /* for printk */ + + + +#include "libreswan/ipsec_kversion.h" /* for malloc switch */ + + + +# ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +# else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +# endif /* MALLOC_SLAB */ + +# include /* error codes */ + +# include /* size_t */ + +# include /* mark_bh */ + + + +# include /* struct device, and other headers */ + +# include /* eth_type_trans */ + +# include /* struct iphdr */ + +# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + +# include /* struct ipv6hdr */ + +# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ + +extern int debug_pfkey; + + + +# include + + + +#include "libreswan/ipsec_encap.h" + + + +#else /* __KERNEL__ */ + + + +# include + +# include + +# include + + + +# include + +# include "constants.h" + + + +#endif /* __KERNEL__ */ + + + + + +#include + +#include + + + +#include "libreswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ + + + +/* + + * how to handle debugging for pfkey. + + */ + +#include + + + +unsigned int pfkey_lib_debug = PF_KEY_DEBUG_PARSE_NONE; + +int (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); + +int (*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, K_SADB_SATYPE_ESP, "ESP" }, + + { IPPROTO_AH, K_SADB_SATYPE_AH, "AH" }, + + { IPPROTO_IPIP, K_SADB_X_SATYPE_IPIP, "IPIP" }, + +#ifdef CONFIG_KLIPS_IPCOMP + + { IPPROTO_COMP, K_SADB_X_SATYPE_COMP, "COMP" }, + +#endif /* CONFIG_KLIPS_IPCOMP */ + + { IPPROTO_INT, K_SADB_X_SATYPE_INT, "INT" }, + +#else /* __KERNEL__ */ + + { SA_ESP, K_SADB_SATYPE_ESP, "ESP" }, + + { SA_AH, K_SADB_SATYPE_AH, "AH" }, + + { SA_IPIP, K_SADB_X_SATYPE_IPIP, "IPIP" }, + + { SA_COMP, K_SADB_X_SATYPE_COMP, "COMP" }, + + { SA_INT, K_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 k_sadb_sa *pfkey_sa = (struct k_sadb_sa *)pfkey_ext; + + + + /* sanity checks... */ + + if(!pfkey_sa) { + + ERROR("pfkey_sa_parse: " + + "NULL pointer passed in.\n"); + + SENDERR(EINVAL); + + } + + + + + + + + if(pfkey_sa->sadb_sa_len !=sizeof(struct k_sadb_sa)/IPSEC_PFKEYv2_ALIGN + + && 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 k_sadb_sa)); + + SENDERR(EINVAL); + + } + + + +#if K_SADB_EALG_MAX < 255 + + if(pfkey_sa->sadb_sa_encrypt > K_SADB_EALG_MAX) { + + ERROR( + + "pfkey_sa_parse: " + + "pfkey_sa->sadb_sa_encrypt=%d > K_SADB_EALG_MAX=%d.\n", + + pfkey_sa->sadb_sa_encrypt, + + K_SADB_EALG_MAX); + + SENDERR(EINVAL); + + } + +#endif + + + +#if K_SADB_AALG_MAX < 255 + + if(pfkey_sa->sadb_sa_auth > K_SADB_AALG_MAX) { + + ERROR( + + "pfkey_sa_parse: " + + "pfkey_sa->sadb_sa_auth=%d > K_SADB_AALG_MAX=%d.\n", + + pfkey_sa->sadb_sa_auth, + + K_SADB_AALG_MAX); + + SENDERR(EINVAL); + + } + +#endif + + + +#if K_SADB_SASTATE_MAX < 255 + + if(pfkey_sa->sadb_sa_state > K_SADB_SASTATE_MAX) { + + ERROR( + + "pfkey_sa_parse: " + + "state=%d exceeds MAX=%d.\n", + + pfkey_sa->sadb_sa_state, + + K_SADB_SASTATE_MAX); + + SENDERR(EINVAL); + + } + +#endif + + + + if(pfkey_sa->sadb_sa_state == K_SADB_SASTATE_DEAD) { + + ERROR( + + "pfkey_sa_parse: " + + "state=%d is DEAD=%d.\n", + + pfkey_sa->sadb_sa_state, + + K_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 == K_SADB_EXT_SA) || + + (pfkey_sa->sadb_sa_exttype == K_SADB_X_EXT_SA2))) + + { + + ERROR( + + "pfkey_sa_parse: " + + "unknown exttype=%d, expecting K_SADB_EXT_SA=%d or K_SADB_X_EXT_SA2=%d.\n", + + pfkey_sa->sadb_sa_exttype, + + K_SADB_EXT_SA, + + K_SADB_X_EXT_SA2); + + SENDERR(EINVAL); + + } + + + + if(pfkey_sa->sadb_sa_len > sizeof(struct sadb_sa)/IPSEC_PFKEYv2_ALIGN) { + + if(pfkey_sa->sadb_x_sa_ref == IPSEC_SAREF_NULL || + + pfkey_sa->sadb_x_sa_ref == ~(IPSEC_SAREF_NULL)) + + { + + pfkey_sa->sadb_x_sa_ref = IPSEC_SAREF_NULL; + + } + + } + + + + 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 != K_SADB_EXT_LIFETIME_HARD) && + + (pfkey_lifetime->sadb_lifetime_exttype != K_SADB_EXT_LIFETIME_SOFT) && + + (pfkey_lifetime->sadb_lifetime_exttype != K_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.\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); + +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 K_SADB_EXT_ADDRESS_SRC: + + case K_SADB_EXT_ADDRESS_DST: + + case K_SADB_EXT_ADDRESS_PROXY: + + case K_SADB_X_EXT_ADDRESS_DST2: + + case K_SADB_X_EXT_ADDRESS_SRC_FLOW: + + case K_SADB_X_EXT_ADDRESS_DST_FLOW: + + case K_SADB_X_EXT_ADDRESS_SRC_MASK: + + case K_SADB_X_EXT_ADDRESS_DST_MASK: + +#ifdef NAT_TRAVERSAL + + case K_SADB_X_EXT_NAT_T_OA: + +#endif + + break; + + default: + + ERROR( + + "pfkey_address_parse: " + + "unexpected ext_type=%d.\n", + + pfkey_address->sadb_address_exttype); + + SENDERR(ENODEV); + + } + + + + 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 == K_SADB_EXT_KEY_AUTH) || + + (pfkey_key->sadb_key_exttype == K_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 > K_SADB_IDENTTYPE_MAX) { + + ERROR( + + "pfkey_ident_parse: " + + "ident_type=%d out of range, must be less than %d.\n", + + pfkey_ident->sadb_ident_type, + + K_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 == K_SADB_EXT_IDENTITY_SRC) || + + (pfkey_ident->sadb_ident_exttype == K_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 k_sadb_comb *k_pfkey_comb = (struct k_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++) { + + struct sadb_comb *pfkey_comb = (struct sadb_comb *)k_pfkey_comb; + + if(pfkey_comb->sadb_comb_auth > K_SADB_AALG_MAX) { + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + + "pfkey_prop_parse: " + + "pfkey_comb[%d]->sadb_comb_auth=%d > K_SADB_AALG_MAX=%d.\n", + + i, + + pfkey_comb->sadb_comb_auth, + + K_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 K_SADB_EALG_MAX < 255 + + if(pfkey_comb->sadb_comb_encrypt > K_SADB_EALG_MAX) { + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + + "pfkey_comb_parse: " + + "pfkey_comb[%d]->sadb_comb_encrypt=%d > K_SADB_EALG_MAX=%d.\n", + + i, + + pfkey_comb->sadb_comb_encrypt, + + K_SADB_EALG_MAX); + + SENDERR(EINVAL); + + } + +#endif + + + + 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); + + } + + + +#ifdef COMB_PACKETS + + 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, + + k_pfkey_comb->sadb_x_comb_soft_packets, + + k_pfkey_comb->sadb_x_comb_hard_packets); + + SENDERR(EINVAL); + + } + +#endif + + + + 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 K_SADB_EXT_SUPPORTED_AUTH: + + if(pfkey_alg->sadb_alg_id > K_SADB_AALG_MAX) { + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + + "pfkey_supported_parse: " + + "alg[%d], alg_id=%d > K_SADB_AALG_MAX=%d, fatal.\n", + + i, + + pfkey_alg->sadb_alg_id, + + K_SADB_AALG_MAX); + + SENDERR(EINVAL); + + } + + break; + + case SADB_EXT_SUPPORTED_ENCRYPT: + +#if K_SADB_EALG_MAX < 255 + + if(pfkey_alg->sadb_alg_id > K_SADB_EALG_MAX) { + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + + "pfkey_supported_parse: " + + "alg[%d], alg_id=%d > K_SADB_EALG_MAX=%d, fatal.\n", + + i, + + pfkey_alg->sadb_alg_id, + + K_SADB_EALG_MAX); + + SENDERR(EINVAL); + + } + +#endif + + break; + + default: + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + + "pfkey_supported_parse: " + + "alg[%d], alg_id=%d > K_SADB_EALG_MAX=%d, fatal.\n", + + i, + + pfkey_alg->sadb_alg_id, + + K_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 > K_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, K_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 + + + +DEBUG_NO_STATIC int + +pfkey_x_ext_outif_parse(struct sadb_ext *pfkey_ext) + +{ + + int error = 0; + + struct sadb_x_plumbif *p = (struct sadb_x_plumbif *)pfkey_ext; + + + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_outif_parse:\n"); + + /* sanity checks... */ + + + + if (p->sadb_x_outif_len != IPSEC_PFKEYv2_WORDS(sizeof(*p))) { + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + + "pfkey_x_outif_parse: size wrong ext_len=%d, key_ext_len=%d.\n", + + p->sadb_x_outif_len, (int)sizeof(*p)); + + SENDERR(EINVAL); + + } + + + + errlab: + + return error; + +} + + + +DEBUG_NO_STATIC int + +pfkey_x_ext_saref_parse(struct sadb_ext *pfkey_ext) + +{ + + int error = 0; + + struct sadb_x_saref *p = (struct sadb_x_saref *)pfkey_ext; + + + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_saref_parse:\n"); + + /* sanity checks... */ + + + + if (p->sadb_x_saref_len != IPSEC_PFKEYv2_WORDS(sizeof(*p))) { + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + + "pfkey_x_saref_parse: size wrong ext_len=%d, key_ext_len=%d.\n", + + p->sadb_x_saref_len, (int)sizeof(*p)); + + SENDERR(EINVAL); + + } + + + + errlab: + + return error; + +} + + + + + +#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 + +DEFINEPARSER(pfkey_x_ext_outif_parse); + +DEFINEPARSER(pfkey_x_ext_saref_parse); + + + +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, + +#else + + NULL,NULL,NULL,NULL, + +#endif + + &pfkey_x_ext_outif_parse_def, + + &pfkey_x_ext_saref_parse_def, + +}; + + + +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; + + pfkey_ext_track 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 -= IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg)); + + + + 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 > K_SADB_MAX) { + + ERROR("pfkey_msg_parse: " + + "msg type=%d > max=%d.\n", + + pfkey_msg->sadb_msg_type, + + K_SADB_MAX); + + SENDERR(EINVAL); + + } + + + + switch(pfkey_msg->sadb_msg_type) { + + case K_SADB_GETSPI: + + case K_SADB_UPDATE: + + case K_SADB_ADD: + + case K_SADB_DELETE: + + case K_SADB_GET: + + case K_SADB_X_GRPSA: + + case K_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 K_SADB_ACQUIRE: + + case K_SADB_REGISTER: + + case K_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 != K_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\n", + + remain + + ); + + + + 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) { + + ERROR("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 > K_SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) { + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + + "pfkey_msg_parse: " + + "ext type %d(%s) invalid, K_SADB_EXT_MAX=%d.\n", + + pfkey_ext->sadb_ext_type, + + pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), + + K_SADB_EXT_MAX); + + SENDERR(EINVAL); + + } + + + + /* Have we already seen this type of extension? */ + + if(extensions[pfkey_ext->sadb_ext_type] != NULL) + + { + + ERROR("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) { + + ERROR("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(!pfkey_permitted_extension(dir,pfkey_msg->sadb_msg_type,pfkey_ext->sadb_ext_type)) { + + ERROR("ext type %d(%s) not permitted (parse)\n", + + pfkey_ext->sadb_ext_type, + + pfkey_v2_sadb_ext_string(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))) { + + ERROR("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[pfkey_ext->sadb_ext_type] = pfkey_ext; + + pfkey_mark_extension(pfkey_ext->sadb_ext_type,&extensions_seen); + + + + 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); + + } + + + + /* 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(pfkey_extensions_missing(dir,pfkey_msg->sadb_msg_type,extensions_seen)) { + + ERROR("required extensions missing.seen=%08llx.\n",(unsigned long long)extensions_seen); + + SENDERR(EINVAL); + + } + + + + if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type == K_SADB_X_DELFLOW) + + && ((extensions_seen & K_SADB_X_EXT_ADDRESS_DELFLOW) + + != K_SADB_X_EXT_ADDRESS_DELFLOW) + + && (((extensions_seen & (1<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 %16llx must be present or %16llx must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n", + + (unsigned long long)K_SADB_X_EXT_ADDRESS_DELFLOW + + - (extensions_seen & K_SADB_X_EXT_ADDRESS_DELFLOW), + + (unsigned long long)(1<sadb_msg_type) { + + case K_SADB_ADD: + + case K_SADB_UPDATE: + + /* check maturity */ + + if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != + + K_SADB_SASTATE_MATURE) { + + DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, + + "pfkey_msg_parse: " + + "state=%d for add or update should be MATURE=%d.\n", + + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, + + K_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 k_sadb_sa*)extensions[SADB_EXT_SA]) && + + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_auth != + + SADB_AALG_NONE)) { + + ERROR("pfkey_msg_parse: " + + "auth alg is zero, must be non-zero for AH SAs.\n"); + + SENDERR(EINVAL); + + } + + if(((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt != + + SADB_EALG_NONE) { + + ERROR("pfkey_msg_parse: " + + "AH handed encalg=%d, must be zero.\n", + + ((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt); + + SENDERR(EINVAL); + + } + + break; + + case SADB_SATYPE_ESP: + + if(!(((struct k_sadb_sa*)extensions[SADB_EXT_SA]) && + + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != + + SADB_EALG_NONE)) { + + ERROR("pfkey_msg_parse: " + + "encrypt alg=%d is zero, must be non-zero for ESP=%d SAs.\n", + + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, + + ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); + + SENDERR(EINVAL); + + } + + if((((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt == + + SADB_EALG_NULL) && + + (((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth == + + SADB_AALG_NONE) ) { + + ERROR("pfkey_msg_parse: " + + "ESP handed encNULL+authNONE, illegal combination.\n"); + + SENDERR(EINVAL); + + } + + break; + + case K_SADB_X_SATYPE_COMP: + + if(!(((struct k_sadb_sa*)extensions[SADB_EXT_SA]) && + + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != + + SADB_EALG_NONE)) { + + ERROR("pfkey_msg_parse: " + + "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n", + + ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, + + ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); + + SENDERR(EINVAL); + + } + + if(((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth != + + SADB_AALG_NONE) { + + ERROR("pfkey_msg_parse: " + + "COMP handed auth=%d, must be zero.\n", + + ((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth); + + SENDERR(EINVAL); + + } + + break; + + default: + + break; + + } + + if(ntohl(((struct k_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 k_sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi)); + + SENDERR(EINVAL); + + } + + default: + + break; + + } + + + +errlab: + + return error; + +} + + + +/* + + * 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,3015 @@ + +/* + + * @(#) 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 . + + * + + * 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. + + * + + */ + + + +/* + + * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. + + */ + + + + + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + + + +#include + + + +#include + + + +#ifdef SPINLOCK + +# ifdef SPINLOCK_23 + +# include /* *lock* */ + +# else /* SPINLOCK_23 */ + +# include /* *lock* */ + +# endif /* SPINLOCK_23 */ + +#endif /* SPINLOCK */ + +#ifdef NET_21 + +# include /* inet_addr_type */ + +# include + +# define ip_chk_addr inet_addr_type + +# define IS_MYADDR RTN_LOCAL + +#endif + + + +#include + +#ifdef NETLINK_SOCK + +# include + +#else + +# include + +#endif + + + +#include /* get_random_bytes() */ + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/ipsec_sa.h" + + + +#include "libreswan/ipsec_radij.h" + +#include "libreswan/ipsec_xform.h" + +#include "libreswan/ipsec_ah.h" + +#include "libreswan/ipsec_esp.h" + +#include "libreswan/ipsec_tunnel.h" + +#include "libreswan/ipsec_mast.h" + +#include "libreswan/ipsec_rcv.h" + +#include "libreswan/ipcomp.h" + + + +#include + +#include + + + +#include "libreswan/ipsec_proto.h" + +#include "libreswan/ipsec_alg.h" + + + +#include "libreswan/ipsec_kern24.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) + +{ + + int rc; + + KLIPS_PRINT(debug_pfkey, "Calling SA_INIT\n"); + + rc = ipsec_sa_init(ipsp); + + return rc; + +} + + + +int + +pfkey_safe_build(int error, struct sadb_ext *extensions[K_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[K_SADB_EXT_MAX+1]; + + struct sadb_msg *pfkey_reply = NULL; + + struct socket_list *pfkey_socketsp; + + uint8_t satype = ((struct sadb_msg*)extensions[K_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[K_SADB_EXT_SPIRANGE]) { + + minspi = ((struct sadb_spirange *)extensions[K_SADB_EXT_SPIRANGE])->sadb_spirange_min; + + maxspi = ((struct sadb_spirange *)extensions[K_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 = KLIPS_SATOT(debug_pfkey, &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 = KLIPS_SATOT(debug_pfkey, &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 = K_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], + + K_SADB_GETSPI, + + satype, + + 0, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + + K_SADB_EXT_SA, + + extr->ips->ips_said.spi, + + 0, + + K_SADB_SASTATE_LARVAL, + + 0, + + 0, + + 0), + + extensions_reply) + + + + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], + + K_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[K_SADB_EXT_ADDRESS_DST], + + K_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[K_SADB_EXT_MAX+1]; + + struct sadb_msg *pfkey_reply = NULL; + + struct socket_list *pfkey_socketsp; + + uint8_t satype = ((struct sadb_msg*)extensions[K_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[K_SADB_EXT_SA])->sadb_sa_state != K_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[K_SADB_EXT_SA])->sadb_sa_state, + + K_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 = KLIPS_SATOT(debug_pfkey, &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 K_SADB_GETSPI first or call K_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))) { + + 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; + + + + /* this will call delchain-equivalent if refcount=>0 */ + + ipsec_sa_put(ipsq); + + } + + + + spin_unlock_bh(&tdb_lock); + + + + if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], + + K_SADB_UPDATE, + + satype, + + 0, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + + K_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), + + extensions_reply) + + /* The 3 lifetime extentions should only be sent if non-zero. */ + + && (extensions[K_SADB_EXT_LIFETIME_HARD] + + ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_HARD], + + K_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[K_SADB_EXT_LIFETIME_SOFT] + + ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_SOFT], + + K_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[K_SADB_EXT_LIFETIME_CURRENT], + + K_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[K_SADB_EXT_ADDRESS_SRC], + + K_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[K_SADB_EXT_ADDRESS_DST], + + K_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[K_SADB_EXT_IDENTITY_SRC], + + K_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[K_SADB_EXT_IDENTITY_DST], + + K_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[K_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[K_SADB_EXT_MAX+1]; + + struct sadb_msg *pfkey_reply = NULL; + + struct socket_list *pfkey_socketsp; + + uint8_t satype = ((struct sadb_msg*)extensions[K_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[K_SADB_EXT_SA])->sadb_sa_state != K_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[K_SADB_EXT_SA])->sadb_sa_state, + + K_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 = KLIPS_SATOT(debug_pfkey, &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 = ipsec_sa_init(extr->ips))) { + + KLIPS_ERROR(debug_pfkey, + + "pfkey_add_parse: " + + "not successful for SA: %s, deleting.\n", + + sa_len ? sa : " (error)"); + + SENDERR(-error); + + } + + + + if(extr->sarefme!=IPSEC_SAREF_NULL + + && extr->ips->ips_ref==IPSEC_SAREF_NULL) { + + extr->ips->ips_ref=extr->sarefme; + + } + + + + if(extr->sarefhim!=IPSEC_SAREF_NULL + + && extr->ips->ips_refhim==IPSEC_SAREF_NULL) { + + extr->ips->ips_refhim=extr->sarefhim; + + } + + + + /* attach it to the SAref table */ + + if((error = ipsec_sa_intern(extr->ips)) != 0) { + + KLIPS_ERROR(debug_pfkey, + + "pfkey_add_parse: " + + "failed to intern SA as SAref#%lu\n" + + , (unsigned long)extr->ips->ips_ref); + + 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], + + K_SADB_ADD, + + satype, + + 0, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + + K_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), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_saref_build(&extensions_reply[K_SADB_X_EXT_SAREF], + + extr->ips->ips_ref, + + extr->ips->ips_refhim), + + extensions_reply) + + /* The 3 lifetime extentions should only be sent if non-zero. */ + + && (extensions[K_SADB_EXT_LIFETIME_HARD] + + ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_HARD], + + K_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[K_SADB_EXT_LIFETIME_SOFT] + + ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_SOFT], + + K_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[K_SADB_EXT_ADDRESS_SRC], + + K_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[K_SADB_EXT_ADDRESS_DST], + + K_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[K_SADB_EXT_IDENTITY_SRC], + + K_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[K_SADB_EXT_IDENTITY_DST], + + K_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[K_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(extr->outif != 0 && extr->outif != -1) { + + extr->ips->ips_out = ipsec_mast_get_device(extr->outif); + + extr->ips->ips_transport_direct = ipsec_mast_is_transport(extr->outif); + + } + + + + 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); + + } + + ipsec_sa_put(extr->ips); + + 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[K_SADB_EXT_MAX+1]; + + struct sadb_msg *pfkey_reply = NULL; + + struct socket_list *pfkey_socketsp; + + uint8_t satype = ((struct sadb_msg*)extensions[K_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 = KLIPS_SATOT(debug_pfkey, &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); + + spin_unlock_bh(&tdb_lock); + + + + if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], + + K_SADB_DELETE, + + satype, + + 0, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + + K_SADB_EXT_SA, + + extr->ips->ips_said.spi, + + 0, + + 0, + + 0, + + 0, + + 0), + + extensions_reply) + + + + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], + + K_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[K_SADB_EXT_ADDRESS_DST], + + K_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[K_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 = KLIPS_SATOT(debug_pfkey, &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], + + K_SADB_GET, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype, + + 0, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + + K_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), + + 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[K_SADB_EXT_LIFETIME_CURRENT], + + K_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[K_SADB_EXT_LIFETIME_HARD], + + K_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[K_SADB_EXT_LIFETIME_SOFT], + + K_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[K_SADB_EXT_ADDRESS_SRC], + + K_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[K_SADB_EXT_ADDRESS_DST], + + K_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[K_SADB_EXT_ADDRESS_PROXY], + + K_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[K_SADB_EXT_KEY_AUTH], + + K_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[K_SADB_EXT_KEY_ENCRYPT], + + K_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[K_SADB_EXT_IDENTITY_SRC], + + K_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[K_SADB_EXT_IDENTITY_DST], + + K_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[K_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->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[K_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 > K_SADB_SATYPE_MAX. */ + + if((satype == 0) || (satype > K_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[K_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[K_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 > K_SADB_SATYPE_MAX. */ + + if((satype == 0) || (satype > K_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->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[K_SADB_EXT_RESERVED]); + + errlab: + + return error; + +} + + + +int + +pfkey_register_reply(int satype, struct sadb_msg *sadb_msg) + +{ + + struct sadb_ext *extensions_reply[K_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 > K_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->ias_exttype == K_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->ias_exttype == K_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->ias_exttype == K_SADB_EXT_SUPPORTED_AUTH) { + + alg_ap->sadb_alg_id = pfkey_supported_listp->supportedp->ias_id; + + alg_ap->sadb_alg_ivlen = pfkey_supported_listp->supportedp->ias_ivlen; + + alg_ap->sadb_alg_minbits = pfkey_supported_listp->supportedp->ias_keyminbits; + + alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->ias_keymaxbits; + + 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->ias_exttype == K_SADB_EXT_SUPPORTED_ENCRYPT) { + + alg_ep->sadb_alg_id = pfkey_supported_listp->supportedp->ias_id; + + alg_ep->sadb_alg_ivlen = pfkey_supported_listp->supportedp->ias_ivlen; + + alg_ep->sadb_alg_minbits = pfkey_supported_listp->supportedp->ias_keyminbits; + + alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->ias_keymaxbits; + + 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->ias_exttype, + + pfkey_supported_listp->supportedp->ias_id, + + pfkey_supported_listp->supportedp->ias_ivlen, + + pfkey_supported_listp->supportedp->ias_keyminbits, + + pfkey_supported_listp->supportedp->ias_keymaxbits); + + pfkey_supported_listp = pfkey_supported_listp->next; + + } + + + + if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], + + K_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[K_SADB_EXT_SUPPORTED_AUTH], + + K_SADB_EXT_SUPPORTED_AUTH, + + alg_num_a, + + alg_a), + + extensions_reply) : 1) && + + (alg_num_e ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[K_SADB_EXT_SUPPORTED_ENCRYPT], + + K_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_KLIPS_DEBUG + + uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; + +#endif /* CONFIG_KLIPS_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[K_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; + +} + + + + + +/* + + * + + * flush all SAs from the table + + */ + +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[K_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[K_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[K_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[K_SADB_EXT_MAX+1]; + + struct sadb_msg *pfkey_reply = NULL; + + struct socket_list *pfkey_socketsp; + + uint8_t satype = ((struct sadb_msg*)extensions[K_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 = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa1, sizeof(sa1)); + + if(extr->ips2 != NULL) { + + sa_len2 = KLIPS_SATOT(debug_pfkey, &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_ERROR(debug_pfkey, + + "klips_debug:pfkey_x_grpsa_parse: " + + "reserved ipsec_sa for SA1: %s not found. Call K_SADB_ADD/UPDATE first.\n", + + sa_len1 ? sa1 : " (error)"); + + SENDERR(ENOENT); + + } + + + + if(extr->ips2) { /* GRPSA */ + + + + /* group ips2p to be after ips1p */ + + + + 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 K_SADB_ADD/UPDATE first.\n", + + sa_len2 ? sa2 : " (error)"); + + SENDERR(ENOENT); + + } + + + + /* userspace puts things in inner to outer order */ + + if(ips2p->ips_flags & EMT_INBOUND) { + + struct ipsec_sa *t; + + + + /* exchange ips and ips2 */ + + t = ips1p; + + ips1p = ips2p; + + ips2p = t; + + } + + + + /* Is ips1p already linked? */ + + if(ips1p->ips_next) { + + ipsec_sa_put(ips1p); + + ipsec_sa_put(ips2p); + + spin_unlock_bh(&tdb_lock); + + KLIPS_ERROR(debug_pfkey, + + "klips_debug:pfkey_x_grpsa_parse: " + + "ipsec_sa for SA: %s is already linked.\n", + + sa_len1 ? sa1 : " (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_ERROR(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_next; + + } + + + + /* 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_next = ips2p; + + } else { /* UNGRPSA */ + + while(ips1p) { + + struct ipsec_sa *ipsn; + + + + /* take the reference to next */ + + ipsn = ips1p->ips_next; + + ips1p->ips_next = NULL; + + + + /* drop reference to current */ + + ipsec_sa_put(ips1p); + + + + ips1p = ipsn; + + } + + + + /* note: we have dropped reference to ips1p, and + + * it is now NULL + + */ + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_x_grpsa_parse: " + + "unlinking ipsec_sa SA: %s.\n", + + sa_len1 ? sa1 : " (error)"); + + } + + + + spin_unlock_bh(&tdb_lock); + + + + /* MCR: not only is this ugly to read, and impossible + + * to debug through, but it's also really inefficient. + + * XXX simplify me. + + */ + + if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], + + K_SADB_X_GRPSA, + + satype, + + 0, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + + K_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), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], + + K_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[K_SADB_X_EXT_SATYPE2], + + ((struct sadb_x_satype*)extensions[K_SADB_X_EXT_SATYPE2])->sadb_x_satype_satype + + /* proto2satype(extr->ips2->ips_said.proto) */), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_X_EXT_SA2], + + K_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), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_X_EXT_ADDRESS_DST2], + + K_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_KLIPS_DEBUG + + char buf1[64], buf2[64]; + +#endif /* CONFIG_KLIPS_DEBUG */ + + struct sadb_ext *extensions_reply[K_SADB_EXT_MAX+1]; + + struct sadb_msg *pfkey_reply = NULL; + + struct socket_list *pfkey_socketsp; + + uint8_t satype = ((struct sadb_msg*)extensions[K_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_KLIPS_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_KLIPS_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_next; + + } + + + + 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 = KLIPS_SATOT(debug_pfkey, &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[K_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); + + dst_output(first); + + } + + if(last != NULL) { + + KLIPS_PRINT(debug_eroute, + + "klips_debug:pfkey_x_addflow_parse: " + + "last=0p%p HOLD packet re-injected.\n", + + last); + + dst_output(last); + + } + + } + + + + 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], + + K_SADB_X_ADDFLOW, + + satype, + + 0, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + + K_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), + + extensions_reply) + + && (extensions[K_SADB_EXT_ADDRESS_SRC] + + ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], + + K_SADB_EXT_ADDRESS_SRC, + + 0, /*extr->ips->ips_said.proto,*/ + + 0, + + extr->ips->ips_addr_s), + + extensions_reply) : 1) + + && (extensions[K_SADB_EXT_ADDRESS_DST] + + ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], + + K_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[K_SADB_X_EXT_ADDRESS_SRC_FLOW], + + K_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[K_SADB_X_EXT_ADDRESS_DST_FLOW], + + K_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[K_SADB_X_EXT_ADDRESS_SRC_MASK], + + K_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[K_SADB_X_EXT_ADDRESS_DST_MASK], + + K_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_KLIPS_DEBUG + + char buf1[64], buf2[64]; + +#endif /* CONFIG_KLIPS_DEBUG */ + + struct sadb_ext *extensions_reply[K_SADB_EXT_MAX+1]; + + struct sadb_msg *pfkey_reply = NULL; + + struct socket_list *pfkey_socketsp; + + uint8_t satype = ((struct sadb_msg*)extensions[K_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_KLIPS_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_KLIPS_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], + + K_SADB_X_DELFLOW, + + satype, + + 0, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, + + ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], + + K_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), + + extensions_reply) + + && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_X_EXT_ADDRESS_SRC_FLOW], + + K_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[K_SADB_X_EXT_ADDRESS_DST_FLOW], + + K_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[K_SADB_X_EXT_ADDRESS_SRC_MASK], + + K_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[K_SADB_X_EXT_ADDRESS_DST_MASK], + + K_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[K_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], + + K_SADB_EXPIRE, + + satype, + + 0, + + ++pfkey_msg_seq, + + 0), + + extensions) + + && pfkey_safe_build(error = pfkey_sa_build(&extensions[K_SADB_EXT_SA], + + K_SADB_EXT_SA, + + ipsp->ips_said.spi, + + ipsp->ips_replaywin, + + ipsp->ips_state, + + ipsp->ips_authalg, + + ipsp->ips_encalg, + + ipsp->ips_flags), + + extensions) + + && pfkey_safe_build(error = pfkey_lifetime_build(&extensions[K_SADB_EXT_LIFETIME_CURRENT], + + K_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[K_SADB_EXT_LIFETIME_HARD], + + K_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[K_SADB_EXT_LIFETIME_SOFT], + + K_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[K_SADB_EXT_ADDRESS_SRC], + + K_SADB_EXT_ADDRESS_SRC, + + 0, /* ipsp->ips_said.proto, */ + + 0, + + ipsp->ips_addr_s), + + extensions) + + && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], + + K_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[K_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; */ + + { K_SADB_AALG_MD5HMAC, K_SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, + + 128, 128, 168, 168, + + 0, 0, 0, 0, 0, + + 57600, 86400, 57600, 86400}, + + { K_SADB_AALG_SHA1HMAC, K_SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, + + 160, 160, 168, 168, + + 0, 0, 0, 0, 0, + + 57600, 86400, 57600, 86400}, + + }; + + + + /* XXX This should not be hard-coded. It should be taken from the spdb */ + + uint8_t satype = K_SADB_SATYPE_ESP; + + + + pfkey_extensions_init(extensions); + + + + if((satype == 0) || (satype > K_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], + + K_SADB_ACQUIRE, + + satype, + + 0, + + ++pfkey_msg_seq, + + 0), + + extensions) + + && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_SRC], + + K_SADB_EXT_ADDRESS_SRC, + + ipsp->ips_transport_protocol, + + 0, + + ipsp->ips_addr_s), + + extensions) + + && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], + + K_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[K_SADB_EXT_ADDRESS_PROXY], + + K_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], + + K_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[K_SADB_EXT_IDENTITY_DST], + + K_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[K_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[K_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); + + } + + + +#ifdef KLIPS_PFKEY_ACQUIRE_LOSSAGE + +# if KLIPS_PFKEY_ACQUIRE_LOSSAGE > 0 + + if(sysctl_ipsec_regress_pfkey_lossage) { + + return(0); + + } + +# endif + +#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[K_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) ? K_SADB_SATYPE_ESP : 0; + + + + /* Construct K_SADB_X_NAT_T_NEW_MAPPING message */ + + + + pfkey_extensions_init(extensions); + + + + if((satype == 0) || (satype > K_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], K_SADB_X_NAT_T_NEW_MAPPING, + + satype, 0, ++pfkey_msg_seq, 0), extensions) + + /* SA */ + + && pfkey_safe_build + + (error = pfkey_sa_build(&extensions[K_SADB_EXT_SA], + + K_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[K_SADB_EXT_ADDRESS_SRC], + + K_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[K_SADB_X_EXT_NAT_T_SPORT], + + K_SADB_X_EXT_NAT_T_SPORT, ipsp->ips_natt_sport), extensions) + + /* ADDRESS_DST = new addr */ + + && pfkey_safe_build + + (error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], + + K_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[K_SADB_X_EXT_NAT_T_DPORT], + + K_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) + +{ + + /* K_SADB_X_NAT_T_NEW_MAPPING not used in kernel */ + + return -EINVAL; + +} + +#endif + + + +/******************************* + + * EXTENSION PARSERS FOR KLIPS + + ********************************/ + + + +DEBUG_NO_STATIC int + +pfkey_x_outif_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) + +{ + + struct sadb_x_plumbif *oif; + + + + oif = (struct sadb_x_plumbif *)pfkey_ext; + + + + extr->outif = oif->sadb_x_outif_ifnum; + + + + return 0; + +} + + + +DEBUG_NO_STATIC int + +pfkey_x_saref_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) + +{ + + struct sadb_x_saref *saf; + + + + saf = (struct sadb_x_saref *)pfkey_ext; + + + + extr->sarefme = saf->sadb_x_saref_me; + + extr->sarefhim = saf->sadb_x_saref_him; + + + + return 0; + +} + + + +DEBUG_NO_STATIC int (*ext_processors[K_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, + +#else + + NULL, NULL, NULL, NULL, + +#endif + + pfkey_x_outif_process, + + pfkey_x_saref_process, + +}; + + + + + +/******************************* + + * MESSAGE PARSERS FOR KLIPS + + ********************************/ + + + +/* + + * this is a request to create a new device. Figure out which kind, and call appropriate + + * routine in mast or tunnel code. + + */ + +DEBUG_NO_STATIC int + +pfkey_x_plumb_parse(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr) + +{ + + unsigned int vifnum; + + + + vifnum = extr->outif; + + if(vifnum > IPSECDEV_OFFSET) { + + return ipsec_tunnel_createnum(vifnum-IPSECDEV_OFFSET); + + } else { + + return ipsec_mast_createnum(vifnum); + + } + +} + + + +/* + + * this is a request to create a new device. Figure out which kind, and call appropriate + + * routine in mast or tunnel code. + + * */ + +DEBUG_NO_STATIC int + +pfkey_x_unplumb_parse(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr) + +{ + + unsigned int vifnum; + + + + vifnum = extr->outif; + + if(vifnum > IPSECDEV_OFFSET) { + + return ipsec_tunnel_deletenum(vifnum-IPSECDEV_OFFSET); + + } else { + + return ipsec_mast_deletenum(vifnum); + + } + +} + + + + + +DEBUG_NO_STATIC int (*msg_parsers[K_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, + +#else + + NULL, + +#endif + + pfkey_x_plumb_parse, + + pfkey_x_unplumb_parse, + +}; + + + +int + +pfkey_build_reply(struct sadb_msg *pfkey_msg, + + struct pfkey_extracted_data *extr, + + struct sadb_msg **pfkey_reply) + +{ + + struct sadb_ext *extensions[K_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; // TODO: should this not be negative? + + } + + 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); + + + + if(!error + + && pfkey_required_extension(EXT_BITS_OUT, msg_type, K_SADB_EXT_SA)) { + + + + error = pfkey_sa_build(&extensions[K_SADB_EXT_SA], + + K_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); + + pfkey_safe_build(error, extensions); + + } + + + + if(!error + + && pfkey_required_extension(EXT_BITS_OUT, msg_type, K_SADB_X_EXT_SAREF)) { + + error = pfkey_saref_build(&extensions[K_SADB_X_EXT_SAREF], + + extr->ips->ips_ref, + + extr->ips->ips_refhim); + + pfkey_safe_build(error, extensions); + + } + + + + if(!error + + && pfkey_required_extension(EXT_BITS_OUT,msg_type,K_SADB_EXT_LIFETIME_CURRENT)) { + + error = pfkey_lifetime_build(&extensions + + [K_SADB_EXT_LIFETIME_CURRENT], + + K_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); + + pfkey_safe_build(error, extensions); + + } + + + + if(!error + + && pfkey_required_extension(EXT_BITS_OUT,msg_type,K_SADB_EXT_ADDRESS_SRC)) { + + error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_SRC], + + K_SADB_EXT_ADDRESS_SRC, + + extr->ips->ips_said.proto, + + 0, + + extr->ips->ips_addr_s); + + pfkey_safe_build(error, extensions); + + } + + + + if(!error + + && pfkey_required_extension(EXT_BITS_OUT,msg_type,K_SADB_EXT_ADDRESS_DST)) { + + error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], + + K_SADB_EXT_ADDRESS_DST, + + extr->ips->ips_said.proto, + + 0, + + extr->ips->ips_addr_d); + + pfkey_safe_build(error, 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; + +} + + + +/* + + * interpret a pfkey message for klips usage. + + * it used to be that we provided a reply in a seperate buffer, + + * but now we overwrite the request buffer and return it. + + */ + +int + +pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg) + +{ + + int error = 0; + + int i; + + struct sadb_ext *extensions[K_SADB_EXT_MAX+1]; /* should be kalloc */ + + struct pfkey_extracted_data extr; + + + + memset(&extr, 0, sizeof(extr)); + + + + 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 > K_SADB_SATYPE_MAX) { + + KLIPS_PRINT(debug_pfkey, + + "klips_debug:pfkey_msg_interp: " + + "satype %d > max %d\n", + + pfkey_msg->sadb_msg_satype, + + K_SADB_SATYPE_MAX); + + SENDERR(EINVAL); + + } + + + + switch(pfkey_msg->sadb_msg_type) { + + case K_SADB_GETSPI: + + case K_SADB_UPDATE: + + case K_SADB_ADD: + + case K_SADB_DELETE: + + case K_SADB_X_GRPSA: + + case K_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 <= K_SADB_EXT_MAX;i++) { + + if(extensions[i] != NULL && ext_processors[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); + + } + + + + errlab: + + if(extr.ips != NULL) { + + ipsec_sa_put(extr.ips); + + } + + if(extr.ips2 != NULL) { + + ipsec_sa_put(extr.ips2); + + } + + if (extr.eroute != NULL) { + + kfree(extr.eroute); + + } + + return(error); + +} + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/prng.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,202 @@ + +/* + + * 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 . + + * + + * 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.8 2005/08/25 01:20:21 paul Exp $ + + */ + +#include "libreswan.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 MAXCOUNT 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 < MAXCOUNT - dstlen) + + prng->count += dstlen; + + else + + prng->count = MAXCOUNT; + +} + + + +/* + + - 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 + +#include + + + +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/net/ipsec/radij.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,1013 @@ + +char radij_c_version[] = "RCSID $Id: radij.c,v 1.48 2005/04/29 05:10:22 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. + + */ + + + +#ifndef AUTOCONF_INCLUDED + +#include + +#endif + +#include + +#include /* printk() */ + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef MALLOC_SLAB + +# include /* kmalloc() */ + +#else /* MALLOC_SLAB */ + +# include /* kmalloc() */ + +#endif /* MALLOC_SLAB */ + +#include /* error codes */ + +#include /* size_t */ + +#include /* mark_bh */ + + + +#include /* struct device, and other headers */ + +#include /* eth_type_trans */ + +#include /* struct iphdr */ + +#include + +#ifdef NET_21 + +# include + +#endif /* NET_21 */ + + + +#include + + + +#include + + + +#include "libreswan/radij.h" + +#include "libreswan/ipsec_encap.h" + +#include "libreswan/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_KLIPS_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_KLIPS_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_KLIPS_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_KLIPS_DEBUG */ + + /* Process leaves */ + + while ((rn = base)) { + + base = rn->rj_dupedkey; + +#ifdef CONFIG_KLIPS_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_KLIPS_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; irj_off); + + } else { + + printk("klips_debug:"); + + for (i=0; irj_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; + +} + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/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 . + + * + + * 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.9 2004/07/10 07:48:37 mcr Exp $ + + */ + +#include "libreswan.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/net/ipsec/satot.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,134 @@ + +/* + + * 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 . + + * + + * 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.13 2004/07/10 07:48:37 mcr Exp $ + + */ + +#include "libreswan.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) { + + char intunk[10]; + + 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: snprintf(intunk, 10, "%%unk-%d", ntohl(sa->spi)); p = intunk; 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/net/ipsec/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 . + + * + + * 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.8 2004/07/10 07:48:37 mcr Exp $ + + */ + +#include "libreswan.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/net/ipsec/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 . + + * + + * 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.11 2004/07/10 07:48:37 mcr Exp $ + + */ + +#include "libreswan.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/net/ipsec/sysctl_net_ipsec.c Mon Feb 9 13:51:03 2004 + @@ -0,0 +1,363 @@ + +/* + + * 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 . + + * + + * 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.17.10.2 2007/10/30 21:42:25 paul Exp $ + + */ + + + +/* -*- linux-c -*- + + * + + * Initiated April 3, 1998, Richard Guy Briggs + + */ + + + +#include + +#include + +#include + + + +#include "libreswan/ipsec_param.h" + + + +#ifdef CONFIG_SYSCTL + + + +#define NET_IPSEC 2112 /* Random number */ + +#ifdef CONFIG_KLIPS_DEBUG + +extern int debug_ah; + +extern int debug_esp; + +extern int debug_mast; + +extern int debug_tunnel; + +extern int debug_xmit; + +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_KLIPS_IPCOMP + +extern int sysctl_ipsec_debug_ipcomp; + +#endif /* CONFIG_KLIPS_IPCOMP */ + +#endif /* CONFIG_KLIPS_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_KLIPS_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_KLIPS_DEBUG */ + + NET_IPSEC_ICMP=13, + + NET_IPSEC_INBOUND_POLICY_CHECK=14, + + NET_IPSEC_TOS=15, + + NET_IPSEC_REGRESS_PFKEY_LOSSAGE=16, + + NET_IPSEC_DEBUG_MAST=17, + + NET_IPSEC_DEBUG_XMIT=18, + +}; + + + +static ctl_table ipsec_table[] = { + +#ifdef CONFIG_KLIPS_DEBUG + +#ifdef CTL_TABLE_PARENT + + { .ctl_name = NET_IPSEC_DEBUG_AH, + + .procname = "debug_ah", + + .data = &debug_ah, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_ESP, + + .procname = "debug_esp", + + .data = &debug_esp, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_MAST, + + .procname = "debug_mast", + + .data = &debug_mast, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_TUNNEL, + + .procname = "debug_tunnel", + + .data = &debug_tunnel, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_XMIT, + + .procname = "debug_xmit", + + .data = &debug_xmit, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_EROUTE, + + .procname = "debug_eroute", + + .data = &debug_eroute, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_SPI, + + .procname = "debug_spi", + + .data = &debug_spi, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_RADIJ, + + .procname = "debug_radij", + + .data = &debug_radij, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_NETLINK, + + .procname = "debug_netlink", + + .data = &debug_netlink, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_XFORM, + + .procname = "debug_xform", + + .data = &debug_xform, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_RCV, + + .procname = "debug_rcv", + + .data = &debug_rcv, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_PFKEY, + + .procname = "debug_pfkey", + + .data = &debug_pfkey, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_DEBUG_VERBOSE, + + .procname = "debug_verbose", + + .data = &sysctl_ipsec_debug_verbose, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + +#else + + { NET_IPSEC_DEBUG_AH, "debug_ah", &debug_ah, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_ESP, "debug_esp", &debug_esp, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_MAST, "debug_mast", &debug_mast, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_TUNNEL, "debug_tunnel", &debug_tunnel, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_TUNNEL, "debug_xmit", &debug_xmit, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_EROUTE, "debug_eroute", &debug_eroute, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_SPI, "debug_spi", &debug_spi, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_RADIJ, "debug_radij", &debug_radij, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_NETLINK, "debug_netlink", &debug_netlink, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_XFORM, "debug_xform", &debug_xform, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_RCV, "debug_rcv", &debug_rcv, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_PFKEY, "debug_pfkey", &debug_pfkey, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_DEBUG_VERBOSE, "debug_verbose",&sysctl_ipsec_debug_verbose, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + +#endif /* CTL_TABLE_PARENT */ + +#endif /* CONFIG_KLIPS_DEBUG */ + + + +#ifdef CONFIG_KLIPS_IPCOMP + +#ifdef CTL_TABLE_PARENT + + { .ctl_name = NET_IPSEC_DEBUG_IPCOMP, + + .procname = "debug_ipcomp", + + .data = &sysctl_ipsec_debug_ipcomp, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + +#else + + { NET_IPSEC_DEBUG_IPCOMP, "debug_ipcomp", &sysctl_ipsec_debug_ipcomp, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + +#endif + +#endif /* CONFIG_KLIPS_IPCOMP */ + + + +#ifdef CONFIG_KLIPS_REGRESS + +#ifdef CTL_TABLE_PARENT + + { + + .ctl_name = NET_IPSEC_REGRESS_PFKEY_LOSSAGE, + + .procname = "pfkey_lossage", + + .data = &sysctl_ipsec_regress_pfkey_lossage, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + +#else + + { NET_IPSEC_REGRESS_PFKEY_LOSSAGE, "pfkey_lossage", + + &sysctl_ipsec_regress_pfkey_lossage, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + +#endif /* CTL_TABLE_PARENT */ + +#endif /* CONFIG_KLIPS_REGRESS */ + + + +#ifdef CTL_TABLE_PARENT + + { .ctl_name = NET_IPSEC_ICMP, + + .procname = "icmp", + + .data = &sysctl_ipsec_icmp, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_INBOUND_POLICY_CHECK, + + .procname = "inbound_policy_check", + + .data = &sysctl_ipsec_inbound_policy_check, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + + + { .ctl_name = NET_IPSEC_TOS, + + .procname = "tos", + + .data = &sysctl_ipsec_tos, + + .maxlen = sizeof(int), + + .mode = 0644, + + .child = NULL, + + .proc_handler = &proc_dointvec, + + }, + + {0} + +#else + + { NET_IPSEC_ICMP, "icmp", &sysctl_ipsec_icmp, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_INBOUND_POLICY_CHECK, "inbound_policy_check", &sysctl_ipsec_inbound_policy_check, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + { NET_IPSEC_TOS, "tos", &sysctl_ipsec_tos, + + sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec}, + + {0} + +#endif + +}; + + + +static ctl_table ipsec_net_table[] = { + +#ifdef CTL_TABLE_PARENT + + { .ctl_name = NET_IPSEC, + + .procname = "ipsec", + + .data = NULL, + + .maxlen = 0, + + .mode = 0555, + + .child = ipsec_table, + + .proc_handler = NULL, + + }, + + { 0 } + +#else + + { NET_IPSEC, "ipsec", NULL, 0, 0555, ipsec_table }, + + { 0 } + +#endif + +}; + + + +static ctl_table ipsec_root_table[] = { + +#ifdef CTL_TABLE_PARENT + + { .ctl_name = CTL_NET, + + .procname = "net", + + .data = NULL, + + .maxlen = 0, + + .mode = 0555, + + .child = ipsec_net_table, + + .proc_handler = NULL, + + }, + + { 0 } + +#else + + { CTL_NET, "net", NULL, 0, 0555, ipsec_net_table }, + + { 0 } + +#endif + +}; + + + +static struct ctl_table_header *ipsec_table_header; + + + +int ipsec_sysctl_register(void) + +{ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + + ipsec_table_header = register_sysctl_table(ipsec_root_table); + +#else + + ipsec_table_header = register_sysctl_table(ipsec_root_table, 0); + +#endif + + if (!ipsec_table_header) { + + return -ENOMEM; + + } + + return 0; + +} + + + +void ipsec_sysctl_unregister(void) + +{ + + unregister_sysctl_table(ipsec_table_header); + +} + + + +#endif /* CONFIG_SYSCTL */ + + + +/* + + * + + * Local Variables: + + * c-file-style: "linux" + + * End: + + * + + */ + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/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.4 2004/07/10 07:48:39 mcr Exp $ */ + + + +/* #define GEN_TREES_H */ + + + +#include "deflate.h" + + + +#ifdef DEBUG + +# include + +#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< dist code (0..29) */ + + dist = 0; + + for (code = 0 ; code < 16; code++) { + + base_dist[code] = dist; + + for (n = 0; n < (1<>= 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 + +# 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<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/net/ipsec/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/net/ipsec/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 . + + * + + * 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.10 2004/07/10 07:48:37 mcr Exp $ + + */ + +#include "libreswan.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/net/ipsec/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 . + + * + + * 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.5 2004/07/10 07:48:37 mcr Exp $ + + */ + +#include "libreswan.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/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 . + + * + + * 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 + +#endif + + + +#include "libreswan.h" + + + +#define V "2.5.51s" /* substituted in by Makefile */ + +static const char libreswan_number[] = V; + +static const char libreswan_string[] = "Libreswan " V; + + + +/* + + - ipsec_version_code - return IPsec version number/code, as string + + */ + +const char * + +ipsec_version_code() + +{ + + return libreswan_number; + +} + + + +/* + + - ipsec_version_string - return full version string + + */ + +const char * + +ipsec_version_string() + +{ + + return libreswan_string; + +} + --- /dev/null Tue Mar 11 13:02:56 2003 + +++ linux/net/ipsec/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.5 2004/07/10 07:48:40 mcr Exp $ */ + + + +#include + + + +#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 */ + --- swan26/net/ipv4/af_inet.c.orig Wed Jun 16 01:18:58 2004 + +++ swan26/net/ipv4/af_inet.c Fri Aug 13 23:09:27 2004 + @@ -1169,6 +1169,18 @@ + #if defined(CONFIG_IP_MROUTE) + ip_mr_init(); + #endif + + + +#if defined(CONFIG_KLIPS) + + { + + extern int ipsec_klips_init(void); + + /* + + * Initialise AF_INET ESP and AH protocol support including + + * e-routing and SA tables + + */ + + ipsec_klips_init(); + + } + +#endif /* CONFIG_IPSEC */ + + + /* + * Initialise per-cpu ipv4 mibs + */ + --- /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='2.5.51s' + make[1]: Leaving directory `/vol/git/libreswan.sony' diff -c -w -r -N linux-2.6.16-ng-natt/README.libreswan-2 linux-2.6.16-ng-natt-klips/README.libreswan-2 *** linux-2.6.16-ng-natt/README.libreswan-2 1969-12-31 19:00:00.000000000 -0500 --- linux-2.6.16-ng-natt-klips/README.libreswan-2 2008-06-01 17:37:11.000000000 -0400 *************** *** 0 **** --- 1,112 ---- + * + * RCSID $Id: README.libreswan-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.libreswan-2,v $ + * Revision 1.1 2003/12/10 01:07:49 mcr + * documentation for additions. + * + *