]> err.no Git - linux-2.6/blobdiff - net/xfrm/xfrm_user.c
[NETFILTER]: CLUSTERIP: fix memcpy() length typo
[linux-2.6] / net / xfrm / xfrm_user.c
index bd8e6882c0836b8d318f3f8185daa915b218eea2..c35336a0f71b5c50cca286fc2eca45043d205807 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;
@@ -296,19 +289,16 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
        if (err < 0) {
                x->km.state = XFRM_STATE_DEAD;
                xfrm_state_put(x);
-               return err;
+               goto out;
        }
 
        c.seq = nlh->nlmsg_seq;
        c.pid = nlh->nlmsg_pid;
-       if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
-               c.event = XFRM_SAP_ADDED;
-       else
-               c.event = XFRM_SAP_UPDATED;
+       c.event = nlh->nlmsg_type;
 
        km_state_notify(x, &c);
+out:
        xfrm_state_put(x);
-
        return err;
 }
 
@@ -336,7 +326,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
 
        c.seq = nlh->nlmsg_seq;
        c.pid = nlh->nlmsg_pid;
-       c.event = XFRM_SAP_DELETED;
+       c.event = nlh->nlmsg_type;
        km_state_notify(x, &c);
        xfrm_state_put(x);
 
@@ -728,11 +718,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
                return err;
        }
 
-       if (!excl)
-               c.event = XFRM_SAP_UPDATED;
-       else
-               c.event = XFRM_SAP_ADDED;
-
+       c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
        c.pid = nlh->nlmsg_pid;
        km_policy_notify(xp, p->dir, &c);
@@ -883,7 +869,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
                                              MSG_DONTWAIT);
                }
        } else {
-               c.event = XFRM_SAP_DELETED;
+               c.data.byid = p->index;
+               c.event = nlh->nlmsg_type;
                c.seq = nlh->nlmsg_seq;
                c.pid = nlh->nlmsg_pid;
                km_policy_notify(xp, p->dir, &c);
@@ -900,8 +887,8 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma
        struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
 
        xfrm_state_flush(p->proto);
-       c.data = p->proto;
-       c.event = XFRM_SAP_FLUSHED;
+       c.data.proto = p->proto;
+       c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
        c.pid = nlh->nlmsg_pid;
        km_state_notify(NULL, &c);
@@ -914,7 +901,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x
        struct km_event c;
 
        xfrm_policy_flush();
-       c.event = XFRM_SAP_FLUSHED;
+       c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
        c.pid = nlh->nlmsg_pid;
        km_policy_notify(NULL, 0, &c);
@@ -1129,19 +1116,17 @@ nlmsg_failure:
 static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
 {
        struct sk_buff *skb;
-       int hard = c ->data;
+       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;
 
-       if (build_expire(skb, x, hard) < 0)
+       if (build_expire(skb, x, c->data.hard) < 0)
                BUG();
 
-       NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
-
-       return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
+       NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE;
+       return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
 }
 
 static int xfrm_notify_sa_flush(struct km_event *c)
@@ -1162,11 +1147,12 @@ static int xfrm_notify_sa_flush(struct km_event *c)
        nlh->nlmsg_flags = 0;
 
        p = NLMSG_DATA(nlh);
-       p->proto = c->data;
+       p->proto = c->data.proto;
 
        nlh->nlmsg_len = skb->tail - b;
 
-       return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+       NETLINK_CB(skb).dst_group = XFRMNLGRP_SA;
+       return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
 
 nlmsg_failure:
        kfree_skb(skb);
@@ -1175,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)
@@ -1191,30 +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;
-       u32 nlt;
        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;
 
-       if (c->event == XFRM_SAP_ADDED)
-               nlt = XFRM_MSG_NEWSA;
-       else if (c->event == XFRM_SAP_UPDATED)
-               nlt = XFRM_MSG_UPDSA;
-       else if (c->event == XFRM_SAP_DELETED)
-               nlt = XFRM_MSG_DELSA;
-       else
-               goto nlmsg_failure;
-
-       nlh = NLMSG_PUT(skb, c->pid, c->seq, nlt, 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)
@@ -1231,7 +1226,8 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
 
        nlh->nlmsg_len = skb->tail - b;
 
-       return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+       NETLINK_CB(skb).dst_group = XFRMNLGRP_SA;
+       return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
 
 nlmsg_failure:
 rtattr_failure:
