blob: 891a6090cc099d2f88e15aa33ff68db982132d6e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Eric Dumazetba899662005-08-26 12:05:31 -070015static kmem_cache_t *secpath_cachep __read_mostly;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016
17void __secpath_destroy(struct sec_path *sp)
18{
19 int i;
20 for (i = 0; i < sp->len; i++)
Herbert Xudbe5b4a2006-04-01 00:54:16 -080021 xfrm_state_put(sp->xvec[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 kmem_cache_free(secpath_cachep, sp);
23}
24EXPORT_SYMBOL(__secpath_destroy);
25
26struct sec_path *secpath_dup(struct sec_path *src)
27{
28 struct sec_path *sp;
29
30 sp = kmem_cache_alloc(secpath_cachep, SLAB_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++)
Herbert Xudbe5b4a2006-04-01 00:54:16 -080040 xfrm_state_hold(sp->xvec[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 }
42 atomic_set(&sp->refcnt, 1);
43 return sp;
44}
45EXPORT_SYMBOL(secpath_dup);
46
47/* Fetch spi and seq from ipsec header */
48
49int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *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;
Alexey Dobriyan4195f812006-05-22 16:53:22 -070065 *spi = htonl(ntohs(*(u16*)(skb->h.raw + 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 *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 = *(u32*)(skb->h.raw + offset);
76 *seq = *(u32*)(skb->h.raw + offset_seq);
77 return 0;
78}
79EXPORT_SYMBOL(xfrm_parse_spi);
80
81void __init xfrm_input_init(void)
82{
83 secpath_cachep = kmem_cache_create("secpath_cache",
84 sizeof(struct sec_path),
85 0, SLAB_HWCACHE_ALIGN,
86 NULL, NULL);
87 if (!secpath_cachep)
88 panic("XFRM: failed to allocate secpath_cache\n");
89}