示例#1
0
DEBUG_NO_STATIC int ipsec_mast_open(struct net_device *dev)
{
	struct mastpriv *prv = netdev_to_mastpriv(dev);

	prv = prv;

	/*
	 * Can't open until attached.
	 */

	KLIPS_PRINT(debug_mast & DB_MAST_INIT,
		    "klips_debug:ipsec_mast_open: "
		    "dev = %s\n",
		    dev->name);

	return 0;
}
示例#2
0
IPSEC_PROCFS_DEBUG_NO_STATIC
int ipsec_klipsdebug_show(struct seq_file *seq, void *offset)
{
	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
		    "klips_debug:ipsec_klipsdebug_show: seq=%p, offset=%p\n",
		    seq, offset);

	seq_printf(seq, "debug_tunnel=%08x.\n", debug_tunnel);
	seq_printf(seq, "debug_xform=%08x.\n", debug_xform);
	seq_printf(seq, "debug_eroute=%08x.\n", debug_eroute);
	seq_printf(seq, "debug_spi=%08x.\n", debug_spi);
	seq_printf(seq, "debug_radij=%08x.\n", debug_radij);
	seq_printf(seq, "debug_esp=%08x.\n", debug_esp);
	seq_printf(seq, "debug_ah=%08x.\n", debug_ah);
	seq_printf(seq, "debug_rcv=%08x.\n", debug_rcv);
	seq_printf(seq, "debug_pfkey=%08x.\n", debug_pfkey);
	return 0;
}
示例#3
0
int
ipsec_saref_freelist_init(void)
{
	int i;

	KLIPS_PRINT(debug_xform,
		    "klips_debug:ipsec_saref_freelist_init: "
		    "initialising %u elements of FreeList.\n",
		    IPSEC_SA_REF_FREELIST_NUM_ENTRIES);

	for(i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) {
		ipsec_sadb.refFreeList[i] = IPSEC_SAREF_NULL;
	}
	ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL;
	ipsec_sadb.refFreeListCont = IPSEC_SAREF_FIRST;
	ipsec_sadb.refFreeListTail = IPSEC_SAREF_NULL;
       
	return 0;
}
示例#4
0
IPSEC_PROCFS_DEBUG_NO_STATIC
int ipsec_saraw_show(struct seq_file *seq, void *offset)
{
	struct ipsec_sa *sa_p;
	extern struct ipsec_sa *ipsec_sa_raw;

	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
		    "klips_debug:ipsec_saraw_show: seq=%p offset=%p\n",
		    seq, offset);

	spin_lock_bh(&tdb_lock);

	for (sa_p = ipsec_sa_raw; sa_p; sa_p = sa_p->ips_raw)
		ipsec_spi_format(sa_p, seq);

	spin_unlock_bh(&tdb_lock);

	return 0;
}
示例#5
0
文件: ipsec_mast.c 项目: OPSF/uClinux
static void klips_get_secpath_refs(struct sec_path *sp,
		xfrm_sec_unique_t *refme, xfrm_sec_unique_t *refhim)
{
	struct ipsec_sa *sa1;

	if(sp==NULL) return;

	KLIPS_PRINT(debug_rcv, "klips_debug:klips_get_secpath_refs: "
			"retrieving saref=%u from sp=%p\n",
		    sp->ref, sp);

	*refme = sp->ref;

	sa1 = ipsec_sa_getbyref(sp->ref, IPSEC_REFOTHER);
	*refhim = sa1 ? sa1->ips_refhim : 0;

	if(sa1)
		ipsec_sa_put(sa1, IPSEC_REFOTHER);
}
示例#6
0
IPSEC_PROCFS_DEBUG_NO_STATIC
int ipsec_spi_show(struct seq_file *seq, void *offset)
{
	int i;
	struct ipsec_sa *sa_p;

	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
		    "klips_debug:ipsec_spi_show: seq=%p offset=%p\n",
		    seq, offset);

	spin_lock_bh(&tdb_lock);

	for (i = 0; i < SADB_HASHMOD; i++)
		for (sa_p = ipsec_sadb_hash[i]; sa_p; sa_p = sa_p->ips_hnext)
			ipsec_spi_format(sa_p, seq);

	spin_unlock_bh(&tdb_lock);

	return 0;
}
示例#7
0
文件: ipsec_sa.c 项目: mcr/bluerose
struct ipsec_sa*
ipsec_sa_alloc(int*error) /* pass in error var by pointer */
{
	struct ipsec_sa* ips;

	if((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) {
		KLIPS_PRINT(debug_xform,
			    "ipsec_sa_alloc: "
			    "memory allocation error\n");
		*error = -ENOMEM;
		return NULL;
	}
	memset((caddr_t)ips, 0, sizeof(*ips));

	/* return with at least counter = 1 */
	ipsec_sa_get(ips);

	*error = 0;
	return(ips);
}
示例#8
0
DEBUG_NO_STATIC int
ipsec_mast_open(struct device *dev)
{
	struct ipsecpriv *prv = dev->priv;
	
	/*
	 * Can't open until attached.
	 */

	KLIPS_PRINT(debug_mast & DB_MAST_INIT,
		    "klips_debug:ipsec_mast_open: "
		    "dev = %s, prv->dev = %s\n",
		    dev->name, prv->dev?prv->dev->name:"NONE");

	if (prv->dev == NULL)
		return -ENODEV;
	
	MOD_INC_USE_COUNT;
	return 0;
}
示例#9
0
DEBUG_NO_STATIC int
ipsec_mast_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
{
	KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
		    "klips_debug:ipsec_mast_neigh_setup_dev: "
		    "setting up %s\n",
		    dev ? dev->name : "NULL");

        if (p->tbl->family == AF_INET) {
                p->neigh_setup = ipsec_mast_neigh_setup;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)
		NEIGH_VAR_SET(p, UCAST_PROBES, 0);
		NEIGH_VAR_SET(p, MCAST_PROBES, 0);
#else
                p->ucast_probes = 0;
                p->mcast_probes = 0;
#endif
        }
        return 0;
}
示例#10
0
void ipsec_sa_untern(struct ipsec_sa *ips)
{
	IPsecSAref_t ref = ips->ips_ref;
	int error;

	/* verify that we are removing correct item! */
	error = ipsec_saref_verify_slot(ref);
	if (error)
		return;

	if (IPsecSAref2SA(ref) == ips) {
		IPsecSAref2SA(ref) = NULL;
		ipsec_sa_put(ips, IPSEC_REFINTERN);
	} else {
		KLIPS_PRINT(debug_xform,
			    "ipsec_sa_untern: "
			    "ref=%u -> %p but untern'ing %p\n", ref,
			    IPsecSAref2SA(ref), ips);
	}

}
示例#11
0
IPSEC_PROCFS_DEBUG_NO_STATIC
int ipsec_saref_show(struct seq_file *seq, void *offset)
{
	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
		    "klips_debug:ipsec_saref_show: seq=%p offset=%p\n",
		    seq, offset);

#ifdef IP_IPSEC_REFINFO
	seq_printf(seq, "refinfo patch applied\n");
#endif

#ifdef IP_IPSEC_BINDREF
	seq_printf(seq, "bindref patch applied\n");
#endif

#ifdef CONFIG_INET_IPSEC_SAREF
	seq_printf(seq, "saref enabled (%s)\n", ipsec_version_code());
#else
	seq_printf(seq, "saref disabled (%s)\n", ipsec_version_code());
#endif

	return 0;
}
示例#12
0
/*
   The ipsec_sa table better *NOT* be locked before it is handed in, or SMP locks will happen
 */
int ipsec_sa_add(struct ipsec_sa *ips)
{
	int error = 0;
	unsigned int hashval;

	if (ips == NULL) {
		KLIPS_PRINT(debug_xform,
			    "klips_error:ipsec_sa_add: "
			    "null pointer passed in!\n");
		return -ENODATA;
	}
	hashval = IPS_HASH(&ips->ips_said);

	ipsec_sa_get(ips, IPSEC_REFSAADD);
	spin_lock_bh(&tdb_lock);

	ips->ips_hnext = ipsec_sadb_hash[hashval];
	ipsec_sadb_hash[hashval] = ips;

	spin_unlock_bh(&tdb_lock);

	return error;
}
示例#13
0
文件: ipsec_sa.c 项目: ysleu/RTL8685
/*
  The tdb table better *NOT* be locked before it is handed in, or SMP locks will happen
*/
int
ipsec_sa_put(struct ipsec_sa *ips)
{
	int error = 0;
	unsigned int hashval;

	if(!ips) {
		KLIPS_PRINT(debug_xform,
			    "klips_error:puttdb: "
			    "null pointer passed in!\n");
		return -ENODATA;
	}
	hashval = ((ips->ips_said.spi + ips->ips_said.dst.s_addr + ips->ips_said.proto) % SADB_HASHMOD);

	spin_lock_bh(&tdb_lock);
	
	ips->ips_hnext = ipsec_sadb_hash[hashval];
	ipsec_sadb_hash[hashval] = ips;
	
	spin_unlock_bh(&tdb_lock);

	return error;
}
示例#14
0
文件: ipsec_mast.c 项目: OPSF/uClinux
static void
ipsec_mast_xsm_complete(
	struct ipsec_xmit_state *ixs,
	enum ipsec_xmit_value stat)
{
	if (stat != IPSEC_XMIT_OK) {
		KLIPS_PRINT(debug_mast,
				"klips_debug:ipsec_mast_xsm_complete: "
				"ipsec_xsm failed: %d\n",
				stat);
		goto cleanup;
	}

#ifdef NAT_TRAVERSAL
	/* do any final NAT-encapsulation */
	stat = ipsec_nat_encap(ixs);
	if(stat != IPSEC_XMIT_OK) {
		goto cleanup;
	}
#endif

