if ((rt->rta_len - sizeof(*rt)) < sizeof(*encap))
return -EINVAL;
- encap = RTA_DATA(rt);
- switch (encap->encap_type) {
- case UDP_ENCAP_ESPINUDP:
- case UDP_ENCAP_ESPINUDP_NON_IKE:
- break;
- default:
- return -ENOPROTOOPT;
- }
-
return 0;
}
return err;
}
-static int attach_one_algo(struct xfrm_algo **algpp, struct rtattr *u_arg)
+static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
+ struct xfrm_algo_desc *(*get_byname)(char *),
+ struct rtattr *u_arg)
{
struct rtattr *rta = u_arg;
struct xfrm_algo *p, *ualg;
+ struct xfrm_algo_desc *algo;
if (!rta)
return 0;
ualg = RTA_DATA(rta);
+
+ algo = get_byname(ualg->alg_name);
+ if (!algo)
+ return -ENOSYS;
+ *props = algo->desc.sadb_alg_id;
+
p = kmalloc(sizeof(*ualg) + ualg->alg_key_len, GFP_KERNEL);
if (!p)
return -ENOMEM;
copy_from_user_state(x, p);
- if ((err = attach_one_algo(&x->aalg, xfrma[XFRMA_ALG_AUTH-1])))
+ if ((err = attach_one_algo(&x->aalg, &x->props.aalgo,
+ xfrm_aalg_get_byname,
+ xfrma[XFRMA_ALG_AUTH-1])))
goto error;
- if ((err = attach_one_algo(&x->ealg, xfrma[XFRMA_ALG_CRYPT-1])))
+ if ((err = attach_one_algo(&x->ealg, &x->props.ealgo,
+ xfrm_ealg_get_byname,
+ xfrma[XFRMA_ALG_CRYPT-1])))
goto error;
- if ((err = attach_one_algo(&x->calg, xfrma[XFRMA_ALG_COMP-1])))
+ if ((err = attach_one_algo(&x->calg, &x->props.calgo,
+ xfrm_calg_get_byname,
+ xfrma[XFRMA_ALG_COMP-1])))
goto error;
if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
goto error;
struct xfrm_state *x;
struct xfrm_userspi_info *p;
struct sk_buff *resp_skb;
+ xfrm_address_t *daddr;
+ int family;
int err;
p = NLMSG_DATA(nlh);
err = verify_userspi_info(p);
if (err)
goto out_noput;
- x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
- &p->info.id.daddr,
- &p->info.saddr, 1,
- p->info.family);
+
+ family = p->info.family;
+ daddr = &p->info.id.daddr;
+
+ x = NULL;
+ if (p->info.seq) {
+ x = xfrm_find_acq_byseq(p->info.seq);
+ if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
+ xfrm_state_put(x);
+ x = NULL;
+ }
+ }
+
+ if (!x)
+ x = xfrm_find_acq(p->info.mode, p->info.reqid,
+ p->info.id.proto, daddr,
+ &p->info.saddr, 1,
+ family);
err = -ENOENT;
if (x == NULL)
goto out_noput;