2005-04-17 02:20:36 +04:00
/*
* xfrm_input . c
*
* Changes :
* YOSHIFUJI Hideaki @ USAGI
* Split up af - specific portion
2007-02-09 17:25:29 +03:00
*
2005-04-17 02:20:36 +04:00
*/
# include <linux/slab.h>
# include <linux/module.h>
# include <net/ip.h>
# include <net/xfrm.h>
2006-12-07 07:33:20 +03:00
static struct kmem_cache * secpath_cachep __read_mostly ;
2005-04-17 02:20:36 +04:00
void __secpath_destroy ( struct sec_path * sp )
{
int i ;
for ( i = 0 ; i < sp - > len ; i + + )
2006-04-01 12:54:16 +04:00
xfrm_state_put ( sp - > xvec [ i ] ) ;
2005-04-17 02:20:36 +04:00
kmem_cache_free ( secpath_cachep , sp ) ;
}
EXPORT_SYMBOL ( __secpath_destroy ) ;
struct sec_path * secpath_dup ( struct sec_path * src )
{
struct sec_path * sp ;
2006-12-07 07:33:16 +03:00
sp = kmem_cache_alloc ( secpath_cachep , GFP_ATOMIC ) ;
2005-04-17 02:20:36 +04:00
if ( ! sp )
return NULL ;
sp - > len = 0 ;
if ( src ) {
int i ;
memcpy ( sp , src , sizeof ( * sp ) ) ;
for ( i = 0 ; i < sp - > len ; i + + )
2006-04-01 12:54:16 +04:00
xfrm_state_hold ( sp - > xvec [ i ] ) ;
2005-04-17 02:20:36 +04:00
}
atomic_set ( & sp - > refcnt , 1 ) ;
return sp ;
}
EXPORT_SYMBOL ( secpath_dup ) ;
/* Fetch spi and seq from ipsec header */
2006-09-28 05:47:59 +04:00
int xfrm_parse_spi ( struct sk_buff * skb , u8 nexthdr , __be32 * spi , __be32 * seq )
2005-04-17 02:20:36 +04:00
{
int offset , offset_seq ;
switch ( nexthdr ) {
case IPPROTO_AH :
offset = offsetof ( struct ip_auth_hdr , spi ) ;
offset_seq = offsetof ( struct ip_auth_hdr , seq_no ) ;
break ;
case IPPROTO_ESP :
offset = offsetof ( struct ip_esp_hdr , spi ) ;
offset_seq = offsetof ( struct ip_esp_hdr , seq_no ) ;
break ;
case IPPROTO_COMP :
if ( ! pskb_may_pull ( skb , sizeof ( struct ip_comp_hdr ) ) )
return - EINVAL ;
2007-04-26 05:04:18 +04:00
* spi = htonl ( ntohs ( * ( __be16 * ) ( skb_transport_header ( skb ) + 2 ) ) ) ;
2005-04-17 02:20:36 +04:00
* seq = 0 ;
return 0 ;
default :
return 1 ;
}
if ( ! pskb_may_pull ( skb , 16 ) )
return - EINVAL ;
2007-04-26 05:04:18 +04:00
* spi = * ( __be32 * ) ( skb_transport_header ( skb ) + offset ) ;
* seq = * ( __be32 * ) ( skb_transport_header ( skb ) + offset_seq ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
EXPORT_SYMBOL ( xfrm_parse_spi ) ;
void __init xfrm_input_init ( void )
{
secpath_cachep = kmem_cache_create ( " secpath_cache " ,
sizeof ( struct sec_path ) ,
2006-08-27 06:25:52 +04:00
0 , SLAB_HWCACHE_ALIGN | SLAB_PANIC ,
2007-07-20 05:11:58 +04:00
NULL ) ;
2005-04-17 02:20:36 +04:00
}