	ipsec_xmit_send(ixs);

cleanup:
	ipsec_xmit_cleanup(ixs);

	if(ixs->ipsp) {
		ipsec_sa_put(ixs->ipsp, IPSEC_REFOTHER);
		ixs->ipsp=NULL;
	}
	if(ixs->skb) {
		ipsec_kfree_skb(ixs->skb);
		ixs->skb=NULL;
	}
	ipsec_xmit_state_delete(ixs);
}
示例#15
0
enum ipsec_rcv_value
ipsec_rcv_ipcomp_checks(struct ipsec_rcv_state *irs,
			struct sk_buff *skb)
{
	int ipcompminlen;

	ipcompminlen = sizeof(struct iphdr);

	if(skb->len < (ipcompminlen + sizeof(struct ipcomphdr))) {
		KLIPS_PRINT(debug_rcv & DB_RX_INAU,
			    "klips_debug:ipsec_rcv_ipcomp_checks: "
			    "runt comp packet of skb->len=%d received from %s, dropped.\n",
			    skb->len,
			    irs->ipsaddr_txt);
		if(irs->stats) {
			irs->stats->rx_errors++;
		}
		return IPSEC_RCV_BADLEN;
	}

	irs->protostuff.ipcompstuff.compp = (struct ipcomphdr *)skb_transport_header(skb);
	irs->said.spi = htonl((__u32)ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi));
	return IPSEC_RCV_OK;
}
示例#16
0
int
ipsec_sadb_init(void)
{
	int error = 0;
	unsigned i;

	for(i = 0; i < SADB_HASHMOD; i++) {
		ipsec_sadb_hash[i] = NULL;
	}
	/* parts above are for the old style SADB hash table */
	

	/* initialise SA reference table */

	/* initialise the main table */
	KLIPS_PRINT(debug_xform,
		    "klips_debug:ipsec_sadb_init: "
		    "initialising main table of size %u (2 ^ %u).\n",
		    IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES,
		    IPSEC_SA_REF_MAINTABLE_IDX_WIDTH);
	{
		unsigned table;
		for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) {
			ipsec_sadb.refTable[table] = NULL;
		}
	}

	/* allocate the first sub-table */
	error = ipsec_SArefSubTable_alloc(0);
	if(error) {
		return error;
	}

	error = ipsec_saref_freelist_init();
	return error;
}
示例#17
0
struct ipsec_sa*ipsec_sa_alloc(int *error) /* pass in error var by pointer */
{
	struct ipsec_sa *ips;

	if ((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) {
		KLIPS_PRINT(debug_xform,
			    "ipsec_sa_alloc: "
			    "memory allocation error\n");
		*error = -ENOMEM;
		return NULL;
	}
	memset((caddr_t)ips, 0, sizeof(*ips));

#ifdef IPSEC_SA_RECOUNT_DEBUG
	ips->ips_raw = ipsec_sa_raw;
	ipsec_sa_raw = ips;
#endif

	/* return with at least counter = 1 */
	ipsec_sa_get(ips, IPSEC_REFALLOC);

	*error = 0;
	return ips;
}
示例#18
0
文件: ipsec_alg.c 项目: dgeo96/pfe
/*
 * 	encryption key context creation function
 * 	called from pfkey_v2_parser.c:pfkey_ips_init() 
 */
int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) {
	int ret=-EINVAL;
	int keyminbits, keymaxbits;
	caddr_t ekp;
	struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc;

	KLIPS_PRINT(debug_pfkey,
		    "klips_debug:ipsec_alg_enc_key_create: "
		    "entering with encalg=%d ixt_e=%p\n",
		    sa_p->ips_encalg, ixt_e);
	if (!ixt_e) {
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:ipsec_alg_enc_key_create: "
			    "NULL ipsec_alg_enc object\n");
		return -EPROTO;
	}
	if (ixt_e->ixt_e_validate_key) {
		if ((ret=ixt_e->ixt_e_validate_key(sa_p)) < 0) {
			KLIPS_PRINT(debug_pfkey,
				"klips_debug:pfkey_ipsec_sa_init: "
				"error calling validate_key() "
				"key_bits_e=%d\n",
				sa_p->ips_key_bits_e);
			goto ixt_out;
		}
	} else {
		keyminbits=ixt_e->ixt_keyminbits;
		keymaxbits=ixt_e->ixt_keymaxbits;
		if(sa_p->ips_key_bits_e<keyminbits || 
				sa_p->ips_key_bits_e>keymaxbits) {
			KLIPS_PRINT(debug_pfkey,
				"klips_debug:ipsec_alg_enc_key_create: "
				"incorrect encryption key size: %d bits -- "
				"must be between %d,%d bits\n" /*octets (bytes)\n"*/,
				sa_p->ips_key_bits_e, keyminbits, keymaxbits);
			ret=-EINVAL;
			goto ixt_out;
		}
	}
	/* save encryption key pointer */
	ekp = sa_p->ips_key_e;

	if((sa_p->ips_key_e = (caddr_t)
	    kmalloc((sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size),
		    GFP_ATOMIC)) == NULL) {
		ret=-ENOMEM;
		goto ixt_out;
	}
	/* zero-out key_e */
	memset(sa_p->ips_key_e, 0, sa_p->ips_key_e_size);

	/* I cast here to allow more decoupling in alg module */
	KLIPS_PRINT(debug_pfkey,
		    "klips_debug:ipsec_alg_enc_key_create: about to call:"
			    "set_key(key_e=%p, ekp=%p, key_size=%d)\n",
			    (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8);
	ret = ixt_e->ixt_e_set_key((caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8);
	/* paranoid */
	memset(ekp, 0, sa_p->ips_key_bits_e/8);
	kfree(ekp);
ixt_out:
	return ret;
}
示例#19
0
enum ipsec_rcv_value ipsec_rcv_ipcomp_decomp(struct ipsec_rcv_state *irs)
{
	unsigned int flags = 0;
	struct ipsec_sa *ipsp = irs->ipsp;
	struct sk_buff *skb;

	skb = irs->skb;

	ipsec_xmit_dmp("ipcomp", skb_transport_header(skb), skb->len);

	if (ipsp == NULL)
		return IPSEC_RCV_SAIDNOTFOUND;

	if (sysctl_ipsec_inbound_policy_check &&
	    ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) !=
	       (ntohl(irs->said.spi) & 0x0000ffff)) &&
	      (ipsp->ips_encalg != ntohl(irs->said.spi))  /* this is a workaround for peer non-compliance with rfc2393 */
	      ))) {
		char sa2[SATOT_BUF];
		size_t sa_len2 = 0;

		sa_len2 = KLIPS_SATOT(debug_rcv, &ipsp->ips_said, 0, sa2,
				      sizeof(sa2));

		KLIPS_PRINT(debug_rcv,
			    "klips_debug:ipsec_rcv_ipcomp_decomp: "
			    "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n",
			    irs->sa_len ? irs->sa : " (error)",
			    sa_len2 ? sa2 : " (error)",
			    ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi),
			    (__u32)ntohl(irs->said.spi),
			    (__u32)ntohl((ipsp->ips_said.spi)),
			    (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff));
		if (irs->stats)
			irs->stats->rx_dropped++;
		return IPSEC_RCV_SAIDNOTFOUND;
	}

	if (lsw_ip_hdr_version(irs) == 6)
		ipsp->ips_comp_ratio_cbytes +=
			ntohs(lsw_ip6_hdr(irs)->payload_len) +
			sizeof(struct ipv6hdr);
	else
		ipsp->ips_comp_ratio_cbytes +=
			ntohs(lsw_ip4_hdr(irs)->tot_len);
	irs->next_header = irs->protostuff.ipcompstuff.compp->ipcomp_nh;

