Commit 3bab27b6 authored by James Morris's avatar James Morris

[IPSEC]: Clean up key manager algorithm handling.

parent e55ee9fd
...@@ -242,17 +242,25 @@ struct sadb_x_ipsecrequest { ...@@ -242,17 +242,25 @@ struct sadb_x_ipsecrequest {
#define SADB_SATYPE_MAX 9 #define SADB_SATYPE_MAX 9
/* Authentication algorithms */ /* Authentication algorithms */
#define SADB_AALG_NONE 0 #define SADB_AALG_NONE 0
#define SADB_AALG_MD5HMAC 2 #define SADB_AALG_MD5HMAC 2
#define SADB_AALG_SHA1HMAC 3 #define SADB_AALG_SHA1HMAC 3
#define SADB_AALG_MAX 3 #define SADB_X_AALG_SHA2_256HMAC 5
#define SADB_X_AALG_SHA2_384HMAC 6
#define SADB_X_AALG_SHA2_512HMAC 7
#define SADB_X_AALG_RIPEMD160HMAC 8
#define SADB_X_AALG_NULL 251 /* kame */
#define SADB_AALG_MAX 251
/* Encryption algorithms */ /* Encryption algorithms */
#define SADB_EALG_NONE 0 #define SADB_EALG_NONE 0
#define SADB_EALG_DESCBC 1 #define SADB_EALG_DESCBC 1
#define SADB_EALG_3DESCBC 2 #define SADB_EALG_3DESCBC 2
#define SADB_EALG_NULL 11 #define SADB_X_EALG_CASTCBC 6
#define SADB_EALG_MAX 11 #define SADB_X_EALG_BLOWFISHCBC 7
#define SADB_EALG_NULL 11
#define SADB_X_EALG_AESCBC 12
#define SADB_EALG_MAX 12
/* Extension Header values */ /* Extension Header values */
#define SADB_EXT_RESERVED 0 #define SADB_EXT_RESERVED 0
......
#ifndef _NET_XFRM_H
#define _NET_XFRM_H
#include <linux/xfrm.h> #include <linux/xfrm.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/pfkeyv2.h>
#include <net/dst.h> #include <net/dst.h>
#include <net/route.h> #include <net/route.h>
#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
extern struct semaphore xfrm_cfg_sem; extern struct semaphore xfrm_cfg_sem;
/* Organization of SPD aka "XFRM rules" /* Organization of SPD aka "XFRM rules"
...@@ -347,6 +353,29 @@ static inline void xfrm_sk_free_policy(struct sock *sk) ...@@ -347,6 +353,29 @@ static inline void xfrm_sk_free_policy(struct sock *sk)
} }
} }
/*
* xfrm algorithm information
*/
struct xfrm_algo_auth_info {
u16 icv_truncbits;
u16 icv_fullbits;
};
struct xfrm_algo_encr_info {
u16 blockbits;
u16 defkeybits;
};
struct xfrm_algo_desc {
char *name;
u8 available:1;
union {
struct xfrm_algo_auth_info auth;
struct xfrm_algo_encr_info encr;
} uinfo;
struct sadb_alg desc;
};
extern void xfrm_state_init(void); extern void xfrm_state_init(void);
extern void xfrm_input_init(void); extern void xfrm_input_init(void);
extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *); extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
...@@ -385,3 +414,15 @@ extern wait_queue_head_t km_waitq; ...@@ -385,3 +414,15 @@ extern wait_queue_head_t km_waitq;
extern void km_warn_expired(struct xfrm_state *x); extern void km_warn_expired(struct xfrm_state *x);
extern void km_expired(struct xfrm_state *x); extern void km_expired(struct xfrm_state *x);
extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol); extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol);
extern void xfrm_probe_algs(void);
extern int xfrm_count_auth_supported(void);
extern int xfrm_count_enc_supported(void);
extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx);
extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name);
extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name);
#endif /* _NET_XFRM_H */
...@@ -22,4 +22,4 @@ obj-$(CONFIG_IP_PNP) += ipconfig.o ...@@ -22,4 +22,4 @@ obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_XFRM_USER) += xfrm_user.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o
obj-y += xfrm_policy.o xfrm_state.o xfrm_input.o obj-y += xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o
...@@ -7,26 +7,31 @@ ...@@ -7,26 +7,31 @@
#include <net/icmp.h> #include <net/icmp.h>
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
#define AH_HLEN_NOICV 12
typedef void (icv_update_fn_t)(struct crypto_tfm *,
struct scatterlist *, unsigned int);
struct ah_data struct ah_data
{ {
u8 *key; u8 *key;
int key_len; int key_len;
u8 *work_digest; u8 *work_icv;
int digest_len; int icv_full_len;
int icv_trunc_len;
void (*digest)(struct ah_data*, void (*icv)(struct ah_data*,
struct sk_buff *skb, struct sk_buff *skb, u8 *icv);
u8 *digest);
struct crypto_tfm *tfm; struct crypto_tfm *tfm;
}; };
/* Clear mutable options and find final destination to substitute /* Clear mutable options and find final destination to substitute
* into IP header for digest calculation. Options are already checked * into IP header for icv calculation. Options are already checked
* for validity, so paranoia is not required. */ * for validity, so paranoia is not required. */
int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr) static int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr)
{ {
unsigned char * optptr = (unsigned char*)(iph+1); unsigned char * optptr = (unsigned char*)(iph+1);
int l = iph->ihl*4 - 20; int l = iph->ihl*4 - 20;
...@@ -66,7 +71,8 @@ int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr) ...@@ -66,7 +71,8 @@ int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr)
return 0; return 0;
} }
void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm) static void skb_ah_walk(const struct sk_buff *skb,
struct crypto_tfm *tfm, icv_update_fn_t icv_update)
{ {
int offset = 0; int offset = 0;
int len = skb->len; int len = skb->len;
...@@ -83,7 +89,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm) ...@@ -83,7 +89,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm)
sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
sg.length = copy; sg.length = copy;
crypto_hmac_update(tfm, &sg, 1); icv_update(tfm, &sg, 1);
if ((len -= copy) == 0) if ((len -= copy) == 0)
return; return;
...@@ -106,7 +112,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm) ...@@ -106,7 +112,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm)
sg.offset = frag->page_offset + offset-start; sg.offset = frag->page_offset + offset-start;
sg.length = copy; sg.length = copy;
crypto_hmac_update(tfm, &sg, 1); icv_update(tfm, &sg, 1);
if (!(len -= copy)) if (!(len -= copy))
return; return;
...@@ -127,7 +133,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm) ...@@ -127,7 +133,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm)
if ((copy = end - offset) > 0) { if ((copy = end - offset) > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
skb_ah_walk(list, tfm); skb_ah_walk(list, tfm, icv_update);
if ((len -= copy) == 0) if ((len -= copy) == 0)
return; return;
offset += copy; offset += copy;
...@@ -144,14 +150,14 @@ ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data) ...@@ -144,14 +150,14 @@ ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
{ {
struct crypto_tfm *tfm = ahp->tfm; struct crypto_tfm *tfm = ahp->tfm;
memset(auth_data, 0, ahp->digest_len); memset(auth_data, 0, ahp->icv_trunc_len);
crypto_hmac_init(tfm, ahp->key, &ahp->key_len); crypto_hmac_init(tfm, ahp->key, &ahp->key_len);
skb_ah_walk(skb, tfm); skb_ah_walk(skb, tfm, crypto_hmac_update);
crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_digest); crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv);
memcpy(auth_data, ahp->work_digest, ahp->digest_len); memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len);
} }
int ah_output(struct sk_buff *skb) static int ah_output(struct sk_buff *skb)
{ {
int err; int err;
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
...@@ -210,11 +216,13 @@ int ah_output(struct sk_buff *skb) ...@@ -210,11 +216,13 @@ int ah_output(struct sk_buff *skb)
ah->nexthdr = iph->protocol; ah->nexthdr = iph->protocol;
} }
ahp = x->data; ahp = x->data;
ah->hdrlen = (((ahp->digest_len + 12 + 7)&~7)>>2)-2; ah->hdrlen = (XFRM_ALIGN8(ahp->icv_trunc_len +
AH_HLEN_NOICV) >> 2) - 2;
ah->reserved = 0; ah->reserved = 0;
ah->spi = x->id.spi; ah->spi = x->id.spi;
ah->seq_no = htonl(++x->replay.oseq); ah->seq_no = htonl(++x->replay.oseq);
ahp->digest(ahp, skb, ah->auth_data); ahp->icv(ahp, skb, ah->auth_data);
top_iph->tos = iph->tos; top_iph->tos = iph->tos;
top_iph->ttl = iph->ttl; top_iph->ttl = iph->ttl;
if (x->props.mode) { if (x->props.mode) {
...@@ -246,6 +254,7 @@ int ah_output(struct sk_buff *skb) ...@@ -246,6 +254,7 @@ int ah_output(struct sk_buff *skb)
int ah_input(struct xfrm_state *x, struct sk_buff *skb) int ah_input(struct xfrm_state *x, struct sk_buff *skb)
{ {
int ah_hlen;
struct iphdr *iph; struct iphdr *iph;
struct ip_auth_hdr *ah; struct ip_auth_hdr *ah;
struct ah_data *ahp; struct ah_data *ahp;
...@@ -255,13 +264,14 @@ int ah_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -255,13 +264,14 @@ int ah_input(struct xfrm_state *x, struct sk_buff *skb)
goto out; goto out;
ah = (struct ip_auth_hdr*)skb->data; ah = (struct ip_auth_hdr*)skb->data;
ahp = x->data; ahp = x->data;
ah_hlen = (ah->hdrlen + 2) << 2;
if (((ah->hdrlen+2)<<2) != ((ahp->digest_len + 12 + 7)&~7))
if (ah_hlen != XFRM_ALIGN8(ahp->icv_full_len + AH_HLEN_NOICV) &&
ah_hlen != XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV))
goto out; goto out;
if (!pskb_may_pull(skb, (ah->hdrlen+2)<<2)) if (!pskb_may_pull(skb, ah_hlen))
goto out; goto out;
/* We are going to _remove_ AH header to keep sockets happy, /* We are going to _remove_ AH header to keep sockets happy,
...@@ -285,17 +295,18 @@ int ah_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -285,17 +295,18 @@ int ah_input(struct xfrm_state *x, struct sk_buff *skb)
goto out; goto out;
} }
{ {
u8 auth_data[ahp->digest_len]; u8 auth_data[ahp->icv_trunc_len];
memcpy(auth_data, ah->auth_data, ahp->digest_len);
memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
skb_push(skb, skb->data - skb->nh.raw); skb_push(skb, skb->data - skb->nh.raw);
ahp->digest(ahp, skb, ah->auth_data); ahp->icv(ahp, skb, ah->auth_data);
if (memcmp(ah->auth_data, auth_data, ahp->digest_len)) { if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
x->stats.integrity_failed++; x->stats.integrity_failed++;
goto out; goto out;
} }
} }
((struct iphdr*)work_buf)->protocol = ah->nexthdr; ((struct iphdr*)work_buf)->protocol = ah->nexthdr;
skb->nh.raw = skb_pull(skb, (ah->hdrlen+2)<<2); skb->nh.raw = skb_pull(skb, ah_hlen);
memcpy(skb->nh.raw, work_buf, iph->ihl*4); memcpy(skb->nh.raw, work_buf, iph->ihl*4);
skb->nh.iph->tot_len = htons(skb->len); skb->nh.iph->tot_len = htons(skb->len);
skb_pull(skb, skb->nh.iph->ihl*4); skb_pull(skb, skb->nh.iph->ihl*4);
...@@ -325,12 +336,13 @@ void ah4_err(struct sk_buff *skb, u32 info) ...@@ -325,12 +336,13 @@ void ah4_err(struct sk_buff *skb, u32 info)
xfrm_state_put(x); xfrm_state_put(x);
} }
int ah_init_state(struct xfrm_state *x, void *args) static int ah_init_state(struct xfrm_state *x, void *args)
{ {
struct ah_data *ahp = NULL; struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc;
if (x->aalg == NULL || x->aalg->alg_key_len == 0 || /* null auth can use a zero length key */
x->aalg->alg_key_len > 512) if (x->aalg->alg_key_len > 512)
goto error; goto error;
ahp = kmalloc(sizeof(*ahp), GFP_KERNEL); ahp = kmalloc(sizeof(*ahp), GFP_KERNEL);
...@@ -344,13 +356,33 @@ int ah_init_state(struct xfrm_state *x, void *args) ...@@ -344,13 +356,33 @@ int ah_init_state(struct xfrm_state *x, void *args)
ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
if (!ahp->tfm) if (!ahp->tfm)
goto error; goto error;
ahp->digest = ah_hmac_digest; ahp->icv = ah_hmac_digest;
ahp->digest_len = 12;
ahp->work_digest = kmalloc(crypto_tfm_alg_digestsize(ahp->tfm), /*
GFP_KERNEL); * Lookup the algorithm description maintained by pfkey,
if (!ahp->work_digest) * verify crypto transform properties, and store information
* we need for AH processing. This lookup cannot fail here
* after a successful crypto_alloc_tfm().
*/
aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name);
BUG_ON(!aalg_desc);
if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
crypto_tfm_alg_digestsize(ahp->tfm)) {
printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm),
aalg_desc->uinfo.auth.icv_fullbits/8);
goto error;
}
ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
ahp->icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL);
if (!ahp->work_icv)
goto error; goto error;
x->props.header_len = (12 + ahp->digest_len + 7)&~7;
x->props.header_len = XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV);
if (x->props.mode) if (x->props.mode)
x->props.header_len += 20; x->props.header_len += 20;
x->data = ahp; x->data = ahp;
...@@ -359,8 +391,8 @@ int ah_init_state(struct xfrm_state *x, void *args) ...@@ -359,8 +391,8 @@ int ah_init_state(struct xfrm_state *x, void *args)
error: error:
if (ahp) { if (ahp) {
if (ahp->work_digest) if (ahp->work_icv)
kfree(ahp->work_digest); kfree(ahp->work_icv);
if (ahp->tfm) if (ahp->tfm)
crypto_free_tfm(ahp->tfm); crypto_free_tfm(ahp->tfm);
kfree(ahp); kfree(ahp);
...@@ -368,13 +400,13 @@ int ah_init_state(struct xfrm_state *x, void *args) ...@@ -368,13 +400,13 @@ int ah_init_state(struct xfrm_state *x, void *args)
return -EINVAL; return -EINVAL;
} }
void ah_destroy(struct xfrm_state *x) static void ah_destroy(struct xfrm_state *x)
{ {
struct ah_data *ahp = x->data; struct ah_data *ahp = x->data;
if (ahp->work_digest) { if (ahp->work_icv) {
kfree(ahp->work_digest); kfree(ahp->work_icv);
ahp->work_digest = NULL; ahp->work_icv = NULL;
} }
if (ahp->tfm) { if (ahp->tfm) {
crypto_free_tfm(ahp->tfm); crypto_free_tfm(ahp->tfm);
...@@ -399,7 +431,7 @@ static struct inet_protocol ah4_protocol = { ...@@ -399,7 +431,7 @@ static struct inet_protocol ah4_protocol = {
.no_policy = 1, .no_policy = 1,
}; };
int __init ah4_init(void) static int __init ah4_init(void)
{ {
SET_MODULE_OWNER(&ah_type); SET_MODULE_OWNER(&ah_type);
if (xfrm_register_type(&ah_type) < 0) { if (xfrm_register_type(&ah_type) < 0) {
......
/*
* xfrm algorithm interface
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/kernel.h>
#include <linux/pfkeyv2.h>
#include <net/xfrm.h>
/*
* Algorithms supported by IPsec. These entries contain properties which
* are used in key negotiation and xfrm processing, and are used to verify
* that instantiated crypto transforms have correct parameters for IPsec
* purposes.
*/
static struct xfrm_algo_desc aalg_list[] = {
{
.name = "digest_null",
.uinfo = {
.auth = {
.icv_truncbits = 0,
.icv_fullbits = 0,
}
},
.desc = {
.sadb_alg_id = SADB_X_AALG_NULL,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 0,
.sadb_alg_maxbits = 0
}
},
{
.name = "md5",
.uinfo = {
.auth = {
.icv_truncbits = 96,
.icv_fullbits = 128,
}
},
.desc = {
.sadb_alg_id = SADB_AALG_MD5HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 128,
.sadb_alg_maxbits = 128
}
},
{
.name = "sha1",
.uinfo = {
.auth = {
.icv_truncbits = 96,
.icv_fullbits = 160,
}
},
.desc = {
.sadb_alg_id = SADB_AALG_SHA1HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 160,
.sadb_alg_maxbits = 160
}
},
{
.name = "sha256",
.uinfo = {
.auth = {
.icv_truncbits = 128,
.icv_fullbits = 256,
}
},
.desc = {
.sadb_alg_id = SADB_X_AALG_SHA2_256HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 256,
.sadb_alg_maxbits = 256
}
},
{
.name = "ripemd160",
.uinfo = {
.auth = {
.icv_truncbits = 96,
.icv_fullbits = 160,
}
},
.desc = {
.sadb_alg_id = SADB_X_AALG_RIPEMD160HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 160,
.sadb_alg_maxbits = 160
}
},
};
static struct xfrm_algo_desc ealg_list[] = {
{
.name = "cipher_null",
.uinfo = {
.encr = {
.blockbits = 8,
.defkeybits = 0,
}
},
.desc = {
.sadb_alg_id = SADB_EALG_NULL,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 0,
.sadb_alg_maxbits = 0
}
},
{
.name = "des",
.uinfo = {
.encr = {
.blockbits = 64,
.defkeybits = 64,
}
},
.desc = {
.sadb_alg_id = SADB_EALG_DESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 64,
.sadb_alg_maxbits = 64
}
},
{
.name = "des3_ede",
.uinfo = {
.encr = {
.blockbits = 64,
.defkeybits = 192,
}
},
.desc = {
.sadb_alg_id = SADB_EALG_3DESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 192,
.sadb_alg_maxbits = 192
}
},
{
.name = "cast128",
.uinfo = {
.encr = {
.blockbits = 64,
.defkeybits = 128,
}
},
.desc = {
.sadb_alg_id = SADB_X_EALG_CASTCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 40,
.sadb_alg_maxbits = 128
}
},
{
.name = "blowfish",
.uinfo = {
.encr = {
.blockbits = 64,
.defkeybits = 128,
}
},
.desc = {
.sadb_alg_id = SADB_X_EALG_BLOWFISHCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 40,
.sadb_alg_maxbits = 448
}
},
{
.name = "aes",
.uinfo = {
.encr = {
.blockbits = 128,
.defkeybits = 128,
}
},
.desc = {
.sadb_alg_id = SADB_X_EALG_AESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 128,
.sadb_alg_maxbits = 256
}
},
};
static inline int aalg_entries(void)
{
return sizeof(aalg_list) / sizeof(aalg_list[0]);
}
static inline int ealg_entries(void)
{
return sizeof(ealg_list) / sizeof(ealg_list[0]);
}
struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
{
int i;
for (i = 0; i < aalg_entries(); i++) {
if (aalg_list[i].desc.sadb_alg_id == alg_id) {
if (aalg_list[i].available)
return &aalg_list[i];
else
break;
}
}
return NULL;
}
struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
{
int i;
for (i = 0; i < ealg_entries(); i++) {
if (ealg_list[i].desc.sadb_alg_id == alg_id) {
if (ealg_list[i].available)
return &ealg_list[i];
else
break;
}
}
return NULL;
}
struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name)
{
int i;
if (!name)
return NULL;
for (i=0; i < aalg_entries(); i++) {
if (strcmp(name, aalg_list[i].name) == 0) {
if (aalg_list[i].available)
return &aalg_list[i];
else
break;
}
}
return NULL;
}
struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name)
{
int i;
if (!name)
return NULL;
for (i=0; i < ealg_entries(); i++) {
if (strcmp(name, ealg_list[i].name) == 0) {
if (ealg_list[i].available)
return &ealg_list[i];
else
break;
}
}
return NULL;
}
struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
{
if (idx >= aalg_entries())
return NULL;
return &aalg_list[idx];
}
struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
{
if (idx >= ealg_entries())
return NULL;
return &ealg_list[idx];
}
/*
* Probe for the availability of crypto algorithms, and set the available
* flag for any algorithms found on the system. This is typically called by
* pfkey during userspace SA add, update or register.
*/
void xfrm_probe_algs(void)
{
int i, status;
BUG_ON(in_softirq());
for (i = 0; i < aalg_entries(); i++) {
status = crypto_alg_available(aalg_list[i].name, 0);
if (aalg_list[i].available != status)
aalg_list[i].available = status;
}
for (i = 0; i < ealg_entries(); i++) {
status = crypto_alg_available(ealg_list[i].name, 0);
if (ealg_list[i].available != status)
ealg_list[i].available = status;
}
}
int xfrm_count_auth_supported(void)
{
int i, n;
for (i = 0, n = 0; i < aalg_entries(); i++)
if (aalg_list[i].available)
n++;
return n;
}
int xfrm_count_enc_supported(void)
{
int i, n;
for (i = 0, n = 0; i < ealg_entries(); i++)
if (ealg_list[i].available)
n++;
return n;
}
...@@ -553,118 +553,6 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void ** ...@@ -553,118 +553,6 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **
return x; return x;
} }
/* Table of algos supported by pfkeyv2 interface. */
struct algo_desc {
char *id;
struct sadb_alg desc;
};
struct algo_desc aalg_list[] = {
{ .id = NULL,
.desc = {
.sadb_alg_id = SADB_AALG_NONE,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 0,
.sadb_alg_maxbits = 0
}
},
{ .id = "md5",
.desc = {
.sadb_alg_id = SADB_AALG_MD5HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 128,
.sadb_alg_maxbits = 128
}
},
{ .id = "sha1",
.desc = {
.sadb_alg_id = SADB_AALG_SHA1HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 160,
.sadb_alg_maxbits = 160
}
}
};
struct algo_desc ealg_list[] = {
{ .id = NULL,
.desc = {
.sadb_alg_id = SADB_EALG_NONE,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 0,
.sadb_alg_maxbits = 2048
}
},
{ .id = "des",
.desc = {
.sadb_alg_id = SADB_EALG_DESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 64,
.sadb_alg_maxbits = 64
}
},
{ .id = "des3_ede",
.desc = {
.sadb_alg_id = SADB_EALG_3DESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 192,
.sadb_alg_maxbits = 192
}
}
};
static struct algo_desc *aalg_get_byid(int alg_id)
{
int i;
for (i=0; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) {
if (aalg_list[i].desc.sadb_alg_id == alg_id)
return &aalg_list[i];
}
return NULL;
}
static struct algo_desc *ealg_get_byid(int alg_id)
{
int i;
for (i=0; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) {
if (ealg_list[i].desc.sadb_alg_id == alg_id)
return &ealg_list[i];
}
return NULL;
}
static struct algo_desc *aalg_get_byname(char *name)
{
int i;
if (!name)
return NULL;
for (i=1; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) {
if (strcmp(name, aalg_list[i].id) == 0)
return &aalg_list[i];
}
return NULL;
}
static struct algo_desc *ealg_get_byname(char *name)
{
int i;
if (!name)
return NULL;
for (i=1; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) {
if (strcmp(name, ealg_list[i].id) == 0)
return &ealg_list[i];
}
return NULL;
}
#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc) static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc)
{ {
...@@ -730,12 +618,12 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, ...@@ -730,12 +618,12 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
sa->sadb_sa_state = SADB_SASTATE_DEAD; sa->sadb_sa_state = SADB_SASTATE_DEAD;
sa->sadb_sa_auth = 0; sa->sadb_sa_auth = 0;
if (x->aalg) { if (x->aalg) {
struct algo_desc *a = aalg_get_byname(x->aalg->alg_name); struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name);
sa->sadb_sa_auth = a ? a->desc.sadb_alg_id : 0; sa->sadb_sa_auth = a ? a->desc.sadb_alg_id : 0;
} }
sa->sadb_sa_encrypt = 0; sa->sadb_sa_encrypt = 0;
if (x->ealg) { if (x->ealg) {
struct algo_desc *a = ealg_get_byname(x->ealg->alg_name); struct xfrm_algo_desc *a = xfrm_ealg_get_byname(x->ealg->alg_name);
sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0; sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0;
} }
sa->sadb_sa_flags = 0; sa->sadb_sa_flags = 0;
...@@ -938,7 +826,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -938,7 +826,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1]; key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
if (sa->sadb_sa_auth) { if (sa->sadb_sa_auth) {
int keysize = 0; int keysize = 0;
struct algo_desc *a = aalg_get_byid(sa->sadb_sa_auth); struct xfrm_algo_desc *a = xfrm_aalg_get_byid(sa->sadb_sa_auth);
if (!a) if (!a)
goto out; goto out;
if (key) if (key)
...@@ -946,7 +834,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -946,7 +834,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL); x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
if (!x->aalg) if (!x->aalg)
goto out; goto out;
strcpy(x->aalg->alg_name, a->id); strcpy(x->aalg->alg_name, a->name);
x->aalg->alg_key_len = 0; x->aalg->alg_key_len = 0;
if (key) { if (key) {
x->aalg->alg_key_len = key->sadb_key_bits; x->aalg->alg_key_len = key->sadb_key_bits;
...@@ -958,7 +846,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -958,7 +846,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
if (sa->sadb_sa_encrypt) { if (sa->sadb_sa_encrypt) {
int keysize = 0; int keysize = 0;
struct algo_desc *a = ealg_get_byid(sa->sadb_sa_encrypt); struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt);
if (!a) if (!a)
goto out; goto out;
if (key) if (key)
...@@ -966,7 +854,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -966,7 +854,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
if (!x->ealg) if (!x->ealg)
goto out; goto out;
strcpy(x->ealg->alg_name, a->id); strcpy(x->ealg->alg_name, a->name);
x->ealg->alg_key_len = 0; x->ealg->alg_key_len = 0;
if (key) { if (key) {
x->ealg->alg_key_len = key->sadb_key_bits; x->ealg->alg_key_len = key->sadb_key_bits;
...@@ -1131,6 +1019,8 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, ...@@ -1131,6 +1019,8 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
struct xfrm_state *x; struct xfrm_state *x;
struct xfrm_state *x1; struct xfrm_state *x1;
xfrm_probe_algs();
x = pfkey_msg2xfrm_state(hdr, ext_hdrs); x = pfkey_msg2xfrm_state(hdr, ext_hdrs);
if (IS_ERR(x)) if (IS_ERR(x))
return PTR_ERR(x); return PTR_ERR(x);
...@@ -1238,17 +1128,21 @@ static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocat ...@@ -1238,17 +1128,21 @@ static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocat
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct sadb_msg *hdr; struct sadb_msg *hdr;
int len, ah_len, esp_len, i; int len, auth_len, enc_len, i;
ah_len = sizeof(aalg_list)/sizeof(aalg_list[0]) - 1; auth_len = xfrm_count_auth_supported();
ah_len *= sizeof(struct sadb_alg); if (auth_len) {
esp_len = sizeof(ealg_list)/sizeof(ealg_list[0]) - 1; auth_len *= sizeof(struct sadb_alg);
esp_len *= sizeof(struct sadb_alg); auth_len += sizeof(struct sadb_supported);
if (ah_len) }
ah_len += sizeof(struct sadb_supported);
if (esp_len) enc_len = xfrm_count_enc_supported();
esp_len += sizeof(struct sadb_supported); if (enc_len) {
len = esp_len + ah_len + sizeof(struct sadb_msg); enc_len *= sizeof(struct sadb_alg);
enc_len += sizeof(struct sadb_supported);
}
len = enc_len + auth_len + sizeof(struct sadb_msg);
skb = alloc_skb(len + 16, allocation); skb = alloc_skb(len + 16, allocation);
if (!skb) if (!skb)
...@@ -1259,32 +1153,42 @@ static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocat ...@@ -1259,32 +1153,42 @@ static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocat
hdr->sadb_msg_errno = 0; hdr->sadb_msg_errno = 0;
hdr->sadb_msg_len = len / sizeof(uint64_t); hdr->sadb_msg_len = len / sizeof(uint64_t);
if (ah_len) { if (auth_len) {
struct sadb_supported *sp; struct sadb_supported *sp;
struct sadb_alg *ap; struct sadb_alg *ap;
sp = (struct sadb_supported *) skb_put(skb, ah_len); sp = (struct sadb_supported *) skb_put(skb, auth_len);
ap = (struct sadb_alg *) (sp + 1); ap = (struct sadb_alg *) (sp + 1);
sp->sadb_supported_len = ah_len / sizeof(uint64_t); sp->sadb_supported_len = auth_len / sizeof(uint64_t);
sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH; sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH;
for (i=1; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) for (i = 0; ; i++) {
*ap++ = aalg_list[i].desc; struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
if (!aalg)
break;
if (aalg->available)
*ap++ = aalg->desc;
}
} }
if (esp_len) { if (enc_len) {
struct sadb_supported *sp; struct sadb_supported *sp;
struct sadb_alg *ap; struct sadb_alg *ap;
sp = (struct sadb_supported *) skb_put(skb, esp_len); sp = (struct sadb_supported *) skb_put(skb, enc_len);
ap = (struct sadb_alg *) (sp + 1); ap = (struct sadb_alg *) (sp + 1);
sp->sadb_supported_len = esp_len / sizeof(uint64_t); sp->sadb_supported_len = enc_len / sizeof(uint64_t);
sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT; sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT;
for (i=1; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) for (i = 0; ; i++) {
*ap++ = ealg_list[i].desc; struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
if (!ealg)
break;
if (ealg->available)
*ap++ = ealg->desc;
}
} }
out_put_algs: out_put_algs:
...@@ -1305,6 +1209,8 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg ...@@ -1305,6 +1209,8 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg
pfk->registered |= (1<<hdr->sadb_msg_satype); pfk->registered |= (1<<hdr->sadb_msg_satype);
} }
xfrm_probe_algs();
supp_skb = compose_sadb_supported(hdr, GFP_KERNEL); supp_skb = compose_sadb_supported(hdr, GFP_KERNEL);
if (!supp_skb) { if (!supp_skb) {
if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC) if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC)
...@@ -1955,35 +1861,55 @@ static struct sadb_msg *pfkey_get_base_msg(struct sk_buff *skb, int *errp) ...@@ -1955,35 +1861,55 @@ static struct sadb_msg *pfkey_get_base_msg(struct sk_buff *skb, int *errp)
return hdr; return hdr;
} }
int count_ah_combs(struct xfrm_tmpl *t) static inline int aalg_tmpl_set(struct xfrm_tmpl *t, struct xfrm_algo_desc *d)
{ {
int sz = 0; return t->aalgos & (1 << d->desc.sadb_alg_id);
int i; }
for (i=1; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) { static inline int ealg_tmpl_set(struct xfrm_tmpl *t, struct xfrm_algo_desc *d)
if (t->aalgos&(1<<aalg_list[i].desc.sadb_alg_id)) {
return t->ealgos & (1 << d->desc.sadb_alg_id);
}
static int count_ah_combs(struct xfrm_tmpl *t)
{
int i, sz = 0;
for (i = 0; ; i++) {
struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
if (!aalg)
break;
if (aalg_tmpl_set(t, aalg) && aalg->available)
sz += sizeof(struct sadb_comb); sz += sizeof(struct sadb_comb);
} }
return sz + sizeof(struct sadb_prop); return sz + sizeof(struct sadb_prop);
} }
int count_esp_combs(struct xfrm_tmpl *t) static int count_esp_combs(struct xfrm_tmpl *t)
{ {
int sz = 0; int i, k, sz = 0;
int i, k;
for (i=1; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) { for (i = 0; ; i++) {
if (!(t->ealgos&(1<<ealg_list[i].desc.sadb_alg_id))) struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
if (!ealg)
break;
if (!(ealg_tmpl_set(t, ealg) && ealg->available))
continue; continue;
for (k=1; k<sizeof(aalg_list)/sizeof(aalg_list[0]); k++) {
if (t->aalgos&(1<<aalg_list[i].desc.sadb_alg_id)) for (k = 1; ; k++) {
struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
if (!aalg)
break;
if (aalg_tmpl_set(t, aalg) && aalg->available)
sz += sizeof(struct sadb_comb); sz += sizeof(struct sadb_comb);
} }
} }
return sz + sizeof(struct sadb_prop); return sz + sizeof(struct sadb_prop);
} }
void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t) static void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
{ {
struct sadb_prop *p; struct sadb_prop *p;
int i; int i;
...@@ -1993,15 +1919,19 @@ void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t) ...@@ -1993,15 +1919,19 @@ void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
p->sadb_prop_exttype = SADB_EXT_PROPOSAL; p->sadb_prop_exttype = SADB_EXT_PROPOSAL;
p->sadb_prop_replay = 32; p->sadb_prop_replay = 32;
for (i=1; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) { for (i = 0; ; i++) {
if (t->aalgos&(1<<aalg_list[i].desc.sadb_alg_id)) { struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
if (!aalg)
break;
if (aalg_tmpl_set(t, aalg) && aalg->available) {
struct sadb_comb *c; struct sadb_comb *c;
c = (struct sadb_comb*)skb_put(skb, sizeof(struct sadb_comb)); c = (struct sadb_comb*)skb_put(skb, sizeof(struct sadb_comb));
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
p->sadb_prop_len += sizeof(struct sadb_comb)/8; p->sadb_prop_len += sizeof(struct sadb_comb)/8;
c->sadb_comb_auth = aalg_list[i].desc.sadb_alg_id; c->sadb_comb_auth = aalg->desc.sadb_alg_id;
c->sadb_comb_auth_minbits = aalg_list[i].desc.sadb_alg_minbits; c->sadb_comb_auth_minbits = aalg->desc.sadb_alg_minbits;
c->sadb_comb_auth_maxbits = aalg_list[i].desc.sadb_alg_maxbits; c->sadb_comb_auth_maxbits = aalg->desc.sadb_alg_maxbits;
c->sadb_comb_hard_addtime = 24*60*60; c->sadb_comb_hard_addtime = 24*60*60;
c->sadb_comb_soft_addtime = 20*60*60; c->sadb_comb_soft_addtime = 20*60*60;
c->sadb_comb_hard_usetime = 8*60*60; c->sadb_comb_hard_usetime = 8*60*60;
...@@ -2010,7 +1940,7 @@ void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t) ...@@ -2010,7 +1940,7 @@ void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
} }
} }
void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t) static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
{ {
struct sadb_prop *p; struct sadb_prop *p;
int i, k; int i, k;
...@@ -2020,22 +1950,30 @@ void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t) ...@@ -2020,22 +1950,30 @@ void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
p->sadb_prop_exttype = SADB_EXT_PROPOSAL; p->sadb_prop_exttype = SADB_EXT_PROPOSAL;
p->sadb_prop_replay = 32; p->sadb_prop_replay = 32;
for (i=1; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) { for (i=0; ; i++) {
if (!(t->ealgos&(1<<ealg_list[i].desc.sadb_alg_id))) struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
if (!ealg)
break;
if (!(ealg_tmpl_set(t, ealg) && ealg->available))
continue; continue;
for (k=1; k<sizeof(aalg_list)/sizeof(aalg_list[0]); k++) {
for (k = 1; ; k++) {
struct sadb_comb *c; struct sadb_comb *c;
if (!(t->aalgos&(1<<aalg_list[i].desc.sadb_alg_id))) struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
if (!aalg)
break;
if (!(aalg_tmpl_set(t, aalg) && aalg->available))
continue; continue;
c = (struct sadb_comb*)skb_put(skb, sizeof(struct sadb_comb)); c = (struct sadb_comb*)skb_put(skb, sizeof(struct sadb_comb));
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
p->sadb_prop_len += sizeof(struct sadb_comb)/8; p->sadb_prop_len += sizeof(struct sadb_comb)/8;
c->sadb_comb_auth = aalg_list[k].desc.sadb_alg_id; c->sadb_comb_auth = aalg->desc.sadb_alg_id;
c->sadb_comb_auth_minbits = aalg_list[k].desc.sadb_alg_minbits; c->sadb_comb_auth_minbits = aalg->desc.sadb_alg_minbits;
c->sadb_comb_auth_maxbits = aalg_list[k].desc.sadb_alg_maxbits; c->sadb_comb_auth_maxbits = aalg->desc.sadb_alg_maxbits;
c->sadb_comb_encrypt = ealg_list[i].desc.sadb_alg_id; c->sadb_comb_encrypt = ealg->desc.sadb_alg_id;
c->sadb_comb_encrypt_minbits = ealg_list[i].desc.sadb_alg_minbits; c->sadb_comb_encrypt_minbits = ealg->desc.sadb_alg_minbits;
c->sadb_comb_encrypt_maxbits = ealg_list[i].desc.sadb_alg_maxbits; c->sadb_comb_encrypt_maxbits = ealg->desc.sadb_alg_maxbits;
c->sadb_comb_hard_addtime = 24*60*60; c->sadb_comb_hard_addtime = 24*60*60;
c->sadb_comb_soft_addtime = 20*60*60; c->sadb_comb_soft_addtime = 20*60*60;
c->sadb_comb_hard_usetime = 8*60*60; c->sadb_comb_hard_usetime = 8*60*60;
......
...@@ -323,6 +323,15 @@ EXPORT_SYMBOL(xfrm_policy_flush); ...@@ -323,6 +323,15 @@ EXPORT_SYMBOL(xfrm_policy_flush);
EXPORT_SYMBOL(xfrm_policy_byid); EXPORT_SYMBOL(xfrm_policy_byid);
EXPORT_SYMBOL(xfrm_policy_list); EXPORT_SYMBOL(xfrm_policy_list);
EXPORT_SYMBOL_GPL(xfrm_probe_algs);
EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx);
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
#if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE) #if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE)
/* inet functions common to v4 and v6 */ /* inet functions common to v4 and v6 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment