bridge: add a missing ntohs()
[safe/jmp/linux-2.6] / net / xfrm / xfrm_user.c
index 331ae73..6106b72 100644 (file)
@@ -31,9 +31,6 @@
 #include <linux/in6.h>
 #endif
 
-#define DUMMY_MARK 0
-static struct xfrm_mark dummy_mark = {0, 0};
-
 static inline int aead_len(struct xfrm_algo_aead *alg)
 {
        return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
@@ -449,6 +446,8 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
                        goto error;
        }
 
+       xfrm_mark_get(attrs, &x->mark);
+
        err = xfrm_init_state(x);
        if (err)
                goto error;
@@ -529,11 +528,13 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
                                                 int *errp)
 {
        struct xfrm_state *x = NULL;
+       struct xfrm_mark m;
        int err;
+       u32 mark = xfrm_mark_get(attrs, &m);
 
        if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
                err = -ESRCH;
-               x = xfrm_state_lookup(net, DUMMY_MARK, &p->daddr, p->spi, p->proto, p->family);
+               x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family);
        } else {
                xfrm_address_t *saddr = NULL;
 
@@ -544,7 +545,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
                }
 
                err = -ESRCH;
-               x = xfrm_state_lookup_byaddr(net, DUMMY_MARK, &p->daddr, saddr,
+               x = xfrm_state_lookup_byaddr(net, mark,
+                                            &p->daddr, saddr,
                                             p->proto, p->family);
        }
 
@@ -686,6 +688,9 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
        if (x->encap)
                NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
 
+       if (xfrm_mark_put(skb, &x->mark))
+               goto nla_put_failure;
+
        if (x->security && copy_sec_ctx(x->security, skb) < 0)
                goto nla_put_failure;
 
@@ -950,6 +955,8 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
        xfrm_address_t *daddr;
        int family;
        int err;
+       u32 mark;
+       struct xfrm_mark m;
 
        p = nlmsg_data(nlh);
        err = verify_userspi_info(p);
@@ -960,8 +967,10 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
        daddr = &p->info.id.daddr;
 
        x = NULL;
+
+       mark = xfrm_mark_get(attrs, &m);
        if (p->info.seq) {
-               x = xfrm_find_acq_byseq(net, DUMMY_MARK, p->info.seq);
+               x = xfrm_find_acq_byseq(net, mark, p->info.seq);
                if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
                        xfrm_state_put(x);
                        x = NULL;
@@ -969,7 +978,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
        }
 
        if (!x)
-               x = xfrm_find_acq(net, &dummy_mark, p->info.mode, p->info.reqid,
+               x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid,
                                  p->info.id.proto, daddr,
                                  &p->info.saddr, 1,
                                  family);
@@ -1223,6 +1232,8 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us
        if (err)
                goto error;
 
+       xfrm_mark_get(attrs, &xp->mark);
+
        return xp;
  error:
        *errp = err;
@@ -1369,10 +1380,13 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
                goto nlmsg_failure;
        if (copy_to_user_policy_type(xp->type, skb) < 0)
                goto nlmsg_failure;
+       if (xfrm_mark_put(skb, &xp->mark))
+               goto nla_put_failure;
 
        nlmsg_end(skb, nlh);
        return 0;
 
+nla_put_failure:
 nlmsg_failure:
        nlmsg_cancel(skb, nlh);
        return -EMSGSIZE;
@@ -1444,6 +1458,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
        int err;
        struct km_event c;
        int delete;
+       struct xfrm_mark m;
+       u32 mark = xfrm_mark_get(attrs, &m);
 
        p = nlmsg_data(nlh);
        delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;
@@ -1457,7 +1473,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                return err;
 
        if (p->index)
-               xp = xfrm_policy_byid(net, type, p->dir, p->index, delete, &err);
+               xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err);
        else {
                struct nlattr *rt = attrs[XFRMA_SEC_CTX];
                struct xfrm_sec_ctx *ctx;
@@ -1474,8 +1490,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                        if (err)
                                return err;
                }
-               xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx,
-                                          delete, &err);
+               xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel,
+                                          ctx, delete, &err);
                security_xfrm_policy_free(ctx);
        }
        if (xp == NULL)