#ifdef CONFIG_KLIPS_OCF
	if (irs->ipsp->ocf_in_use)
		return ipsec_ocf_rcv(irs);

#endif

	skb = skb_decompress(skb, ipsp, &flags);
	if (!skb || flags) {
		KLIPS_PRINT(debug_rcv,
			    "klips_debug:ipsec_rcv_ipcomp_decomp: "
			    "skb_decompress() returned error flags=%x, dropped.\n",
			    flags);
		if (irs->stats) {
			if (flags)
				irs->stats->rx_errors++;
			else
				irs->stats->rx_dropped++;
		}
		return IPSEC_RCV_IPCOMPFAILED;
	}

	/* make sure we update the pointer */
	irs->skb = skb;

	irs->iph = (void *) ip_hdr(skb);

	if (lsw_ip_hdr_version(irs) == 6)
		ipsp->ips_comp_ratio_dbytes +=
			ntohs(lsw_ip6_hdr(irs)->payload_len) +
			sizeof(struct ipv6hdr);
	else
		ipsp->ips_comp_ratio_dbytes +=
			ntohs(lsw_ip4_hdr(irs)->tot_len);

	KLIPS_PRINT(debug_rcv,
		    "klips_debug:ipsec_rcv_ipcomp_decomp: "
		    "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n",
		    irs->sa_len ? irs->sa : " (error)",
		    (__u32)ntohl(irs->said.spi),
		    ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0,
		    ipsp != NULL ?
		      (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0,
		    irs->next_header);
	KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, irs->iph);

	return IPSEC_RCV_OK;
}
示例#20
0
文件: ipsec_mast.c 项目: OPSF/uClinux
/*
 *	Called when an ipsec mast device is initialized.
 *	The ipsec mast device structure is passed to us.
 */
int
ipsec_mast_probe(struct net_device *dev)
{
	int i;
	struct ipsecpriv *ipriv;

	KLIPS_PRINT(debug_mast,
		    "klips_debug:ipsec_mast_probe: "
		    "allocating %lu bytes initialising device: %s\n",
		    (unsigned long) sizeof(struct mastpriv),
		    dev->name ? dev->name : "NULL");

#ifndef USE_NETDEV_OPS
	/* Add our mast functions to the device */
	dev->open		= ipsec_mast_open;
	dev->stop		= ipsec_mast_close;
	dev->hard_start_xmit	= ipsec_mast_start_xmit;
	dev->get_stats		= ipsec_mast_get_stats;
	dev->set_multicast_list = NULL;
	dev->do_ioctl		= ipsec_mast_ioctl;
	dev->set_mac_address 	= NULL;
	dev->neigh_setup        = ipsec_mast_neigh_setup_dev;
#endif
#ifdef alloc_netdev
	dev->destructor         = free_netdev;
#endif

#ifndef alloc_netdev
	dev->priv = kmalloc(sizeof(struct mastpriv), GFP_KERNEL);
	if (dev->priv == NULL)
		return -ENOMEM;
#endif
	ipriv = netdev_priv(dev);
	memset(netdev_priv(dev), 0, sizeof(struct mastpriv));

	for(i = 0; i < sizeof(zeroes); i++) {
		((__u8*)(zeroes))[i] = 0;
	}
	
#ifdef HAVE_NETDEV_HEADER_OPS
	dev->header_ops = NULL;
#else
	dev->hard_header	= NULL;
	dev->rebuild_header 	= NULL;
	dev->header_cache_update= NULL;
#endif
	dev->hard_header_len 	= 8+20+20+8;
	dev->mtu		= 0;
	dev->addr_len		= 0;
	dev->type		= ARPHRD_NONE;
	dev->tx_queue_len	= 10;		
#ifdef IFF_XMIT_DST_RELEASE
	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
#endif
	memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN);	/* what if this is not attached to ethernet? */

	/* New-style flags. */
	dev->flags		= IFF_NOARP;

	/* pick a random ethernet address for now. */
	random_ether_addr(dev->dev_addr);

	/* We're done.  Have I forgotten anything? */
	return 0;
}
示例#21
0
文件: ipsec_mast.c 项目: OPSF/uClinux
int
ipsec_mast_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
{
	struct net_device *dev = ptr;
	struct mastpriv *priv = netdev_priv(dev);

	priv = priv;

	if (dev == NULL) {
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "dev=NULL for event type %ld.\n",
			    event);
		return(NOTIFY_DONE);
	}

	/* check for loopback devices */
	if (dev && (dev->flags & IFF_LOOPBACK)) {
		return(NOTIFY_DONE);
	}

	switch (event) {
	case NETDEV_DOWN:
		/* look very carefully at the scope of these compiler
		   directives before changing anything... -- RGB */

	case NETDEV_UNREGISTER:
		switch (event) {
		case NETDEV_DOWN:
			KLIPS_PRINT(debug_mast & DB_MAST_INIT,
				    "klips_debug:ipsec_mast_device_event: "
				    "NETDEV_DOWN dev=%s flags=%x\n",
				    dev->name,
				    dev->flags);
			if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) {
				printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n",
				       dev->name);
			}
			break;
		case NETDEV_UNREGISTER:
			KLIPS_PRINT(debug_mast & DB_MAST_INIT,
				    "klips_debug:ipsec_mast_device_event: "
				    "NETDEV_UNREGISTER dev=%s flags=%x\n",
				    dev->name,
				    dev->flags);
			break;
		}
		break;

	case NETDEV_UP:
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "NETDEV_UP dev=%s\n",
			    dev->name);
		break;

	case NETDEV_REBOOT:
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "NETDEV_REBOOT dev=%s\n",
			    dev->name);
		break;

	case NETDEV_CHANGE:
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "NETDEV_CHANGE dev=%s flags=%x\n",
			    dev->name,
			    dev->flags);
		break;

	case NETDEV_REGISTER:
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "NETDEV_REGISTER dev=%s\n",
			    dev->name);
		break;

	case NETDEV_CHANGEMTU:
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "NETDEV_CHANGEMTU dev=%s to mtu=%d\n",
			    dev->name,
			    dev->mtu);
		break;

	case NETDEV_CHANGEADDR:
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "NETDEV_CHANGEADDR dev=%s\n",
			    dev->name);
		break;

	case NETDEV_GOING_DOWN:
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "NETDEV_GOING_DOWN dev=%s\n",
			    dev->name);
		break;

	case NETDEV_CHANGENAME:
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "NETDEV_CHANGENAME dev=%s\n",
			    dev->name);
		break;

	default:
		KLIPS_PRINT(debug_mast & DB_MAST_INIT,
			    "klips_debug:ipsec_mast_device_event: "
			    "event type %ld unrecognised for dev=%s\n",
			    event,
			    dev->name);
		break;
	}
	return NOTIFY_DONE;
}
示例#22
0
文件: ipsec_mast.c 项目: OPSF/uClinux
/*
 * Revectored calls.
 * For each of these calls, a field exists in our private structure.
 */
DEBUG_NO_STATIC int
ipsec_mast_hard_header(struct sk_buff *skb, struct net_device *dev,
	unsigned short type, void *daddr, void *saddr, unsigned len)
{
	struct mastpriv *prv = (struct mastpriv *)netdev_priv(dev);
	struct net_device_stats *stats;	/* This device's statistics */
	int ret = 0;
	
	if(skb == NULL) {
		KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
			    "klips_debug:ipsec_mast_hard_header: "
			    "no skb...\n");
		return -ENODATA;
	}

	if(dev == NULL) {
		KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
			    "klips_debug:ipsec_mast_hard_header: "
			    "no device...\n");
		return -ENODEV;
	}

	KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
		    "klips_debug:ipsec_mast_hard_header: "
		    "skb->dev=%s\n",
		    dev->name);
	
	if(prv == NULL) {
		KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
			    "klips_debug:ipsec_mast_hard_header: "
			    "no private space associated with dev=%s\n",
			    dev->name ? dev->name : "NULL");
		return -ENODEV;
	}

	stats = (struct net_device_stats *) &(prv->mystats);

	/* check if we have to send a IPv6 packet. It might be a Router
	   Solicitation, where the building of the packet happens in
	   reverse order:
	   1. ll hdr,
	   2. IPv6 hdr,
	   3. ICMPv6 hdr
	   -> skb->nh.raw is still uninitialized when this function is
	   called!!  If this is no IPv6 packet, we can print debugging
	   messages, otherwise we skip all debugging messages and just
	   build the ll header */
	if(type != ETH_P_IPV6) {
		/* execute this only, if we don't have to build the
		   header for a IPv6 packet */
		if(!prv->hard_header) {
			KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
				    "klips_debug:ipsec_mast_hard_header: "
				    "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ",
				    saddr,
				    daddr,
				    len,
				    type,
				    dev->name);
			KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC,
					"ip=%08x->%08x\n",
					(__u32)ntohl(skb->nh.iph->saddr),
					(__u32)ntohl(skb->nh.iph->daddr) );
			stats->tx_dropped++;
			return -ENODEV;
		}
	} else {
		KLIPS_PRINT(debug_mast,
			    "klips_debug:ipsec_mast_hard_header: "
			    "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n");
	}                                                                      

	return ret;
}
示例#23
0
文件: ipsec_mast.c 项目: OPSF/uClinux
/*
 *	This function assumes it is being called from dev_queue_xmit()
 *	and that skb is filled properly by that function.
 */
