From 980ebd25794f0f87ac32844e2c73e9e81f0a72ba Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:16:40 -0800 Subject: [PATCH] [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. The kernel returns an SADB_ACQUIRE message to registered sockets. 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 Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 +- net/xfrm/xfrm_state.c | 5 ++-- 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 }, -- 2.20.1