--- linux-2.4.21/drivers/addon/cipe4/Makefile.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/Makefile Fri Jul 25 15:12:33 2003 @@ -0,0 +1,23 @@ +# -*-Makefile-*- template for the CIPE kernel module and driver. +# Copyright 1996 Olaf Titz +# +# 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. + +O_TARGET := cipdb.o + +obj-y := module.o device.o sock.o output.o encaps.o crc32.o bf.o +obj-m := $(O_TARGET) + +ifeq ($(ARCH),i386) + obj-y += bf-i386.o +endif + +include $(TOPDIR)/Rules.make + +ifeq ($(ARCH),i386) +bf-i386.o: bf-i386.S + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< +endif --- linux-2.4.21/drivers/addon/cipe4/ciped.h.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/ciped.h Fri Jul 25 15:12:33 2003 @@ -0,0 +1,43 @@ +/* + CIPE - encrypted IP over UDP tunneling + + ciped.h - prototypes for user level routines + + Copyright 1997 Olaf Titz + + 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. +*/ +/* $Id: ciped.h,v 1.6 2000/12/16 17:49:06 olaf Exp $ */ + +#include +#include +#include "cipe.h" +#include "options.h" + +/* options.c */ +struct options { + const char * const oname; + const char otyp; + union { + int ovint; + char *ovstr; + struct sockaddr_in *ovsaddr; + } ov; +}; +extern struct options opts[]; +#define Tbool 0 +#define Tint 1 +#define Tstr 2 +#define Taddr 3 +#define Tuaddr 4 +#define Ttaddr 5 +#define Tsecret 6 + +#define OI(x) (opts[O##x].ov.ovint) +#define OS(x) (opts[O##x].ov.ovstr) +#define OA(x) (opts[O##x].ov.ovsaddr) +#define OAaddr(x) (OA(x)->sin_addr) +#define OAport(x) (OA(x)->sin_port) --- linux-2.4.21/drivers/addon/cipe4/cipe.h.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/cipe.h Fri Jul 25 15:12:33 2003 @@ -0,0 +1,426 @@ +/* + CIPE - encrypted IP over UDP tunneling + + cipe.h - contains definitions, includes etc. common to all modules + + Copyright 1996-2000 Olaf Titz + + 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. +*/ +/* $Id: cipe.h,v 1.38.2.2 2002/06/28 23:38:53 olaf Exp $ */ + +#ifndef _CIPE_H_ +#define _CIPE_H_ + +#include "crypto.h" +#ifdef __KERNEL__ +#include +#else +#include +#endif + +/*** The kernel/user IOCTL interface ***/ + +/* ioctls for setup and key exchange */ +/* #define SIOCxIFCIPxxx (SIOCDEVPRIVATE+x) */ +/* All ioctls are passed a struct ifreq which contains the + device name in ifr_name and a pointer to the actual control struct + in ifr_data. */ + +#if 0 +/* Get interface parameters. Currently unused */ +#define SIOCGIFCIPPAR (SIOCDEVPRIVATE+0) +struct siocgifcippar { + unsigned long magic; + /* SOCKS5 relayer */ + unsigned long sockshost; + unsigned short socksport; + /* Timeouts (in seconds) */ + int tmo_keyxchg; + int tmo_keylife; + /* Flags */ + int flags; + int cttl; +}; +#endif + +/* Set interface parameters. */ +#define SIOCSIFCIPPAR (SIOCDEVPRIVATE+1) +struct siocsifcippar { + unsigned long magic; + /* SOCKS5 relayer */ + unsigned long sockshost; + unsigned short socksport; + /* Timeouts (in seconds) */ + int tmo_keyxchg; + int tmo_keylife; + /* Flags */ + int flags; + int cttl; +}; + +/* Set a key. */ +#define SIOCSIFCIPKEY (SIOCDEVPRIVATE+2) +#define KEY_STATIC 1 +#define KEY_SEND 2 +#define KEY_RECV 3 +#define KEY_INVAL 8 +#define KEY_MAXLEN 32 +struct siocsifcipkey { + unsigned long magic; + int which; + char thekey[KEY_MAXLEN]; + int keylen; +}; + +/* Attach a socket. */ +#define SIOCSIFCIPATT (SIOCDEVPRIVATE+3) +struct siocsifcipatt { + unsigned long magic; + int fd; +}; + +/* Allocate/deallocate a device. */ +#define SIOCSIFCIPALL (SIOCDEVPRIVATE+4) +#define SIOCSIFCIPUNA (SIOCDEVPRIVATE+5) +struct siocsifcipall { + unsigned long magic; + int num; + char name[IFNAMSIZ]; +}; + +/* Flag values. */ +#define CIPF_MAY_CLEAR 0x0100 +#define CIPF_MAY_STKEY 0x0200 +#define CIPF_MAY_DYNIP 0x0400 +#define CIPF_DO_CSUM 0x0800 + +/*** Key exchange related definitions ***/ + +/* Minimum kxc block. */ +#define KEYXCHGBLKMIN 64 +/* Maximum kxc block, padded with random bytes */ +#define KEYXCHGBLKMAX (KEYXCHGBLKMIN+256) +/* Position of the timestamp */ +#define KEYXCHGTSPOS 56 +/* Type words. Only 4 are possible. */ +#define TW_DATA 0 +#define TW_NEWKEY 2 +#define TW_CTRL 4 +#define TW_RSVD2 6 +/* error indication, no valid type word */ +#define TW_ERROR 1 + +/* NEWKEY (key exchange mode 1) subtypes. */ +#define NK_RREQ 0 /* not used in protocol */ +#define NK_REQ 1 /* send me your new key */ +#define NK_IND 2 /* this is my new key */ +#define NK_ACK 3 /* i have your new key */ + +/* CTRL subtypes. By now sent in a TW_NEWKEY packet. */ +#define CT_DUMMY 0x70 /* ignore */ +#define CT_DEBUG 0x71 /* log */ +#define CT_PING 0x72 /* send PONG */ +#define CT_PONG 0x73 +#define CT_KILL 0x74 /* exit */ +#define CT_CONFREQ 0x75 /* log, send CONF */ +#define CT_CONF 0x76 /* log */ + +/*** Kernel-module internal stuff ***/ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) +#define LINUX_21 +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#define LINUX_23 +#endif +#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)) && defined(__i386__) +#define REGPARM /* __attribute__((regparm,3)) XX needs testing */ +#else +#define REGPARM +#endif + +#ifdef LINUX_21 +#ifndef SPIN_LOCK_UNLOCKED /* 2.2/2.4 incompat */ +#include +#endif +#endif + +#if 1 /* Lock tracing */ +#define DOLOCK(s) ({ printk(KERN_DEBUG DEVNAME ": " #s " at %s:%d\n", \ + __FILE__, __LINE__); s; }) +#else +#define DOLOCK(s) s +#endif + +#ifdef LINUX_23 +#define tasklist_LOCK() DOLOCK(read_lock(&tasklist_lock)) +#define tasklist_UNLOCK() DOLOCK(read_unlock(&tasklist_lock)) +#else +#define tasklist_LOCK() /* nop */ +#define tasklist_UNLOCK() /* nop */ +#endif + +#ifdef LINUX_21 +/* In 2.1 the ioctl operations are run under lock. Beware of deadlocks. */ +#define cipe_alloc_LOCK() 0 /* nop */ +#define cipe_alloc_UNLOCK() /* nop */ +#else +extern struct semaphore cipe_alloc_sem; +#define cipe_alloc_LOCK() DOLOCK(down_interruptible(&cipe_alloc_sem)) +#define cipe_alloc_UNLOCK() DOLOCK(up(&cipe_alloc_sem)) +#endif + +#ifdef LINUX_21 +#define FLEN "%d" +#else +#define FLEN "%ld" +#endif + +#ifdef LINUX_23 +#define rtnl_LOCK() DOLOCK(rtnl_lock()) +#define rtnl_UNLOCK() DOLOCK(rtnl_unlock()) +#else +#define rtnl_LOCK() /* nop */ +#define rtnl_UNLOCK() /* nop */ +#endif + +#ifdef LINUX_23 +#define NET_DEVICE net_device +#define DEV_STATS net_device_stats +#else +#define NET_DEVICE device +#define DEV_STATS enet_statistics +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127) +#define timeout_t unsigned long +#else +#define timeout_t long +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,99) +#define HAVE_DEVNAME_ARRAY +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17) +#define get_fast_time do_gettimeofday +#endif + +/* The header we add to each packet */ +#ifdef VER_ETH +#define cipehdrlen (sizeof(struct iphdr)+sizeof(struct udphdr)+blockSize+ETH_HLEN) +#else +#ifdef VER_SHORT +#define cipehdrlen (sizeof(struct iphdr)+sizeof(struct udphdr)) +#else +#define cipehdrlen (sizeof(struct iphdr)+sizeof(struct udphdr)+blockSize) +#endif +#endif +/* ...plus a real hardware header (common case) */ +#define cipexhdrl (cipehdrlen+((ETH_HLEN+15)&~15)) +/* max. padding at the end */ +#if ProtocolVersion >= 3 +#define cipefootlen 12 /* 7 bytes pad, 1 byte type, 4 bytes CRC */ +#else +#define cipefootlen 10 /* 8 bytes pad, 2 bytes CRC */ +#endif + +/* A CIPE device's parameter block */ + +#define CIPE_MAGIC (htonl(0x43495045)) +struct cipe { + __u32 magic; + struct NET_DEVICE *dev; + /* Set by user process */ + __u32 peeraddr; + __u32 myaddr; + __u16 peerport; + __u16 myport; + __u32 sockshost; + __u16 socksport; + short cttl; +#ifdef Crypto_IDEA + Key key_e, key_d, skey_e, rkey_d; +#endif +#ifdef Crypto_Blowfish + Key key, skey, rkey; + #define key_e key + #define key_d key + #define skey_e skey + #define rkey_d rkey +#endif + unsigned long tmo_keyxchg; + unsigned long tmo_keylife; + /* Internal */ + unsigned long timekx; + unsigned long timeskey; + unsigned long timerkey; + int cntskey; + int cntrkey; + struct sock *sock; + int flags; +#ifdef LINUX_21 + char recursion; +#endif + pid_t owner; + /* Statistics */ +#ifdef LINUX_21 + struct net_device_stats stat; +#else + struct enet_statistics stat; +#endif + /* Socket interface stuff */ + struct proto *udp_prot; + struct proto cipe_proto; +}; + +/* Flag values (internally used) */ +#define CIPF_HAVE_KEY 0x0001 +#define CIPF_HAVE_SKEY 0x0002 +#define CIPF_HAVE_RKEY 0x0004 +#define CIPF_MASK_INT 0x00FF +#define CIPF_MASK_EXT 0xFF00 + +#define MAXBLKS 32767 /* max # blocks to encrypt using one key */ + +/* Define, init and check a struct cipe * variable. */ +#define DEVTOCIPE(dev,c,err) \ + struct cipe *c = (struct cipe*)(dev->priv); \ + if (!c || c->magic!=CIPE_MAGIC) return err; + +/* Master control struct */ +struct cipe_ctrl { +#ifndef HAVE_DEVNAME_ARRAY + char name[IFNAMSIZ]; +#endif + struct cipe cipe; + struct NET_DEVICE dev; +}; + +extern struct cipe_ctrl **cipe_ctrls; +extern int cipe_maxdev; + +/* SOCKS5 encapsulation header */ +struct sockshdr { + char rsv[2]; + char frag; + char atyp; + __u32 dstaddr __attribute__((packed)); + __u16 dstport __attribute__((packed)); +}; + +#ifdef DEBUG +extern int cipe_debug; + +#if 0 +/* Lock around our printks, to avoid mixing up dumps. NOT for regular use. */ +extern spinlock_t cipe_printk_lock; +#define LOCK_PRINTK unsigned long flags; spin_lock_irqsave(&cipe_printk_lock, flags) +#define UNLOCK_PRINTK spin_unlock_irqrestore(&cipe_printk_lock, flags) +#else +#define LOCK_PRINTK /* nop */ +#define UNLOCK_PRINTK /* nop */ +#endif + +#define DEB_CALL 1 +#define DEB_INP 2 +#define DEB_OUT 4 +#define DEB_CRYPT 8 +#define DEB_KXC 16 +#define DEB_PKIN 32 +#define DEB_PKOU 64 +#define DEB_CHKP 128 + +#define dprintk(l,p) if(cipe_debug&l){LOCK_PRINTK; printk p; UNLOCK_PRINTK;} + +#else +#define dprintk(l,p) /* nop */ + +#endif /* DEBUG */ + +#if defined(DEBUG) && defined(LINUX_23) +#define __CHECKPOINT(F,L) printk(KERN_DEBUG "CHECKPOINT " F ":%d\n", L) +#define CHECKPOINT if (cipe_debug&DEB_CHKP){\ + LOCK_PRINTK; __CHECKPOINT(__FILE__,__LINE__); UNLOCK_PRINTK;\ + current->state=TASK_INTERRUPTIBLE; schedule_timeout(HZ/20); } +#else +#define CHECKPOINT /* nop */ +#endif + +static inline void nf_conntrack_null(struct sk_buff *skb) +{ +#ifdef CONFIG_NETFILTER + nf_conntrack_put(skb->nfct); + skb->nfct = NULL; +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug = 0; +#endif +#endif +} + +/* internal routines */ +/* module.c */ +extern void cipe_use_module(void); +extern void cipe_unuse_module(void); +extern int cipe_check_kernel(void); +/* device.c */ +extern void cipe_prnpad(unsigned char *buf, int len) REGPARM; +extern void cipe_close(struct cipe *c); +extern const char *cipe_ntoa(__u32 addr) REGPARM; +/* sock.c */ +extern int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm) + REGPARM; +extern void cipe_fakenkey(struct cipe *c, char typ) REGPARM; +/* output.c */ +#ifdef DEBUG +extern void cipe_dump_packet(char *title, struct sk_buff *skb, int dumpskb) + REGPARM; +#endif +extern int cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev); +/* encaps.c */ +extern void cipe_encrypt(struct cipe *c, unsigned char *buf, + int *len, int typcode) REGPARM; +extern unsigned short cipe_decrypt(struct cipe *c, unsigned char *buf, + int *len) REGPARM; +#ifndef VER_SHORT +extern void cipe_cryptpad(unsigned char *buf) REGPARM; +extern void cipe_cryptpad_iv(unsigned char *buf) REGPARM; +#endif + +#endif /* __KERNEL__ */ + +#ifdef VER_CRC32 +/* crc32.c */ +extern unsigned long crc32(const unsigned char *s, unsigned int len); +#else +/* crc.c */ +extern unsigned short block_crc(unsigned char *d, int len); +#endif + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +#ifndef DEVNAME +#define DEVNAME "cip" VERNAME CRNAME +#endif + +#endif /* _CIPE_H_ */ --- linux-2.4.21/drivers/addon/cipe4/config.h.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/config.h Fri Jul 25 15:12:33 2003 @@ -0,0 +1,54 @@ +/* config.h. Generated automatically by configure. */ +/* + CIPE - encrypted IP over UDP tunneling + + Copyright 1999 Olaf Titz + + 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. +*/ + +/* Config-dependent defines. Always include this first. */ +/* @api means the next line is used for determining the version magic */ + +/* Version of the CIPE package @api */ +#define VERSION "1.5.4" +#define VERSION_MAJ 1 + +/* Encapsulation protocol version @api */ +#define ProtocolVersion 4 + +/* Cipher algorithm selection @api */ +/* #undef Crypto_IDEA */ +/* Cipher algorithm selection @api */ +#define Crypto_Blowfish 1 + +/* Assembler module selection */ +/* #undef ASM_IDEA_Crypt */ +#ifdef __i386 +#define ASM_BF_Crypt 1 +#endif + +/* Debug code in kernel */ +#define DEBUG 1 + +/* Use old key parser */ +/* #undef BUG_COMPATIBLE */ + +/* Dynamic device allocation @api */ +/* #undef NO_DYNDEV */ + +/* Syslog facility */ +#define LOGFAC LOG_DAEMON + +/* Memory management functions (kernel version dependent?) */ +#define HAVE_MLOCK 1 +#define HAVE_MLOCKALL 1 + +/* End of autoconf options */ + +/* This tells the Blowfish module to omit unneeded code */ +#define BF_DONTNEED_BE + --- linux-2.4.21/drivers/addon/cipe4/crc32.c.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/crc32.c Fri Jul 25 15:12:33 2003 @@ -0,0 +1,111 @@ + /* ============================================================= */ + /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */ + /* code or tables extracted from it, as desired without restriction. */ + /* */ + /* First, the polynomial itself and its table of feedback terms. The */ + /* polynomial is */ + /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ + /* */ + /* Note that we take it "backwards" and put the highest-order term in */ + /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ + /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ + /* the MSB being 1. */ + /* */ + /* Note that the usual hardware shift register implementation, which */ + /* is what we're using (we're merely optimizing it by doing eight-bit */ + /* chunks at a time) shifts bits into the lowest-order term. In our */ + /* implementation, that means shifting towards the right. Why do we */ + /* do it this way? Because the calculated CRC must be transmitted in */ + /* order from highest-order term to lowest-order term. UARTs transmit */ + /* characters in order from LSB to MSB. By storing the CRC this way, */ + /* we hand it to the UART in the order low-byte to high-byte; the UART */ + /* sends each low-bit to hight-bit; and the result is transmission bit */ + /* by bit from highest- to lowest-order term without requiring any bit */ + /* shuffling on our part. Reception works similarly. */ + /* */ + /* The feedback terms table consists of 256, 32-bit entries. Notes: */ + /* */ + /* The table can be generated at runtime if desired; code to do so */ + /* is shown later. It might not be obvious, but the feedback */ + /* terms simply represent the results of eight shift/xor opera- */ + /* tions for all combinations of data and CRC register values. */ + /* */ + /* The values must be right-shifted by eight bits by the "updcrc" */ + /* logic; the shift must be unsigned (bring in zeroes). On some */ + /* hardware you could probably optimize the shift in assembler by */ + /* using byte-swap instructions. */ + /* polynomial $edb88320 */ + /* */ + /* -------------------------------------------------------------------- */ + +static unsigned long crc32_tab[] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL + }; + +/* Return a 32-bit CRC of the contents of the buffer. */ + +unsigned long crc32(const unsigned char *s, unsigned int len) +{ + unsigned int i; + unsigned long crc32val; + + crc32val = 0; + for (i = 0; i < len; i ++) + { + crc32val = + crc32_tab[(crc32val ^ s[i]) & 0xff] ^ + (crc32val >> 8); + } + return crc32val; +} --- linux-2.4.21/drivers/addon/cipe4/crypto.h.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/crypto.h Fri Jul 25 15:12:33 2003 @@ -0,0 +1,100 @@ +/* + CIPE - encrypted IP over UDP tunneling + + crypto.h - configuration of the crypto algorithm + + Copyright 1996 Olaf Titz + + 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. +*/ +/* $Id: crypto.h,v 1.8 2000/09/13 21:46:41 olaf Exp $ */ + +#ifndef _CRYPTO_H_ +#define _CRYPTO_H_ + +#include "version.h" + +typedef unsigned long part; +/* the longest integer so that sizeof(part) divides blockSize. + Used only for optimizing block-copy and block-XOR operations. */ + +#if ProtocolVersion == 1 + +#ifdef OLDNAMES +#define VERNAME "1" +#else +#define VERNAME "a" +#endif +#define VER_BACK /* encryption progress backwards */ +#define VER_SHORT /* no IV in packet */ + +#elif ProtocolVersion == 2 + +#ifdef OLDNAMES +#define VERNAME "2" +#else +#define VERNAME "b" +#endif + +#elif ProtocolVersion == 3 + +#ifdef OLDNAMES +#define VERNAME "3" +#else +#define VERNAME "c" +#endif +#define VER_CRC32 /* checksums are 32bit */ + +#elif ProtocolVersion == 4 + +#ifdef OLDNAMES +#define VERNAME "4" +#else +#define VERNAME "d" +#endif +#define VER_CRC32 +#define VER_ETH + +#else +#error "Must specify correct ProtocolVersion" +#endif + + +#ifdef Crypto_IDEA +#define CRYPTO "IDEA" +#define CRNAME "i" +#define CRNAMEC 'i' +#define CRNUM 0 +#include "idea0.h" +#define Key Idea_Key +#define keySize Idea_keySize +#define UserKey Idea_UserKey +#define userKeySize Idea_userKeySize +#define ExpandUserKey Idea_ExpandUserKey +#define InvertKey Idea_InvertKey +#define blockSize Idea_dataSize + +#else +#ifdef Crypto_Blowfish +#define CRYPTO "Blowfish" +#define CRNAME "b" +#define CRNAMEC 'b' +#define CRNUM 1 +#include "bf.h" +#define Key Blowfish_Key +#define keySize sizeof(Blowfish_Key) +#define UserKey Blowfish_UserKey +#define userKeySize 16 /* arbitrary, but matches IDEA */ +#define ExpandUserKey(u,k) Blowfish_ExpandUserKey(u,userKeySize,k) +#define InvertKey(x,y) /* noop */ +#define blockSize sizeof(Blowfish_Data) + +#else +#error "Must specify Crypto_IDEA or Crypto_Blowfish" +#endif +#endif + +#endif --- linux-2.4.21/drivers/addon/cipe4/encaps.c.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/encaps.c Fri Jul 25 15:12:33 2003 @@ -0,0 +1,313 @@ +/* + CIPE - encrypted IP over UDP tunneling + + encaps.c - do encryption + + Copyright 1996 Olaf Titz + + 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. +*/ +/* $Id: encaps.c,v 1.18 2000/09/13 21:46:41 olaf Exp $ */ + +#include "cipe.h" +#include +#include + +static inline void xorbuf(part *dst, part *src) +{ + int i; + for (i=0; i0) { + memcpy(r, p, blockSize); + ecb_dec(p, p, key); + xorbuf(p, q); + s=q; q=r; r=s; + p-=blockSize/sizeof(part); + } + } else { + while (i-->0) { + xorbuf(p, q); + ecb_enc(p, p, key); + q=p; + p-=blockSize/sizeof(part); + } + } +} + +#else + +/* + CBC encryption/decryption routines. + Note: the block to encrypt includes the IV, while decryption swallows + the IV. Length is always including IV. +*/ + +#define partinc(p) ((p)+blockSize/sizeof(part)) + +static void cbc_enc(unsigned char *msg, int len, Key * const key) +{ + part *p=(part *)msg; + int i=len/blockSize; + +#if 0 + dprintk(DEB_CRYPT, (KERN_DEBUG "cbc_enc: %08x %08x ", + *((__u32*)partinc(msg)), *(__u32*)key)); +#endif + while (--i>0) { + xorbuf(partinc(p), p); + p=partinc(p); + ecb_enc(p, p, *key); + } +#if 0 + dprintk(DEB_CRYPT, ("%08x\n", *((__u32*)partinc(msg)))); +#endif +} + +static void cbc_dec(unsigned char *msg, int len, Key * const key) +{ + part *p=(part *)msg; + int i=len/blockSize; + part r[blockSize/sizeof(part)]; + +#if 0 + dprintk(DEB_CRYPT, (KERN_DEBUG "cbc_dec: %08x %08x ", + *(__u32*)msg, *(__u32*)key)); +#endif + while (--i>0) { + ecb_dec(partinc(p), r, *key); + xorbuf(p, r); + p=partinc(p); + } +#if 0 + dprintk(DEB_CRYPT, ("%08x\n", *(__u32*)msg)); +#endif +} + +#endif + +#ifndef VER_SHORT +/* Fill a block of length blockSize with strong random numbers. + Used for generating IVs. */ +void cipe_cryptpad(unsigned char *buf) +{ + static int padcnt=MAXBLKS; + static Key padkey; + + if (++padcnt>MAXBLKS) { + /* make a new random key */ + UserKey k; + dprintk(DEB_CRYPT, (KERN_INFO "%s: re-keying cryptpad\n", DEVNAME)); + cipe_prnpad((unsigned char*)k, sizeof(UserKey)); + ExpandUserKey(k, padkey); + padcnt=0; + } + *(int *)(buf)=padcnt; + cipe_prnpad(buf+sizeof(int), blockSize-sizeof(int)); + ecb_enc((part*)buf, (part*)buf, padkey); +} + +void cipe_cryptpad_iv(unsigned char *buf) +{ + int i=5; + do { + cipe_cryptpad(buf); + if (*((__u32 *)buf) & htonl(0x7FFFFFFF)) + break; + } while (i-->0); + if (!i) + printk(KERN_CRIT "cipe_cryptpad_iv failed"); +} +#endif + + +void cipe_checkskey(struct cipe *c) +{ + if ((++c->cntskey>MAXBLKS) || (jiffies>c->timeskey)) { + /* make the control process send an NK_IND */ + cipe_fakenkey(c, NK_REQ); + c->timeskey=jiffies+c->tmo_keyxchg; + if (c->cntskey>MAXBLKS) + c->cntskey-=1000; + } +} + +void cipe_checkrkey(struct cipe *c) +{ + if ((c->flags&CIPF_HAVE_RKEY) && + ((++c->cntrkey>MAXBLKS*2) || (jiffies>c->timerkey))) { + /* make the control process send an NK_REQ */ + cipe_fakenkey(c, NK_RREQ); + c->flags&=~CIPF_HAVE_RKEY; + c->timerkey=jiffies+c->tmo_keyxchg; + if (c->cntrkey>MAXBLKS*2) + c->cntrkey-=1000; + } +} + +void cipe_nodynkey(struct cipe *c) +{ + if (jiffies>c->timerkey) { + /* make the control process send an NK_REQ */ + cipe_fakenkey(c, NK_RREQ); + c->timerkey=jiffies+c->tmo_keyxchg; + } + dprintk(DEB_CRYPT, (KERN_INFO "%s: missing dynamic key\n", + c->dev->name)); +} + +#if ProtocolVersion >= 3 + +/* Encryption/decryption version 3 */ + +void cipe_encrypt(struct cipe *c, unsigned char *buf, int *len, int typ) +{ + unsigned char p=7-(((*len)+4)&7); + /* merge key flag in IV */ + *buf&=0x7F; + if (c->flags&CIPF_HAVE_SKEY) + *buf|=0x80; + /* pad */ + cipe_prnpad(buf+(*len), p); + (*len)+=p+5; + /* set type and crc */ + *(buf+(*len)-5)=typ|(p<<4); + *((unsigned long *)(buf+(*len)-4))= + htonl(crc32(buf+blockSize, (*len)-blockSize-4)); + + dprintk(DEB_CRYPT, (KERN_INFO "%s: encrypt typ %d pad %d len %d\n", + c->dev->name, typ, p, *len)); + cbc_enc(buf, *len, c->flags&CIPF_HAVE_SKEY ? &c->skey_e : &c->key_e); + cipe_checkskey(c); +} + +unsigned short cipe_decrypt(struct cipe *c, unsigned char *buf, int *len) +{ + unsigned char p; + + if (((*buf)&0x80) && !(c->flags&CIPF_HAVE_RKEY)) { + cipe_nodynkey(c); + return TW_ERROR; /* can't decrypt - no valid key */ + } + cbc_dec(buf, *len, ((*buf)&0x80) ? &c->rkey_d : &c->key_d); + (*len)-=blockSize; + if (*((unsigned long *)(buf+(*len)-4)) != htonl(crc32(buf, (*len)-4))) { + dprintk(DEB_CRYPT, (KERN_INFO "%s: decrypt CRC error\n", + c->dev->name)); + return TW_ERROR; + } + p=*(buf+(*len)-5); + (*len)-=(p>>4)&7; + cipe_checkrkey(c); +#define CTLBITS 0x06 + dprintk(DEB_CRYPT, (KERN_INFO "%s: decrypt len=%d pad=%d typ=%02X\n", + c->dev->name, (*len), (p>>4)&7, p&CTLBITS)); + return (p&CTLBITS); +} + +#else + +/* Encryption/decryption version 1 and 2 */ + +void cipe_encrypt(struct cipe *c, unsigned char *buf, int *len, int typ) +{ + unsigned short x; + unsigned char p; + + p=8-((*len)&7); + cipe_prnpad(buf+(*len), p); + (*len)+=p; + +#ifdef VER_SHORT + x=((block_crc(buf, *len)&0xFFFE)^((p&7)<<8)^typ)|(c->haveskey); +#else + x=((block_crc(buf+blockSize, (*len)-blockSize)&0xFFFE) + ^((p&7)<<8)^typ)|(c->haveskey); +#endif +#ifdef VER_BACK + cbc_b(buf, *len, c->haveskey ? &c->skey_e : &c->key_e, 0); +#else + cbc_enc(buf, *len, c->haveskey ? &c->skey_e : &c->key_e); +#endif + + dprintk(DEB_CRYPT, (KERN_INFO "%s: encrypt pad %d\n", c->dev->name, p)); + buf[(*len)++]=x>>8; + buf[(*len)++]=x&255; + cipe_checkskey(c); +} + +unsigned short cipe_decrypt(struct cipe *c, unsigned char *buf, int *len) +{ + unsigned short x=(buf[(*len)-1])+(buf[(*len)-2]<<8); + unsigned char p; + + if ((x&1) && !(c->haverkey)) { + cipe_nodynkey(c); + return TW_ERROR; /* can't decrypt - no valid key */ + } + (*len)-=2; + if (*len<9 +#ifndef VER_SHORT + +blockSize +#endif + ) + return TW_ERROR; /* short packet */ + +#ifdef VER_BACK + cbc_b(buf, *len, (x&1) ? &c->rkey_d : &c->key_d, 1); +#else + cbc_dec(buf, *len, (x&1) ? &c->rkey_d : &c->key_d); +#endif +#ifndef VER_SHORT + (*len)-=blockSize; +#endif + + x^=block_crc(buf, *len); + p=(x>>8)&7; if (!p) p=8; + (*len)-=p; + cipe_checkrkey(c); + +#define CTLBITS 0xF8FE + dprintk(DEB_CRYPT, (KERN_INFO "%s: decrypt pad %d typ %04X\n", + c->dev->name, (x>>8)&7, x&CTLBITS)); + return (x&CTLBITS); /* delete the control bits */ +} + +#endif --- linux-2.4.21/drivers/addon/cipe4/ioctl.h.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/ioctl.h Fri Jul 25 15:12:33 2003 @@ -0,0 +1,24 @@ +/* + CIPE - encrypted IP over UDP tunneling + + ioctl.h - prototype for the ioctl interface, user part + + Copyright 1996 Olaf Titz + + 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. +*/ +/* $Id: ioctl.h,v 1.3 2000/03/27 17:38:23 olaf Exp $ */ + +#include "cipe.h" + +#ifdef SIOCGIFCIPPAR +extern int ioctl_getpar(int fd, char *ifname, struct siocgifcippar *sio); +#endif +extern int ioctl_setpar(int fd, char *ifname, struct siocsifcippar *sio); +extern int ioctl_setkey(int fd, char *ifname, struct siocsifcipkey *sio); +extern int ioctl_attach(int fd, char *ifname, struct siocsifcipatt *sio); +extern int ioctl_alloc(int fd, char *ifname, struct siocsifcipall *sio); +extern int ioctl_unalloc(int fd, char *ifname, struct siocsifcipall *sio); --- linux-2.4.21/drivers/addon/cipe4/module.c.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/module.c Fri Jul 25 15:12:33 2003 @@ -0,0 +1,89 @@ +/* + CIPE - encrypted IP over UDP tunneling + + module.c - kernel module interface stuff + + Copyright 1996 Olaf Titz + + 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. +*/ +/* $Id: module.c,v 1.5.2.1 2002/05/30 11:49:17 olaf Exp $ */ + +#include "cipe.h" +#include +#include + +/* We put this all here so that none of the other source files needs + to include , which could lead to collisions. */ + +#ifdef LINUX_21 +MODULE_AUTHOR("Olaf Titz "); +MODULE_DESCRIPTION("Encrypting IP-over-UDP tunnel"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +MODULE_SUPPORTED_DEVICE(DEVNAME); +MODULE_PARM(cipe_maxdev,"i"); +MODULE_PARM_DESC(cipe_maxdev,"Maximum device number supported"); +#ifdef DEBUG +MODULE_PARM(cipe_debug,"i"); +MODULE_PARM_DESC(cipe_debug,"Debugging level"); +#endif +#endif + +void cipe_use_module(void) +{ + MOD_INC_USE_COUNT; +} + +void cipe_unuse_module(void) +{ + MOD_DEC_USE_COUNT; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,0,30) +/* older kernel not always exported this */ + +int bad_user_access_length(void) +{ + panic("bad_user_access_length in " DEVNAME); +} + +#endif + +/* HACK: sanity check on SMP/non-SMP. + Is this really necessary? */ +int cipe_check_kernel(void) +{ + int s=0; + const char *p=system_utsname.version; + while (p[0] && p[1] && p[2]) { + if (p[0]=='S' && p[1]=='M' && p[2]=='P') { + s=1; + break; + } + ++p; + } + if ( +#ifdef __SMP__ + ! +#endif + s) { + printk(KERN_ERR + DEVNAME ": driver (" +#ifndef __SMP__ + "not " +#endif + "SMP) " + "mismatches kernel (" +#ifdef __SMP__ + "not " +#endif + "SMP)\n"); + return -EINVAL; + } + return 0; +} --- linux-2.4.21/drivers/addon/cipe4/options.h.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/options.h Fri Jul 25 15:12:33 2003 @@ -0,0 +1,29 @@ +/* File generated by genoptions.pl, do not edit */ + +#define Odevice 0 +#define Odebug 1 +#define Oipaddr 2 +#define Optpaddr 3 +#define Omask 4 +#define Obcast 5 +#define Omtu 6 +#define Ometric 7 +#define Octtl 8 +#define Ome 9 +#define Opeer 10 +#define Okey 11 +#define Onokey 12 +#define Osocks 13 +#define Otokxc 14 +#define Otokey 15 +#define Oipup 16 +#define Oipdown 17 +#define Oarg 18 +#define Omaxerr 19 +#define Otokxts 20 +#define Oping 21 +#define Otoping 22 +#define Odynip 23 +#define Ohwaddr 24 +#define Oifconfig 25 +#define Ochecksum 26 --- linux-2.4.21/drivers/addon/cipe4/output.c.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/output.c Fri Jul 25 15:12:33 2003 @@ -0,0 +1,621 @@ +/* + CIPE - encrypted IP over UDP tunneling + + output.c - the sending part of the CIPE device + + Copyright 1996 Olaf Titz + + 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. +*/ +/* $Id: output.c,v 1.40.2.2 2002/06/28 23:38:53 olaf Exp $ */ + +#include "cipe.h" + +#include +#include +#include +#include +#include +#include +#ifdef LINUX_24 +#include +#include +#endif + +#ifdef DEBUG + +#include "../lib/hexdump.c" + +void cipe_dump_packet(char *title, struct sk_buff *skb, int dumpskb) +{ + LOCK_PRINTK; + if (dumpskb) { + printk(KERN_DEBUG "SKB (%s):\n", skb->dev?skb->dev->name:""); + cipe_hexdump((unsigned char *)skb, sizeof(*skb)); + } + printk(KERN_DEBUG + "%s: packet len=" FLEN " dev=%s\n", + title, skb->len, skb->dev?skb->dev->name:""); + cipe_hexdump((unsigned char *)skb->data, skb->tail-skb->data); + UNLOCK_PRINTK; +} +#endif + +#ifdef LINUX_21 + +/* An adapted version of Linux 2.1 net/ipv4/ipip.c output routine. */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,37) +#define ip_ident(h,d) (h)->id=htons(ip_id_count++) +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) +#define ip_ident(h,d) ip_select_ident(h,d) +#else +#define ip_ident(h,d) ip_select_ident(h,d,NULL) +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,36) +/* this is not exactly the newer kernel's routine, it just does what we need */ +struct sk_buff *skb_copy_expand(struct sk_buff *skb, int max_headroom, + int max_tailroom, int gfp) +{ + struct sk_buff *n=alloc_skb(skb->len+max_headroom+max_tailroom, gfp); + if (n) { + skb_reserve(n, max_headroom); + skb_put(n,skb->len); + memcpy(n->data,skb->data,skb->len); + n->priority=skb->priority; + n->protocol=skb->protocol; + n->dev=skb->dev; + n->dst=dst_clone(skb->dst); + memcpy(n->cb, skb->cb, sizeof(skb->cb)); + n->used=skb->used; + n->is_clone=0; + atomic_set(&n->users, 1); + n->pkt_type=skb->pkt_type; + n->stamp=skb->stamp; + n->security=skb->security; +#ifdef CONFIG_IP_FIREWALL + n->fwmark = skb->fwmark; +#endif + } + return n; +} +#endif + +int cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev) +{ + struct cipe *tunnel = (struct cipe*)(dev->priv); + struct rtable *rt = NULL; /* Route to the other host */ + struct NET_DEVICE *tdev; /* Device to other host */ + struct iphdr *old_iph; + u8 tos = 0; + u16 df = 0; + u8 ttl; + + struct iphdr *iph; /* Our new IP header */ + struct udphdr *udph; + int max_headroom; /* The extra header space needed */ + int max_tailroom; + u32 dst = tunnel->peeraddr; + int mtu; + int length = skb->len; + + dprintk(DEB_OUT, (KERN_INFO "%s: cipe_xmit len=%d\n", dev->name, + length)); + if (tunnel->magic!=CIPE_MAGIC) { + printk(KERN_ERR DEVNAME + ": cipe_xmit called with wrong struct\n"); + return 0; + } +#ifdef DEBUG + if (cipe_debug&DEB_PKOU) + cipe_dump_packet("original", skb, 1); +#endif +#ifdef VER_ETH + /* A packet can contain anything. If sending from a bridge, + the header pointers are invalid. So compute our own. */ + old_iph = (skb->protocol==htons(ETH_P_IP)) + ? (struct iphdr*)(skb->data+ETH_HLEN) + : NULL; +#else + old_iph = skb->nh.iph; /* we get only proper IP packets */ +#endif + if (old_iph) { + int ilen = ntohs(old_iph->tot_len) +#ifdef VER_ETH + +ETH_HLEN +#endif + ; + if (length!=ilen) { + printk(KERN_ERR "%s: cipe_xmit packet length problem %d/%d\n", + dev->name, length, ilen); + goto tx_error_out; + } + tos = old_iph->tos; + df = old_iph->frag_off&__constant_htons(IP_DF); + ttl = tunnel->cttl ? tunnel->cttl : old_iph->ttl; + } else { + ttl = tunnel->cttl ? tunnel->cttl : 64; /* XX */ + } + + if (tunnel->recursion++) { + printk(KERN_ERR "%s: cipe_xmit reentrance\n", dev->name); + tunnel->stat.collisions++; + goto tx_error_out; + } +#ifndef VER_ETH + if (skb->protocol != __constant_htons(ETH_P_IP)) + goto tx_error_out; +#endif + +#if 0 + dprintk(DEB_OUT, (KERN_DEBUG "routing dst=%s src=%s tos=%x oif=%d\n", + cipe_ntoa(0, dst), cipe_ntoa(1, tunnel->myaddr), + RT_TOS(tos), tunnel->sock->bound_dev_if)); +#endif + if (ip_route_output(&rt, dst, tunnel->sock->rcv_saddr, RT_TOS(tos), + tunnel->sock->bound_dev_if)) { + dprintk(DEB_OUT, (KERN_NOTICE "%s: no route\n", dev->name)); + tunnel->stat.tx_carrier_errors++; + dst_link_failure(skb); + goto tx_error_out; + } + if (rt->rt_src!=tunnel->myaddr) { + printk(KERN_NOTICE "%s: changing my address: %s\n", dev->name, + cipe_ntoa(rt->rt_src)); + tunnel->myaddr=tunnel->sock->saddr=rt->rt_src; + } + + tdev = rt->u.dst.dev; + dprintk(DEB_OUT, (KERN_DEBUG "route dev=%s flags=%x type=%x\n", + tdev->name, rt->rt_flags, rt->rt_type)); + + if (tdev == dev) { + printk(KERN_ERR "%s: looped route\n", dev->name); + tunnel->stat.collisions++; + goto tx_error; + } + + mtu = rt->u.dst.pmtu - (cipehdrlen+cipefootlen); + if (tunnel->sockshost) + mtu -= sizeof(struct sockshdr); + + dprintk(DEB_OUT, (KERN_DEBUG "pmtu=%d dmtu=%d size=%d\n", + mtu, tdev->mtu, skb->len)); + + if (mtu < 68) { + printk(KERN_ERR "%s: MTU too small\n", dev->name); + tunnel->stat.collisions++; + goto tx_error; + } + if (skb->dst && mtu < skb->dst->pmtu) { + skb->dst->pmtu = mtu; + dprintk(DEB_OUT, (KERN_NOTICE "%s: adjusting PMTU\n", dev->name)); +#if 0 + /* TEST: is this OK? */ + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); + goto tx_error; +#endif + } + + if (old_iph && (old_iph->frag_off&__constant_htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) { + dprintk(DEB_OUT, (KERN_NOTICE "%s: fragmentation needed\n", dev->name)); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); + goto tx_error; + } + + max_headroom = ((tdev->hard_header_len+cipehdrlen+ + ((tunnel->sockshost) ? sizeof(struct sockshdr) : 0) + )+16)&(~15); + max_tailroom = (tunnel->flags&CIPF_HAVE_KEY) ? cipefootlen : 0; + { + struct sk_buff *n= skb_copy_expand(skb, max_headroom, + max_tailroom, GFP_ATOMIC); + if (!n) { + printk(KERN_INFO "%s: Out of memory, dropped packet\n", + dev->name); + goto tx_error; + } + if (skb->sk) + skb_set_owner_w(n, skb->sk); + dev_kfree_skb(skb); + skb = n; + } + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); + dst_release(skb->dst); + skb->dst = &rt->u.dst; + skb->protocol = htons(ETH_P_IP); + + if (tunnel->flags&CIPF_HAVE_KEY) { +#ifndef VER_SHORT + /* Add an IV */ + cipe_cryptpad_iv(skb_push(skb, blockSize)); + length+=blockSize; +#endif + if (!tunnel->flags&CIPF_MAY_STKEY && !tunnel->flags&CIPF_HAVE_SKEY) + /* Attempt to encrypt data using invalid static key */ + goto tx_error; + cipe_encrypt(tunnel, skb->data, &length, TW_DATA); + /* This is incorrect - the tail room gets first used and then + reserved. Doesn't matter in the current (2.0.29) implementation + of skb_put though. Alternative solution would ruin the nice + module separation - we don't need to know the real amount + of padding here. */ + if (length-skb->len > skb->end-skb->tail) { + printk(KERN_ERR "%s: tailroom problem %d %d %ld\n", + dev->name, length, skb->len, skb->end-skb->tail); + goto tx_error; + } + (void) skb_put(skb, length-skb->len); + } else if (!tunnel->flags&CIPF_MAY_CLEAR) { + goto tx_error; + } + + if (tunnel->sockshost) { + /* Install a SOCKS header */ + struct sockshdr *sh = (struct sockshdr *) + skb_push(skb, sizeof(struct sockshdr)); + memset(sh, 0, 4); + sh->atyp=1; + /* sockshost and socksport contain the real peer's address + and the configured/guessed peer is really the socks relayer! */ + sh->dstaddr=tunnel->sockshost; + sh->dstport=tunnel->socksport; + length+=sizeof(struct sockshdr); + } + + /* Install our new headers */ + udph = skb->h.uh = (struct udphdr *) skb_push(skb, sizeof(struct udphdr)); + skb->mac.raw = skb_push(skb, sizeof(struct iphdr)); + iph = skb->nh.iph = (struct iphdr *) skb->mac.raw; + + /* + * Push down and install the CIPE/UDP header. + */ + iph->version = 4; + iph->ihl = sizeof(struct iphdr)>>2; + iph->tos = tos; + iph->tot_len = htons(skb->len); + ip_ident(iph, &rt->u.dst); + iph->frag_off = df; + iph->ttl = ttl; + iph->protocol = IPPROTO_UDP; + iph->saddr = rt->rt_src; + iph->daddr = rt->rt_dst; + + ip_send_check(iph); + + udph->source = tunnel->myport; + udph->dest = tunnel->peerport; + udph->len = htons(length+sizeof(struct udphdr)); + /* Encrypted packets are checksummed already, so we can safely + ignore the UDP checksum. Provide a means to do it nonetheless */ + udph->check = 0; + if (tunnel->flags&CIPF_DO_CSUM) { + udph->check=csum_tcpudp_magic( + iph->saddr, iph->daddr, + length+sizeof(struct udphdr), IPPROTO_UDP, + csum_partial((char *)udph, length+sizeof(struct udphdr), 0)); + if (!udph->check) + udph->check=-1; + } + + tunnel->stat.tx_bytes += skb->len; + tunnel->stat.tx_packets++; + dprintk(DEB_OUT, (KERN_INFO + "%s: sending %d from %s:%d to %s:%d\n", + dev->name, skb->len, + cipe_ntoa(iph->saddr), ntohs(udph->source), + cipe_ntoa(iph->daddr), ntohs(udph->dest))); + if (tunnel->sockshost) + dprintk(DEB_OUT, (KERN_INFO "%s: via SOCKS to %s:%d\n", dev->name, + cipe_ntoa(tunnel->sockshost), + ntohs(tunnel->socksport))); +#if 0 + dprintk(DEB_OUT, (KERN_INFO "dst: (%d,%d) %s %d %d\n", + skb->dst->refcnt, skb->dst->use, + skb->dst->dev->name, skb->dst->pmtu, + skb->dst->error)); +#endif +#ifdef DEBUG + if (cipe_debug&DEB_PKOU) + cipe_dump_packet("sending", skb, 0); +#endif + nf_conntrack_null(skb); +#ifdef LINUX_24 + { + int err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, + rt->u.dst.dev, ip_send); + if (err==NET_XMIT_SUCCESS || err==NET_XMIT_CN) { + tunnel->stat.tx_bytes += skb->len; + tunnel->stat.tx_packets++; + } else { + tunnel->stat.tx_errors++; + tunnel->stat.tx_aborted_errors++; + } + } +#else + ip_send(skb); +#endif + tunnel->recursion--; + return 0; + + tx_error: + ip_rt_put(rt); + tx_error_out: + tunnel->stat.tx_errors++; + dev_kfree_skb(skb); + tunnel->recursion--; + return 0; +} + +#else /* LINUX_21 */ + +/* An adapted version of Linux 2.0 drivers/net/new_tunnel.c. */ + +#ifdef SO_BINDTODEVICE + #define iproute(t,o,d) ip_rt_route(t,o,d) +#else + #define iproute(t,o,d) ip_rt_route(t,o) +#endif + +#if LINUX_VERSION_CODE < 131102 /* < 2.0.30 */ + #include + #ifdef CONFIG_IP_FORWARD + #define ipforward(s,d,o,t) ip_forward(s,d,o,t) + #else + #error "Requires IP forwarding enabled in kernel" + #endif +#else /* >= 2.0.30 */ + #define ipforward(s,d,o,t) (sysctl_ip_forward ? ip_forward(s,d,o,t) : -1) +#endif + +int cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev) +{ + struct enet_statistics *stats; /* This device's statistics */ + struct rtable *rt; /* Route to the other host */ + struct NET_DEVICE *tdev; /* Device to other host */ + struct iphdr *iph; /* Our new IP header */ + struct udphdr *udph; + __u32 target; /* The other host's IP address */ + int max_headroom; /* The extra header space needed */ + int max_tailroom; + int tos, ttl, length; + DEVTOCIPE(dev,c,0); + + if (skb == NULL || dev == NULL) { + dprintk(DEB_OUT, (KERN_INFO "%s: nothing to do\n", dev->name)); + return 0; + } + + /* + * Make sure we are not busy (check lock variable) + */ + stats = &(c->stat); + if (dev->tbusy != 0) + { + printk(KERN_WARNING "%s: device timeout (really possible?)\n", + dev->name); + dev->tbusy=0; + stats->tx_errors++; + return(1); + } + +#ifdef DEBUG + if (cipe_debug&DEB_PKOU) + cipe_dump_packet("original", skb, 0); +#endif + /* + * First things first. Look up the destination address in the + * routing tables + */ + target = c->peeraddr; + if ((!target) || (!c->peerport) || (!c->myport)) { + /* unconfigured device */ + printk(KERN_INFO "%s: unconfigured\n", dev->name); + goto error; + } + if ((rt = iproute(target, 0, skb->sk?skb->sk->bound_device:NULL)) == NULL) + { + /* No route to host */ + printk(KERN_INFO "%s: target unreachable\n", dev->name); + goto error; + } + dprintk(DEB_OUT, (KERN_INFO + "%s: routing to %08lX from %08lX via %08lX dev %s\n", + dev->name, ntohl(rt->rt_dst), ntohl(rt->rt_src), + ntohl(rt->rt_gateway), rt->rt_dev->name)); + + tdev = rt->rt_dev; + ip_rt_put(rt); + + if (tdev == dev) + { + /* Tunnel to ourselves? -- I don't think so. */ + printk ( KERN_INFO "%s: Packet targetted at myself!\n" , dev->name); + goto error; + } + + /* + * Okay, now see if we can stuff it in the buffer as-is. We can not. + */ + max_headroom = (((tdev->hard_header_len+15)&~15)+cipehdrlen+ + ((c->sockshost) ? sizeof(struct sockshdr) : 0)); + max_tailroom = (c->flags&CIPF_HAVE_KEY) ? cipefootlen : 0; + { + struct sk_buff *new_skb; + + if ( !(new_skb = + dev_alloc_skb(skb->len+max_headroom+max_tailroom)) ) + { + printk(KERN_INFO "%s: Out of memory, dropped packet\n", + dev->name); + dev->tbusy = 0; + stats->tx_dropped++; + dev_kfree_skb(skb, FREE_WRITE); + return 0; + } + new_skb->free = 1; + + /* + * Reserve space for our header and the lower device header + */ + skb_reserve(new_skb, max_headroom); + + /* + * Copy the old packet to the new buffer. + * Note that new_skb->h.iph will be our (tunnel driver's) header + * and new_skb->ip_hdr is the IP header of the old packet. + */ + new_skb->ip_hdr = (struct iphdr *) skb_put(new_skb, skb->len); + new_skb->mac.raw = new_skb->data; + new_skb->dev = skb->dev; + memcpy(new_skb->ip_hdr, skb->data, skb->len); + memset(new_skb->proto_priv, 0, sizeof(skb->proto_priv)); + + /* Free the old packet, we no longer need it */ + dev_kfree_skb(skb, FREE_WRITE); + skb = new_skb; + } +#ifdef VER_ETH + if (skb->mac.ethernet->h_proto==htons(ETH_P_IP)) { +#endif + tos = skb->ip_hdr->tos; + ttl = skb->ip_hdr->ttl; +#ifdef VER_ETH + } else { + tos = 0; + ttl = 64; + } +#endif + length = skb->len; + if (c->flags&CIPF_HAVE_KEY) { +#ifndef VER_SHORT + /* Add an IV */ + cipe_cryptpad(skb_push(skb, blockSize)); + length+=blockSize; +#endif + if (!c->flags&CIPF_MAY_STKEY && !c->flags&CIPF_HAVE_SKEY) + /* Attempt to encrypt data using invalid static key */ + goto error; + cipe_encrypt(c, skb->data, &length, TW_DATA); + /* This is incorrect - the tail room gets first used and then + reserved. Doesn't matter in the current (2.0.29) implementation + of skb_put though. Alternative solution would ruin the nice + module separation - we don't need to know the real amount + of padding here. */ + (void) skb_put(skb, length-skb->len); + } else if (!c->flags&CIPF_MAY_CLEAR) { + goto error; + } + + if (c->sockshost) { + /* Install a SOCKS header */ + struct sockshdr *sh = (struct sockshdr *) + skb_push(skb, sizeof(struct sockshdr)); + memset(sh, 0, 4); + sh->atyp=1; + /* sockshost and socksport contain the real peer's address + and the configured/guessed peer is really the socks relayer! */ + sh->dstaddr=c->sockshost; + sh->dstport=c->socksport; + length+=sizeof(struct sockshdr); + } + + /* Install our new headers */ + udph = (struct udphdr *) skb_push(skb, sizeof(struct udphdr)); + skb->h.iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr)); + + /* + * Push down and install the CIPE/UDP header. + */ + + iph = skb->h.iph; + iph->version = 4; + iph->tos = tos; + + /* In new_tunnel.c, we use the original packet's TTL here. + Setting a new TTL behaves better to the user, and RFC2003 + recommends it too. But this doesn't fully protect against + routing loops. So make it configurable via an argument: + "cttl" gives the TTL value; if 0 use the packet's + value. Default should be 64, as with the other protocols + (ip_statistics.IpDefaultTTL, but this variable is not + available for modules). */ + + iph->ttl = c->cttl ? c->cttl : ttl; + + iph->frag_off = 0; + iph->daddr = target; + iph->saddr = c->myaddr; /* tdev->pa_addr; */ + iph->protocol = IPPROTO_UDP; + iph->ihl = 5; + iph->tot_len = htons(skb->len); + iph->id = htons(ip_id_count++); /* Race condition here? */ + ip_send_check(iph); + + udph->source = c->myport; + udph->dest = c->peerport; + udph->len = htons(length+sizeof(struct udphdr)); + /* Encrypted packets are checksummed already, so we can safely + ignore the UDP checksum. Provide a means to do it nonetheless */ + udph->check = 0; + if (c->flags&CIPF_DO_CSUM) { + udph->check=csum_tcpudp_magic( + iph->saddr, iph->daddr, + length+sizeof(struct udphdr), IPPROTO_UDP, + csum_partial((char *)udph, length+sizeof(struct udphdr), 0)); + if (!udph->check) + udph->check=-1; + } + + skb->ip_hdr = skb->h.iph; + skb->protocol = htons(ETH_P_IP); + + /* + * Send the packet on its way! + * Note that dev_queue_xmit() will eventually free the skb. + * If ip_forward() made a copy, it will return 1 so we can free. + */ + + dprintk(DEB_OUT, (KERN_INFO "%s: send to %s via %s\n", + dev->name, cipe_ntoa(target), tdev->name)); + +#ifdef DEBUG + if (cipe_debug&DEB_PKOU) + cipe_dump_packet("sending", skb, 0); +#endif + switch (ipforward(skb, dev, IPFWD_NOTTLDEC, target)) { + case -1: + printk(KERN_INFO "%s: forwarding failed\n", dev->name); + /* fall thru */ + case 1: + dev_kfree_skb(skb, FREE_WRITE); + /* Does it really need dev_ here? I think so. */ + break; + default: + /* nothing to do */ + } + + /* + * Clean up: We're done with the route and the packet + */ + + /* Record statistics and return */ + stats->tx_packets++; + dev->tbusy=0; + return 0; + + error: + stats->tx_errors++; + dev_kfree_skb(skb, FREE_WRITE); + dev->tbusy=0; + return 0; +} + +#endif /* LINUX_21 */ --- linux-2.4.21/drivers/addon/cipe4/sock.c.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/sock.c Fri Jul 25 15:12:33 2003 @@ -0,0 +1,731 @@ +/* + CIPE - encrypted IP over UDP tunneling + + sock.c - socket/input interface + + Copyright 1996 Olaf Titz + + 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. +*/ +/* $Id: sock.c,v 1.33.2.3 2002/06/28 23:38:53 olaf Exp $ */ + +#include "cipe.h" + +#include +#include +#include +#include +#include +#ifdef LINUX_21 +#include +#else +typedef unsigned short mm_segment_t; +#endif + +#ifdef LINUX_21 +#define kfreeskb(s,t) kfree_skb(s) +#define saddr(skb) ((skb)->nh.iph->saddr) +#define daddr(skb) ((skb)->nh.iph->daddr) +#else +#define kfreeskb(s,t) kfree_skb(s,t) +#define saddr(skb) ((skb)->saddr) +#define daddr(skb) ((skb)->daddr) +#endif + +/* Rewire generic socket operations to our device-specific ones. + We have new routines for close, sendmsg, recvmsg. */ + +#ifndef LINUX_21 +#define user_data protinfo.af_packet.bound_dev +#endif + +/* init struct cipe *c based on struct sock *sk */ +#define SOCKTOC(nam,sk,c,r) \ + struct cipe *c=(struct cipe *)sk->user_data; \ + if ((!c) || (c->magic!=CIPE_MAGIC)) { \ + printk(KERN_ERR "Ouch: SOCKTOC " nam "\n"); return r; } \ + else { \ + dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", c->dev->name)); } + + +/* Close the socket */ +void cipe_sock_close(struct sock *sock, timeout_t timeout) +{ + SOCKTOC("sock_close",sock,c,); + c->sock=NULL; + + /* Put back the old protocol block and let it do the close */ + sock->prot=c->udp_prot; + sock->prot->close(sock, timeout); + if (c->dev->flags&IFF_UP) { + rtnl_LOCK(); + dev_close(c->dev); + rtnl_UNLOCK(); + } else { + cipe_close(c); + } +} + +/* Anything we send to this socket is in fact a key exchange block. + Encode and encrypt it accordingly. +*/ +int cipe_sendmsg(struct sock *sock, struct msghdr *msg, int len +#ifndef LINUX_21 + , int nonblock, int flags +#endif + ) +{ + struct msghdr mymsg; + struct iovec myio[2]; + struct sockaddr_in sa; + struct sockshdr sh; + int e, n=0; + unsigned char buf[KEYXCHGBLKMAX+blockSize]; + SOCKTOC("cipe_sendmsg",sock,c,-ENOSYS); + + if (len>KEYXCHGBLKMAX) + return -EMSGSIZE; +#ifdef VER_SHORT + if (msg->msg_flags&MSG_OOB) + return -EINVAL; +#endif + cipe_prnpad(buf, sizeof(buf)); +#ifdef VER_SHORT + memcpy_fromiovec(buf, msg->msg_iov, len); +#else + memcpy_fromiovec(buf+blockSize, msg->msg_iov, len); + len+=blockSize; +#endif + if (!(msg->msg_flags&MSG_OOB)) { + if (buf[0 +#ifndef VER_SHORT + +blockSize +#endif + ]>=CT_DUMMY) { + if (!c->flags&CIPF_HAVE_KEY) + return -EINVAL; + buf[KEYXCHGTSPOS-1]='\0'; + } else { + if (lenmsg_flags&MSG_OOB) { + memset(buf, 0, blockSize); + } else { + len=KEYXCHGBLKMIN+buf[sizeof(buf)-1]; /* random */ + cipe_encrypt(c, buf, &len, TW_NEWKEY); + } + + sa.sin_family=AF_INET; + sa.sin_addr.s_addr=c->peeraddr; + sa.sin_port=c->peerport; + + if (c->sockshost) { + /* Prepend a socks header. */ + memset(&sh, 0, sizeof(sh)); + sh.atyp=1; + sh.dstaddr=c->sockshost; + sh.dstport=c->socksport; + myio[n].iov_base=&sh; + myio[n].iov_len=sizeof(sh); + ++n; + } + myio[n].iov_base=&buf; + myio[n].iov_len=len; + /* mymsg=*msg; */ + mymsg.msg_name=&sa; + mymsg.msg_namelen=sizeof(sa); + mymsg.msg_iov=myio; + mymsg.msg_iovlen=n+1; + /* just to be sure */ + mymsg.msg_control=NULL; + mymsg.msg_controllen=0; + mymsg.msg_flags=0; + + /* Call the real thing. Pretend this is user space segment. */ + { + mm_segment_t fs=get_fs(); + set_fs(get_ds()); + if (c->sockshost) + len+=sizeof(struct sockshdr); + dprintk(DEB_KXC, (KERN_INFO "%s: real sendmsg len %d text=%04x...\n", + c->dev->name, len, + ntohs(*((unsigned short *)(myio[n].iov_base))))); + e=c->udp_prot->sendmsg(sock, &mymsg, len +#ifndef LINUX_21 + , nonblock, flags +#endif + ); + set_fs(fs); + } + return e; +} + +/* Check if we have a new peer */ +static void checkpeer(struct cipe *c, __u32 saddr, __u16 sport) +{ + if (c->sockshost) { + if (c->sockshost==saddr && c->socksport==sport) + return; + /* sockshost and socksport contain the real peer's address + and the configured/guessed peer is really the socks relayer! */ + c->sockshost=saddr; + c->socksport=sport; + } else { + if (c->peeraddr==saddr && c->peerport==sport) + return; + c->peeraddr=saddr; + c->peerport=sport; + } + printk(KERN_NOTICE "%s: new peer %s:%d\n", + c->dev->name, cipe_ntoa(saddr), ntohs(sport)); +} + +/* Decrypt a received packet. Requeue it or return kxc block. */ +/* On entry the packet starts with the original UDP header, + ip_hdr and h.uh are set to the IP and UDP headers. */ +struct sk_buff *cipe_decrypt_skb(struct cipe *c, struct sock *sk, + struct sk_buff *skb, + int *msgflag) +{ + struct sk_buff *n=NULL; + int length; + __u32 rsaddr; + __u16 rsport; + +#ifdef DEBUG + if (cipe_debug&DEB_PKIN) + cipe_dump_packet("received", skb, 1); +#endif + length=ntohs(skb->h.uh->len)-sizeof(struct udphdr); +#if 0 /* UDP should check this */ + if (length!=skb->len-sizeof(struct udphdr)) { + dprintk(DEB_INP, (KERN_INFO "%s: bogus UDP length (%d/%d)\n", + c->dev->name, length, + skb->len-sizeof(struct udphdr))); + goto framerr; + } +#endif + if (length<9+(c->sockshost?sizeof(struct sockshdr):0)) { + /* XX hardcoded IV size */ + printk(KERN_INFO "%s: got short packet from %s\n", c->dev->name, + cipe_ntoa(saddr(skb))); + goto framerr; + } + + n=alloc_skb(skb->len, GFP_KERNEL); + if (!n) { + printk(KERN_WARNING "%s: cipe_decrypt_skb: out of memory\n", + c->dev->name); + ++c->stat.rx_dropped; + return NULL; + } +#if 0 /*def LINUX_21*/ + if (skb->sk) + skb_set_owner_r(n, skb->sk); +#endif +#ifndef LINUX_21 + n->free=1; +#endif + n->dev=c->dev; + + /* Copy the datagram into new buffer, skip IP header */ + /* We must copy here because raw sockets get only a clone of the + skbuff, so they would receive the plaintext */ + dprintk(DEB_INP, (KERN_INFO DEVNAME + ": sa=%s da=%s us=%d ud=%d ul=%d\n", + cipe_ntoa(saddr(skb)), cipe_ntoa(daddr(skb)), + ntohs(skb->h.uh->source), ntohs(skb->h.uh->dest), + ntohs(skb->h.uh->len))); + + /* why did this get swapped?? */ +#ifdef LINUX_21 + rsaddr=saddr(skb); +#else + rsaddr=daddr(skb); +#endif + rsport=skb->h.uh->source; + skb_put(n,skb->len); + memcpy(n->data, skb->h.raw, skb->len); + n->h.uh=(struct udphdr *)n->data; + + if (c->sockshost) { + /* Pull out the SOCKS header and correct the peer's address. */ + struct sockshdr *sh; + sh=(struct sockshdr *)skb_pull(n, sizeof(struct udphdr)); + dprintk(DEB_INP, (KERN_INFO "socks: fr=%d at=%d da=%s dp=%d\n", + sh->frag, sh->atyp, + cipe_ntoa(sh->dstaddr), ntohs(sh->dstport))); + if (sh->frag || (sh->atyp!=1)) + goto error; + /* Pull out UDP header */ +#ifdef LINUX_21 + n->nh.iph=(struct iphdr *)skb_pull(n, sizeof(struct sockshdr)); +#else + n->ip_hdr=(struct iphdr *)skb_pull(n, sizeof(struct sockshdr)); +#endif + /***saddr(n)=sh->dstaddr;*/ + rsaddr=sh->dstaddr; + rsport=n->h.uh->source=sh->dstport; + length-=sizeof(struct sockshdr); + } else { + /* Pull out UDP header */ +#ifdef LINUX_21 + n->nh.iph=(struct iphdr *) skb_pull(n, sizeof(struct udphdr)); +#else + n->ip_hdr=(struct iphdr *) skb_pull(n, sizeof(struct udphdr)); +#endif + /***saddr(n)=rsaddr;*/ + n->h.uh->source=rsport; + } + +#ifndef VER_SHORT + if (!(*((__u32 *)n->data) & htonl(0x7FFFFFFF))) { + dprintk(DEB_INP, (KERN_INFO "got unencrypted packet (iv=0) len=%d\n", + length)); + skb_pull(n, blockSize); + /* XX not sure about TW_CTRL handling... */ + switch (*n->data) { + /* Restrict what can be received unencrypted. */ + case CT_DUMMY: case CT_DEBUG: case CT_CONFREQ: case CT_CONF: + break; + default: + printk(KERN_WARNING + "%s: got disallowed unencrypted control %02x\n", + c->dev->name, *n->data); + goto error; + } +#ifdef LINUX_21 + get_fast_time(&n->stamp); +#endif + /* No checkpeer() here because not authenticated! */ + n->h.uh->check=0; + return n; + } +#endif + if (c->flags&CIPF_HAVE_KEY) { + if (length%blockSize) { + printk(KERN_INFO "%s: got bogus length=%d\n", c->dev->name, + length); + goto error; + } + switch (cipe_decrypt(c, n->data, &length)) { + case TW_DATA: + if (!c->flags&CIPF_MAY_STKEY && !c->flags&CIPF_HAVE_RKEY) { + printk(KERN_ERR "%s: got data using invalid static key\n", + c->dev->name); + goto error; + } + break; + case TW_CTRL: + /* return it as a control block - out of band datagram */ + *msgflag|=MSG_OOB; + /* fall thru */ + case TW_NEWKEY: + /* return it as key exchange block - proper UDP datagram */ + dprintk(DEB_INP, (KERN_DEBUG "TW_NEWKEY data=%p len=" FLEN + " length=%d\n", n->data, n->len, length)); +#ifdef LINUX_21 + get_fast_time(&n->stamp); +#endif + skb_trim(n, length); + checkpeer(c, rsaddr, rsport); +#if 0 + n->saddr=c->myaddr; + n->daddr=c->peeraddr; +#endif + n->h.uh->check=0; + return n; + default: + /* Bogus packet etc. */ + ++c->stat.rx_crc_errors; + goto error; + } + } else if (!c->flags&CIPF_MAY_CLEAR) { + goto error; + } + + dprintk(DEB_INP, (KERN_DEBUG "TW_DATA data=%p len=" FLEN "length=%d\n", + n->data, n->len, length)); + skb_trim(n, length); + checkpeer(c, rsaddr, rsport); + /* adjust pointers */ +#ifdef VER_ETH + n->protocol = eth_type_trans(n, c->dev); + /* n->pkt_type = PACKET_HOST; */ +#else + n->mac.raw=n->data; /* no hw header */ + n->protocol = htons(ETH_P_IP); + n->pkt_type = PACKET_HOST; +#endif +#ifdef LINUX_21 + n->nh.raw=n->data; + memset(&(IPCB(n)->opt), 0, sizeof(IPCB(n)->opt)); +#else + n->h.iph=(struct iphdr *)n->data; + memset(n->proto_priv, 0, sizeof(struct options)); +#endif + if (lengthsockshost?sizeof(struct sockshdr):0)) { + printk(KERN_INFO "%s: got short packet from %s\n", c->dev->name, + cipe_ntoa(saddr(skb))); + goto framerr; + } + + n->ip_summed = 0; + /* this prints nonsense for non-IP packets. Ignore that. */ + dprintk(DEB_INP, (KERN_INFO "%s: real src %s dst %s len %d\n", + n->dev->name, cipe_ntoa(saddr(n)), + cipe_ntoa(daddr(n)), length)); + +#ifdef DEBUG + if (cipe_debug&DEB_PKIN) + cipe_dump_packet("decrypted", n, 1); +#ifdef LINUX_23 + dprintk(DEB_INP, (KERN_DEBUG "%s state=%ld refcnt=%d\n", n->dev->name, n->dev->state, + atomic_read(&n->dev->refcnt))); +#endif +#endif + + /* requeue */ + netif_rx(n); +#ifdef LINUX_21 + c->stat.rx_bytes+=skb->len; /* count carrier-level bytes */ +#endif + c->stat.rx_packets++; + return NULL; + + framerr: + ++c->stat.rx_frame_errors; /* slightly abuse this */ + error: + ++c->stat.rx_errors; + if (n) + kfreeskb(n, FREE_READ); + return NULL; +} + +/* Receive message. If encrypted, put it through the mill. + If decrypted, return it as key exchange block. + This is mostly from net/ipv4/udp.c, but cipe_decrypt_skb pulls the + UDP header. +*/ + +int cipe_recvmsg(struct sock *sk, struct msghdr *msg, int len, + int noblock, int flags,int *addr_len) +{ + int copied; + struct sk_buff *skb, *skn; + int er=0; + struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name; + SOCKTOC("cipe_recvmsg",sk,c,-ENOSYS); + + /* + * Check any passed addresses + */ + + if (addr_len) + *addr_len=sizeof(*sin); + + /* + * From here the generic datagram does a lot of the work. Come + * the finished NET3, it will do _ALL_ the work! + */ + + do { + /* CIPE: look if the packet is encrypted, repeat until + a decrypted one is found */ + skn=NULL; + skb=skb_recv_datagram(sk,flags,noblock,&er); + if(skb==NULL) { + dprintk(DEB_KXC, (KERN_INFO "%s: skb_recv_datagram: %d\n", + c->dev->name, er)); + return er; + } + + if (!skb->h.uh->source) { + /* Synthetic KXC packets are marked by source port 0. + Correct this - we know the truth from our structure. + Perhaps it would be better to not correct it so the + user level daemon can spot the difference? */ + skb->h.uh->source=c->peerport; + skb_pull(skb, sizeof(struct udphdr)); + break; + } + skn=cipe_decrypt_skb(c, sk, skb, &(msg->msg_flags)); + skb_free_datagram(sk, skb); + skb=skn; + } while (skb==NULL); + + dprintk(DEB_INP, (KERN_INFO "%s: returning " FLEN " flags %04x\n", + c->dev->name, skb->len, msg->msg_flags)); + copied = skb->len; + if (copied > len) + { + copied = len; +#ifdef LINUX_21 + msg->msg_flags |= MSG_TRUNC; +#endif + } + if (copied<=0) { + printk(KERN_ERR "cipe_recvmsg: bogus length %d\n", copied); + goto out_free; + } + + /* + * FIXME : should use udp header size info value + */ +#ifdef LINUX_21 +#if 0 + er = skb_copy_datagram_iovec(skb, skb->data-skb-h.raw, + msg->msg_iov, copied); +#else + er = memcpy_toiovec(msg->msg_iov, skb->data, copied); +#endif + if (er<0) + goto out_free; +#else +#if 0 + skb_copy_datagram_iovec(skb,of,msg->msg_iov,copied); +#else + memcpy_toiovec(msg->msg_iov, skb->data, copied); +#endif +#endif + sk->stamp=skb->stamp; + + /* Copy the address. */ + if (sin +#ifdef LINUX_21 + && skb->nh.iph /* Fake KXC has no address */ +#endif + ) { + sin->sin_family = AF_INET; + sin->sin_port = skb->h.uh->source; + sin->sin_addr.s_addr = daddr(skb); + } + er=copied; + + out_free: + if (skb==skn) + /* the buffer was a copy made by decryption */ + kfreeskb(skb, FREE_READ); + else + skb_free_datagram(sk, skb); + + return(er); +} + +#ifdef LINUX_21 + +#include + +int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm) +{ + struct file *file; + struct inode *inode; + struct socket *sock; + struct sock *sk; +#if 0 + struct in_device *indev; +#endif + struct cipe *c0; + DEVTOCIPE(dev,c,-ENODEV); + + if (c->sock) + return -EBUSY; + if (!(file=fget(parm->fd))) + return(-EBADF); + inode = file->f_dentry->d_inode; + if (!inode || !inode->i_sock || !(sock=&inode->u.socket_i)) { + fput(file); + return(-ENOTSOCK); + } + if (sock->file != file) { + printk(KERN_ERR DEVNAME ": socki_lookup: socket file changed!\n"); + sock->file = file; + } + + fput(file); + if (sock->type!=SOCK_DGRAM) + return(-ESOCKTNOSUPPORT); + if (sock->ops->family!=AF_INET) + return(-EAFNOSUPPORT); + + sk=sock->sk; + if (sk->state!=TCP_ESTABLISHED) + return(-ENOTCONN); + if (((c0=(struct cipe *)sk->user_data)) && + (c0->magic==CIPE_MAGIC)) + return(-EBUSY); /* socket is already attached */ + + cipe_use_module(); + c->owner=current->pid; + c->sock=sk; + c->peeraddr=sk->daddr; + c->peerport=sk->dport; + c->myaddr=sk->saddr; + if (c->flags&CIPF_MAY_DYNIP) + sk->rcv_saddr=0; + c->myport=htons(sk->num); + /* Disconnect socket, we might receive from somewhere else */ + sk->daddr=0; + sk->dport=0; + + /* Fill an otherwise unused field in the sock struct with this info. + This field is conveniently named and the kernel uses it only for RPC. */ + sk->user_data=c; + sk->no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1; + + /* Set up new socket operations */ + c->udp_prot=sk->prot; + c->cipe_proto=*sk->prot; + c->cipe_proto.close=cipe_sock_close; + c->cipe_proto.sendmsg=cipe_sendmsg; + c->cipe_proto.recvmsg=cipe_recvmsg; + sk->prot=&c->cipe_proto; + +#if 0 + /* (Try to) Set our dummy hardware address from the IP address. */ + /* This does not work, because the IP address is set + _after_ the attach... */ + if ((indev=dev->ip_ptr)) { + struct in_ifaddr **ifap = NULL; + struct in_ifaddr *ifa = NULL; + for (ifap=&indev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) + if (strcmp(dev->name, ifa->ifa_label) == 0) + break; + if (ifa) { + char *x=(char *)&ifa->ifa_local; + dev->dev_addr[3]=x[1]|0x80; + dev->dev_addr[4]=x[2]; + dev->dev_addr[5]=x[3]; + } + } +#endif + + return(0); +} + + +#else /* LINUX_21 */ + +#define sreturn(x) {sti(); return((x));} + +int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm) +{ + struct file *file; + struct inode *inode; + struct socket *sock; + struct sock *sk; + int fd=parm->fd; + struct cipe *c0; + DEVTOCIPE(dev,c,-ENODEV); + cli(); + if (c->sock) + sreturn(-EBUSY); + + /* Find the socket (from net/socket.c) */ + if (fd < 0 || fd >= NR_OPEN || !(file = current->files->fd[fd])) + sreturn(-EBADF); + inode = file->f_inode; + if (!inode || !inode->i_sock) + sreturn(-ENOTSOCK); + sock=&inode->u.socket_i; + if (sock->type!=SOCK_DGRAM) + sreturn(-ESOCKTNOSUPPORT); + if (sock->ops->family!=AF_INET) + sreturn(-EAFNOSUPPORT); + sk=(struct sock *)sock->data; + if (sk->state!=TCP_ESTABLISHED) + sreturn(-ENOTCONN); + if (((c0=(struct cipe *)sk->protinfo.af_packet.bound_dev)) && + (c0->magic==CIPE_MAGIC)) + sreturn(-EBUSY); /* socket is already attached */ + + cipe_use_module(); + c->owner=current->pid; + c->sock=sk; + c->peeraddr=sk->daddr; + c->peerport=sk->dummy_th.dest; + c->myaddr=sk->saddr; + if (c->flags&CIPF_MAY_DYNIP) + sk->rcv_saddr=0; + c->myport=sk->dummy_th.source; + /* Disconnect socket, we might receive from somewhere else */ + sk->daddr=0; + sk->dummy_th.dest=0; + + /* Set up new socket operations */ + c->udp_prot=sk->prot; + c->cipe_proto=*sk->prot; + c->cipe_proto.close=cipe_sock_close; + c->cipe_proto.sendmsg=cipe_sendmsg; + c->cipe_proto.recvmsg=cipe_recvmsg; + sk->prot=&c->cipe_proto; + + /* Fill an otherwise unused field in the sock struct with this info. + Actually, this is very similar to a packet socket! + The ugly cast saves us one deref in the actual ops */ + sk->protinfo.af_packet.bound_dev=(struct NET_DEVICE *)c; + sk->no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1; + + sti(); + return 0; +} + +#endif + + +/* Build and enqueue a fake UDP packet to receive. + Note that these are neither encrypted nor SOCKSed. +*/ +void cipe_fakenkey(struct cipe *c, char typ) +{ + int len=sizeof(struct udphdr)+KEYXCHGBLKMIN; + struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC); + + if (!skb) { + printk(KERN_WARNING "%s: cipe_fakenkey: out of memory\n", + c->dev->name); + return; /* not much we can do */ + } + + dprintk(DEB_KXC, (KERN_INFO "%s: fake kxc block typ=%d\n", + c->dev->name, typ)); + + skb->sk=NULL; + skb->dev=c->dev; + + skb->h.uh=(struct udphdr *)skb->data; + skb->len=len; +#ifdef LINUX_21 + skb->nh.iph=NULL; +#else + saddr(skb)=c->myaddr; + daddr(skb)=c->peeraddr; + skb->free=1; /* Discard after use */ + skb->ip_hdr=NULL; +#endif + skb->h.uh->source=0; /* mark as KXC packet */ + skb->h.uh->dest=c->myport; + len-=sizeof(struct udphdr); + skb->h.uh->len=htons(len); + skb->h.uh->check=0; + skb->mac.raw=skb->data; /* no hardware header */ + + /* All those contortions for just one byte of payload data. + Since we generate only NK_RREQ and NK_REQ it's effectively + one _bit_... */ + skb->data[sizeof(struct udphdr)]=typ; + (*(__u32 *)(skb->data+sizeof(struct udphdr)+KEYXCHGTSPOS))= + htonl(CURRENT_TIME); /* even need timestamp */ + + if (sock_queue_rcv_skb(c->sock, skb)<0) { + printk(KERN_WARNING "%s: cipe_fakenkey: enqueuing failed\n", + c->dev->name); + kfreeskb(skb, FREE_WRITE); + } +} --- linux-2.4.21/drivers/addon/cipe4/version.h.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/version.h Fri Jul 25 15:12:33 2003 @@ -0,0 +1,5 @@ +#define VERSION "1.5.4" +#define ProtocolVersion 3 +#define Crypto_IDEA 1 +#undef Crypto_Blowfish +#undef NO_DYNDEV --- linux-2.4.21/drivers/addon/cipe4/bf.c.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/bf.c Fri Jul 25 15:12:33 2003 @@ -0,0 +1,552 @@ +/* + Bruce Schneier's Blowfish. + Author: Olaf Titz + + This code is in the public domain. + + $Id: bf.c,v 1.4 2000/10/26 10:11:08 olaf Exp $ +*/ + +#include "bf.h" + +#ifdef __KERNEL__ +#include +#include +#else +#include +#endif + +#ifndef ASM_BF_Crypt + +/* The generic big/little endian routines use the following imported + from under Linux: + __u32 __be32_to_cpup(__u32 *p); + __u32 __cpu_to_be32(__u32 x); + __u32 __le32_to_cpup(__u32 *p); + __u32 __cpu_to_le32(__u32 x); + These are macros. We provide replacements if necessary (non-Linux). + XXX the pointer types are wrong, but else a cast would be necessary. +*/ + +#ifdef __GNUC__ +#define INLINE static inline +#else +#define INLINE static +#endif + +#ifndef __be32_to_cpup +INLINE __u32 __be32_to_cpup(unsigned char *p) +{ + return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]; +} +#endif + +#ifndef __cpu_to_be32 +INLINE __u32 __cpu_to_be32(__u32 x) +{ + register unsigned char *p=(unsigned char *)&x; + return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]; +} +#endif + +#ifndef __le32_to_cpup +INLINE __u32 __le32_to_cpup(unsigned char *p) +{ + return (p[3]<<24)+(p[2]<<16)+(p[1]<<8)+p[0]; +} +#endif + +#ifndef __cpu_to_le32 +INLINE __u32 __cpu_to_le32(__u32 x) +{ + register unsigned char *p=(unsigned char *)&x; + return (p[3]<<24)+(p[2]<<16)+(p[1]<<8)+p[0]; +} +#endif + +/* Macros to implement the round function. */ + +/* access the P and S boxes in key array */ +#define P(n) (key[(n)]) +#define S0(n) (key[(n)+18]) +#define S1(n) (key[(n)+274]) +#define S2(n) (key[(n)+530]) +#define S3(n) (key[(n)+786]) +/* access byte in word */ +#define B0(x) (((x)>>24)&255) +#define B1(x) (((x)>>16)&255) +#define B2(x) (((x)>>8)&255) +#define B3(x) (((x))&255) +/* one raw round sans swap. p is running ptr into P box array */ +#define F(x) (((S0(B0(x))+S1(B1(x)))^S2(B2(x)))+S3(B3(x))) +#define RoundP(a,b) (a)^=(*p++)^F(b) +#define RoundN(a,b) (a)^=(*p--)^F(b) + +/* 16 rounds with running pointer and word swapping */ +#define RoundsP \ + RoundP(r, l); RoundP(l, r); \ + RoundP(r, l); RoundP(l, r); \ + RoundP(r, l); RoundP(l, r); \ + RoundP(r, l); RoundP(l, r); \ + RoundP(r, l); RoundP(l, r); \ + RoundP(r, l); RoundP(l, r); \ + RoundP(r, l); RoundP(l, r); \ + RoundP(r, l); RoundP(l, r) + +#define RoundsN \ + RoundN(r, l); RoundN(l, r); \ + RoundN(r, l); RoundN(l, r); \ + RoundN(r, l); RoundN(l, r); \ + RoundN(r, l); RoundN(l, r); \ + RoundN(r, l); RoundN(l, r); \ + RoundN(r, l); RoundN(l, r); \ + RoundN(r, l); RoundN(l, r); \ + RoundN(r, l); RoundN(l, r) + +/* Native byte order routines */ + +void _N_Blowfish_Encrypt(void *dataIn, void *dataOut, + const Blowfish_Key key) +{ + register const __u32 *p=(const __u32 *)key; + register unsigned long + l=((__u32 *)dataIn)[0]^(*p++), + r=((__u32 *)dataIn)[1]; + RoundsP; + ((__u32 *)dataOut)[0]=r^(*p); + ((__u32 *)dataOut)[1]=l; +} + +void _N_Blowfish_Decrypt(void *dataIn, void *dataOut, + const Blowfish_Key key) +{ + register const __u32 *p=((const __u32 *)key)+17; + register unsigned long + l=((__u32 *)dataIn)[0]^(*p--), + r=((__u32 *)dataIn)[1]; + RoundsN; + ((__u32 *)dataOut)[0]=r^(*p); + ((__u32 *)dataOut)[1]=l; +} + +/* Big-endian routines (i.e. real Blowfish) */ + +#ifndef BF_DONTNEED_BE +#ifndef BF_NATIVE_BE +void B_Blowfish_Encrypt(void *dataIn, void *dataOut, + const Blowfish_Key key) +{ + register const __u32 *p=(const __u32 *)key; + register unsigned long + l=__be32_to_cpup(dataIn)^(*p++), + r=__be32_to_cpup(dataIn+4); + RoundsP; + ((__u32 *)dataOut)[0]=__cpu_to_be32(r^(*p)); + ((__u32 *)dataOut)[1]=__cpu_to_be32(l); +} + +void B_Blowfish_Decrypt(void *dataIn, void *dataOut, + const Blowfish_Key key) +{ + register const __u32 *p=((const __u32 *)key)+17; + register unsigned long + l=__be32_to_cpup(dataIn)^(*p--), + r=__be32_to_cpup(dataIn+4); + RoundsN; + ((__u32 *)dataOut)[0]=__cpu_to_be32(r^(*p)); + ((__u32 *)dataOut)[1]=__cpu_to_be32(l); +} +#endif +#endif + +/* Little-endian routines */ + +#ifndef BF_DONTNEED_LE +#ifndef BF_NATIVE_LE +void L_Blowfish_Encrypt(void *dataIn, void *dataOut, + const Blowfish_Key key) +{ + register const __u32 *p=key; + register unsigned long + l=__le32_to_cpup(dataIn)^(*p++), + r=__le32_to_cpup(dataIn+4); + RoundsP; + ((__u32 *)dataOut)[0]=__cpu_to_le32(r^(*p)); + ((__u32 *)dataOut)[1]=__cpu_to_le32(l); +} + +void L_Blowfish_Decrypt(void *dataIn, void *dataOut, + const Blowfish_Key key) +{ + register const __u32 *p=key+17; + register unsigned long + l=__le32_to_cpup(dataIn)^(*p--), + r=__le32_to_cpup(dataIn+4); + RoundsN; + ((__u32 *)dataOut)[0]=__cpu_to_le32(r^(*p)); + ((__u32 *)dataOut)[1]=__cpu_to_le32(l); +} +#endif +#endif + +/* Key setup */ + +void Blowfish_ExpandUserKey(const char *userKey, int userKeyLen, + Blowfish_Key key) +{ + char d[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + int i, j; + __u32 u; + + #define UK (userKey[j]&255) + #define UKI if (++j>=userKeyLen) j=0 + for (i=j=0; i<18; ++i) { + u=UK; UKI; + u=(u<<8)+UK; UKI; + u=(u<<8)+UK; UKI; + u=(u<<8)+UK; UKI; + key[i]=Blowfish_Init_Key[i]^u; + } + memcpy(key+18, Blowfish_Init_Key+18, 4096); + for (i=0; i<1042; i+=2) { + _N_Blowfish_Encrypt(d, d, key); + key[i]=((__u32 *)d)[0]; + key[i+1]=((__u32 *)d)[1]; + } +} + +#endif + +/* The initialization key. According to Schneier, this is not a magic + pattern but simply the first 33344 (after point) bits of "pi". */ + +const Blowfish_Key Blowfish_Init_Key = { + /* The eighteen P boxes @ 1 word */ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b, + /* The four S boxes @ 256 words */ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 +}; + +#if (defined(TEST) && !defined(__KERNEL__)) + +#include + +/* Test vectors from Schneier's reference implementation */ + +char test1k[] = "abcdefghijklmnopqrstuvwxyz"; +char btest1p[] = { 0x42, 0x4c, 0x4f, 0x57, 0x46, 0x49, 0x53, 0x48 }; +char btest1c[] = { 0x32, 0x4e, 0xd0, 0xfe, 0xf4, 0x13, 0xa2, 0x03 }; + +char test2k[] = "Who is John Galt?"; +char btest2p[] = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }; +char btest2c[] = { 0xcc, 0x91, 0x73, 0x2b, 0x80, 0x22, 0xf6, 0x84 }; + +/* Non-official little endian test ciphertext vectors */ +char btest1l[] = { 0x82, 0x4d, 0x92, 0x0d, 0x00, 0x4d, 0x7e, 0xe3 }; +char btest2l[] = { 0xd4, 0xf9, 0xb0, 0x06, 0xd3, 0x84, 0x92, 0x7e }; + +typedef void (*BFTransform)(void *dataIn, void *dataOut, + const Blowfish_Key key); + +int ftest(char *k, char *p, char *c, + BFTransform Encrypt, BFTransform Decrypt) +{ + Blowfish_Key kk; + unsigned char dd[8]; + int e=0; + + Blowfish_ExpandUserKey(k, strlen(k), kk); + Encrypt(p, dd, kk); + printf(" %02x%02x%02x%02x %02x%02x%02x%02x ", + dd[0], dd[1], dd[2], dd[3], dd[4], dd[5], dd[6], dd[7]); + if (memcmp(dd, c, 8)) { + printf("encrypt failed "); + ++e; + } + Decrypt(dd, dd, kk); + printf(" %02x%02x%02x%02x %02x%02x%02x%02x ", + dd[0], dd[1], dd[2], dd[3], dd[4], dd[5], dd[6], dd[7]); + if (memcmp(dd, p, 8)) { + printf("decrypt failed "); + ++e; + } + printf("%s\n", e?"":"passed"); + return e; +} + +int main() +{ + int e=0; + printf("Big-endian:\n"); + printf(" Test 1: "); + e+=ftest(test1k, btest1p, btest1c, B_Blowfish_Encrypt, B_Blowfish_Decrypt); + printf(" Test 2: "); + e+=ftest(test2k, btest2p, btest2c, B_Blowfish_Encrypt, B_Blowfish_Decrypt); + printf("Little-endian:\n"); + printf(" Test 1: "); + e+=ftest(test1k, btest1p, btest1l, L_Blowfish_Encrypt, L_Blowfish_Decrypt); + printf(" Test 2: "); + e+=ftest(test2k, btest2p, btest2l, L_Blowfish_Encrypt, L_Blowfish_Decrypt); + return e; +} + +#endif --- linux-2.4.21/drivers/addon/cipe4/bf.h.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/bf.h Fri Jul 25 15:12:33 2003 @@ -0,0 +1,100 @@ +/* + Bruce Schneier's Blowfish. + Author: Olaf Titz + + This code is in the public domain. + + $Id: bf.h,v 1.4 2000/10/06 23:15:05 olaf Exp $ +*/ + +#ifndef _BF_H_ +#define _BF_H_ + +#include /* gives __u32 as an unsigned 32bit integer */ +/* PORTABILITY: under non-Linux, + omit this include and insert an appropriate typedef +*/ + +#ifdef __KERNEL__ +#include +#endif +/* PORTABILITY: under non-Linux, omit this include. + Generic, endian-neutral, slower C routines will be used instead of + the assembler versions found in the kernel includes. +*/ + +/* This is ugly, but seems the easiest way to find an endianness test + which works both in kernel and user mode. + This is only an optimization - everything works even if none of the + tests are defined. +*/ +#ifdef __BYTE_ORDER +#if __BYTE_ORDER == __BIG_ENDIAN +#define BF_NATIVE_BE +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define BF_NATIVE_LE +#endif +#else +#ifdef __BIG_ENDIAN +#define BF_NATIVE_BE +#endif +#ifdef __LITTLE_ENDIAN +#define BF_NATIVE_LE +#endif +#endif + +/* The data block processed by the encryption algorithm - 64 bits */ +typedef __u32 Blowfish_Data[2]; +/* The key as entered by the user - size may vary */ +typedef char Blowfish_UserKey[16]; +/* The expanded key for internal use - 18+4*256 words*/ +typedef __u32 Blowfish_Key[1042]; + +/* Byteorder-dependent handling of data encryption: Blowfish is by + definition big-endian. However, there are broken implementations on + little-endian machines which treat the data as little-endian. + This module provides both variants. + */ + +/* Native byte order. For internal use ONLY. */ +extern void _N_Blowfish_Encrypt(void *dataIn, void *dataOut, + const Blowfish_Key key); +extern void _N_Blowfish_Decrypt(void *dataIn, void *dataOut, + const Blowfish_Key key); + +#ifndef BF_DONTNEED_BE +/* Big endian. This is the "real" Blowfish. */ +#ifdef BF_NATIVE_BE +#define B_Blowfish_Encrypt _N_Blowfish_Encrypt +#define B_Blowfish_Decrypt _N_Blowfish_Decrypt +#else +extern void B_Blowfish_Encrypt(void *dataIn, void *dataOut, + const Blowfish_Key key); +extern void B_Blowfish_Decrypt(void *dataIn, void *dataOut, + const Blowfish_Key key); +#endif +#endif + +#ifndef BF_DONTNEED_LE +/* Little endian. To be compatible with other LE implementations. */ +#ifdef BF_NATIVE_LE +#define L_Blowfish_Encrypt _N_Blowfish_Encrypt +#define L_Blowfish_Decrypt _N_Blowfish_Decrypt +#else +extern void L_Blowfish_Encrypt(void *dataIn, void *dataOut, + const Blowfish_Key key); +extern void L_Blowfish_Decrypt(void *dataIn, void *dataOut, + const Blowfish_Key key); +#endif +#endif + +/* User key expansion. This is not byteorder dependent as all common + implementations get it right (i.e. big-endian). */ + +extern void Blowfish_ExpandUserKey(const char *userKey, int userKeyLen, + Blowfish_Key key); + +extern const Blowfish_Key Blowfish_Init_Key; + +#endif --- linux-2.4.21/drivers/addon/cipe4/bf-i386.S.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/bf-i386.S Fri Jul 25 15:12:33 2003 @@ -0,0 +1,272 @@ +/* + Bruce Schneier's Blowfish in i386 assembler (for linux/gcc) + Author: Olaf Titz + + This code is in the public domain. + + $Id: bf-i386.S,v 1.6 2000/11/16 16:45:00 olaf Exp $ +*/ + +#ifdef ASM_BF_Crypt + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif + +/* This header just defines ENTRY to make an appropriate global symbol */ +#include + +/* Look for CONFIG_X86_BSWAP (defined for 486 and up) */ +#include + +#define PosP0 0 +#define PosP17 68 +#define PosS0 72 +#define PosS1 1096 +#define PosS2 2120 +#define PosS3 3144 +#define KeyLenL 1042 +#define KeyLenB 521 + +/* This code is optimized for speed rather than size - loops unrolled. etc. */ + +/* + Endian-ness is taken care of by (a) the order of shifts in the Round + macro and (b) the order of shifts below under the ukx label. + The key tables and user data are stored and processed in the CPU + byte order. +*/ + +/* Do one round */ +#define Round(lw,rw) \ + movl rw, %edx; \ + shrl $24, %edx; \ + movl PosS0(%edi,%edx,4), %eax; \ + movl rw, %edx; \ + shrl $16, %edx; \ + andl $0xFF, %edx; \ + addl PosS1(%edi,%edx,4), %eax; \ + movl rw, %edx; \ + shrl $8, %edx; \ + andl $0xFF, %edx; \ + xorl PosS2(%edi,%edx,4), %eax; \ + movl rw, %edx; \ + andl $0xFF, %edx; \ + addl PosS3(%edi,%edx,4), %eax; \ + xorl %eax, lw; \ + lodsl; \ + xorl %eax, lw + +/* Words in %ebx, %ecx - Key in %edi - P-index in %esi - result swapped */ +blowfish: + lodsl + xorl %eax, %ebx + Round(%ecx,%ebx); Round(%ebx,%ecx) + Round(%ecx,%ebx); Round(%ebx,%ecx) + Round(%ecx,%ebx); Round(%ebx,%ecx) + Round(%ecx,%ebx); Round(%ebx,%ecx) + Round(%ecx,%ebx); Round(%ebx,%ecx) + Round(%ecx,%ebx); Round(%ebx,%ecx) + Round(%ecx,%ebx); Round(%ebx,%ecx) + Round(%ecx,%ebx); Round(%ebx,%ecx) + lodsl + xorl %eax, %ecx + ret + +/* Endianness swap operation. Is there an easier way to decompose + %ebx into %bl and %bh within a macro? */ +#ifdef CONFIG_X86_BSWAP +#define swab32(x,h,l) bswap x +#else +#define swab32(x,h,l) \ + xchgb h, l; \ + rorl $16, x; \ + xchgb h, l +#endif + + +/* Function prototype prologue/epilogue. Sets up registers etc. + This is all code common to the six encrypt/decrypt functions. + They have the prototype + extern void FUNCTION(void *dataIn, void *dataOut, const Blowfish_Key key); + for the following FUNCTIONs: + _N_Blowfish_Encrypt, _N_Blowfish_Decrypt (native-endian) + B_Blowfish_Encrypt, B_Blowfish_Decrypt (big-endian) + L_Blowfish_Encrypt, L_Blowfish_Decrypt (little-endian) + Of course, in the i386 implementation, native==little-endian. +*/ + +/* saved regs relative to %esp */ +#define sebx 0 +#define sebp 4 +#define sesi 8 +#define sedi 12 +#define SAVE 16 /* no. of bytes the saved registers occupy */ +/* arguments relative to %esp */ +#define dataIn SAVE+4(%esp) +#define dataOut SAVE+8(%esp) +#define key SAVE+12(%esp) + +#define PROLOG \ + /* save registers */ \ + subl $SAVE, %esp; \ + movl %ebx, sebx(%esp); \ + movl %ebp, sebp(%esp); \ + movl %esi, sesi(%esp); \ + movl %edi, sedi(%esp); \ + /* load data */ \ + movl dataIn, %esi; \ + movl (%esi), %ebx; \ + movl 4(%esi), %ecx; \ + /* load key */ \ + movl key, %edi; + +#define EPILOG \ + /* store data */ \ + movl dataOut, %edi; \ + movl %ebx, 4(%edi); \ + movl %ecx, (%edi); \ + /* restore registers */ \ + movl sedi(%esp), %edi; \ + movl sesi(%esp), %esi; \ + movl sebp(%esp), %ebp; \ + movl sebx(%esp), %ebx; \ + addl $SAVE, %esp; \ + ret + +#define FORWARD \ + movl %edi, %esi; \ + cld + +#define BACKWARD \ + leal PosP17(%edi), %esi; \ + std + +#define SWAP \ + swab32(%ebx,%bh,%bl); \ + swab32(%ecx,%ch,%cl) + +/* N.B. In Linux 2.3, the D flag is assumed to be zero all the time. + Thus after BACKWARD an additional cld is necessary. */ + +#ifndef BF_DONTNEED_LE +ENTRY(L_Blowfish_Encrypt) +#endif +ENTRY(_N_Blowfish_Encrypt) + PROLOG + FORWARD + call blowfish + EPILOG + +#ifndef BF_DONTNEED_LE +ENTRY(L_Blowfish_Decrypt) +#endif +ENTRY(_N_Blowfish_Decrypt) + PROLOG + BACKWARD + call blowfish + cld + EPILOG + +#ifndef BF_DONTNEED_BE +ENTRY(B_Blowfish_Encrypt) + PROLOG + SWAP + FORWARD + call blowfish + SWAP + EPILOG + +ENTRY(B_Blowfish_Decrypt) + PROLOG + SWAP + BACKWARD + call blowfish + cld + SWAP + EPILOG +#endif + + +/* load byte from key, start over if exhausted */ +#define lodsbw(base,len) \ + lodsb; \ + decl %ecx; \ + cmpl $0, %ecx; \ + jg 1f; \ + movl base, %esi; \ + movl len, %ecx; \ +1: + +/* + void Blowfish_ExpandUserKey(const char *userKey, int userKeyLen, + Blowfish_Key key); +*/ + +ENTRY(Blowfish_ExpandUserKey) + pushl %ebx + pushl %ebp + pushl %esi + pushl %edi +#define SAVE 16 /* no. of bytes the saved registers occupy */ +/* arguments relative to %esp */ +#define userKey SAVE+4(%esp) +#define userKeyLen SAVE+8(%esp) +#define key SAVE+12(%esp) +#define key_push SAVE+16(%esp) /* key with one word pushed */ + + /* Copy the init vector into key */ + leal SYMBOL_NAME(Blowfish_Init_Key), %esi + movl key, %edi + movl $KeyLenL, %ecx + cld + rep; movsl + /* XOR the user key into the P table */ + movl key, %edi + movl $18, %ebp + movl userKey, %esi + movl userKeyLen, %ecx +ukx: + /* process one 32-bit word swapped */ + lodsbw(userKey, userKeyLen) + shll $8, %eax + lodsbw(userKey, userKeyLen) + shll $8, %eax + lodsbw(userKey, userKeyLen) + shll $8, %eax + lodsbw(userKey, userKeyLen) + xorl %eax, (%edi) + addl $4, %edi + decl %ebp + cmpl $0, %ebp + jg ukx + + /* Now do the repeated encryption process */ + xorl %ebx, %ebx + xorl %ecx, %ecx + movl $KeyLenB, %ebp + movl key, %edi +ukb: + pushl %edi + movl key_push, %edi + movl %edi, %esi + call blowfish + popl %edi + xchgl %ebx, %ecx + movl %ebx, (%edi) + movl %ecx, 4(%edi) + addl $8, %edi + decl %ebp + cmpl $0, %ebp + jg ukb + + popl %edi + popl %esi + popl %ebp + popl %ebx + ret +#undef dataIn +#undef dataOut +#undef key + +#endif /* ASM_BF_Crypt */ --- linux-2.4.21/drivers/addon/cipe4/device.c.CIPE4 Fri Jul 25 15:12:33 2003 +++ linux-2.4.21/drivers/addon/cipe4/device.c Fri Jul 25 15:13:36 2003 @@ -0,0 +1,636 @@ +/* + CIPE - encrypted IP over UDP tunneling + + device.c - the net device driver + + Copyright 1996 Olaf Titz + + 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. +*/ +/* $Id: device.c,v 1.42 2000/11/19 23:08:34 olaf Exp $ */ + +#include "cipe.h" +#include "version.h" +#include +#include +#include +#include + +#ifdef LINUX_21 +#include +#include +#else +#define register_netdevice register_netdev +#define unregister_netdevice unregister_netdev +#endif + +/*** Globals ***/ + +static const char driver_version[]=VERSION; + +struct cipe_ctrl **cipe_ctrls = NULL; +#ifdef NO_DYNDEV +int cipe_maxdev = 4; /* changeable via insmod */ +#else +int cipe_maxdev = 100; /* changeable via insmod */ +#endif +#ifdef DEBUG +int cipe_debug = DEB_CALL; /* changeable via insmod */ +#endif + +/* clear all potentially sensitive info and stats */ +static void cipe_zero_c(struct cipe *c) +{ + memset(&(c->peeraddr), 0, + offsetof(struct cipe, udp_prot)-offsetof(struct cipe, peeraddr)); + /* reset these to sensible values */ + c->tmo_keyxchg = 10*HZ; + c->tmo_keylife = 10*60*HZ; +} + +/* weak but fast PRNG, used for padding only */ +static __u32 prnseed; +void cipe_prnpad(unsigned char *buf, int len) +{ + while (len>0) { + prnseed=prnseed*0x01001001+1; + if (len>=2) { + *(__u16 *)buf=prnseed>>16; + len-=2; buf+=2; + } else { + *buf=(prnseed>>24)^jiffies; return; + } + } +} + +#ifdef DO_LOCK_PRINTK +spinlock_t cipe_printk_lock = SPIN_LOCK_UNLOCKED; +#endif + +/* inet_ntoa() for multiple use. */ +#ifdef __SMP__ +#define NTOABUFS 16 +#else +#define NTOABUFS 4 +#endif +static char ntoabuf[NTOABUFS][16]; +static int ntoaptr=0; +#ifdef LINUX_21 +spinlock_t cipe_ntoa_lock=SPIN_LOCK_UNLOCKED; +#endif + +const char *cipe_ntoa(const __u32 addr) +{ + const unsigned char *x=(const unsigned char *)&addr; + char *p; + int b, i; +#ifdef LINUX_21 + unsigned long flags; + spin_lock_irqsave(&cipe_ntoa_lock, flags); +#endif + b=ntoaptr; + if (++b>=NTOABUFS) + b=0; + ntoaptr=b; +#ifdef LINUX_21 + spin_unlock_irqrestore(&cipe_ntoa_lock, flags); +#endif + p=ntoabuf[b]; + for (i=0; i<4; ++i) { + int k=x[i]/100; + int l=(x[i]/10)%10; + if (k) + *p++=k+'0'; + if (k || l) + *p++=l+'0'; + *p++=(x[i]%10)+'0'; + if (i<3) + *p++='.'; + } + *p='\0'; + return ntoabuf[b]; +} + +/*** IOCTL handlers ***/ + +#ifdef SIOCGIFCIPPAR +static int cipe_getpar(struct NET_DEVICE *dev, struct siocgifcippar *parm) +{ + DEVTOCIPE(dev,c,-ENODEV); + + parm->sockshost=c->sockshost; + parm->socksport=c->socksport; + parm->tmo_keyxchg=c->tmo_keyxchg/HZ; + parm->tmo_keylife=c->tmo_keylife/HZ; + parm->flags=c->flags; + parm->cttl=c->cttl; + return 0; +} +#endif + +static int cipe_setpar(struct NET_DEVICE *dev, struct siocsifcippar *parm) +{ + DEVTOCIPE(dev,c,-ENODEV); + + if (parm->sockshost) + c->sockshost=parm->sockshost; + if (parm->socksport) + c->socksport=parm->socksport; + if (parm->tmo_keyxchg>10*60*HZ) + return -EINVAL; + if (parm->tmo_keyxchg) + c->tmo_keyxchg=parm->tmo_keyxchg*HZ; + if (parm->tmo_keylife>24*60*60*HZ) + return -EINVAL; + if (parm->tmo_keylife) + c->tmo_keylife=parm->tmo_keylife*HZ; + c->flags=(parm->flags&CIPF_MASK_EXT)|(c->flags&CIPF_MASK_INT); + c->cttl=parm->cttl; + dprintk(DEB_CALL, (KERN_DEBUG "%s: setpar %s:%d %ld %ld %04x %d\n", + dev->name, + cipe_ntoa(c->sockshost), ntohs(c->socksport), + c->tmo_keyxchg, c->tmo_keylife, + c->flags, c->cttl)); + return 0; +} + +static int cipe_setkey(struct NET_DEVICE *dev, struct siocsifcipkey *parm) +{ + DEVTOCIPE(dev,c,-ENODEV); + + dprintk(DEB_KXC, (KERN_INFO "%s: setkey %d\n", dev->name, parm->which)); + switch (parm->which) { + case KEY_STATIC: + ExpandUserKey(parm->thekey, c->key_e); +#if 0 + dprintk(DEB_CRYPT, (KERN_DEBUG "ExpandUserKey: %08x\n", + *(__u32*)(c->key_e))); +#endif + InvertKey(c->key_e, c->key_d); + c->flags|=CIPF_HAVE_KEY; + break; + case KEY_SEND: + ExpandUserKey(parm->thekey, c->skey_e); + c->timeskey=jiffies+c->tmo_keylife; + c->cntskey=0; + c->flags|=CIPF_HAVE_SKEY; + break; + case KEY_RECV: + ExpandUserKey(parm->thekey, c->rkey_d); + InvertKey(c->rkey_d, c->rkey_d); + c->timerkey=jiffies+2*c->tmo_keylife; /* allow for fuzz */ + c->cntrkey=0; + c->flags|=CIPF_HAVE_RKEY; + break; + case KEY_STATIC+KEY_INVAL: + c->flags&=~(CIPF_HAVE_KEY|CIPF_HAVE_SKEY|CIPF_HAVE_RKEY); + memset(&(c->key_e), 0, sizeof(c->key_e)); + memset(&(c->key_d), 0, sizeof(c->key_d)); + break; + case KEY_SEND+KEY_INVAL: + c->flags&=~CIPF_HAVE_SKEY; + memset(&(c->skey_e), 0, sizeof(c->skey_e)); + c->timeskey=jiffies+c->tmo_keyxchg; + break; + case KEY_RECV+KEY_INVAL: + c->flags&=~CIPF_HAVE_RKEY; + memset(&(c->rkey_d), 0, sizeof(c->rkey_d)); + c->timerkey=jiffies+c->tmo_keyxchg; + break; + default: + return -EINVAL; + } + return 0; +} + +static int cipe_alloc_dev(int n); +static void cipe_unalloc_dev(int n); + +static int cipe_owner(struct cipe *c) +{ + struct task_struct *p; + pid_t pid=c->owner; + if (!pid) return 0; + tasklist_LOCK(); + p=current; + do { + if (p->pid==pid) { + tasklist_UNLOCK(); + return pid; + } + p=p->next_task; + } while (p!=current); + tasklist_UNLOCK(); + return 0; +} + +#define cipe_nowner(n) cipe_owner(&cipe_ctrls[(n)]->cipe) + +static int cipe_alloc(struct NET_DEVICE *dev, struct siocsifcipall *parm) +{ +#ifdef NO_DYNDEV + return -ENOSYS; +#else + int n=parm->num; + int e; + if (n>=cipe_maxdev) + return -EINVAL; + if ((e=cipe_alloc_LOCK())) + return e; + if (n>=0) { + if (cipe_ctrls[n]) { + if (cipe_ctrls[n]->cipe.sock || (e=cipe_nowner(n))) { + printk(KERN_DEBUG DEVNAME ": dev %d busy pid=%d\n", n, e); + e=-EBUSY; + } else { + cipe_ctrls[n]->cipe.owner=current->pid; + } + } else { + e=cipe_alloc_dev(n); + } + } else { + e=-EMFILE; + for (n=0; ncipe.owner=current->pid; + e=0; + break; + } + } + } + if (!e) { + parm->num=n; + strncpy(parm->name, cipe_ctrls[n]->dev.name, sizeof(parm->name)-1); + parm->name[sizeof(parm->name)-1]='\0'; + } + cipe_alloc_UNLOCK(); + return e; +#endif +} + +static int cipe_unalloc(struct NET_DEVICE *dev, struct siocsifcipall *parm) +{ +#ifdef NO_DYNDEV + return -ENOSYS; +#else + int e; + if (parm->num<0 || parm->num>=cipe_maxdev) + return -EINVAL; + if ((e=cipe_alloc_LOCK())) + return e; + if (cipe_ctrls[parm->num]->cipe.sock) { + e=-EBUSY; + } else { + if (parm->num>0) + cipe_unalloc_dev(parm->num); + } + cipe_alloc_UNLOCK(); + return e; +#endif +} + + +/*** Device operation handlers ***/ + +int cipe_dev_ioctl(struct NET_DEVICE *dev, struct ifreq *ifr, int cmd) +{ + int e=-EINVAL; + +#ifdef LINUX_21 + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + +#define doioctl(nam,fun,str) { \ + struct str parm; \ + dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", dev->name)); \ + if ((e=copy_from_user((void*)&parm,(void*)ifr->ifr_data, \ + sizeof(parm)))<0) \ + goto out; \ + if ((e=fun(dev, &parm))<0) \ + goto out; \ + e=copy_to_user((void*)ifr->ifr_data, (void*)&parm, sizeof(parm)); \ + goto out; \ + } + +#else + + if (!suser()) + return -EPERM; + +#define doioctl(nam,fun,str) { \ + struct str parm; \ + dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", dev->name)); \ + if ((e=verify_area(VERIFY_READ, ifr->ifr_data, sizeof(parm)))<0) \ + goto out; \ + memcpy_fromfs((void*)&parm, (void*)ifr->ifr_data, sizeof(parm)); \ + if ((e=fun(dev, &parm))<0) \ + goto out; \ + if ((e=verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(parm)))<0) \ + goto out; \ + memcpy_tofs((void*)ifr->ifr_data, (void*)&parm, sizeof(parm)); \ + goto out; \ + } + +#endif + + cipe_use_module(); + switch (cmd) { +#ifdef SIOCGIFCIPPAR + case SIOCGIFCIPPAR: + doioctl("getpar", cipe_getpar, siocgifcippar); +#endif + case SIOCSIFCIPPAR: + doioctl("setpar", cipe_setpar, siocsifcippar); + case SIOCSIFCIPKEY: + doioctl("setkey", cipe_setkey, siocsifcipkey); + case SIOCSIFCIPATT: + doioctl("attach", cipe_attach, siocsifcipatt); + case SIOCSIFCIPALL: + doioctl("alloc", cipe_alloc, siocsifcipall); + case SIOCSIFCIPUNA: + doioctl("unalloc", cipe_unalloc, siocsifcipall); + /* default: e=-EINVAL; */ + } + + out: + cipe_unuse_module(); + return e; + +#undef doioctl +} + +int cipe_dev_open(struct NET_DEVICE *dev) +{ + DEVTOCIPE(dev,c,-ENODEV); + if (!c->sock) + return -ENXIO; + dprintk(DEB_CALL, (KERN_INFO "%s: opened\n", dev->name)); + return 0; +} + +void cipe_close(struct cipe *c) +{ + cipe_zero_c(c); + dprintk(DEB_CALL, (KERN_INFO "%s: closed\n", c->dev->name)); + cipe_unuse_module(); +} + +int cipe_dev_close(struct NET_DEVICE *dev) +{ + struct cipe *c = (struct cipe*)(dev->priv); + if ((!c) || (c->magic!=CIPE_MAGIC)) { + printk(KERN_WARNING "%s: cipe_dev_close: no valid struct\n", + dev->name); + return 0; + } + if (c->sock) { + dprintk(DEB_CALL, (KERN_INFO "%s: closing\n", c->dev->name)); + /* Tell the attached socket we're going down */ + c->sock->shutdown=SHUTDOWN_MASK; + c->sock->zapped=1; + c->sock->err=ENXIO; + c->sock->error_report(c->sock); +#ifdef LINUX_21 + if (!cipe_owner(c)) { + /* SHOULD NOT HAPPEN. Socket is probably left orphaned. + This is really only an emergency path to allow closing + the device after an Oops. */ + printk(KERN_ERR "cipe_dev_close: not owned??\n"); + cipe_close(c); + } +#endif + } else { + cipe_close(c); + } + return 0; +} + +struct DEV_STATS *cipe_get_stats(struct NET_DEVICE *dev) +{ + DEVTOCIPE(dev,c,NULL); + return &(c->stat); +} + +int cipe_set_mac(struct NET_DEVICE *dev, void *p) +{ + struct sockaddr *addr=p; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + return 0; +} + + +/*** Initialization and finalization stuff ***/ + +#ifndef LINUX_21 +static inline void dev_init_buffers(struct NET_DEVICE *dev) +{ + int i; + for (i = 0; i < DEV_NUMBUFFS; i++) { + skb_queue_head_init(&dev->buffs[i]); + } +} +#endif + +static int cipe_init_dev(struct NET_DEVICE *dev) +{ + struct cipe *c = (struct cipe*)(dev->priv); + if (!c) + return -ENODEV; + + memset(c, 0, sizeof(struct cipe)); /* zero the device struct along */ + c->magic = CIPE_MAGIC; + c->dev = dev; + cipe_zero_c(c); + + /* Device parameters. */ +#ifdef VER_ETH + ether_setup(dev); /* sets hard_header etc. */ +#endif + /* Procedural */ + dev->open = cipe_dev_open; + dev->stop = cipe_dev_close; + dev->hard_start_xmit = cipe_xmit; + dev->set_mac_address = cipe_set_mac; + dev->do_ioctl = cipe_dev_ioctl; + dev->get_stats = cipe_get_stats; + + /* "Hardware" */ +#ifndef VER_ETH + dev->type = ARPHRD_TUNNEL; + dev->hard_header_len = 0; /* we copy anyway to expand */ + dev->tx_queue_len = 100; /* matches ethernet */ +#endif + dev->mtu = ETH_DATA_LEN + -sizeof(struct sockshdr) + -cipehdrlen + -cipefootlen; + + +#ifdef LINUX_21 + dev->iflink = -1; +#else + dev->family = AF_INET; + dev->pa_alen = 4; + dev->metric = 1; +#endif + dev_init_buffers(dev); + + /* New-style flags */ +#ifndef VER_ETH + dev->flags = IFF_POINTOPOINT|IFF_NOARP; +#endif + return 0; +} + +#ifndef LINUX_21 +struct semaphore cipe_alloc_sem=MUTEX; +#endif + +static int cipe_alloc_dev(int n) +{ + int e=0; + struct cipe_ctrl *cc; + struct NET_DEVICE *d; + + dprintk(DEB_CALL, (KERN_INFO DEVNAME ": cipe_alloc_dev %d\n", n)); + if (!(cc=kmalloc(sizeof(struct cipe_ctrl), GFP_KERNEL))) { + cipe_ctrls[n]=NULL; + printk(KERN_ERR DEVNAME ": failed to allocate device %d\n", n); + return -ENOMEM; + } + + memset((void *)cc, 0, sizeof(*cc)); +/* If this doesn't compile, define or undefine HAVE_DEVNAME_ARRAY + in cipe.h accordingly. */ +#ifdef HAVE_DEVNAME_ARRAY + sprintf(cc->dev.name, DEVNAME "%d", n); +#else + sprintf(cc->name, DEVNAME "%d", n); + cc->dev.name = cc->name; +#endif + cc->dev.base_addr = n; /* dummy */ + cc->dev.priv = (void*)&(cc->cipe); + cc->dev.next = NULL; + cc->dev.init = cipe_init_dev; /* called by register_netdevice */ + +#if 1 + /* Generate a dummy MAC address. This code seems to be in accordance + to the address assignments as of RFC1700, pp.172f. + We use 00-00-5E-vv-nn-zz with + vv=1pppccc0, p=protocol, c=crypto, + nn=device number, zz=from MAC of first eth device. + */ + cc->dev.dev_addr[2]=0x5E; + cc->dev.dev_addr[3]=0x80+(ProtocolVersion<<4)+(CRNUM<<1); + cc->dev.dev_addr[4]=n; + for (d=dev_base; d; d=d->next) + if (d->type==ARPHRD_ETHER) { + cc->dev.dev_addr[5]=d->dev_addr[5]; + break; + } +#else + /* MAC address will be generated from IP as with PLIP. FC-FC-ip-ip-ip-ip */ + cc->dev.dev_addr[1]=cc->dev.dev_addr[0]=0xFC; +#endif + memset(d->broadcast, 0xFF, ETH_ALEN); + cc->dev.addr_len=ETH_ALEN; + + e=register_netdevice(&(cc->dev)); + if (e<0) { + kfree(cc); + printk(KERN_ERR + "%s: register_netdevice() failed\n", cc->dev.name); + cc=NULL; + } else { + cc->cipe.owner=current->pid; + } + cipe_ctrls[n]=cc; + return e; +} + +static void cipe_unalloc_dev(int n) +{ + struct cipe_ctrl *cc=cipe_ctrls[n]; + if (!cc) + return; + dprintk(DEB_CALL, (KERN_INFO DEVNAME ": cipe_unalloc_dev %d\n", n)); + if (cc->cipe.magic!=CIPE_MAGIC) { + printk(KERN_WARNING DEVNAME ": Ouch: cipe_unalloc_dev() wrong struct\n"); + return; + } + unregister_netdevice(&(cc->dev)); + cipe_ctrls[n]=NULL; + kfree(cc); +} + +int init_module(void) +{ + int e=cipe_check_kernel(); + if (e<0) + return e; + + /* sanity check on insmod-provided data */ + if (cipe_maxdev<1) cipe_maxdev=1; +#ifdef NO_DYNDEV + if (cipe_maxdev>100) cipe_maxdev=100; +#else + if (cipe_maxdev>10000) cipe_maxdev=10000; +#endif + +#ifdef DEBUG + printk(KERN_INFO + DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2000, %d channels, debug=%d\n", + driver_version, cipe_maxdev, cipe_debug); +#else + printk(KERN_INFO + DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2000, %d channels\n", + driver_version, cipe_maxdev); +#endif + + prnseed=(~jiffies)^CURRENT_TIME; + cipe_ctrls = (struct cipe_ctrl **) kmalloc(sizeof(void*)*cipe_maxdev, + GFP_KERNEL); + if (!cipe_ctrls) { + printk(KERN_ERR + DEVNAME ": failed to allocate master control structure\n"); + return -ENOMEM; + } + memset(cipe_ctrls, 0, sizeof(void*)*cipe_maxdev); +#ifdef NO_DYNDEV + { + int i; + rtnl_LOCK(); + for (i=0; i