int
ipsec_mast_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct ipsec_xmit_state *ixs;
	IPsecSAref_t SAref;

	KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_start_xmit: skb=%p\n", skb);
	if(skb == NULL) {
		printk("ipsec_mast_start_xmit: "
			"passed NULL\n");
		return 0;
	}
		
	ixs = ipsec_xmit_state_new(dev);
	if(ixs == NULL)
		return NETDEV_TX_BUSY;

	ixs->dev = dev;
	ixs->skb = skb;
	SAref = 0;
#ifdef NETDEV_25
#if defined(CONFIG_NETFILTER)
	if(skb->nfmark & IPSEC_NFMARK_IS_SAREF_BIT) {
		SAref = NFmark2IPsecSAref(skb->nfmark);
		KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_start_xmit: "
				"getting SAref=%d from nfmark\n",
				SAref);
	}
#endif
#endif

#ifdef CONFIG_INET_IPSEC_SAREF
	if(skb->sp && skb->sp->ref != IPSEC_SAREF_NULL) {
		SAref = skb->sp->ref;
		KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_start_xmit: "
				"getting SAref=%d from sec_path\n",
				SAref);
	}
#endif

	if (ipsec_xmit_sanity_check_skb(ixs) != IPSEC_XMIT_OK) {
		ipsec_xmit_cleanup(ixs);
		ipsec_xmit_state_delete(ixs);
		return 0;
	}

	ixs->ipsp = ipsec_sa_getbyref(SAref, IPSEC_REFOTHER);
	if(ixs->ipsp == NULL) {
		KLIPS_ERROR(debug_mast, "klips_debug:ipsec_mast_start_xmit: "
				"%s: no SA for saref=%d\n",
				dev->name, SAref);
		ipsec_xmit_cleanup(ixs);
		ipsec_xmit_state_delete(ixs);
		return 0;
	}

	/* make sure this packet can go out on this SA */
	if (ipsec_mast_check_outbound_policy(ixs)) {
		ipsec_xmit_cleanup(ixs);
		ipsec_xmit_state_delete(ixs);
		return 0;
	}

	/* fill in outgoing_said using the ipsp we have */
	ixs->outgoing_said = ixs->ipsp->ips_said;

#ifdef NETDEV_25
#if defined(CONFIG_NETFILTER)
	/* prevent recursion through the saref route */
	if(skb->nfmark & 0x80000000) {
		skb->nfmark = 0;
	}
#endif
#endif
#if 0
	/* TODO: do we have to also have to do this? */
	if(skb->sp && skb->sp->ref != IPSEC_SAREF_NULL) {
		secpath_put(skb->sp);
		skb->sp = NULL;
	}
#endif

	/*
	 * we should be calculating the MTU by looking up a route
	 * based upon the destination in the SA, and then cache
	 * it into the SA, but we don't do that right now.
	 */
	ixs->cur_mtu = 1460;
	ixs->physmtu = 1460;

	ixs->mast_mode = 1;
	ixs->xsm_complete = ipsec_mast_xsm_complete;
	ixs->state = IPSEC_XSM_INIT2;	/* we start later in the process */
	ixs->prv = netdev_priv(ixs->dev);
	ixs->stats = (struct net_device_stats *) &(ixs->prv->mystats);

	ipsec_xsm(ixs);
	return 0;

}
示例#24
0
文件: ipsec_mast.c 项目: OPSF/uClinux
/*
 * Verify that the skb can go out on this ipsp.
 * Return 0 if OK, error code otherwise.
 */
static int
ipsec_mast_check_outbound_policy(struct ipsec_xmit_state *ixs)
{
	int failed_outbound_check = 0;
	struct ipsec_sa *ipsp = ixs->ipsp;

	if (!ixs || !ixs->ipsp || !ixs->iph)
		return -EFAULT;

	/* Note: "xor" (^) logically replaces "not equal"
	 * (!=) and "bitwise or" (|) logically replaces
	 * "boolean or" (||).  This is done to speed up
	 * execution by doing only bitwise operations and
	 * no branch operations */
	if (osw_ip_hdr_version(ixs) == 4) {
		struct iphdr *ipp = osw_ip4_hdr(ixs);
		if (ip_address_family(&ipsp->ips_said.dst) != AF_INET) {
			failed_outbound_check = 1;
		} else if (((ipp->saddr & ipsp->ips_mask_s.u.v4.sin_addr.s_addr)
				^ ipsp->ips_flow_s.u.v4.sin_addr.s_addr)
				| ((ipp->daddr & ipsp->ips_mask_d.u.v4.sin_addr.s_addr)
				^ ipsp->ips_flow_d.u.v4.sin_addr.s_addr)) {
			failed_outbound_check = 1;
		}
	} else if (osw_ip_hdr_version(ixs) == 6) {
		struct ipv6hdr *ipp6 = osw_ip6_hdr(ixs);
		if (ip_address_family(&ipsp->ips_said.dst) != AF_INET6) {
			failed_outbound_check = 1;
		} else if (((ipp6->saddr.s6_addr32[0] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[0])
				^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[0])
				| ((ipp6->daddr.s6_addr32[0] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[0])
				^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[0])) {
			failed_outbound_check = 1;
		} else if (((ipp6->saddr.s6_addr32[1] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[1])
				^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[1])
				| ((ipp6->daddr.s6_addr32[1] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[1])
				^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[1])) {
			failed_outbound_check = 1;
		} else if (((ipp6->saddr.s6_addr32[2] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[2])
				^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[2])
				| ((ipp6->daddr.s6_addr32[2] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[2])
				^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[2])) {
			failed_outbound_check = 1;
		} else if (((ipp6->saddr.s6_addr32[3] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[3])
				^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[3])
				| ((ipp6->daddr.s6_addr32[3] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[3])
				^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[3])) {
			failed_outbound_check = 1;
		}
	}
	if (failed_outbound_check) {
		char saddr_txt[ADDRTOA_BUF], daddr_txt[ADDRTOA_BUF];
		char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF];

		if (ipsp->ips_flow_s.u.v4.sin_family == AF_INET6) {
			subnet6toa(&ipsp->ips_flow_s.u.v6.sin6_addr,
					&ipsp->ips_mask_s.u.v6.sin6_addr,
					0, sflow_txt, sizeof(sflow_txt));
			subnet6toa(&ipsp->ips_flow_d.u.v6.sin6_addr,
					&ipsp->ips_mask_d.u.v6.sin6_addr,
					0, dflow_txt, sizeof(dflow_txt));
			inet_addrtot(AF_INET6, &osw_ip6_hdr(ixs)->saddr, 0, saddr_txt,
					sizeof(saddr_txt));
			inet_addrtot(AF_INET6, &osw_ip6_hdr(ixs)->daddr, 0, daddr_txt,
					sizeof(daddr_txt));
		} else {
			subnettoa(ipsp->ips_flow_s.u.v4.sin_addr,
					ipsp->ips_mask_s.u.v4.sin_addr,
					0, sflow_txt, sizeof(sflow_txt));
			subnettoa(ipsp->ips_flow_d.u.v4.sin_addr,
					ipsp->ips_mask_d.u.v4.sin_addr,
					0, dflow_txt, sizeof(dflow_txt));
			inet_addrtot(AF_INET, &osw_ip4_hdr(ixs)->saddr, 0, saddr_txt,
					sizeof(saddr_txt));
			inet_addrtot(AF_INET, &osw_ip4_hdr(ixs)->daddr, 0, daddr_txt,
					sizeof(daddr_txt));
		}

		if (!ixs->sa_len) ixs->sa_len = KLIPS_SATOT(debug_mast,
				&ixs->outgoing_said, 0,
				ixs->sa_txt, sizeof(ixs->sa_txt));

		KLIPS_PRINT(debug_mast,
			    "klips_debug:ipsec_mast_check_outbound_policy: "
			    "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n",
			    ixs->sa_len ? ixs->sa_txt : " (error)",
			    sflow_txt, dflow_txt, saddr_txt, daddr_txt);
		if(ixs->stats)
			ixs->stats->rx_dropped++;
		return -EACCES;
	}