@@ -1547,6 +1563,7 @@ static inline size_t xfrm_aevent_msgsize(void)
        return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
               + nla_total_size(sizeof(struct xfrm_replay_state))
               + nla_total_size(sizeof(struct xfrm_lifetime_cur))
+              + nla_total_size(sizeof(struct xfrm_mark))
               + nla_total_size(4) /* XFRM_AE_RTHR */
               + nla_total_size(4); /* XFRM_AE_ETHR */
 }
@@ -1579,6 +1596,9 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
                NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH,
                            x->replay_maxage * 10 / HZ);
 
+       if (xfrm_mark_put(skb, &x->mark))
+               goto nla_put_failure;
+
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
@@ -1594,6 +1614,8 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct sk_buff *r_skb;
        int err;
        struct km_event c;
+       u32 mark;
+       struct xfrm_mark m;
        struct xfrm_aevent_id *p = nlmsg_data(nlh);
        struct xfrm_usersa_id *id = &p->sa_id;
 
@@ -1601,7 +1623,9 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (r_skb == NULL)
                return -ENOMEM;
 
-       x = xfrm_state_lookup(net, DUMMY_MARK, &id->daddr, id->spi, id->proto, id->family);
+       mark = xfrm_mark_get(attrs, &m);
+
+       x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
        if (x == NULL) {
                kfree_skb(r_skb);
                return -ESRCH;
@@ -1632,6 +1656,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct xfrm_state *x;
        struct km_event c;
        int err = - EINVAL;
+       u32 mark = 0;
+       struct xfrm_mark m;
        struct xfrm_aevent_id *p = nlmsg_data(nlh);
        struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
        struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
@@ -1643,7 +1669,9 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (!(nlh->nlmsg_flags&NLM_F_REPLACE))
                return err;
 
-       x = xfrm_state_lookup(net, DUMMY_MARK, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
+       mark = xfrm_mark_get(attrs, &m);
+
+       x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
        if (x == NULL)
                return -ESRCH;
 
@@ -1706,13 +1734,15 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct xfrm_userpolicy_info *p = &up->pol;
        u8 type = XFRM_POLICY_TYPE_MAIN;
        int err = -ENOENT;
+       struct xfrm_mark m;
+       u32 mark = xfrm_mark_get(attrs, &m);
 
        err = copy_from_user_policy_type(&type, attrs);
        if (err)
                return err;
 
        if (p->index)
-               xp = xfrm_policy_byid(net, type, p->dir, p->index, 0, &err);
+               xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err);
        else {
                struct nlattr *rt = attrs[XFRMA_SEC_CTX];
                struct xfrm_sec_ctx *ctx;
@@ -1729,7 +1759,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
                        if (err)
                                return err;
                }
-               xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, 0, &err);
+               xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir,
+                                          &p->sel, ctx, 0, &err);
                security_xfrm_policy_free(ctx);
        }
        if (xp == NULL)
@@ -1769,8 +1800,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
        int err;
        struct xfrm_user_expire *ue = nlmsg_data(nlh);
        struct xfrm_usersa_info *p = &ue->state;
+       struct xfrm_mark m;
+       u32 mark = xfrm_mark_get(attrs, &m);;
 
-       x = xfrm_state_lookup(net, DUMMY_MARK, &p->id.daddr, p->id.spi, p->id.proto, p->family);
+       x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family);
 
        err = -ENOENT;
        if (x == NULL)
@@ -1804,6 +1837,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct xfrm_user_tmpl *ut;
        int i;
        struct nlattr *rt = attrs[XFRMA_TMPL];
+       struct xfrm_mark mark;
 
        struct xfrm_user_acquire *ua = nlmsg_data(nlh);
        struct xfrm_state *x = xfrm_state_alloc(net);
@@ -1812,6 +1846,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (!x)
                goto nomem;
 
+       xfrm_mark_get(attrs, &mark);
+
        err = verify_newpolicy_info(&ua->policy);
        if (err)
                goto bad_policy;
@@ -1824,7 +1860,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
        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));
