[MIPS] Alchemy: micro-optimizatize time code.
[linux-2.6/mini2440.git] / net / xfrm / xfrm_input.c
blobcb97fda1b6dfa196aedea7e091599cb944b61950
1 /*
2 * xfrm_input.c
4 * Changes:
5 * YOSHIFUJI Hideaki @USAGI
6 * Split up af-specific portion
8 */
10 #include <linux/slab.h>
11 #include <linux/module.h>
12 #include <net/ip.h>
13 #include <net/xfrm.h>
15 static struct kmem_cache *secpath_cachep __read_mostly;
17 void __secpath_destroy(struct sec_path *sp)
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);
24 EXPORT_SYMBOL(__secpath_destroy);
26 struct sec_path *secpath_dup(struct sec_path *src)
28 struct sec_path *sp;
30 sp = kmem_cache_alloc(secpath_cachep, GFP_ATOMIC);
31 if (!sp)
32 return NULL;
34 sp->len = 0;
35 if (src) {
36 int i;
38 memcpy(sp, src, sizeof(*sp));
39 for (i = 0; i < sp->len; i++)
40 xfrm_state_hold(sp->xvec[i]);
42 atomic_set(&sp->refcnt, 1);
43 return sp;
45 EXPORT_SYMBOL(secpath_dup);
47 /* Fetch spi and seq from ipsec header */
49 int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
51 int offset, offset_seq;
52 int hlen;
54 switch (nexthdr) {
55 case IPPROTO_AH:
56 hlen = sizeof(struct ip_auth_hdr);
57 offset = offsetof(struct ip_auth_hdr, spi);
58 offset_seq = offsetof(struct ip_auth_hdr, seq_no);
59 break;
60 case IPPROTO_ESP:
61 hlen = sizeof(struct ip_esp_hdr);
62 offset = offsetof(struct ip_esp_hdr, spi);
63 offset_seq = offsetof(struct ip_esp_hdr, seq_no);
64 break;
65 case IPPROTO_COMP:
66 if (!pskb_may_pull(skb, sizeof(struct ip_comp_hdr)))
67 return -EINVAL;
68 *spi = htonl(ntohs(*(__be16*)(skb_transport_header(skb) + 2)));
69 *seq = 0;
70 return 0;
71 default:
72 return 1;
75 if (!pskb_may_pull(skb, hlen))
76 return -EINVAL;
78 *spi = *(__be32*)(skb_transport_header(skb) + offset);
79 *seq = *(__be32*)(skb_transport_header(skb) + offset_seq);
80 return 0;
82 EXPORT_SYMBOL(xfrm_parse_spi);
84 void __init xfrm_input_init(void)
86 secpath_cachep = kmem_cache_create("secpath_cache",
87 sizeof(struct sec_path),
88 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
89 NULL);