⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipsec_sa.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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.25 2004/08/22 20:12:16 mcr Exp $ * * This is the file formerly known as "ipsec_xform.h" * */#include <linux/config.h>#include <linux/version.h>#include <linux/kernel.h> /* printk() */#include "openswan/ipsec_param.h"#ifdef MALLOC_SLAB# include <linux/slab.h> /* kmalloc() */#else /* MALLOC_SLAB */# include <linux/malloc.h> /* kmalloc() */#endif /* MALLOC_SLAB */#include <linux/vmalloc.h> /* vmalloc() */#include <linux/errno.h>  /* error codes */#include <linux/types.h>  /* size_t */#include <linux/interrupt.h> /* mark_bh */#include <linux/netdevice.h>   /* struct device, and other headers */#include <linux/etherdevice.h> /* eth_type_trans */#include <linux/ip.h>          /* struct iphdr */#include <linux/skbuff.h>#include <openswan.h>#ifdef SPINLOCK#ifdef SPINLOCK_23#include <linux/spinlock.h> /* *lock* */#else /* SPINLOCK_23 */#include <asm/spinlock.h> /* *lock* */#endif /* SPINLOCK_23 */#endif /* SPINLOCK */#ifdef NET_21#include <asm/uaccess.h>#include <linux/in6.h>#endif#include <asm/checksum.h>#include <net/ip.h>#include "openswan/radij.h"#include "openswan/ipsec_stats.h"#include "openswan/ipsec_life.h"#include "openswan/ipsec_sa.h"#include "openswan/ipsec_xform.h"#include "openswan/ipsec_encap.h"#include "openswan/ipsec_radij.h"#include "openswan/ipsec_xform.h"#include "openswan/ipsec_ipe4.h"#include "openswan/ipsec_ah.h"#include "openswan/ipsec_esp.h"#include <pfkeyv2.h>#include <pfkey.h>#include "openswan/ipsec_proto.h"#include "openswan/ipsec_alg.h"#ifdef CONFIG_KLIPS_DEBUGint debug_xform = 0;#endif /* CONFIG_KLIPS_DEBUG */#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD];#ifdef SPINLOCKspinlock_t tdb_lock = SPIN_LOCK_UNLOCKED;#else /* SPINLOCK */spinlock_t tdb_lock;#endif /* SPINLOCK */struct ipsec_sadb ipsec_sadb;#if IPSEC_SA_REF_CODE/* the sub table must be narrower (or equal) in bits than the variable type   in the main table to count the number of unused entries in it. */typedef struct {	int testSizeOf_refSubTable :		((sizeof(IPsecRefTableUnusedCount) * 8) < IPSEC_SA_REF_SUBTABLE_IDX_WIDTH ? -1 : 1);} dummy;/* The field where the saref will be hosted in the skb must be wide enough to   accomodate the information it needs to store. */typedef struct {	int testSizeOf_refField : 		(IPSEC_SA_REF_HOST_FIELD_WIDTH < IPSEC_SA_REF_TABLE_IDX_WIDTH ? -1 : 1 );} dummy2;#define IPS_HASH(said) (((said)->spi + (said)->dst.u.v4.sin_addr.s_addr + (said)->proto) % SADB_HASHMOD)voidipsec_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;}intipsec_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;}intipsec_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 */intipsec_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;}intipsec_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_CODEIPsecSAref_tipsec_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 */intipsec_sa_print(struct ipsec_sa *ips){        char sa[SATOT_BUF];	size_t sa_len;	printk(KERN_INFO "klips_debug:   SA:");	if(ips == NULL) {		printk("NULL\n");		return -ENOENT;	}	printk(" ref=%d", ips->ips_ref);	printk(" refcount=%d", atomic_read(&ips->ips_refcount));	if(ips->ips_hnext != NULL) {		printk(" hnext=0p%p", ips->ips_hnext);	}	if(ips->ips_inext != NULL) {		printk(" inext=0p%p", ips->ips_inext);	}	if(ips->ips_onext != NULL) {		printk(" onext=0p%p", ips->ips_onext);	}	sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));	printk(" said=%s", sa_len ? sa : " (error)");	if(ips->ips_seq) {		printk(" seq=%u", ips->ips_seq);	}	if(ips->ips_pid) {		printk(" pid=%u", ips->ips_pid);	}	if(ips->ips_authalg) {		printk(" authalg=%u", ips->ips_authalg);	}	if(ips->ips_encalg) {		printk(" encalg=%u", ips->ips_encalg);	}	printk(" XFORM=%s%s%s", IPS_XFORM_NAME(ips));	if(ips->ips_replaywin) {		printk(" ooowin=%u", ips->ips_replaywin);	}	if(ips->ips_flags) {		printk(" flags=%u", ips->ips_flags);	}	if(ips->ips_addr_s) {		char buf[SUBNETTOA_BUF];		addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr,			0, buf, sizeof(buf));		printk(" src=%s", buf);	}	if(ips->ips_addr_d) {		char buf[SUBNETTOA_BUF];		addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr,			0, buf, sizeof(buf));		printk(" dst=%s", buf);	}	if(ips->ips_addr_p) {		char buf[SUBNETTOA_BUF];		addrtoa(((struct sockaddr_in*)(ips->ips_addr_p))->sin_addr,			0, buf, sizeof(buf));		printk(" proxy=%s", buf);	}	if(ips->ips_key_bits_a) {		printk(" key_bits_a=%u", ips->ips_key_bits_a);	}	if(ips->ips_key_bits_e) {		printk(" key_bits_e=%u", ips->ips_key_bits_e);	}	printk("\n");	return 0;}struct ipsec_sa*ipsec_sa_alloc(int*error) /* pass in error var by pointer */{	struct ipsec_sa* ips;	if((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) {		KLIPS_PRINT(debug_xform,			    "klips_debug:ipsec_sa_alloc: "			    "memory allocation error\n");		*error = -ENOMEM;		return NULL;	}	memset((caddr_t)ips, 0, sizeof(*ips));#if IPSEC_SA_REF_CODE	ips->ips_ref = ipsec_SAref_alloc(error); /* pass in error return by pointer */	KLIPS_PRINT(debug_xform,		    "klips_debug:ipsec_sa_alloc: "		    "allocated %lu bytes for ipsec_sa struct=0p%p ref=%d.\n",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -