diff options
author | Stephane Bryant <stephane.ml.bryant@gmail.com> | 2016-03-26 03:42:11 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2016-03-29 07:26:38 -0400 |
commit | 15824ab29f364abd3299ecd17ea48473d971aa79 (patch) | |
tree | 09b403b832f68bdfbb3e65a016d0a692f0d2578e /net/netfilter | |
parent | ac28634456867b23b95faccba7997a62ec430603 (diff) |
netfilter: bridge: pass L2 header and VLAN as netlink attributes in queues to userspace
- This creates 2 netlink attribute NFQA_VLAN and NFQA_L2HDR.
- These are filled up for the PF_BRIDGE family on the way to userspace.
- NFQA_VLAN is a nested attribute, with the NFQA_VLAN_PROTO and the
NFQA_VLAN_TCI carrying the corresponding vlan_proto and vlan_tci
fields from the skb using big endian ordering (and using the CFI
bit as the VLAN_TAG_PRESENT flag in vlan_tci as in the skb)
Signed-off-by: Stephane Bryant <stephane.ml.bryant@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nfnetlink_queue.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 75429997ed41..6889c7c855d1 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -295,6 +295,59 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata) | |||
295 | return seclen; | 295 | return seclen; |
296 | } | 296 | } |
297 | 297 | ||
298 | static u32 nfqnl_get_bridge_size(struct nf_queue_entry *entry) | ||
299 | { | ||
300 | struct sk_buff *entskb = entry->skb; | ||
301 | u32 nlalen = 0; | ||
302 | |||
303 | if (entry->state.pf != PF_BRIDGE || !skb_mac_header_was_set(entskb)) | ||
304 | return 0; | ||
305 | |||
306 | if (skb_vlan_tag_present(entskb)) | ||
307 | nlalen += nla_total_size(nla_total_size(sizeof(__be16)) + | ||
308 | nla_total_size(sizeof(__be16))); | ||
309 | |||
310 | if (entskb->network_header > entskb->mac_header) | ||
311 | nlalen += nla_total_size((entskb->network_header - | ||
312 | entskb->mac_header)); | ||
313 | |||
314 | return nlalen; | ||
315 | } | ||
316 | |||
317 | static int nfqnl_put_bridge(struct nf_queue_entry *entry, struct sk_buff *skb) | ||
318 | { | ||
319 | struct sk_buff *entskb = entry->skb; | ||
320 | |||
321 | if (entry->state.pf != PF_BRIDGE || !skb_mac_header_was_set(entskb)) | ||
322 | return 0; | ||
323 | |||
324 | if (skb_vlan_tag_present(entskb)) { | ||
325 | struct nlattr *nest; | ||
326 | |||
327 | nest = nla_nest_start(skb, NFQA_VLAN | NLA_F_NESTED); | ||
328 | if (!nest) | ||
329 | goto nla_put_failure; | ||
330 | |||
331 | if (nla_put_be16(skb, NFQA_VLAN_TCI, htons(entskb->vlan_tci)) || | ||
332 | nla_put_be16(skb, NFQA_VLAN_PROTO, entskb->vlan_proto)) | ||
333 | goto nla_put_failure; | ||
334 | |||
335 | nla_nest_end(skb, nest); | ||
336 | } | ||
337 | |||
338 | if (entskb->mac_header < entskb->network_header) { | ||
339 | int len = (int)(entskb->network_header - entskb->mac_header); | ||
340 | |||
341 | if (nla_put(skb, NFQA_L2HDR, len, skb_mac_header(entskb))) | ||
342 | goto nla_put_failure; | ||
343 | } | ||
344 | |||
345 | return 0; | ||
346 | |||
347 | nla_put_failure: | ||
348 | return -1; | ||
349 | } | ||
350 | |||
298 | static struct sk_buff * | 351 | static struct sk_buff * |
299 | nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | 352 | nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, |
300 | struct nf_queue_entry *entry, | 353 | struct nf_queue_entry *entry, |
@@ -334,6 +387,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
334 | if (entskb->tstamp.tv64) | 387 | if (entskb->tstamp.tv64) |
335 | size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); | 388 | size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); |
336 | 389 | ||
390 | size += nfqnl_get_bridge_size(entry); | ||
391 | |||
337 | if (entry->state.hook <= NF_INET_FORWARD || | 392 | if (entry->state.hook <= NF_INET_FORWARD || |
338 | (entry->state.hook == NF_INET_POST_ROUTING && entskb->sk == NULL)) | 393 | (entry->state.hook == NF_INET_POST_ROUTING && entskb->sk == NULL)) |
339 | csum_verify = !skb_csum_unnecessary(entskb); | 394 | csum_verify = !skb_csum_unnecessary(entskb); |
@@ -497,6 +552,9 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
497 | } | 552 | } |
498 | } | 553 | } |
499 | 554 | ||
555 | if (nfqnl_put_bridge(entry, skb) < 0) | ||
556 | goto nla_put_failure; | ||
557 | |||
500 | if (entskb->tstamp.tv64) { | 558 | if (entskb->tstamp.tv64) { |
501 | struct nfqnl_msg_packet_timestamp ts; | 559 | struct nfqnl_msg_packet_timestamp ts; |
502 | struct timespec64 kts = ktime_to_timespec64(skb->tstamp); | 560 | struct timespec64 kts = ktime_to_timespec64(skb->tstamp); |