+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;
+}
+