diff options
| author | James Morris <jmorris@intercode.com.au> | 2003-03-22 10:09:21 -0800 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2003-03-22 10:09:21 -0800 |
| commit | bfe169a17ab83d4a3295c22eef8f376d6a12ef4c (patch) | |
| tree | e06642dad552c207b3e167f380037ac7750b7488 | |
| parent | e5c1202f2ad98663dc1ecaaa4a21a6773ea1c9fb (diff) | |
[IPSEC] Add initial compression support for pfkey and xfrm_algo.
| -rw-r--r-- | include/linux/pfkeyv2.h | 8 | ||||
| -rw-r--r-- | include/net/xfrm.h | 8 | ||||
| -rw-r--r-- | net/ipv4/xfrm_algo.c | 83 | ||||
| -rw-r--r-- | net/key/af_key.c | 54 | ||||
| -rw-r--r-- | net/netsyms.c | 3 |
5 files changed, 140 insertions, 16 deletions
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h index c6e4e6e29f10..efb41c857ea3 100644 --- a/include/linux/pfkeyv2.h +++ b/include/linux/pfkeyv2.h @@ -262,6 +262,14 @@ struct sadb_x_ipsecrequest { #define SADB_X_EALG_AESCBC 12 #define SADB_EALG_MAX 12 +/* Compression algorithms */ +#define SADB_X_CALG_NONE 0 +#define SADB_X_CALG_OUI 1 +#define SADB_X_CALG_DEFLATE 2 +#define SADB_X_CALG_LZS 3 +#define SADB_X_CALG_LZJH 4 +#define SADB_X_CALG_MAX 4 + /* Extension Header values */ #define SADB_EXT_RESERVED 0 #define SADB_EXT_SA 1 diff --git a/include/net/xfrm.h b/include/net/xfrm.h index f8b5e811c161..d6ffb9aed327 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -391,12 +391,17 @@ struct xfrm_algo_encr_info { u16 defkeybits; }; +struct xfrm_algo_comp_info { + u16 threshold; +}; + struct xfrm_algo_desc { char *name; u8 available:1; union { struct xfrm_algo_auth_info auth; struct xfrm_algo_encr_info encr; + struct xfrm_algo_comp_info comp; } uinfo; struct sadb_alg desc; }; @@ -453,10 +458,13 @@ 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_calg_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_calg_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); +extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name); static __inline__ int addr_match(void *token1, void *token2, int prefixlen) { diff --git a/net/ipv4/xfrm_algo.c b/net/ipv4/xfrm_algo.c index 5ff82327c232..920e9dc667df 100644 --- a/net/ipv4/xfrm_algo.c +++ b/net/ipv4/xfrm_algo.c @@ -219,6 +219,36 @@ static struct xfrm_algo_desc ealg_list[] = { }, }; +static struct xfrm_algo_desc calg_list[] = { +{ + .name = "deflate", + .uinfo = { + .comp = { + .threshold = 90, + } + }, + .desc = { .sadb_alg_id = SADB_X_CALG_DEFLATE } +}, +{ + .name = "lzs", + .uinfo = { + .comp = { + .threshold = 90, + } + }, + .desc = { .sadb_alg_id = SADB_X_CALG_LZS } +}, +{ + .name = "lzjh", + .uinfo = { + .comp = { + .threshold = 50, + } + }, + .desc = { .sadb_alg_id = SADB_X_CALG_LZJH } +}, +}; + static inline int aalg_entries(void) { return sizeof(aalg_list) / sizeof(aalg_list[0]); @@ -229,6 +259,12 @@ static inline int ealg_entries(void) return sizeof(ealg_list) / sizeof(ealg_list[0]); } +static inline int calg_entries(void) +{ + return sizeof(calg_list) / sizeof(calg_list[0]); +} + +/* Todo: generic iterators */ struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id) { int i; @@ -259,6 +295,21 @@ struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id) return NULL; } +struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id) +{ + int i; + + for (i = 0; i < calg_entries(); i++) { + if (calg_list[i].desc.sadb_alg_id == alg_id) { + if (calg_list[i].available) + return &calg_list[i]; + else + break; + } + } + return NULL; +} + struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name) { int i; @@ -295,6 +346,24 @@ struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name) return NULL; } +struct xfrm_algo_desc *xfrm_calg_get_byname(char *name) +{ + int i; + + if (!name) + return NULL; + + for (i=0; i < calg_entries(); i++) { + if (strcmp(name, calg_list[i].name) == 0) { + if (calg_list[i].available) + return &calg_list[i]; + else + break; + } + } + return NULL; +} + struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx) { if (idx >= aalg_entries()) @@ -311,6 +380,14 @@ struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx) return &ealg_list[idx]; } +struct xfrm_algo_desc *xfrm_calg_get_byidx(unsigned int idx) +{ + if (idx >= calg_entries()) + return NULL; + + return &calg_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 @@ -334,6 +411,12 @@ void xfrm_probe_algs(void) if (ealg_list[i].available != status) ealg_list[i].available = status; } + + for (i = 0; i < calg_entries(); i++) { + status = crypto_alg_available(calg_list[i].name, 0); + if (calg_list[i].available != status) + calg_list[i].available = status; + } #endif } diff --git a/net/key/af_key.c b/net/key/af_key.c index 3e1ffac2c473..e9d2ebedb153 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -667,10 +667,17 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, sa->sadb_sa_auth = a ? a->desc.sadb_alg_id : 0; } sa->sadb_sa_encrypt = 0; + BUG_ON(x->ealg && x->calg); if (x->ealg) { struct xfrm_algo_desc *a = xfrm_ealg_get_byname(x->ealg->alg_name); sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0; } + /* KAME compatible: sadb_sa_encrypt is overloaded with calg id */ + if (x->calg) { + struct xfrm_algo_desc *a = xfrm_calg_get_byname(x->calg->alg_name); + sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0; + } + sa->sadb_sa_flags = 0; /* hard time */ @@ -896,6 +903,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, Hence, we have to _ignore_ sadb_sa_state, which is also reasonable. */ if (sa->sadb_sa_auth > SADB_AALG_MAX || + (hdr->sadb_msg_satype == SADB_X_SATYPE_IPCOMP && + sa->sadb_sa_encrypt > SADB_X_CALG_MAX) || sa->sadb_sa_encrypt > SADB_EALG_MAX) return ERR_PTR(-EINVAL); key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1]; @@ -953,24 +962,35 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, x->props.aalgo = sa->sadb_sa_auth; /* x->algo.flags = sa->sadb_sa_flags; */ } - key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; if (sa->sadb_sa_encrypt) { - int keysize = 0; - struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt); - if (!a) - goto out; - if (key) - keysize = (key->sadb_key_bits + 7) / 8; - x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); - if (!x->ealg) - goto out; - strcpy(x->ealg->alg_name, a->name); - x->ealg->alg_key_len = 0; - if (key) { - x->ealg->alg_key_len = key->sadb_key_bits; - memcpy(x->ealg->alg_key, key+1, keysize); + if (hdr->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) { + struct xfrm_algo_desc *a = xfrm_calg_get_byid(sa->sadb_sa_encrypt); + if (!a) + goto out; + x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL); + if (!x->calg) + goto out; + strcpy(x->calg->alg_name, a->name); + x->props.calgo = sa->sadb_sa_encrypt; + } else { + int keysize = 0; + struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt); + if (!a) + goto out; + key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; + if (key) + keysize = (key->sadb_key_bits + 7) / 8; + x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); + if (!x->ealg) + goto out; + strcpy(x->ealg->alg_name, a->name); + x->ealg->alg_key_len = 0; + if (key) { + x->ealg->alg_key_len = key->sadb_key_bits; + memcpy(x->ealg->alg_key, key+1, keysize); + } + x->props.ealgo = sa->sadb_sa_encrypt; } - x->props.ealgo = sa->sadb_sa_encrypt; } /* x->algo.flags = sa->sadb_sa_flags; */ @@ -1024,6 +1044,8 @@ out: kfree(x->aalg); if (x->ealg) kfree(x->ealg); + if (x->calg) + kfree(x->calg); kfree(x); return ERR_PTR(-ENOBUFS); } diff --git a/net/netsyms.c b/net/netsyms.c index 0fb028543f3d..52b0b4ec1146 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -349,10 +349,13 @@ 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_calg_get_byidx); EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid); EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid); +EXPORT_SYMBOL_GPL(xfrm_calg_get_byid); EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname); EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname); +EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); #if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE) EXPORT_SYMBOL_GPL(skb_ah_walk); #endif |
