]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/xfrm/xfrm_user.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[karo-tx-linux.git] / net / xfrm / xfrm_user.c
index 1ae3ec7c18b0de977b1b781c8fee72d8357543bc..8f131c10a6f3d6793c6d0a049108ab66ccaa8664 100644 (file)
 #include <linux/in6.h>
 #endif
 
-static inline int aead_len(struct xfrm_algo_aead *alg)
-{
-       return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
-}
-
 static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
 {
        struct nlattr *rt = attrs[type];
@@ -142,7 +137,8 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
        if (!rt)
                return 0;
 
-       if (p->id.proto != IPPROTO_ESP)
+       /* As only ESP and AH support ESN feature. */
+       if ((p->id.proto != IPPROTO_ESP) && (p->id.proto != IPPROTO_AH))
                return -EINVAL;
 
        if (p->replay_window != 0)
@@ -886,6 +882,7 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb)
        return 0;
 }
 
+static const struct nla_policy xfrma_policy[XFRMA_MAX+1];
 static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
 {
        struct net *net = sock_net(skb->sk);
@@ -901,8 +898,31 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
        info.nlmsg_flags = NLM_F_MULTI;
 
        if (!cb->args[0]) {
+               struct nlattr *attrs[XFRMA_MAX+1];
+               struct xfrm_address_filter *filter = NULL;
+               u8 proto = 0;
+               int err;
+
                cb->args[0] = 1;
-               xfrm_state_walk_init(walk, 0);
+
+               err = nlmsg_parse(cb->nlh, 0, attrs, XFRMA_MAX,
+                                 xfrma_policy);
+               if (err < 0)
+                       return err;
+
+               if (attrs[XFRMA_ADDRESS_FILTER]) {
+                       filter = kmalloc(sizeof(*filter), GFP_KERNEL);
+                       if (filter == NULL)
+                               return -ENOMEM;
+
+                       memcpy(filter, nla_data(attrs[XFRMA_ADDRESS_FILTER]),
+                              sizeof(*filter));
+               }
+
+               if (attrs[XFRMA_PROTO])
+                       proto = nla_get_u8(attrs[XFRMA_PROTO]);
+
+               xfrm_state_walk_init(walk, proto, filter);
        }
 
        (void) xfrm_state_walk(net, walk, dump_one_state, &info);
@@ -1226,7 +1246,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs
                return 0;
 
        uctx = nla_data(rt);
-       return security_xfrm_policy_alloc(&pol->security, uctx);
+       return security_xfrm_policy_alloc(&pol->security, uctx, GFP_KERNEL);
 }
 
 static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
@@ -1631,7 +1651,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                if (rt) {
                        struct xfrm_user_sec_ctx *uctx = nla_data(rt);
 
-                       err = security_xfrm_policy_alloc(&ctx, uctx);
+                       err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL);
                        if (err)
                                return err;
                }
@@ -1933,7 +1953,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
                if (rt) {
                        struct xfrm_user_sec_ctx *uctx = nla_data(rt);
 
-                       err = security_xfrm_policy_alloc(&ctx, uctx);
+                       err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL);
                        if (err)
                                return err;
                }
@@ -2308,6 +2328,8 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
        [XFRMA_TFCPAD]          = { .type = NLA_U32 },
        [XFRMA_REPLAY_ESN_VAL]  = { .len = sizeof(struct xfrm_replay_state_esn) },
        [XFRMA_SA_EXTRA_FLAGS]  = { .type = NLA_U32 },
+       [XFRMA_PROTO]           = { .type = NLA_U8 },
+       [XFRMA_ADDRESS_FILTER]  = { .len = sizeof(struct xfrm_address_filter) },
 };
 
 static const struct xfrm_link {
@@ -2981,6 +3003,11 @@ static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
        return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC);
 }
 
+static bool xfrm_is_alive(const struct km_event *c)
+{
+       return (bool)xfrm_acquire_is_on(c->net);
+}
+
 static struct xfrm_mgr netlink_mgr = {
        .id             = "netlink",
        .notify         = xfrm_send_state_notify,
@@ -2990,6 +3017,7 @@ static struct xfrm_mgr netlink_mgr = {
        .report         = xfrm_send_report,
        .migrate        = xfrm_send_migrate,
        .new_mapping    = xfrm_send_mapping,
+       .is_alive       = xfrm_is_alive,
 };
 
 static int __net_init xfrm_user_net_init(struct net *net)