#if 0
	{
		char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF];
		char saddr_txt[ADDRTOA_BUF], daddr_txt[ADDRTOA_BUF];
		struct in_addr ipaddr;

		subnettoa(ixs->ipsp->ips_flow_s.u.v4.sin_addr,
			  ixs->ipsp->ips_mask_s.u.v4.sin_addr,
			  0, sflow_txt, sizeof(sflow_txt));
		subnettoa(ixs->ipsp->ips_flow_d.u.v4.sin_addr,
			  ixs->ipsp->ips_mask_d.u.v4.sin_addr,
			  0, dflow_txt, sizeof(dflow_txt));

		ipaddr.s_addr = ixs->iph->saddr;
		addrtoa(ipaddr, 0, saddr_txt, sizeof(saddr_txt));
		ipaddr.s_addr = ixs->iph->daddr;
		addrtoa(ipaddr, 0, daddr_txt, sizeof(daddr_txt));

		if (!ixs->sa_len) ixs->sa_len = KLIPS_SATOT(debug_mast,
				&ixs->outgoing_said, 0,
				ixs->sa_txt, sizeof(ixs->sa_txt));

		KLIPS_PRINT(debug_mast,
			    "klips_debug:ipsec_mast_check_outbound_policy: "
			    "SA:%s, inner tunnel policy [%s -> %s] agrees with pkt contents [%s -> %s].\n",
			    ixs->sa_len ? ixs->sa_txt : " (error)",
			    sflow_txt, dflow_txt, saddr_txt, daddr_txt);
	}
#endif

	return 0;
}
示例#25
0
文件: ipsec_mast.c 项目: OPSF/uClinux
/* Paul: This seems to be unused dead code */
enum ipsec_xmit_value
ipsec_mast_send(struct ipsec_xmit_state*ixs)
{
	/* new route/dst cache code from James Morris */
	ixs->skb->dev = ixs->physdev;
	/*skb_orphan(ixs->skb);*/
	if((ixs->error = ip_route_output(&ixs->route,
				    ixs->skb->nh.iph->daddr,
				    ixs->pass ? 0 : ixs->skb->nh.iph->saddr,
				    RT_TOS(ixs->skb->nh.iph->tos),
				    ixs->physdev->ifindex /* rgb: should this be 0? */))) {
		ixs->stats->tx_errors++;
		KLIPS_PRINT(debug_mast & DB_MAST_XMIT,
			    "klips_debug:ipsec_mast_send: "
			    "ip_route_output failed with error code %d, dropped\n",
			    ixs->error);
		return IPSEC_XMIT_ROUTEERR;
	}
	if(ixs->dev == ixs->route->u.dst.dev) {
		ip_rt_put(ixs->route);
		/* This is recursion, drop it. */
		ixs->stats->tx_errors++;
		KLIPS_PRINT(debug_mast & DB_MAST_XMIT,
			    "klips_debug:ipsec_mast_send: "
			    "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n",
			    ixs->dev->name);
		return IPSEC_XMIT_RECURSDETECT;
	}
	dst_release(skb_dst(ixs->skb));
	skb_dst_set(ixs->skb, &ixs->route->u.dst);
	ixs->stats->tx_bytes += ixs->skb->len;
	if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) {
		ixs->stats->tx_errors++;
		printk(KERN_WARNING
		       "klips_error:ipsec_mast_send: "
		       "tried to __skb_pull nh-data=%ld, %d available.  This should never happen, please report.\n",
		       (unsigned long)(ixs->skb->nh.raw - ixs->skb->data),
		       ixs->skb->len);
		return IPSEC_XMIT_PUSHPULLERR;
	}
	__skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data);

	ipsec_nf_reset(ixs->skb);

	KLIPS_PRINT(debug_mast & DB_MAST_XMIT,
		    "klips_debug:ipsec_mast_send: "
		    "...done, calling ip_send() on device:%s\n",
		    ixs->skb->dev ? ixs->skb->dev->name : "NULL");
	KLIPS_IP_PRINT(debug_mast & DB_MAST_XMIT, ixs->skb->nh.iph);
	{
		int err;

		err = NF_HOOK(PF_INET, OSW_NF_INET_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev,
			      ipsec_mast_xmit2);
		if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) {
			if(net_ratelimit())
				printk(KERN_ERR
				       "klips_error:ipsec_mast_send: "
				       "ip_send() failed, err=%d\n", 
				       -err);
			ixs->stats->tx_errors++;
			ixs->stats->tx_aborted_errors++;
			ixs->skb = NULL;
			return IPSEC_XMIT_IPSENDFAILURE;
		}
	}
	ixs->stats->tx_packets++;
        ixs->skb = NULL;

        return IPSEC_XMIT_OK;
}
示例#26
0
static int ipsec_ocf_xmit_cb(struct cryptop *crp)
{
	struct ipsec_xmit_state *ixs =
		(struct ipsec_xmit_state *)crp->crp_opaque;
	struct iphdr *newiph;
	struct ipcomphdr *cmph;
	unsigned orig_len, comp_len;
	struct cryptodesc *crdc = NULL;

	KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
		    "klips_debug:ipsec_ocf_xmit_cb\n");

	if (ixs == NULL) {
		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb: "
			    "NULL ixs in callback\n");
		return 0;
	}

	/*
	 * we must update the state before returning to the state machine.
	 * if we have an error,  terminate the processing by moving to the DONE
	 * state
	 */

	ixs->state = IPSEC_XSM_DONE; /* assume bad xmit */
	if (crp->crp_etype) {
		ptrdiff_t ptr_delta;

		if (crp->crp_etype == EAGAIN) {
			/* Session has been migrated. Store the new session id and retry */
			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
				    "klips_debug:ipsec_ocf_xmit_cb: crypto session migrated\n");
			ixs->ipsp->ocf_cryptoid = crp->crp_sid;
			/* resubmit request */
			if (crypto_dispatch(crp) == 0)
				return 0;
			/* resubmit failed */
		}

		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb: "
			    "error in processing 0x%x\n",
			    crp->crp_etype);

		switch (ixs->ipsp->ips_said.proto) {
		case IPPROTO_COMP:
			/*
			 * It's ok for compression to fail... we made a clone
			 * of the packet, so we just revert it now...
			 */
			if (!ixs->pre_ipcomp_skb) {
				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
					    "klips_debug:ipsec_ocf_xmit_cb: "
					    "IPcomp on %u bytes failed, "
					    "but we have no clone!\n",
					    (unsigned int)
					    (lsw_ip_hdr_version(ixs) == 6 ?
					     (ntohs(lsw_ip6_hdr(ixs)->
						    payload_len) +
					      sizeof(struct ipv6hdr))
					     :
					     ntohs(lsw_ip4_hdr(
							   ixs)->tot_len)) -
					    ixs->iphlen);
				/* this is a fail. */
				break;
			}

			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
				    "klips_debug:ipsec_ocf_xmit_cb: "
				    "IPcomp on %u bytes failed, "
				    "using backup clone.\n",
				    (unsigned int)
				    (lsw_ip_hdr_version(ixs) == 6 ?
				     (ntohs(lsw_ip6_hdr(ixs)->payload_len) +
				      sizeof(struct ipv6hdr)) :
				     ntohs(lsw_ip4_hdr(ixs)->tot_len)) -
				    ixs->iphlen);

			ptr_delta = ixs->pre_ipcomp_skb->data - ixs->skb->data;
			ixs->iph           =
				(void*)((char*)ixs->iph + ptr_delta);

			/*
			 * can not free it here, because we are under
			 * IRQ, potentially, so queue it for later
			 */
			kfree_skb(ixs->skb);
			ixs->skb = ixs->pre_ipcomp_skb;
			ixs->pre_ipcomp_skb = NULL;

			skb_set_network_header(ixs->skb,
					       ipsec_skb_offset(ixs->skb,
								((
									 void
									 *)
								 skb_network_header(
									 ixs->
									 skb))
								+
								ptr_delta));
			skb_set_transport_header(ixs->skb,
						 ipsec_skb_offset(ixs->skb,
								  ((
									   void
									   *)
								   skb_transport_header(
									   ixs
									   ->
									   skb))
								  +
								  ptr_delta));
			KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph);

			/* this means we don't compress */
			ixs->state = IPSEC_XSM_CONT;
			break;
		}
		goto bail;
	}

	switch (ixs->ipsp->ips_said.proto) {
	case IPPROTO_ESP:
		/* ESP, nothing to do */
		break;

	case IPPROTO_AH:
		/* AH post processing, put back fields we had to zero */
		if (lsw_ip_hdr_version(ixs) == 4) {
			lsw_ip4_hdr(ixs)->ttl      = ixs->ttl;
			lsw_ip4_hdr(ixs)->check    = ixs->check;
			lsw_ip4_hdr(ixs)->frag_off = ixs->frag_off;
			lsw_ip4_hdr(ixs)->tos      = ixs->tos;
		}
		break;

	case IPPROTO_COMP:
		/* IPcomp fill in the header */
		crdc = crp->crp_desc;

		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
			    "klips_debug:ipsec_ocf_xmit_cb: "
			    "after <%s%s%s>, SA:%s:\n",
			    IPS_XFORM_NAME(ixs->ipsp),
			    ixs->sa_len ? ixs->sa_txt : " (error)");
		KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph);

		orig_len = (lsw_ip_hdr_version(ixs) == 6 ?
			    (ntohs(lsw_ip6_hdr(ixs)->payload_len) +
			     sizeof(struct ipv6hdr)) :
			    ntohs(lsw_ip4_hdr(ixs)->tot_len)) -
			   ixs->iphlen;
		comp_len = crp->crp_olen;

		if (sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
			ipsec_dmp_block("compress after",
					((unsigned char*)ixs->iph) + ixs->iphlen,
					comp_len);
		}

		newiph =
			(struct iphdr *)((char*)ixs->iph -
					 sizeof(struct ipcomphdr));
		cmph = (struct ipcomphdr *)((char*)newiph + ixs->iphlen);

		/* move the ip header to make room for the new ipcomp header */
		memmove(((unsigned char *) ixs->skb->data) -
			sizeof(struct ipcomphdr),
			ixs->skb->data,
			(((unsigned char *) ixs->iph) + ixs->iphlen) -
			((unsigned char *) ixs->skb->data));
		/* DAVIDM check for head room */
		skb_push(ixs->skb, sizeof(struct ipcomphdr));

		ixs->iph = newiph;
		skb_set_network_header(ixs->skb,
				       ipsec_skb_offset(ixs->skb, newiph));
		skb_set_transport_header(ixs->skb,
					 ipsec_skb_offset(ixs->skb,
							  newiph) +
					 ixs->iphlen);

		/* now we can fill in the ipcomp header */
		cmph->ipcomp_nh = ixs->next_header;
		cmph->ipcomp_flags = 0;
		cmph->ipcomp_cpi =
			htons((__u16)(ntohl(ixs->ipsp->ips_said.spi) &
				      0x0000ffff));

		/* update the ip header to reflect the compression */
		if (lsw_ip_hdr_version(ixs) == 6) {
			lsw_ip6_hdr(ixs)->nexthdr     = IPPROTO_COMP;
			lsw_ip6_hdr(ixs)->payload_len = htons(ixs->iphlen +
							      sizeof(struct
								     ipcomphdr) + comp_len -
							      sizeof(struct
								     ipv6hdr));
		} else {
			lsw_ip4_hdr(ixs)->protocol    = IPPROTO_COMP;
			lsw_ip4_hdr(ixs)->tot_len     = htons(ixs->iphlen +
							      sizeof(struct
								     ipcomphdr) +
							      comp_len);
			lsw_ip4_hdr(ixs)->check       = 0;
			lsw_ip4_hdr(ixs)->check       =
				ip_fast_csum((char *) ixs->iph, lsw_ip4_hdr(
						     ixs)->ihl);
		}

		/* Update skb length/tail by "unputting" the shrinkage */
		safe_skb_put(ixs->skb, comp_len - orig_len);

		ixs->ipsp->ips_comp_adapt_skip = 0;
		ixs->ipsp->ips_comp_adapt_tries = 0;

		/* release the backup copy */
		if (ixs->pre_ipcomp_skb) {
			kfree_skb(ixs->pre_ipcomp_skb);
			ixs->pre_ipcomp_skb = NULL;
		}

		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
			    "klips_debug:ipsec_ocf_xmit_cb: "
			    "after <%s%s%s>, SA:%s:\n",
			    IPS_XFORM_NAME(ixs->ipsp),
			    ixs->sa_len ? ixs->sa_txt : " (error)");
		KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph);
		break;
	}

	/* all good */
	ixs->state = IPSEC_XSM_CONT;

