diff options
Diffstat (limited to 'linux/net/ipsec/ipsec_sa.c')
-rw-r--r-- | linux/net/ipsec/ipsec_sa.c | 1031 |
1 files changed, 0 insertions, 1031 deletions
diff --git a/linux/net/ipsec/ipsec_sa.c b/linux/net/ipsec/ipsec_sa.c deleted file mode 100644 index 4f73b92f2..000000000 --- a/linux/net/ipsec/ipsec_sa.c +++ /dev/null @@ -1,1031 +0,0 @@ -/* - * Common routines for IPsec SA maintenance routines. - * - * Copyright (C) 1996, 1997 John Ioannidis. - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Richard Guy Briggs. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: ipsec_sa.c,v 1.3 2004/06/13 19:57:50 as Exp $ - * - * This is the file formerly known as "ipsec_xform.h" - * - */ - -#include <linux/config.h> -#include <linux/version.h> -#include <linux/kernel.h> /* printk() */ - -#include "freeswan/ipsec_param.h" - -#ifdef MALLOC_SLAB -# include <linux/slab.h> /* kmalloc() */ -#else /* MALLOC_SLAB */ -# include <linux/malloc.h> /* kmalloc() */ -#endif /* MALLOC_SLAB */ -#include <linux/vmalloc.h> /* vmalloc() */ -#include <linux/errno.h> /* error codes */ -#include <linux/types.h> /* size_t */ -#include <linux/interrupt.h> /* mark_bh */ - -#include <linux/netdevice.h> /* struct device, and other headers */ -#include <linux/etherdevice.h> /* eth_type_trans */ -#include <linux/ip.h> /* struct iphdr */ -#include <linux/skbuff.h> -#include <freeswan.h> -#ifdef SPINLOCK -#ifdef SPINLOCK_23 -#include <linux/spinlock.h> /* *lock* */ -#else /* SPINLOCK_23 */ -#include <asm/spinlock.h> /* *lock* */ -#endif /* SPINLOCK_23 */ -#endif /* SPINLOCK */ -#ifdef NET_21 -#include <asm/uaccess.h> -#include <linux/in6.h> -#endif -#include <asm/checksum.h> -#include <net/ip.h> - -#include "freeswan/radij.h" - -#include "freeswan/ipsec_stats.h" -#include "freeswan/ipsec_life.h" -#include "freeswan/ipsec_sa.h" -#include "freeswan/ipsec_xform.h" - -#include "freeswan/ipsec_encap.h" -#include "freeswan/ipsec_radij.h" -#include "freeswan/ipsec_xform.h" -#include "freeswan/ipsec_ipe4.h" -#include "freeswan/ipsec_ah.h" -#include "freeswan/ipsec_esp.h" - -#include <pfkeyv2.h> -#include <pfkey.h> - -#include "freeswan/ipsec_proto.h" -#include "freeswan/ipsec_alg.h" - - -#ifdef CONFIG_IPSEC_DEBUG -int debug_xform = 0; -#endif /* CONFIG_IPSEC_DEBUG */ - -#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) - -struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD]; -#ifdef SPINLOCK -spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED; -#else /* SPINLOCK */ -spinlock_t tdb_lock; -#endif /* SPINLOCK */ - -struct ipsec_sadb ipsec_sadb; - -#if IPSEC_SA_REF_CODE - -/* the sub table must be narrower (or equal) in bits than the variable type - in the main table to count the number of unused entries in it. */ -typedef struct { - int testSizeOf_refSubTable : - ((sizeof(IPsecRefTableUnusedCount) * 8) < IPSEC_SA_REF_SUBTABLE_IDX_WIDTH ? -1 : 1); -} dummy; - - -/* The field where the saref will be hosted in the skb must be wide enough to - accomodate the information it needs to store. */ -typedef struct { - int testSizeOf_refField : - (IPSEC_SA_REF_HOST_FIELD_WIDTH < IPSEC_SA_REF_TABLE_IDX_WIDTH ? -1 : 1 ); -} dummy2; - - -void -ipsec_SAtest(void) -{ - IPsecSAref_t SAref = 258; - struct ipsec_sa ips; - ips.ips_ref = 772; - - printk("klips_debug:ipsec_SAtest: " - "IPSEC_SA_REF_SUBTABLE_IDX_WIDTH=%u\n" - "IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES=%u\n" - "IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES=%u\n" - "IPSEC_SA_REF_HOST_FIELD_WIDTH=%lu\n" - "IPSEC_SA_REF_TABLE_MASK=%x\n" - "IPSEC_SA_REF_ENTRY_MASK=%x\n" - "IPsecSAref2table(%d)=%u\n" - "IPsecSAref2entry(%d)=%u\n" - "IPsecSAref2NFmark(%d)=%u\n" - "IPsecSAref2SA(%d)=%p\n" - "IPsecSA2SAref(%p)=%d\n" - , - IPSEC_SA_REF_SUBTABLE_IDX_WIDTH, - IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES, - IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES, - (unsigned long) IPSEC_SA_REF_HOST_FIELD_WIDTH, - IPSEC_SA_REF_TABLE_MASK, - IPSEC_SA_REF_ENTRY_MASK, - SAref, IPsecSAref2table(SAref), - SAref, IPsecSAref2entry(SAref), - SAref, IPsecSAref2NFmark(SAref), - SAref, IPsecSAref2SA(SAref), - (&ips), IPsecSA2SAref((&ips)) - ); - return; -} - -int -ipsec_SAref_recycle(void) -{ - int table; - int entry; - int error = 0; - - ipsec_sadb.refFreeListHead = -1; - ipsec_sadb.refFreeListTail = -1; - - if(ipsec_sadb.refFreeListCont == IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_recycle: " - "end of table reached, continuing at start..\n"); - ipsec_sadb.refFreeListCont = 0; - } - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_recycle: " - "recycling, continuing from SAref=%d (0p%p), table=%d, entry=%d.\n", - ipsec_sadb.refFreeListCont, - (ipsec_sadb.refTable[IPsecSAref2table(ipsec_sadb.refFreeListCont)] != NULL) ? IPsecSAref2SA(ipsec_sadb.refFreeListCont) : NULL, - IPsecSAref2table(ipsec_sadb.refFreeListCont), - IPsecSAref2entry(ipsec_sadb.refFreeListCont)); - - for(table = IPsecSAref2table(ipsec_sadb.refFreeListCont); - table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; - table++) { - if(ipsec_sadb.refTable[table] == NULL) { - error = ipsec_SArefSubTable_alloc(table); - if(error) { - return error; - } - } - for(entry = IPsecSAref2entry(ipsec_sadb.refFreeListCont); - entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; - entry++) { - if(ipsec_sadb.refTable[table]->entry[entry] == NULL) { - ipsec_sadb.refFreeList[++ipsec_sadb.refFreeListTail] = IPsecSArefBuild(table, entry); - if(ipsec_sadb.refFreeListTail == (IPSEC_SA_REF_FREELIST_NUM_ENTRIES - 1)) { - ipsec_sadb.refFreeListHead = 0; - ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_recycle: " - "SArefFreeList refilled.\n"); - return 0; - } - } - } - } - - if(ipsec_sadb.refFreeListTail == -1) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_recycle: " - "out of room in the SArefTable.\n"); - - return(-ENOSPC); - } - - ipsec_sadb.refFreeListHead = 0; - ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_recycle: " - "SArefFreeList partly refilled to %d of %d.\n", - ipsec_sadb.refFreeListTail, - IPSEC_SA_REF_FREELIST_NUM_ENTRIES); - return 0; -} - -int -ipsec_SArefSubTable_alloc(unsigned table) -{ - unsigned entry; - struct IPsecSArefSubTable* SArefsub; - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SArefSubTable_alloc: " - "allocating %lu bytes for table %u of %u.\n", - (unsigned long) (IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)), - table, - IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); - - /* allocate another sub-table */ - SArefsub = vmalloc(IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)); - if(SArefsub == NULL) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SArefSubTable_alloc: " - "error allocating memory for table %u of %u!\n", - table, - IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); - return -ENOMEM; - } - - /* add this sub-table to the main table */ - ipsec_sadb.refTable[table] = SArefsub; - - /* initialise each element to NULL */ - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SArefSubTable_alloc: " - "initialising %u elements (2 ^ %u) of table %u.\n", - IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES, - IPSEC_SA_REF_SUBTABLE_IDX_WIDTH, - table); - for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { - SArefsub->entry[entry] = NULL; - } - - return 0; -} -#endif /* IPSEC_SA_REF_CODE */ - -int -ipsec_saref_freelist_init(void) -{ - int i; - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_saref_freelist_init: " - "initialising %u elements of FreeList.\n", - IPSEC_SA_REF_FREELIST_NUM_ENTRIES); - - for(i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) { - ipsec_sadb.refFreeList[i] = IPSEC_SAREF_NULL; - } - ipsec_sadb.refFreeListHead = -1; - ipsec_sadb.refFreeListCont = 0; - ipsec_sadb.refFreeListTail = -1; - - return 0; -} - -int -ipsec_sadb_init(void) -{ - int error = 0; - unsigned i; - - for(i = 0; i < SADB_HASHMOD; i++) { - ipsec_sadb_hash[i] = NULL; - } - /* parts above are for the old style SADB hash table */ - - -#if IPSEC_SA_REF_CODE - /* initialise SA reference table */ - - /* initialise the main table */ - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_init: " - "initialising main table of size %u (2 ^ %u).\n", - IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES, - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH); - { - unsigned table; - for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { - ipsec_sadb.refTable[table] = NULL; - } - } - - /* allocate the first sub-table */ - error = ipsec_SArefSubTable_alloc(0); - if(error) { - return error; - } - - error = ipsec_saref_freelist_init(); -#endif /* IPSEC_SA_REF_CODE */ - return error; -} - -#if IPSEC_SA_REF_CODE -IPsecSAref_t -ipsec_SAref_alloc(int*error) /* pass in error var by pointer */ -{ - IPsecSAref_t SAref; - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_alloc: " - "SAref requested... head=%d, cont=%d, tail=%d, listsize=%d.\n", - ipsec_sadb.refFreeListHead, - ipsec_sadb.refFreeListCont, - ipsec_sadb.refFreeListTail, - IPSEC_SA_REF_FREELIST_NUM_ENTRIES); - - if(ipsec_sadb.refFreeListHead == -1) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_alloc: " - "FreeList empty, recycling...\n"); - *error = ipsec_SAref_recycle(); - if(*error) { - return IPSEC_SAREF_NULL; - } - } - - SAref = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead]; - if(SAref == IPSEC_SAREF_NULL) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_alloc: " - "unexpected error, refFreeListHead = %d points to invalid entry.\n", - ipsec_sadb.refFreeListHead); - *error = -ESPIPE; - return IPSEC_SAREF_NULL; - } - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_alloc: " - "allocating SAref=%d, table=%u, entry=%u of %u.\n", - SAref, - IPsecSAref2table(SAref), - IPsecSAref2entry(SAref), - IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES); - - ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead] = IPSEC_SAREF_NULL; - ipsec_sadb.refFreeListHead++; - if(ipsec_sadb.refFreeListHead > ipsec_sadb.refFreeListTail) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_SAref_alloc: " - "last FreeList entry allocated, resetting list head to empty.\n"); - ipsec_sadb.refFreeListHead = -1; - } - - return SAref; -} -#endif /* IPSEC_SA_REF_CODE */ - -int -ipsec_sa_print(struct ipsec_sa *ips) -{ - char sa[SATOA_BUF]; - size_t sa_len; - - printk(KERN_INFO "klips_debug: SA:"); - if(ips == NULL) { - printk("NULL\n"); - return -ENOENT; - } - printk(" ref=%d", ips->ips_ref); - printk(" refcount=%d", atomic_read(&ips->ips_refcount)); - if(ips->ips_hnext != NULL) { - printk(" hnext=0p%p", ips->ips_hnext); - } - if(ips->ips_inext != NULL) { - printk(" inext=0p%p", ips->ips_inext); - } - if(ips->ips_onext != NULL) { - printk(" onext=0p%p", ips->ips_onext); - } - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - printk(" said=%s", sa_len ? sa : " (error)"); - if(ips->ips_seq) { - printk(" seq=%u", ips->ips_seq); - } - if(ips->ips_pid) { - printk(" pid=%u", ips->ips_pid); - } - if(ips->ips_authalg) { - printk(" authalg=%u", ips->ips_authalg); - } - if(ips->ips_encalg) { - printk(" encalg=%u", ips->ips_encalg); - } - printk(" XFORM=%s%s%s", IPS_XFORM_NAME(ips)); - if(ips->ips_replaywin) { - printk(" ooowin=%u", ips->ips_replaywin); - } - if(ips->ips_flags) { - printk(" flags=%u", ips->ips_flags); - } - if(ips->ips_addr_s) { - char buf[SUBNETTOA_BUF]; - addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, - 0, buf, sizeof(buf)); - printk(" src=%s", buf); - } - if(ips->ips_addr_d) { - char buf[SUBNETTOA_BUF]; - addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, - 0, buf, sizeof(buf)); - printk(" dst=%s", buf); - } - if(ips->ips_addr_p) { - char buf[SUBNETTOA_BUF]; - addrtoa(((struct sockaddr_in*)(ips->ips_addr_p))->sin_addr, - 0, buf, sizeof(buf)); - printk(" proxy=%s", buf); - } - if(ips->ips_key_bits_a) { - printk(" key_bits_a=%u", ips->ips_key_bits_a); - } - if(ips->ips_key_bits_e) { - printk(" key_bits_e=%u", ips->ips_key_bits_e); - } - - printk("\n"); - return 0; -} - -struct ipsec_sa* -ipsec_sa_alloc(int*error) /* pass in error var by pointer */ -{ - struct ipsec_sa* ips; - - if((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_alloc: " - "memory allocation error\n"); - *error = -ENOMEM; - return NULL; - } - memset((caddr_t)ips, 0, sizeof(*ips)); -#if IPSEC_SA_REF_CODE - ips->ips_ref = ipsec_SAref_alloc(error); /* pass in error return by pointer */ - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_alloc: " - "allocated %lu bytes for ipsec_sa struct=0p%p ref=%d.\n", - (unsigned long) sizeof(*ips), - ips, - ips->ips_ref); - if(ips->ips_ref == IPSEC_SAREF_NULL) { - kfree(ips); - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_alloc: " - "SAref allocation error\n"); - return NULL; - } - - atomic_inc(&ips->ips_refcount); - IPsecSAref2SA(ips->ips_ref) = ips; -#endif /* IPSEC_SA_REF_CODE */ - - *error = 0; - return(ips); -} - -int -ipsec_sa_free(struct ipsec_sa* ips) -{ - return ipsec_sa_wipe(ips); -} - -struct ipsec_sa * -ipsec_sa_getbyid(struct sa_id *said) -{ - int hashval; - struct ipsec_sa *ips; - char sa[SATOA_BUF]; - size_t sa_len; - - if(said == NULL) { - KLIPS_PRINT(debug_xform, - "klips_error:ipsec_sa_getbyid: " - "null pointer passed in!\n"); - return NULL; - } - - sa_len = satoa(*said, 0, sa, SATOA_BUF); - - hashval = (said->spi+said->dst.s_addr+said->proto) % SADB_HASHMOD; - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_getbyid: " - "linked entry in ipsec_sa table for hash=%d of SA:%s requested.\n", - hashval, - sa_len ? sa : " (error)"); - - if((ips = ipsec_sadb_hash[hashval]) == NULL) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_getbyid: " - "no entries in ipsec_sa table for hash=%d of SA:%s.\n", - hashval, - sa_len ? sa : " (error)"); - return NULL; - } - - for (; ips; ips = ips->ips_hnext) { - if ((ips->ips_said.spi == said->spi) && - (ips->ips_said.dst.s_addr == said->dst.s_addr) && - (ips->ips_said.proto == said->proto)) { - atomic_inc(&ips->ips_refcount); - return ips; - } - } - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_getbyid: " - "no entry in linked list for hash=%d of SA:%s.\n", - hashval, - sa_len ? sa : " (error)"); - return NULL; -} - -int -ipsec_sa_put(struct ipsec_sa *ips) -{ - char sa[SATOA_BUF]; - size_t sa_len; - - if(ips == NULL) { - KLIPS_PRINT(debug_xform, - "klips_error:ipsec_sa_put: " - "null pointer passed in!\n"); - return -1; - } - - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_put: " - "ipsec_sa SA:%s, ref:%d reference count decremented.\n", - sa_len ? sa : " (error)", - ips->ips_ref); - - atomic_dec(&ips->ips_refcount); - - return 0; -} - -/* - The ipsec_sa table better *NOT* be locked before it is handed in, or SMP locks will happen -*/ -int -ipsec_sa_add(struct ipsec_sa *ips) -{ - int error = 0; - unsigned int hashval; - - if(ips == NULL) { - KLIPS_PRINT(debug_xform, - "klips_error:ipsec_sa_add: " - "null pointer passed in!\n"); - return -ENODATA; - } - hashval = ((ips->ips_said.spi + ips->ips_said.dst.s_addr + ips->ips_said.proto) % SADB_HASHMOD); - - atomic_inc(&ips->ips_refcount); - spin_lock_bh(&tdb_lock); - - ips->ips_hnext = ipsec_sadb_hash[hashval]; - ipsec_sadb_hash[hashval] = ips; - - spin_unlock_bh(&tdb_lock); - - return error; -} - -/* - The ipsec_sa table better be locked before it is handed in, or races might happen -*/ -int -ipsec_sa_del(struct ipsec_sa *ips) -{ - unsigned int hashval; - struct ipsec_sa *ipstp; - char sa[SATOA_BUF]; - size_t sa_len; - - if(ips == NULL) { - KLIPS_PRINT(debug_xform, - "klips_error:ipsec_sa_del: " - "null pointer passed in!\n"); - return -ENODATA; - } - - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - if(ips->ips_inext || ips->ips_onext) { - KLIPS_PRINT(debug_xform, - "klips_error:ipsec_sa_del: " - "SA:%s still linked!\n", - sa_len ? sa : " (error)"); - return -EMLINK; - } - - hashval = ((ips->ips_said.spi + ips->ips_said.dst.s_addr + ips->ips_said.proto) % SADB_HASHMOD); - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_del: " - "deleting SA:%s, hashval=%d.\n", - sa_len ? sa : " (error)", - hashval); - if(ipsec_sadb_hash[hashval] == NULL) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_del: " - "no entries in ipsec_sa table for hash=%d of SA:%s.\n", - hashval, - sa_len ? sa : " (error)"); - return -ENOENT; - } - - if (ips == ipsec_sadb_hash[hashval]) { - ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; - ips->ips_hnext = NULL; - atomic_dec(&ips->ips_refcount); - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_del: " - "successfully deleted first ipsec_sa in chain.\n"); - return 0; - } else { - for (ipstp = ipsec_sadb_hash[hashval]; - ipstp; - ipstp = ipstp->ips_hnext) { - if (ipstp->ips_hnext == ips) { - ipstp->ips_hnext = ips->ips_hnext; - ips->ips_hnext = NULL; - atomic_dec(&ips->ips_refcount); - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_del: " - "successfully deleted link in ipsec_sa chain.\n"); - return 0; - } - } - } - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_del: " - "no entries in linked list for hash=%d of SA:%s.\n", - hashval, - sa_len ? sa : " (error)"); - return -ENOENT; -} - -/* - The ipsec_sa table better be locked before it is handed in, or races - might happen -*/ -int -ipsec_sa_delchain(struct ipsec_sa *ips) -{ - struct ipsec_sa *ipsdel; - int error = 0; - char sa[SATOA_BUF]; - size_t sa_len; - - if(ips == NULL) { - KLIPS_PRINT(debug_xform, - "klips_error:ipsec_sa_delchain: " - "null pointer passed in!\n"); - return -ENODATA; - } - - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_delchain: " - "passed SA:%s\n", - sa_len ? sa : " (error)"); - while(ips->ips_onext != NULL) { - ips = ips->ips_onext; - } - - while(ips) { - /* XXX send a pfkey message up to advise of deleted ipsec_sa */ - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_delchain: " - "unlinking and delting SA:%s", - sa_len ? sa : " (error)"); - ipsdel = ips; - ips = ips->ips_inext; - if(ips != NULL) { - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - ", inext=%s", - sa_len ? sa : " (error)"); - atomic_dec(&ipsdel->ips_refcount); - ipsdel->ips_inext = NULL; - atomic_dec(&ips->ips_refcount); - ips->ips_onext = NULL; - } - KLIPS_PRINT(debug_xform, - ".\n"); - if((error = ipsec_sa_del(ipsdel))) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_delchain: " - "ipsec_sa_del returned error %d.\n", -error); - return error; - } - if((error = ipsec_sa_wipe(ipsdel))) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_delchain: " - "ipsec_sa_wipe returned error %d.\n", -error); - return error; - } - } - return error; -} - -int -ipsec_sadb_cleanup(__u8 proto) -{ - unsigned i; - int error = 0; - struct ipsec_sa *ips, **ipsprev, *ipsdel; - char sa[SATOA_BUF]; - size_t sa_len; - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_cleanup: " - "cleaning up proto=%d.\n", - proto); - - spin_lock_bh(&tdb_lock); - - for (i = 0; i < SADB_HASHMOD; i++) { - ipsprev = &(ipsec_sadb_hash[i]); - ips = ipsec_sadb_hash[i]; - if(ips != NULL) { - atomic_inc(&ips->ips_refcount); - } - for(; ips != NULL;) { - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_cleanup: " - "checking SA:%s, hash=%d, ref=%d", - sa_len ? sa : " (error)", - i, - ips->ips_ref); - ipsdel = ips; - ips = ipsdel->ips_hnext; - if(ips != NULL) { - atomic_inc(&ips->ips_refcount); - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - ", hnext=%s", - sa_len ? sa : " (error)"); - } - if(*ipsprev != NULL) { - sa_len = satoa((*ipsprev)->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - ", *ipsprev=%s", - sa_len ? sa : " (error)"); - if((*ipsprev)->ips_hnext) { - sa_len = satoa((*ipsprev)->ips_hnext->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - ", *ipsprev->ips_hnext=%s", - sa_len ? sa : " (error)"); - } - } - KLIPS_PRINT(debug_xform, - ".\n"); - if(proto == 0 || (proto == ipsdel->ips_said.proto)) { - sa_len = satoa(ipsdel->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_cleanup: " - "deleting SA chain:%s.\n", - sa_len ? sa : " (error)"); - if((error = ipsec_sa_delchain(ipsdel))) { - SENDERR(-error); - } - ipsprev = &(ipsec_sadb_hash[i]); - ips = ipsec_sadb_hash[i]; - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_cleanup: " - "deleted SA chain:%s", - sa_len ? sa : " (error)"); - if(ips != NULL) { - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - ", ipsec_sadb_hash[%d]=%s", - i, - sa_len ? sa : " (error)"); - } - if(*ipsprev != NULL) { - sa_len = satoa((*ipsprev)->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - ", *ipsprev=%s", - sa_len ? sa : " (error)"); - if((*ipsprev)->ips_hnext != NULL) { - sa_len = satoa((*ipsprev)->ips_hnext->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - ", *ipsprev->ips_hnext=%s", - sa_len ? sa : " (error)"); - } - } - KLIPS_PRINT(debug_xform, - ".\n"); - } else { - ipsprev = &ipsdel; - } - if(ipsdel != NULL) { - ipsec_sa_put(ipsdel); - } - } - } - errlab: - - spin_unlock_bh(&tdb_lock); - - -#if IPSEC_SA_REF_CODE - /* clean up SA reference table */ - - /* go through the ref table and clean out all the SAs */ - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_cleanup: " - "removing SAref entries and tables."); - { - unsigned table, entry; - for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_cleanup: " - "cleaning SAref table=%u.\n", - table); - if(ipsec_sadb.refTable[table] == NULL) { - printk("\n"); - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_cleanup: " - "cleaned %u used refTables.\n", - table); - break; - } - for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { - if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { - ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); - ipsec_sadb.refTable[table]->entry[entry] = NULL; - } - } - } - } -#endif /* IPSEC_SA_REF_CODE */ - - return(error); -} - -int -ipsec_sadb_free(void) -{ - int error = 0; - - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_free: " - "freeing SArefTable memory.\n"); - - /* clean up SA reference table */ - - /* go through the ref table and clean out all the SAs if any are - left and free table memory */ - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_free: " - "removing SAref entries and tables.\n"); - { - unsigned table, entry; - for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_free: " - "removing SAref table=%u.\n", - table); - if(ipsec_sadb.refTable[table] == NULL) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sadb_free: " - "removed %u used refTables.\n", - table); - break; - } - for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { - if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { - ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); - ipsec_sadb.refTable[table]->entry[entry] = NULL; - } - } - vfree(ipsec_sadb.refTable[table]); - ipsec_sadb.refTable[table] = NULL; - } - } - - return(error); -} - -int -ipsec_sa_wipe(struct ipsec_sa *ips) -{ - if(ips == NULL) { - return -ENODATA; - } - - /* if(atomic_dec_and_test(ips)) { - }; */ - -#if IPSEC_SA_REF_CODE - /* remove me from the SArefTable */ - { - char sa[SATOA_BUF]; - size_t sa_len; - sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF); - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_wipe: " - "removing SA=%s(0p%p), SAref=%d, table=%d(0p%p), entry=%d from the refTable.\n", - sa_len ? sa : " (error)", - ips, - ips->ips_ref, - IPsecSAref2table(IPsecSA2SAref(ips)), - ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))], - IPsecSAref2entry(IPsecSA2SAref(ips))); - } - if(ips->ips_ref == IPSEC_SAREF_NULL) { - KLIPS_PRINT(debug_xform, - "klips_debug:ipsec_sa_wipe: " - "why does this SA not have a valid SAref?.\n"); - } - ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))]->entry[IPsecSAref2entry(IPsecSA2SAref(ips))] = NULL; - ips->ips_ref = IPSEC_SAREF_NULL; - ipsec_sa_put(ips); -#endif /* IPSEC_SA_REF_CODE */ - - /* paranoid clean up */ - if(ips->ips_addr_s != NULL) { - memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size); - kfree(ips->ips_addr_s); - } - ips->ips_addr_s = NULL; - - if(ips->ips_addr_d != NULL) { - memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size); - kfree(ips->ips_addr_d); - } - ips->ips_addr_d = NULL; - - if(ips->ips_addr_p != NULL) { - memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size); - kfree(ips->ips_addr_p); - } - ips->ips_addr_p = NULL; - -#ifdef CONFIG_IPSEC_NAT_TRAVERSAL - if(ips->ips_natt_oa) { - memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size); - kfree(ips->ips_natt_oa); - } - ips->ips_natt_oa = NULL; -#endif - - if(ips->ips_key_a != NULL) { - memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size); - kfree(ips->ips_key_a); - } - ips->ips_key_a = NULL; - - if(ips->ips_key_e != NULL) { -#ifdef CONFIG_IPSEC_ALG - if (ips->ips_alg_enc&&ips->ips_alg_enc->ixt_e_destroy_key) { - ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc, - ips->ips_key_e); - } else { -#endif /* CONFIG_IPSEC_ALG */ - memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); - kfree(ips->ips_key_e); -#ifdef CONFIG_IPSEC_ALG - } -#endif /* CONFIG_IPSEC_ALG */ - } - ips->ips_key_e = NULL; - - if(ips->ips_iv != NULL) { - memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size); - kfree(ips->ips_iv); - } - ips->ips_iv = NULL; - - if(ips->ips_ident_s.data != NULL) { - memset((caddr_t)(ips->ips_ident_s.data), - 0, - ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); - kfree(ips->ips_ident_s.data); - } - ips->ips_ident_s.data = NULL; - - if(ips->ips_ident_d.data != NULL) { - memset((caddr_t)(ips->ips_ident_d.data), - 0, - ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); - kfree(ips->ips_ident_d.data); - } - ips->ips_ident_d.data = NULL; - -#ifdef CONFIG_IPSEC_ALG - if (ips->ips_alg_enc||ips->ips_alg_auth) { - ipsec_alg_sa_wipe(ips); - } -#endif /* CONFIG_IPSEC_ALG */ - - memset((caddr_t)ips, 0, sizeof(*ips)); - kfree(ips); - ips = NULL; - - return 0; -} |