aboutsummaryrefslogtreecommitdiffstats
path: root/net/key/af_key.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-10-01 10:03:24 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-01 10:03:24 -0400
commit12a169e7d8f4b1c95252d8b04ed0f1033ed7cfe2 (patch)
tree9630d7798d4fdfc06d6001ccd057aff68f39f908 /net/key/af_key.c
parentb262e60309e1b0eb25d300c7e739427d5316abb1 (diff)
ipsec: Put dumpers on the dump list
Herbert Xu came up with the idea and the original patch to make xfrm_state dump list contain also dumpers: As it is we go to extraordinary lengths to ensure that states don't go away while dumpers go to sleep. It's much easier if we just put the dumpers themselves on the list since they can't go away while they're going. I've also changed the order of addition on new states to prevent a never-ending dump. Timo Teräs improved the patch to apply cleanly to latest tree, modified iteration code to be more readable by using a common struct for entries in the list, implemented the same idea for xfrm_policy dumping and moved the af_key specific "last" entry caching to af_key. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Timo Teras <timo.teras@iki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/key/af_key.c')
-rw-r--r--net/key/af_key.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index b7f5a1c353ee..7ae641df70bd 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -58,6 +58,7 @@ struct pfkey_sock {
58 struct xfrm_policy_walk policy; 58 struct xfrm_policy_walk policy;
59 struct xfrm_state_walk state; 59 struct xfrm_state_walk state;
60 } u; 60 } u;
61 struct sk_buff *skb;
61 } dump; 62 } dump;
62}; 63};
63 64
@@ -76,6 +77,10 @@ static int pfkey_can_dump(struct sock *sk)
76static void pfkey_terminate_dump(struct pfkey_sock *pfk) 77static void pfkey_terminate_dump(struct pfkey_sock *pfk)
77{ 78{
78 if (pfk->dump.dump) { 79 if (pfk->dump.dump) {
80 if (pfk->dump.skb) {
81 kfree_skb(pfk->dump.skb);
82 pfk->dump.skb = NULL;
83 }
79 pfk->dump.done(pfk); 84 pfk->dump.done(pfk);
80 pfk->dump.dump = NULL; 85 pfk->dump.dump = NULL;
81 pfk->dump.done = NULL; 86 pfk->dump.done = NULL;
@@ -308,12 +313,25 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
308 313
309static int pfkey_do_dump(struct pfkey_sock *pfk) 314static int pfkey_do_dump(struct pfkey_sock *pfk)
310{ 315{
316 struct sadb_msg *hdr;
311 int rc; 317 int rc;
312 318
313 rc = pfk->dump.dump(pfk); 319 rc = pfk->dump.dump(pfk);
314 if (rc == -ENOBUFS) 320 if (rc == -ENOBUFS)
315 return 0; 321 return 0;
316 322
323 if (pfk->dump.skb) {
324 if (!pfkey_can_dump(&pfk->sk))
325 return 0;
326
327 hdr = (struct sadb_msg *) pfk->dump.skb->data;
328 hdr->sadb_msg_seq = 0;
329 hdr->sadb_msg_errno = rc;
330 pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
331 &pfk->sk);
332 pfk->dump.skb = NULL;
333 }
334
317 pfkey_terminate_dump(pfk); 335 pfkey_terminate_dump(pfk);
318 return rc; 336 return rc;
319} 337}
@@ -1744,9 +1762,14 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
1744 out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); 1762 out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
1745 out_hdr->sadb_msg_errno = 0; 1763 out_hdr->sadb_msg_errno = 0;
1746 out_hdr->sadb_msg_reserved = 0; 1764 out_hdr->sadb_msg_reserved = 0;
1747 out_hdr->sadb_msg_seq = count; 1765 out_hdr->sadb_msg_seq = count + 1;
1748 out_hdr->sadb_msg_pid = pfk->dump.msg_pid; 1766 out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
1749 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk); 1767
1768 if (pfk->dump.skb)
1769 pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
1770 &pfk->sk);
1771 pfk->dump.skb = out_skb;
1772
1750 return 0; 1773 return 0;
1751} 1774}
1752 1775
@@ -2245,7 +2268,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
2245 return 0; 2268 return 0;
2246 2269
2247out: 2270out:
2248 xp->dead = 1; 2271 xp->walk.dead = 1;
2249 xfrm_policy_destroy(xp); 2272 xfrm_policy_destroy(xp);
2250 return err; 2273 return err;
2251} 2274}
@@ -2583,9 +2606,14 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
2583 out_hdr->sadb_msg_type = SADB_X_SPDDUMP; 2606 out_hdr->sadb_msg_type = SADB_X_SPDDUMP;
2584 out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; 2607 out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
2585 out_hdr->sadb_msg_errno = 0; 2608 out_hdr->sadb_msg_errno = 0;
2586 out_hdr->sadb_msg_seq = count; 2609 out_hdr->sadb_msg_seq = count + 1;
2587 out_hdr->sadb_msg_pid = pfk->dump.msg_pid; 2610 out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
2588 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk); 2611
2612 if (pfk->dump.skb)
2613 pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
2614 &pfk->sk);
2615 pfk->dump.skb = out_skb;
2616
2589 return 0; 2617 return 0;
2590} 2618}
2591 2619