bail:
	crypto_freereq(crp);
	crp = NULL;
	ipsec_ocf_queue_task(ipsec_xsm, ixs);
	return 0;
}
示例#27
0
enum ipsec_rcv_value ipsec_ocf_rcv(struct ipsec_rcv_state *irs)
{
	struct cryptop *crp;
	struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL;
	struct ipsec_sa *ipsp;
	int req_count = 0;
	int rc, err;

	KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv\n");

	ipsp = irs->ipsp;
	if (!ipsp) {
		KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: "
			    "no SA for rcv processing\n");
		return IPSEC_RCV_SAIDNOTFOUND;
	}

	if (!irs->skb) {
		KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: no skb\n");
		return IPSEC_RCV_SAIDNOTFOUND;
	}

	switch (ipsp->ips_said.proto) {
	case IPPROTO_COMP:
		rc = ipsec_ocf_ipcomp_copy_expand(irs);
		if (rc != IPSEC_RCV_OK) {
			KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: "
				    "growing skb for ipcomp failed, rc=%d\n",
				    rc);
			return rc;
		}
		break;
	case IPPROTO_ESP:
	case IPPROTO_AH:
		break;
	default:
		KLIPS_PRINT(debug_rcv & DB_RX_XF, "klips_debug:ipsec_ocf_rcv: "
			    "bad protocol %d\n", ipsp->ips_said.proto);
		return IPSEC_RCV_BADPROTO;
	}

	req_count = (ipsp->ips_authalg ? 1 : 0) +
		    (ipsp->ips_encalg  ? 1 : 0);
	crp = crypto_getreq(req_count);

	if (!crp) {
		KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: "
			    "crypto_getreq returned NULL\n");
		return IPSEC_RCV_REALLYBAD;
	}

	/* we currently don't support any chaining across protocols */
	switch (ipsp->ips_said.proto) {
	case IPPROTO_ESP:
		/*
		 * we are decrypting,  from the setup in ipsec_ocf_sa_init above,  we
		 * need to flip the order of hash/cipher for recieve so that it is
		 * hash first then decrypt.  Transmit is ok.
		 */
		if (crp->crp_desc && crp->crp_desc->crd_next) {
			crda = crp->crp_desc;
			crde = crda->crd_next;
		} else {
			crde = crp->crp_desc;
			crda = crde->crd_next;
		}
		break;
	case IPPROTO_COMP:
		crdc = crp->crp_desc;
		break;
	case IPPROTO_AH:
		crda = crp->crp_desc;
		break;
	}

	if (crda) {
		/* Authentication descriptor */
		crda->crd_alg = ipsec_ocf_authalg(ipsp->ips_authalg);
		if (!crda->crd_alg) {
			KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: "
				    "bad auth alg 0x%x\n", ipsp->ips_authalg);
			crypto_freereq(crp);
			return IPSEC_RCV_BADPROTO;
		}

		if (!crde) { /* assuming AH processing */
			/* push the IP header so we can authenticate it */
			skb_push(irs->skb,
				 ((unsigned char *)irs->protostuff.ahstuff.ahp) -
				 ((unsigned char *)irs->iph));
		}

		crda->crd_key          = ipsp->ips_key_a;
		crda->crd_klen         = ipsp->ips_key_bits_a;
		crda->crd_inject       = irs->authenticator - irs->skb->data;

		/* OCF needs cri_mlen initialized in order to properly migrate the
		 * session to another driver */
		crda->crd_mlen = 12;

		/* Copy the authenticator to check aganinst later */
		memcpy(irs->hash, irs->authenticator, 12);

		if (!crde) { /* assume AH processing */
			/* AH processing, save fields we have to zero */
			if (lsw_ip_hdr_version(irs) == 4) {
				irs->ttl                   =
					lsw_ip4_hdr(irs)->ttl;
				irs->check                 =
					lsw_ip4_hdr(irs)->check;
				irs->frag_off              =
					lsw_ip4_hdr(irs)->frag_off;
				irs->tos                   =
					lsw_ip4_hdr(irs)->tos;
				lsw_ip4_hdr(irs)->ttl      = 0;
				lsw_ip4_hdr(irs)->check    = 0;
				lsw_ip4_hdr(irs)->frag_off = 0;
				lsw_ip4_hdr(irs)->tos      = 0;
			}
			crda->crd_len      = irs->skb->len;
			crda->crd_skip     = ((unsigned char *)irs->iph) -
					     irs->skb->data;
			memset(irs->authenticator, 0, 12);
		} else {
			crda->crd_len      = irs->ilen;
			crda->crd_skip     =
				((unsigned char *) irs->protostuff.espstuff.
				 espp) -
				irs->skb->data;
			/*
			 * It would be nice to clear the authenticator here
			 * to be sure we do not see it again later when checking.
			 * We cannot.  Some HW actually expects to check the in-data
			 * hash and and flag an error if it is incorrect.
			 *
			 * What we do to allow this is to pass in the current in-data
			 * value.  Your OCF driver must ensure that it fails a request
			 * for hash+decrypt with an invalid hash value, or returns the
			 * computed in-data hash as requested.
			 *
			 * If your driver does not check the in-data hash but just
			 * computes it value,  you must ensure that it does not return
			 * the original in-data hash by accident.  It must invalidate the
			 * in-data hash itself to force an auth check error.
			 *
			 * All existing drivers that do not care about the current
			 * in-data hash do this by clearing the in-data hash before
			 * processing, either directly or via their implementation.
			 */
#if 0
			memset(irs->authenticator, 0, 12);
#endif
		}
	}

	if (crde) {
		crde->crd_alg = ipsec_ocf_encalg(ipsp->ips_encalg);
		if (!crde->crd_alg) {
			KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: "
				    "bad enc alg 0x%x\n", ipsp->ips_encalg);
			crypto_freereq(crp);
			return IPSEC_RCV_BADPROTO;
		}

		irs->esphlen     = ESP_HEADER_LEN + ipsp->ips_iv_size;
		irs->ilen       -= irs->esphlen;
		crde->crd_skip   =
			(skb_transport_header(irs->skb) -
			 irs->skb->data) + irs->esphlen;
		crde->crd_len    = irs->ilen;
		crde->crd_inject = crde->crd_skip - ipsp->ips_iv_size;
		crde->crd_klen   = ipsp->ips_key_bits_e;
		crde->crd_key    = ipsp->ips_key_e;
	}

	if (crdc) {
		struct ipcomphdr *cmph;
		int compalg = ipsp->ips_encalg;
		/* Decompression descriptor */
		crdc->crd_alg = ipsec_ocf_compalg(compalg);
		if (!crdc->crd_alg) {
			KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: "
				    "bad decomp alg 0x%x\n",
				    ipsp->ips_encalg);
			crypto_freereq(crp);
			return IPSEC_RCV_BADPROTO;
		}
		crdc->crd_flags  = 0;
		/* this is where the current ipcomp header is */
		cmph = (struct ipcomphdr*)((char*)irs->iph + irs->iphlen);
		/* store the nested protocol */
		irs->next_header = cmph->ipcomp_nh;
		/* start decompressing after ip header and the ipcomp header */
		crdc->crd_skip   = ((unsigned char*)irs->iph) + irs->iphlen +
				   sizeof(struct ipcomphdr) - irs->skb->data;
		/* decompress all ip data past the ipcomp header */
		if (lsw_ip_hdr_version(irs) == 6) {
			crdc->crd_len    =
				(ntohs(lsw_ip6_hdr(irs)->payload_len) +
				 sizeof(struct ipv6hdr)) -
				irs->iphlen -
				sizeof(struct ipcomphdr);
		} else {
			crdc->crd_len    = ntohs(lsw_ip4_hdr(irs)->tot_len) -
					   irs->iphlen -
					   sizeof(struct ipcomphdr);
		}
		/* decompress inplace (some hardware can only do inplace) */
		crdc->crd_inject = crdc->crd_skip;
	}

	crp->crp_ilen = irs->skb->len;  /* Total input length */
	crp->crp_olen = irs->skb->len;  /* Total output length */
	crp->crp_flags =
		CRYPTO_F_SKBUF |
		(ipsec_ocf_cbimm ? CRYPTO_F_BATCH : 0) |
		(ipsec_ocf_batch ? CRYPTO_F_BATCH : 0) |
		0;
	crp->crp_buf = (caddr_t) irs->skb;
	crp->crp_callback = ipsec_ocf_rcv_cb;
	crp->crp_sid = ipsp->ocf_cryptoid;
	crp->crp_opaque = (caddr_t) irs;