-
+       xp->mark.m = x->mark.m = mark.m;
+       xp->mark.v = x->mark.v = mark.v;
        ut = nla_data(rt);
        /* extract the templates and for each call km_key */
        for (i = 0; i < xp->xfrm_nr; i++, ut++) {
@@ -2084,6 +2121,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
        [XFRMA_POLICY_TYPE]     = { .len = sizeof(struct xfrm_userpolicy_type)},
        [XFRMA_MIGRATE]         = { .len = sizeof(struct xfrm_user_migrate) },
        [XFRMA_KMADDRESS]       = { .len = sizeof(struct xfrm_user_kmaddress) },
+       [XFRMA_MARK]            = { .len = sizeof(struct xfrm_mark) },
 };
 
 static struct xfrm_link {
@@ -2163,7 +2201,8 @@ static void xfrm_netlink_rcv(struct sk_buff *skb)
 
 static inline size_t xfrm_expire_msgsize(void)
 {
-       return NLMSG_ALIGN(sizeof(struct xfrm_user_expire));
+       return NLMSG_ALIGN(sizeof(struct xfrm_user_expire))
+              + nla_total_size(sizeof(struct xfrm_mark));
 }
 
 static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c)
@@ -2179,7 +2218,13 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
        copy_to_user_state(x, &ue->state);
        ue->hard = (c->data.hard != 0) ? 1 : 0;
 
+       if (xfrm_mark_put(skb, &x->mark))
+               goto nla_put_failure;
+
        return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+       return -EMSGSIZE;
 }
 
 static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
@@ -2191,8 +2236,10 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
        if (skb == NULL)
                return -ENOMEM;
 
-       if (build_expire(skb, x, c) < 0)
-               BUG();
+       if (build_expire(skb, x, c) < 0) {
+               kfree_skb(skb);
+               return -EMSGSIZE;
+       }
 
        return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
 }
@@ -2280,6 +2327,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
        if (c->event == XFRM_MSG_DELSA) {
                len += nla_total_size(headlen);
                headlen = sizeof(*id);
+               len += nla_total_size(sizeof(struct xfrm_mark));
        }
        len += NLMSG_ALIGN(headlen);
 
@@ -2350,6 +2398,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x,
 {
        return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire))
               + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
+              + nla_total_size(sizeof(struct xfrm_mark))
               + nla_total_size(xfrm_user_sec_ctx_size(x->security))
               + userpolicy_type_attrsize();
 }
@@ -2382,9 +2431,12 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
                goto nlmsg_failure;
        if (copy_to_user_policy_type(xp->type, skb) < 0)
                goto nlmsg_failure;
+       if (xfrm_mark_put(skb, &xp->mark))
+               goto nla_put_failure;
 
        return nlmsg_end(skb, nlh);
 
+nla_put_failure:
 nlmsg_failure:
        nlmsg_cancel(skb, nlh);
        return -EMSGSIZE;
@@ -2471,6 +2523,7 @@ static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp)
        return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire))
               + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
               + nla_total_size(xfrm_user_sec_ctx_size(xp->security))
+              + nla_total_size(sizeof(struct xfrm_mark))
               + userpolicy_type_attrsize();
 }
 
@@ -2493,10 +2546,13 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
                goto nlmsg_failure;
        if (copy_to_user_policy_type(xp->type, skb) < 0)
                goto nlmsg_failure;
+       if (xfrm_mark_put(skb, &xp->mark))
+               goto nla_put_failure;
        upe->hard = !!hard;
 
        return nlmsg_end(skb, nlh);
 
+nla_put_failure:
 nlmsg_failure:
        nlmsg_cancel(skb, nlh);
        return -EMSGSIZE;
@@ -2533,6 +2589,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
                headlen = sizeof(*id);
        }
        len += userpolicy_type_attrsize();
+       len += nla_total_size(sizeof(struct xfrm_mark));
        len += NLMSG_ALIGN(headlen);
 
        skb = nlmsg_new(len, GFP_ATOMIC);
@@ -2568,10 +2625,14 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
        if (copy_to_user_policy_type(xp->type, skb) < 0)
                goto nlmsg_failure;
 
+       if (xfrm_mark_put(skb, &xp->mark))
+               goto nla_put_failure;
+
        nlmsg_end(skb, nlh);
 
        return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
 
+nla_put_failure:
 nlmsg_failure:
        kfree_skb(skb);
        return -1;