aboutsummaryrefslogtreecommitdiffstats
path: root/net/key
diff options
context:
space:
mode:
Diffstat (limited to 'net/key')
-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