rcv_migrate:
	if ((err = crypto_dispatch(crp))) {
		KLIPS_PRINT(debug_rcv, "crypto_dispatch rcv failure %u\n",
			    err);
		crypto_freereq(crp);
		return IPSEC_RCV_REALLYBAD;
	}
	if (crp->crp_etype == EAGAIN) {
		/* Session has been migrated. Store the new session id and retry */
		ipsp->ocf_cryptoid = crp->crp_sid;
		goto rcv_migrate;
	}

	return IPSEC_RCV_PENDING;
}
示例#28
0
文件: ipsec_alg.c 项目: dgeo96/pfe
/*
 * 	Must be called from user context
 * 	used at module load type for testing algo implementation
 */
static int ipsec_alg_test_encrypt(int enc_alg, int test) {
	int ret;
	caddr_t buf;
	int iv_size, keysize, key_e_size;
	struct ipsec_alg_enc *ixt_e;
	#define BUFSZ	1024
	#define MARGIN	0
	#define test_enc   (buf+MARGIN)
	#define test_dec   (test_enc+BUFSZ+MARGIN)
	#define test_tmp   (test_dec+BUFSZ+MARGIN)
	#define test_key_e (test_tmp+BUFSZ+MARGIN)
	#define test_iv    (test_key_e+key_e_size+MARGIN)
	#define test_key   (test_iv+iv_size+MARGIN)
	#define test_size  (BUFSZ*3+key_e_size+iv_size+keysize+MARGIN*7)
	ixt_e=(struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, enc_alg);
	if (ixt_e==NULL) {
		KLIPS_PRINT(1, 
			    "klips_debug: %s: "
			    "encalg=%d object not found\n",
			    __FUNCTION__, enc_alg);
		ret=-EINVAL;
		goto out;
	}
	iv_size=ixt_e->ixt_blocksize;
	key_e_size=ixt_e->ixt_e_ctx_size;
	keysize=ixt_e->ixt_e_keylen;
	KLIPS_PRINT(1, 
		    "klips_debug: %s: "
		    "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n",
		    __FUNCTION__, enc_alg, iv_size, key_e_size, keysize);
	if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) {
		ret= -ENOMEM;
		goto out;
	}
	get_random_bytes(test_key, keysize);
	get_random_bytes(test_iv, iv_size);
	ixt_e->ixt_e_set_key(test_key_e, test_key, keysize);
	get_random_bytes(test_enc, BUFSZ);
	memcpy(test_tmp, test_enc, BUFSZ);
	ret=ixt_e->ixt_e_cbc_encrypt(test_key_e, test_enc, test_enc, BUFSZ, test_iv, 1);
	printk(KERN_INFO
		    "klips_info: %s: "
		    "cbc_encrypt=1 ret=%d\n", 
		    	__FUNCTION__, ret);
	ret=memcmp(test_enc, test_tmp, BUFSZ);
	printk(KERN_INFO
		    "klips_info: %s: "
		    "memcmp(enc, tmp) ret=%d: %s\n", ret,
			__FUNCTION__,
			ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" );
	memcpy(test_dec, test_enc, BUFSZ);
	ret=ixt_e->ixt_e_cbc_encrypt(test_key_e, test_dec, test_dec, BUFSZ, test_iv, 0);
	printk(KERN_INFO
		    "klips_info: %s : "
		    "cbc_encrypt=0 ret=%d\n", __FUNCTION__, ret);
	ret=memcmp(test_dec, test_tmp, BUFSZ);
	printk(KERN_INFO
		    "klips_info: %s : "
		    "memcmp(dec,tmp) ret=%d: %s\n", __FUNCTION__, ret,
			ret==0? "OK. (encr->decr->SAME)" : "FAIL! (encr->decr->DIFFers)" );
	{
		/*	Shamelessly taken from drivers/md sources  O:)  */
		unsigned long now;
		int i, count, max=0;
		int encrypt, speed;
		for (encrypt=0; encrypt <2;encrypt ++) {
			for (i = 0; i < 5; i++) {
				now = jiffies;
				count = 0;
				while (jiffies == now) {
					mb();
					ixt_e->ixt_e_cbc_encrypt(test_key_e, test_tmp, test_tmp, BUFSZ, test_iv, encrypt);
					mb();
					count++;
					mb();
				}
				if (count > max)
					max = count;
			}
			speed = max * (HZ * BUFSZ / 1024);
			printk(KERN_INFO
				    "klips_info: %s: "
				    "%s %s speed=%d KB/s\n", 
				    __FUNCTION__, ixt_e->ixt_name,
				    encrypt? "encrypt": "decrypt", speed);
		}
	}
	kfree(buf);
	ipsec_alg_put((struct ipsec_alg *)ixt_e);
out:
	return ret;
	#undef test_enc  
	#undef test_dec  
	#undef test_tmp  
	#undef test_key_e
	#undef test_iv   
	#undef test_key  
	#undef test_size 
}
示例#29
0
文件: ipsec_alg.c 项目: dgeo96/pfe
/*
 * 	Must be called from user context
 * 	used at module load type for testing algo implementation
 */