@@ -1243,13 +1239,13 @@ static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c)
 {
 
        switch (c->event) {
-       case XFRM_SAP_EXPIRED:
+       case XFRM_MSG_EXPIRE:
                return xfrm_exp_state_notify(x, c);
-       case XFRM_SAP_DELETED:
-       case XFRM_SAP_UPDATED:
-       case XFRM_SAP_ADDED:
+       case XFRM_MSG_DELSA:
+       case XFRM_MSG_UPDSA:
+       case XFRM_MSG_NEWSA:
                return xfrm_notify_sa(x, c);
-       case XFRM_SAP_FLUSHED:
+       case XFRM_MSG_FLUSHSA:
                return xfrm_notify_sa_flush(c);
        default:
                 printk("xfrm_user: Unknown SA event %d\n", c->event);
@@ -1309,9 +1305,8 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
        if (build_acquire(skb, x, xt, xp, dir) < 0)
                BUG();
 
-       NETLINK_CB(skb).dst_groups = XFRMGRP_ACQUIRE;
-
-       return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_ACQUIRE, GFP_ATOMIC);
+       NETLINK_CB(skb).dst_group = XFRMNLGRP_ACQUIRE;
+       return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC);
 }
 
 /* User gives us xfrm_user_policy_info followed by an array of 0
@@ -1355,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;
@@ -1404,41 +1402,49 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
        if (skb == NULL)
                return -ENOMEM;
 
-       if (build_polexpire(skb, xp, dir, c->data) < 0)
+       if (build_polexpire(skb, xp, dir, c->data.hard) < 0)
                BUG();
 
-       NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
-
-       return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
+       NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE;
+       return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
 }
 
 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;
-       u32 nlt = 0 ;
        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;
 
-       if (c->event == XFRM_SAP_ADDED)
-               nlt = XFRM_MSG_NEWPOLICY;
-       else if (c->event == XFRM_SAP_UPDATED)
-               nlt = XFRM_MSG_UPDPOLICY;
-       else if (c->event == XFRM_SAP_DELETED)
-               nlt = XFRM_MSG_DELPOLICY;
-       else
-               goto nlmsg_failure;
-
-       nlh = NLMSG_PUT(skb, c->pid, c->seq, nlt, 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;
 
@@ -1448,9 +1454,11 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
 
        nlh->nlmsg_len = skb->tail - b;
 
-       return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+       NETLINK_CB(skb).dst_group = XFRMNLGRP_POLICY;
+       return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
 
 nlmsg_failure:
+rtattr_failure:
        kfree_skb(skb);
        return -1;
 }
@@ -1472,7 +1480,8 @@ static int xfrm_notify_policy_flush(struct km_event *c)
 
        nlh->nlmsg_len = skb->tail - b;
 
-       return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+       NETLINK_CB(skb).dst_group = XFRMNLGRP_POLICY;
+       return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
 
 nlmsg_failure:
        kfree_skb(skb);
@@ -1483,13 +1492,13 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_ev
 {
 
        switch (c->event) {
-       case XFRM_SAP_ADDED:
-       case XFRM_SAP_UPDATED:
-       case XFRM_SAP_DELETED:
+       case XFRM_MSG_NEWPOLICY:
+       case XFRM_MSG_UPDPOLICY:
+       case XFRM_MSG_DELPOLICY:
                return xfrm_notify_policy(xp, dir, c);
-       case XFRM_SAP_FLUSHED:
+       case XFRM_MSG_FLUSHPOLICY:
                return xfrm_notify_policy_flush(c);
-       case XFRM_SAP_EXPIRED:
+       case XFRM_MSG_POLEXPIRE:
                return xfrm_exp_policy_notify(xp, dir, c);
        default:
                printk("xfrm_user: Unknown Policy event %d\n", c->event);
@@ -1511,7 +1520,8 @@ static int __init xfrm_user_init(void)
 {
        printk(KERN_INFO "Initializing IPsec netlink socket\n");
 
-       xfrm_nl = netlink_kernel_create(NETLINK_XFRM, xfrm_netlink_rcv);
+       xfrm_nl = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
+                                       xfrm_netlink_rcv, THIS_MODULE);
        if (xfrm_nl == NULL)
                return -ENOMEM;
 
@@ -1529,3 +1539,4 @@ static void __exit xfrm_user_exit(void)
 module_init(xfrm_user_init);
 module_exit(xfrm_user_exit);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);