diff options
Diffstat (limited to 'net/packet/diag.c')
-rw-r--r-- | net/packet/diag.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/net/packet/diag.c b/net/packet/diag.c index 3dda4ecb9a46..e3975e4d458c 100644 --- a/net/packet/diag.c +++ b/net/packet/diag.c | |||
@@ -67,12 +67,54 @@ static int pdiag_put_mclist(const struct packet_sock *po, struct sk_buff *nlskb) | |||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | static int pdiag_put_ring(struct packet_ring_buffer *ring, int ver, int nl_type, | ||
71 | struct sk_buff *nlskb) | ||
72 | { | ||
73 | struct packet_diag_ring pdr; | ||
74 | |||
75 | if (!ring->pg_vec || ((ver > TPACKET_V2) && | ||
76 | (nl_type == PACKET_DIAG_TX_RING))) | ||
77 | return 0; | ||
78 | |||
79 | pdr.pdr_block_size = ring->pg_vec_pages << PAGE_SHIFT; | ||
80 | pdr.pdr_block_nr = ring->pg_vec_len; | ||
81 | pdr.pdr_frame_size = ring->frame_size; | ||
82 | pdr.pdr_frame_nr = ring->frame_max + 1; | ||
83 | |||
84 | if (ver > TPACKET_V2) { | ||
85 | pdr.pdr_retire_tmo = ring->prb_bdqc.retire_blk_tov; | ||
86 | pdr.pdr_sizeof_priv = ring->prb_bdqc.blk_sizeof_priv; | ||
87 | pdr.pdr_features = ring->prb_bdqc.feature_req_word; | ||
88 | } else { | ||
89 | pdr.pdr_retire_tmo = 0; | ||
90 | pdr.pdr_sizeof_priv = 0; | ||
91 | pdr.pdr_features = 0; | ||
92 | } | ||
93 | |||
94 | return nla_put(nlskb, nl_type, sizeof(pdr), &pdr); | ||
95 | } | ||
96 | |||
97 | static int pdiag_put_rings_cfg(struct packet_sock *po, struct sk_buff *skb) | ||
98 | { | ||
99 | int ret; | ||
100 | |||
101 | mutex_lock(&po->pg_vec_lock); | ||
102 | ret = pdiag_put_ring(&po->rx_ring, po->tp_version, | ||
103 | PACKET_DIAG_RX_RING, skb); | ||
104 | if (!ret) | ||
105 | ret = pdiag_put_ring(&po->tx_ring, po->tp_version, | ||
106 | PACKET_DIAG_TX_RING, skb); | ||
107 | mutex_unlock(&po->pg_vec_lock); | ||
108 | |||
109 | return ret; | ||
110 | } | ||
111 | |||
70 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req, | 112 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req, |
71 | u32 pid, u32 seq, u32 flags, int sk_ino) | 113 | u32 pid, u32 seq, u32 flags, int sk_ino) |
72 | { | 114 | { |
73 | struct nlmsghdr *nlh; | 115 | struct nlmsghdr *nlh; |
74 | struct packet_diag_msg *rp; | 116 | struct packet_diag_msg *rp; |
75 | const struct packet_sock *po = pkt_sk(sk); | 117 | struct packet_sock *po = pkt_sk(sk); |
76 | 118 | ||
77 | nlh = nlmsg_put(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rp), flags); | 119 | nlh = nlmsg_put(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rp), flags); |
78 | if (!nlh) | 120 | if (!nlh) |
@@ -93,6 +135,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag | |||
93 | pdiag_put_mclist(po, skb)) | 135 | pdiag_put_mclist(po, skb)) |
94 | goto out_nlmsg_trim; | 136 | goto out_nlmsg_trim; |
95 | 137 | ||
138 | if ((req->pdiag_show & PACKET_SHOW_RING_CFG) && | ||
139 | pdiag_put_rings_cfg(po, skb)) | ||
140 | goto out_nlmsg_trim; | ||
141 | |||
96 | return nlmsg_end(skb, nlh); | 142 | return nlmsg_end(skb, nlh); |
97 | 143 | ||
98 | out_nlmsg_trim: | 144 | out_nlmsg_trim: |