Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 90014
b: refs/heads/master
c: 83321d6
h: refs/heads/master
v: v3
  • Loading branch information
Timo Teras authored and David S. Miller committed Mar 4, 2008
1 parent 4878fc5 commit c085e6b
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 30 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 26bad2c05eef400d9af16979bd96e301902ebd13
refs/heads/master: 83321d6b9872b94604e481a79dc2c8acbe4ece31
120 changes: 91 additions & 29 deletions trunk/net/key/af_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,45 @@ struct pfkey_sock {
struct sock sk;
int registered;
int promisc;

struct {
uint8_t msg_version;
uint32_t msg_pid;
int (*dump)(struct pfkey_sock *sk);
void (*done)(struct pfkey_sock *sk);
union {
struct xfrm_policy_walk policy;
struct xfrm_state_walk state;
} u;
} dump;
};

static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
{
return (struct pfkey_sock *)sk;
}

static int pfkey_can_dump(struct sock *sk)
{
if (3 * atomic_read(&sk->sk_rmem_alloc) <= 2 * sk->sk_rcvbuf)
return 1;
return 0;
}

static int pfkey_do_dump(struct pfkey_sock *pfk)
{
int rc;

rc = pfk->dump.dump(pfk);
if (rc == -ENOBUFS)
return 0;

pfk->dump.done(pfk);
pfk->dump.dump = NULL;
pfk->dump.done = NULL;
return rc;
}

static void pfkey_sock_destruct(struct sock *sk)
{
skb_queue_purge(&sk->sk_receive_queue);
Expand Down Expand Up @@ -1709,51 +1741,60 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
return 0;
}

struct pfkey_dump_data
{
struct sk_buff *skb;
struct sadb_msg *hdr;
struct sock *sk;
};

static int dump_sa(struct xfrm_state *x, int count, void *ptr)
{
struct pfkey_dump_data *data = ptr;
struct pfkey_sock *pfk = ptr;
struct sk_buff *out_skb;
struct sadb_msg *out_hdr;

if (!pfkey_can_dump(&pfk->sk))
return -ENOBUFS;

out_skb = pfkey_xfrm_state2msg(x);
if (IS_ERR(out_skb))
return PTR_ERR(out_skb);

out_hdr = (struct sadb_msg *) out_skb->data;
out_hdr->sadb_msg_version = data->hdr->sadb_msg_version;
out_hdr->sadb_msg_version = pfk->dump.msg_version;
out_hdr->sadb_msg_type = SADB_DUMP;
out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
out_hdr->sadb_msg_errno = 0;
out_hdr->sadb_msg_reserved = 0;
out_hdr->sadb_msg_seq = count;
out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid;
pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk);
out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
return 0;
}

static int pfkey_dump_sa(struct pfkey_sock *pfk)
{
return xfrm_state_walk(&pfk->dump.u.state, dump_sa, (void *) pfk);
}

static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
{
xfrm_state_walk_done(&pfk->dump.u.state);
}

static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
u8 proto;
struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk };
struct xfrm_state_walk walk;
int rc;
struct pfkey_sock *pfk = pfkey_sk(sk);

if (pfk->dump.dump != NULL)
return -EBUSY;

proto = pfkey_satype2proto(hdr->sadb_msg_satype);
if (proto == 0)
return -EINVAL;

xfrm_state_walk_init(&walk, proto);
rc = xfrm_state_walk(&walk, dump_sa, &data);
xfrm_state_walk_done(&walk);
pfk->dump.msg_version = hdr->sadb_msg_version;
pfk->dump.msg_pid = hdr->sadb_msg_pid;
pfk->dump.dump = pfkey_dump_sa;
pfk->dump.done = pfkey_dump_sa_done;
xfrm_state_walk_init(&pfk->dump.u.state, proto);

return rc;
return pfkey_do_dump(pfk);
}

static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
Expand Down Expand Up @@ -2648,11 +2689,14 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h

static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
{
struct pfkey_dump_data *data = ptr;
struct pfkey_sock *pfk = ptr;
struct sk_buff *out_skb;
struct sadb_msg *out_hdr;
int err;

if (!pfkey_can_dump(&pfk->sk))
return -ENOBUFS;

out_skb = pfkey_xfrm_policy2msg_prep(xp);
if (IS_ERR(out_skb))
return PTR_ERR(out_skb);
Expand All @@ -2662,27 +2706,40 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
return err;

out_hdr = (struct sadb_msg *) out_skb->data;
out_hdr->sadb_msg_version = data->hdr->sadb_msg_version;
out_hdr->sadb_msg_version = pfk->dump.msg_version;
out_hdr->sadb_msg_type = SADB_X_SPDDUMP;
out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
out_hdr->sadb_msg_errno = 0;
out_hdr->sadb_msg_seq = count;
out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid;
pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk);
out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
return 0;
}

static int pfkey_dump_sp(struct pfkey_sock *pfk)
{
return xfrm_policy_walk(&pfk->dump.u.policy, dump_sp, (void *) pfk);
}

static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
{
xfrm_policy_walk_done(&pfk->dump.u.policy);
}

static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk };
struct xfrm_policy_walk walk;
int rc;
struct pfkey_sock *pfk = pfkey_sk(sk);

xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN);
rc = xfrm_policy_walk(&walk, dump_sp, &data);
xfrm_policy_walk_done(&walk);
if (pfk->dump.dump != NULL)
return -EBUSY;

return rc;
pfk->dump.msg_version = hdr->sadb_msg_version;
pfk->dump.msg_pid = hdr->sadb_msg_pid;
pfk->dump.dump = pfkey_dump_sp;
pfk->dump.done = pfkey_dump_sp_done;
xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN);

return pfkey_do_dump(pfk);
}

static int key_notify_policy_flush(struct km_event *c)
Expand Down Expand Up @@ -3687,6 +3744,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
int flags)
{
struct sock *sk = sock->sk;
struct pfkey_sock *pfk = pfkey_sk(sk);
struct sk_buff *skb;
int copied, err;

Expand Down Expand Up @@ -3714,6 +3772,10 @@ static int pfkey_recvmsg(struct kiocb *kiocb,

err = (flags & MSG_TRUNC) ? skb->len : copied;

if (pfk->dump.dump != NULL &&
3 * atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf)
pfkey_do_dump(pfk);

out_free:
skb_free_datagram(sk, skb);
out:
Expand Down

0 comments on commit c085e6b

Please sign in to comment.