diff options
author | Jamal Hadi Salim <hadi@cyberus.ca> | 2006-03-20 19:16:40 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 19:16:40 -0800 |
commit | 980ebd25794f0f87ac32844e2c73e9e81f0a72ba (patch) | |
tree | da52df6e31bd4b2527c223ca2585e0d792bf3ea2 | |
parent | d51d081d65048a7a6f9956a7809c3bb504f3b95d (diff) |
[IPSEC]: Sync series - acquire insert
This introduces a feature similar to the one described in RFC 2367:
"
... the application needing an SA sends a PF_KEY
SADB_ACQUIRE message down to the Key Engine, which then either
returns an error or sends a similar SADB_ACQUIRE message up to one or
more key management applications capable of creating such SAs.
...
...
The third is where an application-layer consumer of security
associations (e.g. an OSPFv2 or RIPv2 daemon) needs a security
association.
Send an SADB_ACQUIRE message from a user process to the kernel.
<base, address(SD), (address(P),) (identity(SD),) (sensitivity,)
proposal>
The kernel returns an SADB_ACQUIRE message to registered
sockets.
<base, address(SD), (address(P),) (identity(SD),) (sensitivity,)
proposal>
The user-level consumer waits for an SADB_UPDATE or SADB_ADD
message for its particular type, and then can use that
association by using SADB_GET messages.
"
An app such as OSPF could then use ipsec KM to get keys
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/xfrm.h | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 5 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 54 |
3 files changed, 58 insertions, 3 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index bc005e62e434..30a940b147b0 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -214,10 +214,10 @@ extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c); extern void km_state_notify(struct xfrm_state *x, struct km_event *c); - #define XFRM_ACQ_EXPIRES 30 struct xfrm_tmpl; +extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); struct xfrm_state_afinfo { unsigned short family; rwlock_t lock; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 8eaee499cad5..a613b5c7d409 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -57,7 +57,7 @@ static int __xfrm_state_delete(struct xfrm_state *x); static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); -static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); +int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); static void km_state_expired(struct xfrm_state *x, int hard); static void xfrm_state_gc_destroy(struct xfrm_state *x) @@ -925,7 +925,7 @@ void km_state_expired(struct xfrm_state *x, int hard) * We send to all registered managers regardless of failure * We are happy with one success */ -static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) +int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) { int err = -EINVAL, acqret; struct xfrm_mgr *km; @@ -939,6 +939,7 @@ static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_polic read_unlock(&xfrm_km_lock); return err; } +EXPORT_SYMBOL(km_query); int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport) { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index e230ba5328d3..d6e6527fd8d7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1232,6 +1232,58 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x return 0; } +static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) +{ + struct xfrm_policy *xp; + struct xfrm_user_tmpl *ut; + int i; + struct rtattr *rt = xfrma[XFRMA_TMPL-1]; + + struct xfrm_user_acquire *ua = NLMSG_DATA(nlh); + struct xfrm_state *x = xfrm_state_alloc(); + int err = -ENOMEM; + + if (!x) + return err; + + err = verify_newpolicy_info(&ua->policy); + if (err) { + printk("BAD policy passed\n"); + kfree(x); + return err; + } + + /* build an XP */ + xp = xfrm_policy_construct(&ua->policy, (struct rtattr **) xfrma, &err); if (!xp) { + kfree(x); + return err; + } + + memcpy(&x->id, &ua->id, sizeof(ua->id)); + memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); + memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); + + ut = RTA_DATA(rt); + /* extract the templates and for each call km_key */ + for (i = 0; i < xp->xfrm_nr; i++, ut++) { + struct xfrm_tmpl *t = &xp->xfrm_vec[i]; + memcpy(&x->id, &t->id, sizeof(x->id)); + x->props.mode = t->mode; + x->props.reqid = t->reqid; + x->props.family = ut->family; + t->aalgos = ua->aalgos; + t->ealgos = ua->ealgos; + t->calgos = ua->calgos; + err = km_query(x, t, xp); + + } + + kfree(x); + kfree(xp); + + return 0; +} + #define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) @@ -1243,6 +1295,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), + [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), @@ -1266,6 +1319,7 @@ static struct xfrm_link { [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, .dump = xfrm_dump_policy }, [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, + [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, |