1 /* 2 * xfrm_input.c 3 * 4 * Changes: 5 * YOSHIFUJI Hideaki @USAGI 6 * Split up af-specific portion 7 * 8 */ 9 10 #include <linux/slab.h> 11 #include <linux/module.h> 12 #include <net/ip.h> 13 #include <net/xfrm.h> 14 15 static struct kmem_cache *secpath_cachep __read_mostly; 16 17 void __secpath_destroy(struct sec_path *sp) 18 { 19 int i; 20 for (i = 0; i < sp->len; i++) 21 xfrm_state_put(sp->xvec[i]); 22 kmem_cache_free(secpath_cachep, sp); 23 } 24 EXPORT_SYMBOL(__secpath_destroy); 25 26 struct sec_path *secpath_dup(struct sec_path *src) 27 { 28 struct sec_path *sp; 29 30 sp = kmem_cache_alloc(secpath_cachep, GFP_ATOMIC); 31 if (!sp) 32 return NULL; 33 34 sp->len = 0; 35 if (src) { 36 int i; 37 38 memcpy(sp, src, sizeof(*sp)); 39 for (i = 0; i < sp->len; i++) 40 xfrm_state_hold(sp->xvec[i]); 41 } 42 atomic_set(&sp->refcnt, 1); 43 return sp; 44 } 45 EXPORT_SYMBOL(secpath_dup); 46 47 /* Fetch spi and seq from ipsec header */ 48 49 int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) 50 { 51 int offset, offset_seq; 52 53 switch (nexthdr) { 54 case IPPROTO_AH: 55 offset = offsetof(struct ip_auth_hdr, spi); 56 offset_seq = offsetof(struct ip_auth_hdr, seq_no); 57 break; 58 case IPPROTO_ESP: 59 offset = offsetof(struct ip_esp_hdr, spi); 60 offset_seq = offsetof(struct ip_esp_hdr, seq_no); 61 break; 62 case IPPROTO_COMP: 63 if (!pskb_may_pull(skb, sizeof(struct ip_comp_hdr))) 64 return -EINVAL; 65 *spi = htonl(ntohs(*(__be16*)(skb_transport_header(skb) + 2))); 66 *seq = 0; 67 return 0; 68 default: 69 return 1; 70 } 71 72 if (!pskb_may_pull(skb, 16)) 73 return -EINVAL; 74 75 *spi = *(__be32*)(skb_transport_header(skb) + offset); 76 *seq = *(__be32*)(skb_transport_header(skb) + offset_seq); 77 return 0; 78 } 79 EXPORT_SYMBOL(xfrm_parse_spi); 80 81 void __init xfrm_input_init(void) 82 { 83 secpath_cachep = kmem_cache_create("secpath_cache", 84 sizeof(struct sec_path), 85 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, 86 NULL); 87 } 88