diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r-- | net/xfrm/xfrm_user.c | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f971ca5645f8..f5fd5b3147cc 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -532,8 +532,6 @@ struct xfrm_dump_info { | |||
532 | struct sk_buff *out_skb; | 532 | struct sk_buff *out_skb; |
533 | u32 nlmsg_seq; | 533 | u32 nlmsg_seq; |
534 | u16 nlmsg_flags; | 534 | u16 nlmsg_flags; |
535 | int start_idx; | ||
536 | int this_idx; | ||
537 | }; | 535 | }; |
538 | 536 | ||
539 | static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) | 537 | static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) |
@@ -600,9 +598,6 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr) | |||
600 | struct nlmsghdr *nlh; | 598 | struct nlmsghdr *nlh; |
601 | int err; | 599 | int err; |
602 | 600 | ||
603 | if (sp->this_idx < sp->start_idx) | ||
604 | goto out; | ||
605 | |||
606 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, | 601 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, |
607 | XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags); | 602 | XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags); |
608 | if (nlh == NULL) | 603 | if (nlh == NULL) |
@@ -615,8 +610,6 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr) | |||
615 | goto nla_put_failure; | 610 | goto nla_put_failure; |
616 | 611 | ||
617 | nlmsg_end(skb, nlh); | 612 | nlmsg_end(skb, nlh); |
618 | out: | ||
619 | sp->this_idx++; | ||
620 | return 0; | 613 | return 0; |
621 | 614 | ||
622 | nla_put_failure: | 615 | nla_put_failure: |
@@ -624,18 +617,32 @@ nla_put_failure: | |||
624 | return err; | 617 | return err; |
625 | } | 618 | } |
626 | 619 | ||
620 | static int xfrm_dump_sa_done(struct netlink_callback *cb) | ||
621 | { | ||
622 | struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; | ||
623 | xfrm_state_walk_done(walk); | ||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | 627 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) |
628 | { | 628 | { |
629 | struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; | ||
629 | struct xfrm_dump_info info; | 630 | struct xfrm_dump_info info; |
630 | 631 | ||
632 | BUILD_BUG_ON(sizeof(struct xfrm_state_walk) > | ||
633 | sizeof(cb->args) - sizeof(cb->args[0])); | ||
634 | |||
631 | info.in_skb = cb->skb; | 635 | info.in_skb = cb->skb; |
632 | info.out_skb = skb; | 636 | info.out_skb = skb; |
633 | info.nlmsg_seq = cb->nlh->nlmsg_seq; | 637 | info.nlmsg_seq = cb->nlh->nlmsg_seq; |
634 | info.nlmsg_flags = NLM_F_MULTI; | 638 | info.nlmsg_flags = NLM_F_MULTI; |
635 | info.this_idx = 0; | 639 | |
636 | info.start_idx = cb->args[0]; | 640 | if (!cb->args[0]) { |
637 | (void) xfrm_state_walk(0, dump_one_state, &info); | 641 | cb->args[0] = 1; |
638 | cb->args[0] = info.this_idx; | 642 | xfrm_state_walk_init(walk, 0); |
643 | } | ||
644 | |||
645 | (void) xfrm_state_walk(walk, dump_one_state, &info); | ||
639 | 646 | ||
640 | return skb->len; | 647 | return skb->len; |
641 | } | 648 | } |
@@ -654,7 +661,6 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, | |||
654 | info.out_skb = skb; | 661 | info.out_skb = skb; |
655 | info.nlmsg_seq = seq; | 662 | info.nlmsg_seq = seq; |
656 | info.nlmsg_flags = 0; | 663 | info.nlmsg_flags = 0; |
657 | info.this_idx = info.start_idx = 0; | ||
658 | 664 | ||
659 | if (dump_one_state(x, 0, &info)) { | 665 | if (dump_one_state(x, 0, &info)) { |
660 | kfree_skb(skb); | 666 | kfree_skb(skb); |
@@ -1232,9 +1238,6 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr | |||
1232 | struct sk_buff *skb = sp->out_skb; | 1238 | struct sk_buff *skb = sp->out_skb; |
1233 | struct nlmsghdr *nlh; | 1239 | struct nlmsghdr *nlh; |
1234 | 1240 | ||
1235 | if (sp->this_idx < sp->start_idx) | ||
1236 | goto out; | ||
1237 | |||
1238 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, | 1241 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, |
1239 | XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags); | 1242 | XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags); |
1240 | if (nlh == NULL) | 1243 | if (nlh == NULL) |
@@ -1250,8 +1253,6 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr | |||
1250 | goto nlmsg_failure; | 1253 | goto nlmsg_failure; |
1251 | 1254 | ||
1252 | nlmsg_end(skb, nlh); | 1255 | nlmsg_end(skb, nlh); |
1253 | out: | ||
1254 | sp->this_idx++; | ||
1255 | return 0; | 1256 | return 0; |
1256 | 1257 | ||
1257 | nlmsg_failure: | 1258 | nlmsg_failure: |
@@ -1259,21 +1260,33 @@ nlmsg_failure: | |||
1259 | return -EMSGSIZE; | 1260 | return -EMSGSIZE; |
1260 | } | 1261 | } |
1261 | 1262 | ||
1263 | static int xfrm_dump_policy_done(struct netlink_callback *cb) | ||
1264 | { | ||
1265 | struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; | ||
1266 | |||
1267 | xfrm_policy_walk_done(walk); | ||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1262 | static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) | 1271 | static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) |
1263 | { | 1272 | { |
1273 | struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; | ||
1264 | struct xfrm_dump_info info; | 1274 | struct xfrm_dump_info info; |
1265 | 1275 | ||
1276 | BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) > | ||
1277 | sizeof(cb->args) - sizeof(cb->args[0])); | ||
1278 | |||
1266 | info.in_skb = cb->skb; | 1279 | info.in_skb = cb->skb; |
1267 | info.out_skb = skb; | 1280 | info.out_skb = skb; |
1268 | info.nlmsg_seq = cb->nlh->nlmsg_seq; | 1281 | info.nlmsg_seq = cb->nlh->nlmsg_seq; |
1269 | info.nlmsg_flags = NLM_F_MULTI; | 1282 | info.nlmsg_flags = NLM_F_MULTI; |
1270 | info.this_idx = 0; | 1283 | |
1271 | info.start_idx = cb->args[0]; | 1284 | if (!cb->args[0]) { |
1272 | (void) xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_one_policy, &info); | 1285 | cb->args[0] = 1; |
1273 | #ifdef CONFIG_XFRM_SUB_POLICY | 1286 | xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); |
1274 | (void) xfrm_policy_walk(XFRM_POLICY_TYPE_SUB, dump_one_policy, &info); | 1287 | } |
1275 | #endif | 1288 | |
1276 | cb->args[0] = info.this_idx; | 1289 | (void) xfrm_policy_walk(walk, dump_one_policy, &info); |
1277 | 1290 | ||
1278 | return skb->len; | 1291 | return skb->len; |
1279 | } | 1292 | } |
@@ -1293,7 +1306,6 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, | |||
1293 | info.out_skb = skb; | 1306 | info.out_skb = skb; |
1294 | info.nlmsg_seq = seq; | 1307 | info.nlmsg_seq = seq; |
1295 | info.nlmsg_flags = 0; | 1308 | info.nlmsg_flags = 0; |
1296 | info.this_idx = info.start_idx = 0; | ||
1297 | 1309 | ||
1298 | if (dump_one_policy(xp, dir, 0, &info) < 0) { | 1310 | if (dump_one_policy(xp, dir, 0, &info) < 0) { |
1299 | kfree_skb(skb); | 1311 | kfree_skb(skb); |
@@ -1891,15 +1903,18 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
1891 | static struct xfrm_link { | 1903 | static struct xfrm_link { |
1892 | int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); | 1904 | int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); |
1893 | int (*dump)(struct sk_buff *, struct netlink_callback *); | 1905 | int (*dump)(struct sk_buff *, struct netlink_callback *); |
1906 | int (*done)(struct netlink_callback *); | ||
1894 | } xfrm_dispatch[XFRM_NR_MSGTYPES] = { | 1907 | } xfrm_dispatch[XFRM_NR_MSGTYPES] = { |
1895 | [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, | 1908 | [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, |
1896 | [XFRM_MSG_DELSA - XFRM_MSG_BASE] = { .doit = xfrm_del_sa }, | 1909 | [XFRM_MSG_DELSA - XFRM_MSG_BASE] = { .doit = xfrm_del_sa }, |
1897 | [XFRM_MSG_GETSA - XFRM_MSG_BASE] = { .doit = xfrm_get_sa, | 1910 | [XFRM_MSG_GETSA - XFRM_MSG_BASE] = { .doit = xfrm_get_sa, |
1898 | .dump = xfrm_dump_sa }, | 1911 | .dump = xfrm_dump_sa, |
1912 | .done = xfrm_dump_sa_done }, | ||
1899 | [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, | 1913 | [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, |
1900 | [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy }, | 1914 | [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy }, |
1901 | [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, | 1915 | [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, |
1902 | .dump = xfrm_dump_policy }, | 1916 | .dump = xfrm_dump_policy, |
1917 | .done = xfrm_dump_policy_done }, | ||
1903 | [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, | 1918 | [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, |
1904 | [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, | 1919 | [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, |
1905 | [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire }, | 1920 | [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire }, |
@@ -1938,7 +1953,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1938 | if (link->dump == NULL) | 1953 | if (link->dump == NULL) |
1939 | return -EINVAL; | 1954 | return -EINVAL; |
1940 | 1955 | ||
1941 | return netlink_dump_start(xfrm_nl, skb, nlh, link->dump, NULL); | 1956 | return netlink_dump_start(xfrm_nl, skb, nlh, link->dump, link->done); |
1942 | } | 1957 | } |
1943 | 1958 | ||
1944 | err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX, | 1959 | err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX, |