static int ipsec_alg_test_auth(int auth_alg, int test) {
	int ret;
	caddr_t buf;
	int blocksize, keysize, key_a_size;
	struct ipsec_alg_auth *ixt_a;
	#define BUFSZ	1024
	#define MARGIN	0
	#define test_auth  (buf+MARGIN)
	#define test_key_a (test_auth+BUFSZ+MARGIN)
	#define test_key   (test_key_a+key_a_size+MARGIN)
	#define test_hash  (test_key+keysize+MARGIN)
	#define test_size  (BUFSZ+key_a_size+keysize+AHHMAC_HASHLEN+MARGIN*4)
	ixt_a=(struct ipsec_alg_auth *)ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, auth_alg);
	if (ixt_a==NULL) {
		KLIPS_PRINT(1, 
			    "klips_debug: %s: "
			    "encalg=%d object not found\n",
			    __FUNCTION__, auth_alg);
		ret=-EINVAL;
		goto out;
	}
	blocksize=ixt_a->ixt_blocksize;
	key_a_size=ixt_a->ixt_a_ctx_size;
	keysize=ixt_a->ixt_a_keylen;
	KLIPS_PRINT(1, 
		    "klips_debug: %s : "
		    "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n",
		    __FUNCTION__, auth_alg, blocksize, key_a_size, keysize);
	if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) {
		ret= -ENOMEM;
		goto out;
	}
	get_random_bytes(test_key, keysize);
	ixt_a->ixt_a_hmac_set_key(test_key_a, test_key, keysize);
	get_random_bytes(test_auth, BUFSZ);
	ret=ixt_a->ixt_a_hmac_hash(test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN);
	printk(KERN_INFO
		    "klips_info: %s: "
		    "ret=%d\n", __FUNCTION__, ret);
	{
		/*	Shamelessly taken from drivers/md sources  O:)  */
		unsigned long now;
		int i, count, max=0;
		int speed;
		for (i = 0; i < 5; i++) {
			now = jiffies;
			count = 0;
			while (jiffies == now) {
				mb();
				ixt_a->ixt_a_hmac_hash(test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN);
				mb();
				count++;
				mb();
			}
			if (count > max)
				max = count;
		}
		speed = max * (HZ * BUFSZ / 1024);
		printk(KERN_INFO
				"klips_info: %s: "
				"%s hash speed=%d KB/s\n", 
				__FUNCTION__, ixt_a->ixt_name,
				speed);
	}
	kfree(buf);
	ipsec_alg_put((struct ipsec_alg *)ixt_a);
out:
	return ret;
	#undef test_auth 
	#undef test_key_a
	#undef test_key  
	#undef test_hash 
	#undef test_size 
}
示例#30
0
static int ipsec_ocf_rcv_cb(struct cryptop *crp)
{
	struct ipsec_rcv_state *irs =
		(struct ipsec_rcv_state *)crp->crp_opaque;
	struct iphdr *newiph;
	unsigned orig_len, decomp_len;
	struct cryptodesc *crdc = NULL;

	KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv_cb\n");

	if (irs == NULL) {
		KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv_cb: "
			    "NULL irs in callback\n");
		return 0;
	}

	/*
	 * we must update the state before returning to the state machine.
	 * if we have an error,  terminate the processing by moving to the DONE
	 * state
	 */

	irs->state = IPSEC_RSM_DONE; /* assume it went badly */

	if (crp->crp_etype) {
		ptrdiff_t ptr_delta;

		if (crp->crp_etype == EAGAIN) {
			/* Session has been migrated. Store the new session id and retry */
			KLIPS_PRINT(debug_rcv,
				    "klips_debug:ipsec_ocf_rcv_cb: crypto session migrated\n");
			irs->ipsp->ocf_cryptoid = crp->crp_sid;
			/* resubmit request */
			if (crypto_dispatch(crp) == 0)
				return 0;
			/* resubmit failed */
		}

		KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv_cb: "
			    "error in processing 0x%x\n", crp->crp_etype);

		switch (irs->ipsp->ips_said.proto) {
		case IPPROTO_COMP:
			/*
			 * we restore the previous skb on error and pretend nothing
			 * happened, just no compression
			 */
			ptr_delta = irs->pre_ipcomp_skb->data - irs->skb->data;
			irs->authenticator =
				(void*)((char*)irs->authenticator + ptr_delta);
			irs->iph           =
				(void*)((char*)irs->iph           + ptr_delta);

			kfree_skb(irs->skb);
			irs->skb = irs->pre_ipcomp_skb;
			irs->pre_ipcomp_skb = NULL;
			break;
		}

		goto bail;
	}

	switch (irs->ipsp->ips_said.proto) {
	case IPPROTO_ESP:
		/* ESP, process it */
		if (ipsec_rcv_esp_post_decrypt(irs) == IPSEC_RCV_OK) {
			/* this one came up good, set next state */
			irs->state = IPSEC_RSM_DECAP_CONT;
		}
		break;

	case IPPROTO_AH:
		/* AH post processing, put back fields we had to zero */
		if (lsw_ip_hdr_version(irs) == 4) {
			lsw_ip4_hdr(irs)->ttl      = irs->ttl;
			lsw_ip4_hdr(irs)->check    = irs->check;
			lsw_ip4_hdr(irs)->frag_off = irs->frag_off;
			lsw_ip4_hdr(irs)->tos      = irs->tos;
		}
		irs->state         = IPSEC_RSM_AUTH_CHK;

		/* pull up the IP header again after processing */
		skb_pull(irs->skb,
			 ((unsigned char *)irs->protostuff.ahstuff.ahp) -
			 ((unsigned char *)irs->iph));

		break;

	case IPPROTO_COMP:
		crdc = crp->crp_desc;

		KLIPS_PRINT(debug_rcv, "comp before adjustments:\n");
		KLIPS_IP_PRINT(debug_rcv & DB_TN_XMIT, irs->iph);

		orig_len = irs->skb->len - sizeof(struct ipcomphdr);
		decomp_len = crp->crp_olen;

		newiph =
			(struct iphdr*)((char*)irs->iph +
					sizeof(struct ipcomphdr));

		KLIPS_PRINT(debug_rcv,
			    "comp results: olen: %u, inject: %u (len=%d) iph->totlen=%u\n",
			    crp->crp_olen, crdc->crd_inject, decomp_len,
			    ntohs(newiph->tot_len));

		/*
		 * move the ip header to consume room previously taken by
		 * the ipcomp header
		 */
		skb_pull(irs->skb, sizeof(struct ipcomphdr));
		memmove(newiph, irs->iph, irs->iphlen);

		/* adjust the ipp pointer to point to the header we decoded */
		irs->iph = newiph;

		skb_set_network_header(irs->skb, ipsec_skb_offset(irs->skb,
								  ((unsigned
								    char *)
								   skb_network_header(
									   irs
									   ->
									   skb))
								  +
								  sizeof(struct
									 ipcomphdr)));
		skb_set_transport_header(irs->skb, ipsec_skb_offset(irs->skb,
								    ((unsigned
								      char *)
								     skb_transport_header(
									     irs
									     ->
									     skb))
								    +
								    sizeof(
									    struct
									    ipcomphdr)));

		if (lsw_ip_hdr_version(irs) == 6) {
			lsw_ip6_hdr(irs)->nexthdr  = irs->next_header;
		} else {
			lsw_ip4_hdr(irs)->protocol = irs->next_header;
			lsw_ip4_hdr(irs)->tot_len = htons(
				irs->iphlen + decomp_len);
			lsw_ip4_hdr(irs)->check = 0;
			lsw_ip4_hdr(irs)->check = ip_fast_csum(irs->iph, lsw_ip4_hdr(
								       irs)->ihl);
		}

		KLIPS_PRINT(debug_rcv, "comp after len adjustments:\n");
		KLIPS_IP_PRINT(debug_rcv & DB_TN_XMIT, irs->iph);

		/* Update skb length/tail by "putting" the growth */
		safe_skb_put(irs->skb, decomp_len - crp->crp_olen);

		/* set the new header in the skb */
		skb_set_network_header(irs->skb,
				       ipsec_skb_offset(irs->skb, irs->iph));
		KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ip_hdr(irs->skb));

		/* relese the backup copy */
		if (irs->pre_ipcomp_skb) {
			kfree_skb(irs->pre_ipcomp_skb);
			irs->pre_ipcomp_skb = NULL;
		}

		/* IPcomp finished, continue processing */
		irs->state = IPSEC_RSM_DECAP_CONT;
		break;
	}

bail:
	crypto_freereq(crp);
	crp = NULL;
	ipsec_ocf_queue_task(ipsec_rsm, irs);
	return 0;
}