aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c71
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
539static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) 537static 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);
618out:
619 sp->this_idx++;
620 return 0; 613 return 0;
621 614
622nla_put_failure: 615nla_put_failure:
@@ -624,18 +617,32 @@ nla_put_failure:
624 return err; 617 return err;
625} 618}
626 619
620static 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
627static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) 627static 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);
1253out:
1254 sp->this_idx++;
1255 return 0; 1256 return 0;
1256 1257
1257nlmsg_failure: 1258nlmsg_failure:
@@ -1259,21 +1260,33 @@ nlmsg_failure:
1259 return -EMSGSIZE; 1260 return -EMSGSIZE;
1260} 1261}
1261 1262
1263static 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
1262static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) 1271static 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] = {
1891static struct xfrm_link { 1903static 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,