/home/lenb/src/to-linus branch 'acpi-2.6.12'
[pandora-kernel.git] / net / xfrm / xfrm_user.c
index 9d30f73..8da3e25 100644 (file)
@@ -249,17 +249,10 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
        if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
                goto error;
 
-       err = -ENOENT;
-       x->type = xfrm_get_type(x->id.proto, x->props.family);
-       if (x->type == NULL)
-               goto error;
-
-       err = x->type->init_state(x, NULL);
+       err = xfrm_init_state(x);
        if (err)
                goto error;
 
-       x->curlft.add_time = (unsigned long) xtime.tv_sec;
-       x->km.state = XFRM_STATE_VALID;
        x->km.seq = p->seq;
 
        return x;
@@ -1123,9 +1116,9 @@ nlmsg_failure:
 static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
 {
        struct sk_buff *skb;
+       int len = NLMSG_LENGTH(sizeof(struct xfrm_user_expire));
 
-       /* fix to do alloc using NLM macros */
-       skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC);
+       skb = alloc_skb(len, GFP_ATOMIC);
        if (skb == NULL)
                return -ENOMEM;
 
@@ -1168,7 +1161,7 @@ nlmsg_failure:
 
 static int inline xfrm_sa_len(struct xfrm_state *x)
 {
-       int l = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
+       int l = 0;
        if (x->aalg)
                l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8);
        if (x->ealg)
@@ -1184,20 +1177,39 @@ static int inline xfrm_sa_len(struct xfrm_state *x)
 static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
 {
        struct xfrm_usersa_info *p;
+       struct xfrm_usersa_id *id;
        struct nlmsghdr *nlh;
        struct sk_buff *skb;
        unsigned char *b;
        int len = xfrm_sa_len(x);
+       int headlen;
+
+       headlen = sizeof(*p);
+       if (c->event == XFRM_MSG_DELSA) {
+               len += RTA_SPACE(headlen);
+               headlen = sizeof(*id);
+       }
+       len += NLMSG_SPACE(headlen);
 
        skb = alloc_skb(len, GFP_ATOMIC);
        if (skb == NULL)
                return -ENOMEM;
        b = skb->tail;
 
-       nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, sizeof(*p));
+       nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
        nlh->nlmsg_flags = 0;
 
        p = NLMSG_DATA(nlh);
+       if (c->event == XFRM_MSG_DELSA) {
+               id = NLMSG_DATA(nlh);
+               memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
+               id->spi = x->id.spi;
+               id->family = x->props.family;
+               id->proto = x->id.proto;
+
+               p = RTA_DATA(__RTA_PUT(skb, XFRMA_SA, sizeof(*p)));
+       }
+
        copy_to_user_state(x, p);
 
        if (x->aalg)
@@ -1338,6 +1350,9 @@ static struct xfrm_policy *xfrm_compile_policy(u16 family, int opt,
        if (nr > XFRM_MAX_DEPTH)
                return NULL;
 
+       if (p->dir > XFRM_POLICY_OUT)
+               return NULL;
+
        xp = xfrm_policy_alloc(GFP_KERNEL);
        if (xp == NULL) {
                *dir = -ENOBUFS;
@@ -1398,20 +1413,39 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
 static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
 {
        struct xfrm_userpolicy_info *p;
+       struct xfrm_userpolicy_id *id;
        struct nlmsghdr *nlh;
        struct sk_buff *skb;
        unsigned char *b;
        int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
-       len += NLMSG_SPACE(sizeof(struct xfrm_userpolicy_info));
+       int headlen;
+
+       headlen = sizeof(*p);
+       if (c->event == XFRM_MSG_DELPOLICY) {
+               len += RTA_SPACE(headlen);
+               headlen = sizeof(*id);
+       }
+       len += NLMSG_SPACE(headlen);
 
        skb = alloc_skb(len, GFP_ATOMIC);
        if (skb == NULL)
                return -ENOMEM;
        b = skb->tail;
 
-       nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, sizeof(*p));
+       nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
 
        p = NLMSG_DATA(nlh);
+       if (c->event == XFRM_MSG_DELPOLICY) {
+               id = NLMSG_DATA(nlh);
+               memset(id, 0, sizeof(*id));
+               id->dir = dir;
+               if (c->data.byid)
+                       id->index = xp->index;
+               else
+                       memcpy(&id->sel, &xp->selector, sizeof(id->sel));
+
+               p = RTA_DATA(__RTA_PUT(skb, XFRMA_POLICY, sizeof(*p)));
+       }
 
        nlh->nlmsg_flags = 0;
 
@@ -1424,6 +1458,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
        return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
 
 nlmsg_failure:
+rtattr_failure:
        kfree_skb(skb);
        return -1;
 }