diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r-- | net/xfrm/xfrm_user.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2f7ddc3a59b4..51398ae6cda8 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -137,7 +137,8 @@ static inline int verify_replay(struct xfrm_usersa_info *p, | |||
137 | if (!rt) | 137 | if (!rt) |
138 | return 0; | 138 | return 0; |
139 | 139 | ||
140 | if (p->id.proto != IPPROTO_ESP) | 140 | /* As only ESP and AH support ESN feature. */ |
141 | if ((p->id.proto != IPPROTO_ESP) && (p->id.proto != IPPROTO_AH)) | ||
141 | return -EINVAL; | 142 | return -EINVAL; |
142 | 143 | ||
143 | if (p->replay_window != 0) | 144 | if (p->replay_window != 0) |
@@ -881,6 +882,7 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb) | |||
881 | return 0; | 882 | return 0; |
882 | } | 883 | } |
883 | 884 | ||
885 | static const struct nla_policy xfrma_policy[XFRMA_MAX+1]; | ||
884 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | 886 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) |
885 | { | 887 | { |
886 | struct net *net = sock_net(skb->sk); | 888 | struct net *net = sock_net(skb->sk); |
@@ -896,8 +898,31 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | |||
896 | info.nlmsg_flags = NLM_F_MULTI; | 898 | info.nlmsg_flags = NLM_F_MULTI; |
897 | 899 | ||
898 | if (!cb->args[0]) { | 900 | if (!cb->args[0]) { |
901 | struct nlattr *attrs[XFRMA_MAX+1]; | ||
902 | struct xfrm_address_filter *filter = NULL; | ||
903 | u8 proto = 0; | ||
904 | int err; | ||
905 | |||
899 | cb->args[0] = 1; | 906 | cb->args[0] = 1; |
900 | xfrm_state_walk_init(walk, 0); | 907 | |
908 | err = nlmsg_parse(cb->nlh, 0, attrs, XFRMA_MAX, | ||
909 | xfrma_policy); | ||
910 | if (err < 0) | ||
911 | return err; | ||
912 | |||
913 | if (attrs[XFRMA_ADDRESS_FILTER]) { | ||
914 | filter = kmalloc(sizeof(*filter), GFP_KERNEL); | ||
915 | if (filter == NULL) | ||
916 | return -ENOMEM; | ||
917 | |||
918 | memcpy(filter, nla_data(attrs[XFRMA_ADDRESS_FILTER]), | ||
919 | sizeof(*filter)); | ||
920 | } | ||
921 | |||
922 | if (attrs[XFRMA_PROTO]) | ||
923 | proto = nla_get_u8(attrs[XFRMA_PROTO]); | ||
924 | |||
925 | xfrm_state_walk_init(walk, proto, filter); | ||
901 | } | 926 | } |
902 | 927 | ||
903 | (void) xfrm_state_walk(net, walk, dump_one_state, &info); | 928 | (void) xfrm_state_walk(net, walk, dump_one_state, &info); |
@@ -2303,6 +2328,8 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
2303 | [XFRMA_TFCPAD] = { .type = NLA_U32 }, | 2328 | [XFRMA_TFCPAD] = { .type = NLA_U32 }, |
2304 | [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) }, | 2329 | [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) }, |
2305 | [XFRMA_SA_EXTRA_FLAGS] = { .type = NLA_U32 }, | 2330 | [XFRMA_SA_EXTRA_FLAGS] = { .type = NLA_U32 }, |
2331 | [XFRMA_PROTO] = { .type = NLA_U8 }, | ||
2332 | [XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) }, | ||
2306 | }; | 2333 | }; |
2307 | 2334 | ||
2308 | static const struct xfrm_link { | 2335 | static const struct xfrm_link { |
@@ -2350,7 +2377,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2350 | link = &xfrm_dispatch[type]; | 2377 | link = &xfrm_dispatch[type]; |
2351 | 2378 | ||
2352 | /* All operations require privileges, even GET */ | 2379 | /* All operations require privileges, even GET */ |
2353 | if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) | 2380 | if (!netlink_net_capable(skb, CAP_NET_ADMIN)) |
2354 | return -EPERM; | 2381 | return -EPERM; |
2355 | 2382 | ||
2356 | if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || | 2383 | if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || |
@@ -2976,6 +3003,11 @@ static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | |||
2976 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); | 3003 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); |
2977 | } | 3004 | } |
2978 | 3005 | ||
3006 | static bool xfrm_is_alive(const struct km_event *c) | ||
3007 | { | ||
3008 | return (bool)xfrm_acquire_is_on(c->net); | ||
3009 | } | ||
3010 | |||
2979 | static struct xfrm_mgr netlink_mgr = { | 3011 | static struct xfrm_mgr netlink_mgr = { |
2980 | .id = "netlink", | 3012 | .id = "netlink", |
2981 | .notify = xfrm_send_state_notify, | 3013 | .notify = xfrm_send_state_notify, |
@@ -2985,6 +3017,7 @@ static struct xfrm_mgr netlink_mgr = { | |||
2985 | .report = xfrm_send_report, | 3017 | .report = xfrm_send_report, |
2986 | .migrate = xfrm_send_migrate, | 3018 | .migrate = xfrm_send_migrate, |
2987 | .new_mapping = xfrm_send_mapping, | 3019 | .new_mapping = xfrm_send_mapping, |
3020 | .is_alive = xfrm_is_alive, | ||
2988 | }; | 3021 | }; |
2989 | 3022 | ||
2990 | static int __net_init xfrm_user_net_init(struct net *net) | 3023 | static int __net_init xfrm_user_net_init(struct net *net) |