Commit bfe169a1 authored by James Morris's avatar James Morris Committed by David S. Miller

[IPSEC] Add initial compression support for pfkey and xfrm_algo.

parent e5c1202f
...@@ -262,6 +262,14 @@ struct sadb_x_ipsecrequest { ...@@ -262,6 +262,14 @@ struct sadb_x_ipsecrequest {
#define SADB_X_EALG_AESCBC 12 #define SADB_X_EALG_AESCBC 12
#define SADB_EALG_MAX 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 */ /* Extension Header values */
#define SADB_EXT_RESERVED 0 #define SADB_EXT_RESERVED 0
#define SADB_EXT_SA 1 #define SADB_EXT_SA 1
......
...@@ -391,12 +391,17 @@ struct xfrm_algo_encr_info { ...@@ -391,12 +391,17 @@ struct xfrm_algo_encr_info {
u16 defkeybits; u16 defkeybits;
}; };
struct xfrm_algo_comp_info {
u16 threshold;
};
struct xfrm_algo_desc { struct xfrm_algo_desc {
char *name; char *name;
u8 available:1; u8 available:1;
union { union {
struct xfrm_algo_auth_info auth; struct xfrm_algo_auth_info auth;
struct xfrm_algo_encr_info encr; struct xfrm_algo_encr_info encr;
struct xfrm_algo_comp_info comp;
} uinfo; } uinfo;
struct sadb_alg desc; struct sadb_alg desc;
}; };
...@@ -453,10 +458,13 @@ extern int xfrm_count_auth_supported(void); ...@@ -453,10 +458,13 @@ extern int xfrm_count_auth_supported(void);
extern int xfrm_count_enc_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_aalg_get_byidx(unsigned int idx);
extern struct xfrm_algo_desc *xfrm_ealg_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_aalg_get_byid(int alg_id);
extern struct xfrm_algo_desc *xfrm_ealg_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_aalg_get_byname(char *name);
extern struct xfrm_algo_desc *xfrm_ealg_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) static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
{ {
......
...@@ -219,6 +219,36 @@ static struct xfrm_algo_desc ealg_list[] = { ...@@ -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) static inline int aalg_entries(void)
{ {
return sizeof(aalg_list) / sizeof(aalg_list[0]); return sizeof(aalg_list) / sizeof(aalg_list[0]);
...@@ -229,6 +259,12 @@ static inline int ealg_entries(void) ...@@ -229,6 +259,12 @@ static inline int ealg_entries(void)
return sizeof(ealg_list) / sizeof(ealg_list[0]); 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) struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
{ {
int i; int i;
...@@ -259,6 +295,21 @@ struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id) ...@@ -259,6 +295,21 @@ struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
return NULL; 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) struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name)
{ {
int i; int i;
...@@ -295,6 +346,24 @@ struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name) ...@@ -295,6 +346,24 @@ struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name)
return NULL; 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) struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
{ {
if (idx >= aalg_entries()) if (idx >= aalg_entries())
...@@ -311,6 +380,14 @@ struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx) ...@@ -311,6 +380,14 @@ struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
return &ealg_list[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 * Probe for the availability of crypto algorithms, and set the available
* flag for any algorithms found on the system. This is typically called by * flag for any algorithms found on the system. This is typically called by
...@@ -334,6 +411,12 @@ void xfrm_probe_algs(void) ...@@ -334,6 +411,12 @@ void xfrm_probe_algs(void)
if (ealg_list[i].available != status) if (ealg_list[i].available != status)
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 #endif
} }
......
...@@ -667,10 +667,17 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, ...@@ -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_auth = a ? a->desc.sadb_alg_id : 0;
} }
sa->sadb_sa_encrypt = 0; sa->sadb_sa_encrypt = 0;
BUG_ON(x->ealg && x->calg);
if (x->ealg) { if (x->ealg) {
struct xfrm_algo_desc *a = xfrm_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;
} }
/* 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; sa->sadb_sa_flags = 0;
/* hard time */ /* hard time */
...@@ -896,6 +903,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -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. Hence, we have to _ignore_ sadb_sa_state, which is also reasonable.
*/ */
if (sa->sadb_sa_auth > SADB_AALG_MAX || 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) sa->sadb_sa_encrypt > SADB_EALG_MAX)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1]; 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, ...@@ -953,24 +962,35 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
x->props.aalgo = sa->sadb_sa_auth; x->props.aalgo = sa->sadb_sa_auth;
/* x->algo.flags = sa->sadb_sa_flags; */ /* x->algo.flags = sa->sadb_sa_flags; */
} }
key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
if (sa->sadb_sa_encrypt) { if (sa->sadb_sa_encrypt) {
int keysize = 0; if (hdr->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {
struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt); struct xfrm_algo_desc *a = xfrm_calg_get_byid(sa->sadb_sa_encrypt);
if (!a) if (!a)
goto out; goto out;
if (key) x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
keysize = (key->sadb_key_bits + 7) / 8; if (!x->calg)
x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); goto out;
if (!x->ealg) strcpy(x->calg->alg_name, a->name);
goto out; x->props.calgo = sa->sadb_sa_encrypt;
strcpy(x->ealg->alg_name, a->name); } else {
x->ealg->alg_key_len = 0; int keysize = 0;
if (key) { struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt);
x->ealg->alg_key_len = key->sadb_key_bits; if (!a)
memcpy(x->ealg->alg_key, key+1, keysize); 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; */ /* x->algo.flags = sa->sadb_sa_flags; */
...@@ -1024,6 +1044,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -1024,6 +1044,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
kfree(x->aalg); kfree(x->aalg);
if (x->ealg) if (x->ealg)
kfree(x->ealg); kfree(x->ealg);
if (x->calg)
kfree(x->calg);
kfree(x); kfree(x);
return ERR_PTR(-ENOBUFS); return ERR_PTR(-ENOBUFS);
} }
......
...@@ -349,10 +349,13 @@ EXPORT_SYMBOL_GPL(xfrm_count_auth_supported); ...@@ -349,10 +349,13 @@ EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx); EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
EXPORT_SYMBOL_GPL(xfrm_ealg_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_aalg_get_byid);
EXPORT_SYMBOL_GPL(xfrm_ealg_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_aalg_get_byname);
EXPORT_SYMBOL_GPL(xfrm_ealg_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) #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); EXPORT_SYMBOL_GPL(skb_ah_walk);
#endif #endif
......
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