diff options
Diffstat (limited to 'net/packet')
-rw-r--r-- | net/packet/Kconfig | 8 | ||||
-rw-r--r-- | net/packet/Makefile | 2 | ||||
-rw-r--r-- | net/packet/af_packet.c | 145 | ||||
-rw-r--r-- | net/packet/diag.c | 242 | ||||
-rw-r--r-- | net/packet/internal.h | 121 |
5 files changed, 393 insertions, 125 deletions
diff --git a/net/packet/Kconfig b/net/packet/Kconfig index 0060e3b396b7..cc55b35f80e5 100644 --- a/net/packet/Kconfig +++ b/net/packet/Kconfig | |||
@@ -14,3 +14,11 @@ config PACKET | |||
14 | be called af_packet. | 14 | be called af_packet. |
15 | 15 | ||
16 | If unsure, say Y. | 16 | If unsure, say Y. |
17 | |||
18 | config PACKET_DIAG | ||
19 | tristate "Packet: sockets monitoring interface" | ||
20 | depends on PACKET | ||
21 | default n | ||
22 | ---help--- | ||
23 | Support for PF_PACKET sockets monitoring interface used by the ss tool. | ||
24 | If unsure, say Y. | ||
diff --git a/net/packet/Makefile b/net/packet/Makefile index 81183eabfdec..9df61347a3c3 100644 --- a/net/packet/Makefile +++ b/net/packet/Makefile | |||
@@ -3,3 +3,5 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PACKET) += af_packet.o | 5 | obj-$(CONFIG_PACKET) += af_packet.o |
6 | obj-$(CONFIG_PACKET_DIAG) += af_packet_diag.o | ||
7 | af_packet_diag-y += diag.o | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index c5c9e2a54218..94060edbbd70 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -93,6 +93,8 @@ | |||
93 | #include <net/inet_common.h> | 93 | #include <net/inet_common.h> |
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | #include "internal.h" | ||
97 | |||
96 | /* | 98 | /* |
97 | Assumptions: | 99 | Assumptions: |
98 | - if device has no dev->hard_header routine, it adds and removes ll header | 100 | - if device has no dev->hard_header routine, it adds and removes ll header |
@@ -146,14 +148,6 @@ dev->hard_header == NULL (ll header is added by device, we cannot control it) | |||
146 | 148 | ||
147 | /* Private packet socket structures. */ | 149 | /* Private packet socket structures. */ |
148 | 150 | ||
149 | struct packet_mclist { | ||
150 | struct packet_mclist *next; | ||
151 | int ifindex; | ||
152 | int count; | ||
153 | unsigned short type; | ||
154 | unsigned short alen; | ||
155 | unsigned char addr[MAX_ADDR_LEN]; | ||
156 | }; | ||
157 | /* identical to struct packet_mreq except it has | 151 | /* identical to struct packet_mreq except it has |
158 | * a longer address field. | 152 | * a longer address field. |
159 | */ | 153 | */ |
@@ -175,63 +169,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
175 | #define BLK_PLUS_PRIV(sz_of_priv) \ | 169 | #define BLK_PLUS_PRIV(sz_of_priv) \ |
176 | (BLK_HDR_LEN + ALIGN((sz_of_priv), V3_ALIGNMENT)) | 170 | (BLK_HDR_LEN + ALIGN((sz_of_priv), V3_ALIGNMENT)) |
177 | 171 | ||
178 | /* kbdq - kernel block descriptor queue */ | ||
179 | struct tpacket_kbdq_core { | ||
180 | struct pgv *pkbdq; | ||
181 | unsigned int feature_req_word; | ||
182 | unsigned int hdrlen; | ||
183 | unsigned char reset_pending_on_curr_blk; | ||
184 | unsigned char delete_blk_timer; | ||
185 | unsigned short kactive_blk_num; | ||
186 | unsigned short blk_sizeof_priv; | ||
187 | |||
188 | /* last_kactive_blk_num: | ||
189 | * trick to see if user-space has caught up | ||
190 | * in order to avoid refreshing timer when every single pkt arrives. | ||
191 | */ | ||
192 | unsigned short last_kactive_blk_num; | ||
193 | |||
194 | char *pkblk_start; | ||
195 | char *pkblk_end; | ||
196 | int kblk_size; | ||
197 | unsigned int knum_blocks; | ||
198 | uint64_t knxt_seq_num; | ||
199 | char *prev; | ||
200 | char *nxt_offset; | ||
201 | struct sk_buff *skb; | ||
202 | |||
203 | atomic_t blk_fill_in_prog; | ||
204 | |||
205 | /* Default is set to 8ms */ | ||
206 | #define DEFAULT_PRB_RETIRE_TOV (8) | ||
207 | |||
208 | unsigned short retire_blk_tov; | ||
209 | unsigned short version; | ||
210 | unsigned long tov_in_jiffies; | ||
211 | |||
212 | /* timer to retire an outstanding block */ | ||
213 | struct timer_list retire_blk_timer; | ||
214 | }; | ||
215 | |||
216 | #define PGV_FROM_VMALLOC 1 | 172 | #define PGV_FROM_VMALLOC 1 |
217 | struct pgv { | ||
218 | char *buffer; | ||
219 | }; | ||
220 | |||
221 | struct packet_ring_buffer { | ||
222 | struct pgv *pg_vec; | ||
223 | unsigned int head; | ||
224 | unsigned int frames_per_block; | ||
225 | unsigned int frame_size; | ||
226 | unsigned int frame_max; | ||
227 | |||
228 | unsigned int pg_vec_order; | ||
229 | unsigned int pg_vec_pages; | ||
230 | unsigned int pg_vec_len; | ||
231 | |||
232 | struct tpacket_kbdq_core prb_bdqc; | ||
233 | atomic_t pending; | ||
234 | }; | ||
235 | 173 | ||
236 | #define BLOCK_STATUS(x) ((x)->hdr.bh1.block_status) | 174 | #define BLOCK_STATUS(x) ((x)->hdr.bh1.block_status) |
237 | #define BLOCK_NUM_PKTS(x) ((x)->hdr.bh1.num_pkts) | 175 | #define BLOCK_NUM_PKTS(x) ((x)->hdr.bh1.num_pkts) |
@@ -269,52 +207,6 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *, | |||
269 | struct tpacket3_hdr *); | 207 | struct tpacket3_hdr *); |
270 | static void packet_flush_mclist(struct sock *sk); | 208 | static void packet_flush_mclist(struct sock *sk); |
271 | 209 | ||
272 | struct packet_fanout; | ||
273 | struct packet_sock { | ||
274 | /* struct sock has to be the first member of packet_sock */ | ||
275 | struct sock sk; | ||
276 | struct packet_fanout *fanout; | ||
277 | struct tpacket_stats stats; | ||
278 | union tpacket_stats_u stats_u; | ||
279 | struct packet_ring_buffer rx_ring; | ||
280 | struct packet_ring_buffer tx_ring; | ||
281 | int copy_thresh; | ||
282 | spinlock_t bind_lock; | ||
283 | struct mutex pg_vec_lock; | ||
284 | unsigned int running:1, /* prot_hook is attached*/ | ||
285 | auxdata:1, | ||
286 | origdev:1, | ||
287 | has_vnet_hdr:1; | ||
288 | int ifindex; /* bound device */ | ||
289 | __be16 num; | ||
290 | struct packet_mclist *mclist; | ||
291 | atomic_t mapped; | ||
292 | enum tpacket_versions tp_version; | ||
293 | unsigned int tp_hdrlen; | ||
294 | unsigned int tp_reserve; | ||
295 | unsigned int tp_loss:1; | ||
296 | unsigned int tp_tstamp; | ||
297 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | ||
298 | }; | ||
299 | |||
300 | #define PACKET_FANOUT_MAX 256 | ||
301 | |||
302 | struct packet_fanout { | ||
303 | #ifdef CONFIG_NET_NS | ||
304 | struct net *net; | ||
305 | #endif | ||
306 | unsigned int num_members; | ||
307 | u16 id; | ||
308 | u8 type; | ||
309 | u8 defrag; | ||
310 | atomic_t rr_cur; | ||
311 | struct list_head list; | ||
312 | struct sock *arr[PACKET_FANOUT_MAX]; | ||
313 | spinlock_t lock; | ||
314 | atomic_t sk_ref; | ||
315 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | ||
316 | }; | ||
317 | |||
318 | struct packet_skb_cb { | 210 | struct packet_skb_cb { |
319 | unsigned int origlen; | 211 | unsigned int origlen; |
320 | union { | 212 | union { |
@@ -334,11 +226,6 @@ struct packet_skb_cb { | |||
334 | (((x)->kactive_blk_num < ((x)->knum_blocks-1)) ? \ | 226 | (((x)->kactive_blk_num < ((x)->knum_blocks-1)) ? \ |
335 | ((x)->kactive_blk_num+1) : 0) | 227 | ((x)->kactive_blk_num+1) : 0) |
336 | 228 | ||
337 | static struct packet_sock *pkt_sk(struct sock *sk) | ||
338 | { | ||
339 | return (struct packet_sock *)sk; | ||
340 | } | ||
341 | |||
342 | static void __fanout_unlink(struct sock *sk, struct packet_sock *po); | 229 | static void __fanout_unlink(struct sock *sk, struct packet_sock *po); |
343 | static void __fanout_link(struct sock *sk, struct packet_sock *po); | 230 | static void __fanout_link(struct sock *sk, struct packet_sock *po); |
344 | 231 | ||
@@ -968,7 +855,8 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *pkc, | |||
968 | ppd->hv1.tp_vlan_tci = vlan_tx_tag_get(pkc->skb); | 855 | ppd->hv1.tp_vlan_tci = vlan_tx_tag_get(pkc->skb); |
969 | ppd->tp_status = TP_STATUS_VLAN_VALID; | 856 | ppd->tp_status = TP_STATUS_VLAN_VALID; |
970 | } else { | 857 | } else { |
971 | ppd->hv1.tp_vlan_tci = ppd->tp_status = 0; | 858 | ppd->hv1.tp_vlan_tci = 0; |
859 | ppd->tp_status = TP_STATUS_AVAILABLE; | ||
972 | } | 860 | } |
973 | } | 861 | } |
974 | 862 | ||
@@ -1243,7 +1131,8 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev, | |||
1243 | return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); | 1131 | return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); |
1244 | } | 1132 | } |
1245 | 1133 | ||
1246 | static DEFINE_MUTEX(fanout_mutex); | 1134 | DEFINE_MUTEX(fanout_mutex); |
1135 | EXPORT_SYMBOL_GPL(fanout_mutex); | ||
1247 | static LIST_HEAD(fanout_list); | 1136 | static LIST_HEAD(fanout_list); |
1248 | 1137 | ||
1249 | static void __fanout_link(struct sock *sk, struct packet_sock *po) | 1138 | static void __fanout_link(struct sock *sk, struct packet_sock *po) |
@@ -1364,9 +1253,9 @@ static void fanout_release(struct sock *sk) | |||
1364 | if (!f) | 1253 | if (!f) |
1365 | return; | 1254 | return; |
1366 | 1255 | ||
1256 | mutex_lock(&fanout_mutex); | ||
1367 | po->fanout = NULL; | 1257 | po->fanout = NULL; |
1368 | 1258 | ||
1369 | mutex_lock(&fanout_mutex); | ||
1370 | if (atomic_dec_and_test(&f->sk_ref)) { | 1259 | if (atomic_dec_and_test(&f->sk_ref)) { |
1371 | list_del(&f->list); | 1260 | list_del(&f->list); |
1372 | dev_remove_pack(&f->prot_hook); | 1261 | dev_remove_pack(&f->prot_hook); |
@@ -2063,7 +1952,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2063 | int tp_len, size_max; | 1952 | int tp_len, size_max; |
2064 | unsigned char *addr; | 1953 | unsigned char *addr; |
2065 | int len_sum = 0; | 1954 | int len_sum = 0; |
2066 | int status = 0; | 1955 | int status = TP_STATUS_AVAILABLE; |
2067 | int hlen, tlen; | 1956 | int hlen, tlen; |
2068 | 1957 | ||
2069 | mutex_lock(&po->pg_vec_lock); | 1958 | mutex_lock(&po->pg_vec_lock); |
@@ -2428,10 +2317,13 @@ static int packet_release(struct socket *sock) | |||
2428 | net = sock_net(sk); | 2317 | net = sock_net(sk); |
2429 | po = pkt_sk(sk); | 2318 | po = pkt_sk(sk); |
2430 | 2319 | ||
2431 | spin_lock_bh(&net->packet.sklist_lock); | 2320 | mutex_lock(&net->packet.sklist_lock); |
2432 | sk_del_node_init_rcu(sk); | 2321 | sk_del_node_init_rcu(sk); |
2322 | mutex_unlock(&net->packet.sklist_lock); | ||
2323 | |||
2324 | preempt_disable(); | ||
2433 | sock_prot_inuse_add(net, sk->sk_prot, -1); | 2325 | sock_prot_inuse_add(net, sk->sk_prot, -1); |
2434 | spin_unlock_bh(&net->packet.sklist_lock); | 2326 | preempt_enable(); |
2435 | 2327 | ||
2436 | spin_lock(&po->bind_lock); | 2328 | spin_lock(&po->bind_lock); |
2437 | unregister_prot_hook(sk, false); | 2329 | unregister_prot_hook(sk, false); |
@@ -2630,10 +2522,13 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, | |||
2630 | register_prot_hook(sk); | 2522 | register_prot_hook(sk); |
2631 | } | 2523 | } |
2632 | 2524 | ||
2633 | spin_lock_bh(&net->packet.sklist_lock); | 2525 | mutex_lock(&net->packet.sklist_lock); |
2634 | sk_add_node_rcu(sk, &net->packet.sklist); | 2526 | sk_add_node_rcu(sk, &net->packet.sklist); |
2527 | mutex_unlock(&net->packet.sklist_lock); | ||
2528 | |||
2529 | preempt_disable(); | ||
2635 | sock_prot_inuse_add(net, &packet_proto, 1); | 2530 | sock_prot_inuse_add(net, &packet_proto, 1); |
2636 | spin_unlock_bh(&net->packet.sklist_lock); | 2531 | preempt_enable(); |
2637 | 2532 | ||
2638 | return 0; | 2533 | return 0; |
2639 | out: | 2534 | out: |
@@ -3854,7 +3749,7 @@ static int packet_seq_show(struct seq_file *seq, void *v) | |||
3854 | po->ifindex, | 3749 | po->ifindex, |
3855 | po->running, | 3750 | po->running, |
3856 | atomic_read(&s->sk_rmem_alloc), | 3751 | atomic_read(&s->sk_rmem_alloc), |
3857 | sock_i_uid(s), | 3752 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)), |
3858 | sock_i_ino(s)); | 3753 | sock_i_ino(s)); |
3859 | } | 3754 | } |
3860 | 3755 | ||
@@ -3886,7 +3781,7 @@ static const struct file_operations packet_seq_fops = { | |||
3886 | 3781 | ||
3887 | static int __net_init packet_net_init(struct net *net) | 3782 | static int __net_init packet_net_init(struct net *net) |
3888 | { | 3783 | { |
3889 | spin_lock_init(&net->packet.sklist_lock); | 3784 | mutex_init(&net->packet.sklist_lock); |
3890 | INIT_HLIST_HEAD(&net->packet.sklist); | 3785 | INIT_HLIST_HEAD(&net->packet.sklist); |
3891 | 3786 | ||
3892 | if (!proc_net_fops_create(net, "packet", 0, &packet_seq_fops)) | 3787 | if (!proc_net_fops_create(net, "packet", 0, &packet_seq_fops)) |
diff --git a/net/packet/diag.c b/net/packet/diag.c new file mode 100644 index 000000000000..39bce0d50df9 --- /dev/null +++ b/net/packet/diag.c | |||
@@ -0,0 +1,242 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/sock_diag.h> | ||
3 | #include <linux/net.h> | ||
4 | #include <linux/netdevice.h> | ||
5 | #include <linux/packet_diag.h> | ||
6 | #include <net/net_namespace.h> | ||
7 | #include <net/sock.h> | ||
8 | |||
9 | #include "internal.h" | ||
10 | |||
11 | static int pdiag_put_info(const struct packet_sock *po, struct sk_buff *nlskb) | ||
12 | { | ||
13 | struct packet_diag_info pinfo; | ||
14 | |||
15 | pinfo.pdi_index = po->ifindex; | ||
16 | pinfo.pdi_version = po->tp_version; | ||
17 | pinfo.pdi_reserve = po->tp_reserve; | ||
18 | pinfo.pdi_copy_thresh = po->copy_thresh; | ||
19 | pinfo.pdi_tstamp = po->tp_tstamp; | ||
20 | |||
21 | pinfo.pdi_flags = 0; | ||
22 | if (po->running) | ||
23 | pinfo.pdi_flags |= PDI_RUNNING; | ||
24 | if (po->auxdata) | ||
25 | pinfo.pdi_flags |= PDI_AUXDATA; | ||
26 | if (po->origdev) | ||
27 | pinfo.pdi_flags |= PDI_ORIGDEV; | ||
28 | if (po->has_vnet_hdr) | ||
29 | pinfo.pdi_flags |= PDI_VNETHDR; | ||
30 | if (po->tp_loss) | ||
31 | pinfo.pdi_flags |= PDI_LOSS; | ||
32 | |||
33 | return nla_put(nlskb, PACKET_DIAG_INFO, sizeof(pinfo), &pinfo); | ||
34 | } | ||
35 | |||
36 | static int pdiag_put_mclist(const struct packet_sock *po, struct sk_buff *nlskb) | ||
37 | { | ||
38 | struct nlattr *mca; | ||
39 | struct packet_mclist *ml; | ||
40 | |||
41 | mca = nla_nest_start(nlskb, PACKET_DIAG_MCLIST); | ||
42 | if (!mca) | ||
43 | return -EMSGSIZE; | ||
44 | |||
45 | rtnl_lock(); | ||
46 | for (ml = po->mclist; ml; ml = ml->next) { | ||
47 | struct packet_diag_mclist *dml; | ||
48 | |||
49 | dml = nla_reserve_nohdr(nlskb, sizeof(*dml)); | ||
50 | if (!dml) { | ||
51 | rtnl_unlock(); | ||
52 | nla_nest_cancel(nlskb, mca); | ||
53 | return -EMSGSIZE; | ||
54 | } | ||
55 | |||
56 | dml->pdmc_index = ml->ifindex; | ||
57 | dml->pdmc_type = ml->type; | ||
58 | dml->pdmc_alen = ml->alen; | ||
59 | dml->pdmc_count = ml->count; | ||
60 | BUILD_BUG_ON(sizeof(dml->pdmc_addr) != sizeof(ml->addr)); | ||
61 | memcpy(dml->pdmc_addr, ml->addr, sizeof(ml->addr)); | ||
62 | } | ||
63 | |||
64 | rtnl_unlock(); | ||
65 | nla_nest_end(nlskb, mca); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
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 | |||
112 | static int pdiag_put_fanout(struct packet_sock *po, struct sk_buff *nlskb) | ||
113 | { | ||
114 | int ret = 0; | ||
115 | |||
116 | mutex_lock(&fanout_mutex); | ||
117 | if (po->fanout) { | ||
118 | u32 val; | ||
119 | |||
120 | val = (u32)po->fanout->id | ((u32)po->fanout->type << 16); | ||
121 | ret = nla_put_u32(nlskb, PACKET_DIAG_FANOUT, val); | ||
122 | } | ||
123 | mutex_unlock(&fanout_mutex); | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req, | ||
129 | u32 pid, u32 seq, u32 flags, int sk_ino) | ||
130 | { | ||
131 | struct nlmsghdr *nlh; | ||
132 | struct packet_diag_msg *rp; | ||
133 | struct packet_sock *po = pkt_sk(sk); | ||
134 | |||
135 | nlh = nlmsg_put(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rp), flags); | ||
136 | if (!nlh) | ||
137 | return -EMSGSIZE; | ||
138 | |||
139 | rp = nlmsg_data(nlh); | ||
140 | rp->pdiag_family = AF_PACKET; | ||
141 | rp->pdiag_type = sk->sk_type; | ||
142 | rp->pdiag_num = ntohs(po->num); | ||
143 | rp->pdiag_ino = sk_ino; | ||
144 | sock_diag_save_cookie(sk, rp->pdiag_cookie); | ||
145 | |||
146 | if ((req->pdiag_show & PACKET_SHOW_INFO) && | ||
147 | pdiag_put_info(po, skb)) | ||
148 | goto out_nlmsg_trim; | ||
149 | |||
150 | if ((req->pdiag_show & PACKET_SHOW_MCLIST) && | ||
151 | pdiag_put_mclist(po, skb)) | ||
152 | goto out_nlmsg_trim; | ||
153 | |||
154 | if ((req->pdiag_show & PACKET_SHOW_RING_CFG) && | ||
155 | pdiag_put_rings_cfg(po, skb)) | ||
156 | goto out_nlmsg_trim; | ||
157 | |||
158 | if ((req->pdiag_show & PACKET_SHOW_FANOUT) && | ||
159 | pdiag_put_fanout(po, skb)) | ||
160 | goto out_nlmsg_trim; | ||
161 | |||
162 | return nlmsg_end(skb, nlh); | ||
163 | |||
164 | out_nlmsg_trim: | ||
165 | nlmsg_cancel(skb, nlh); | ||
166 | return -EMSGSIZE; | ||
167 | } | ||
168 | |||
169 | static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
170 | { | ||
171 | int num = 0, s_num = cb->args[0]; | ||
172 | struct packet_diag_req *req; | ||
173 | struct net *net; | ||
174 | struct sock *sk; | ||
175 | struct hlist_node *node; | ||
176 | |||
177 | net = sock_net(skb->sk); | ||
178 | req = nlmsg_data(cb->nlh); | ||
179 | |||
180 | mutex_lock(&net->packet.sklist_lock); | ||
181 | sk_for_each(sk, node, &net->packet.sklist) { | ||
182 | if (!net_eq(sock_net(sk), net)) | ||
183 | continue; | ||
184 | if (num < s_num) | ||
185 | goto next; | ||
186 | |||
187 | if (sk_diag_fill(sk, skb, req, NETLINK_CB(cb->skb).pid, | ||
188 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
189 | sock_i_ino(sk)) < 0) | ||
190 | goto done; | ||
191 | next: | ||
192 | num++; | ||
193 | } | ||
194 | done: | ||
195 | mutex_unlock(&net->packet.sklist_lock); | ||
196 | cb->args[0] = num; | ||
197 | |||
198 | return skb->len; | ||
199 | } | ||
200 | |||
201 | static int packet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | ||
202 | { | ||
203 | int hdrlen = sizeof(struct packet_diag_req); | ||
204 | struct net *net = sock_net(skb->sk); | ||
205 | struct packet_diag_req *req; | ||
206 | |||
207 | if (nlmsg_len(h) < hdrlen) | ||
208 | return -EINVAL; | ||
209 | |||
210 | req = nlmsg_data(h); | ||
211 | /* Make it possible to support protocol filtering later */ | ||
212 | if (req->sdiag_protocol) | ||
213 | return -EINVAL; | ||
214 | |||
215 | if (h->nlmsg_flags & NLM_F_DUMP) { | ||
216 | struct netlink_dump_control c = { | ||
217 | .dump = packet_diag_dump, | ||
218 | }; | ||
219 | return netlink_dump_start(net->diag_nlsk, skb, h, &c); | ||
220 | } else | ||
221 | return -EOPNOTSUPP; | ||
222 | } | ||
223 | |||
224 | static const struct sock_diag_handler packet_diag_handler = { | ||
225 | .family = AF_PACKET, | ||
226 | .dump = packet_diag_handler_dump, | ||
227 | }; | ||
228 | |||
229 | static int __init packet_diag_init(void) | ||
230 | { | ||
231 | return sock_diag_register(&packet_diag_handler); | ||
232 | } | ||
233 | |||
234 | static void __exit packet_diag_exit(void) | ||
235 | { | ||
236 | sock_diag_unregister(&packet_diag_handler); | ||
237 | } | ||
238 | |||
239 | module_init(packet_diag_init); | ||
240 | module_exit(packet_diag_exit); | ||
241 | MODULE_LICENSE("GPL"); | ||
242 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 17 /* AF_PACKET */); | ||
diff --git a/net/packet/internal.h b/net/packet/internal.h new file mode 100644 index 000000000000..44945f6b7252 --- /dev/null +++ b/net/packet/internal.h | |||
@@ -0,0 +1,121 @@ | |||
1 | #ifndef __PACKET_INTERNAL_H__ | ||
2 | #define __PACKET_INTERNAL_H__ | ||
3 | |||
4 | struct packet_mclist { | ||
5 | struct packet_mclist *next; | ||
6 | int ifindex; | ||
7 | int count; | ||
8 | unsigned short type; | ||
9 | unsigned short alen; | ||
10 | unsigned char addr[MAX_ADDR_LEN]; | ||
11 | }; | ||
12 | |||
13 | /* kbdq - kernel block descriptor queue */ | ||
14 | struct tpacket_kbdq_core { | ||
15 | struct pgv *pkbdq; | ||
16 | unsigned int feature_req_word; | ||
17 | unsigned int hdrlen; | ||
18 | unsigned char reset_pending_on_curr_blk; | ||
19 | unsigned char delete_blk_timer; | ||
20 | unsigned short kactive_blk_num; | ||
21 | unsigned short blk_sizeof_priv; | ||
22 | |||
23 | /* last_kactive_blk_num: | ||
24 | * trick to see if user-space has caught up | ||
25 | * in order to avoid refreshing timer when every single pkt arrives. | ||
26 | */ | ||
27 | unsigned short last_kactive_blk_num; | ||
28 | |||
29 | char *pkblk_start; | ||
30 | char *pkblk_end; | ||
31 | int kblk_size; | ||
32 | unsigned int knum_blocks; | ||
33 | uint64_t knxt_seq_num; | ||
34 | char *prev; | ||
35 | char *nxt_offset; | ||
36 | struct sk_buff *skb; | ||
37 | |||
38 | atomic_t blk_fill_in_prog; | ||
39 | |||
40 | /* Default is set to 8ms */ | ||
41 | #define DEFAULT_PRB_RETIRE_TOV (8) | ||
42 | |||
43 | unsigned short retire_blk_tov; | ||
44 | unsigned short version; | ||
45 | unsigned long tov_in_jiffies; | ||
46 | |||
47 | /* timer to retire an outstanding block */ | ||
48 | struct timer_list retire_blk_timer; | ||
49 | }; | ||
50 | |||
51 | struct pgv { | ||
52 | char *buffer; | ||
53 | }; | ||
54 | |||
55 | struct packet_ring_buffer { | ||
56 | struct pgv *pg_vec; | ||
57 | unsigned int head; | ||
58 | unsigned int frames_per_block; | ||
59 | unsigned int frame_size; | ||
60 | unsigned int frame_max; | ||
61 | |||
62 | unsigned int pg_vec_order; | ||
63 | unsigned int pg_vec_pages; | ||
64 | unsigned int pg_vec_len; | ||
65 | |||
66 | struct tpacket_kbdq_core prb_bdqc; | ||
67 | atomic_t pending; | ||
68 | }; | ||
69 | |||
70 | extern struct mutex fanout_mutex; | ||
71 | #define PACKET_FANOUT_MAX 256 | ||
72 | |||
73 | struct packet_fanout { | ||
74 | #ifdef CONFIG_NET_NS | ||
75 | struct net *net; | ||
76 | #endif | ||
77 | unsigned int num_members; | ||
78 | u16 id; | ||
79 | u8 type; | ||
80 | u8 defrag; | ||
81 | atomic_t rr_cur; | ||
82 | struct list_head list; | ||
83 | struct sock *arr[PACKET_FANOUT_MAX]; | ||
84 | spinlock_t lock; | ||
85 | atomic_t sk_ref; | ||
86 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | ||
87 | }; | ||
88 | |||
89 | struct packet_sock { | ||
90 | /* struct sock has to be the first member of packet_sock */ | ||
91 | struct sock sk; | ||
92 | struct packet_fanout *fanout; | ||
93 | struct tpacket_stats stats; | ||
94 | union tpacket_stats_u stats_u; | ||
95 | struct packet_ring_buffer rx_ring; | ||
96 | struct packet_ring_buffer tx_ring; | ||
97 | int copy_thresh; | ||
98 | spinlock_t bind_lock; | ||
99 | struct mutex pg_vec_lock; | ||
100 | unsigned int running:1, /* prot_hook is attached*/ | ||
101 | auxdata:1, | ||
102 | origdev:1, | ||
103 | has_vnet_hdr:1; | ||
104 | int ifindex; /* bound device */ | ||
105 | __be16 num; | ||
106 | struct packet_mclist *mclist; | ||
107 | atomic_t mapped; | ||
108 | enum tpacket_versions tp_version; | ||
109 | unsigned int tp_hdrlen; | ||
110 | unsigned int tp_reserve; | ||
111 | unsigned int tp_loss:1; | ||
112 | unsigned int tp_tstamp; | ||
113 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | ||
114 | }; | ||
115 | |||
116 | static struct packet_sock *pkt_sk(struct sock *sk) | ||
117 | { | ||
118 | return (struct packet_sock *)sk; | ||
119 | } | ||
120 | |||
121 | #endif | ||