netfilter: fix looped (broad|multi)cast's MAC handling
authorNicolas Cavallari <cavallar@lri.fr>
Thu, 16 Jun 2011 15:27:04 +0000 (17:27 +0200)
committerPatrick McHardy <kaber@trash.net>
Thu, 16 Jun 2011 15:27:04 +0000 (17:27 +0200)
By default, when broadcast or multicast packet are sent from a local
application, they are sent to the interface then looped by the kernel
to other local applications, going throught netfilter hooks in the
process.

These looped packet have their MAC header removed from the skb by the
kernel looping code. This confuse various netfilter's netlink queue,
netlink log and the legacy ip_queue, because they try to extract a
hardware address from these packets, but extracts a part of the IP
header instead.

This patch prevent NFQUEUE, NFLOG and ip_QUEUE to include a MAC header
if there is none in the packet.

Signed-off-by: Nicolas Cavallari <cavallar@lri.fr>
Signed-off-by: Patrick McHardy <kaber@trash.net>
net/ipv4/netfilter/ip_queue.c
net/ipv6/netfilter/ip6_queue.c
net/netfilter/nfnetlink_log.c
net/netfilter/nfnetlink_queue.c

index f7f9bd7ba12d8b4f6d0f938835efac7e34dfbed5..5c9b9d963918aa538086239d2351afea574324cb 100644 (file)
@@ -203,7 +203,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
        else
                pmsg->outdev_name[0] = '\0';
 
-       if (entry->indev && entry->skb->dev) {
+       if (entry->indev && entry->skb->dev &&
+           entry->skb->mac_header != entry->skb->network_header) {
                pmsg->hw_type = entry->skb->dev->type;
                pmsg->hw_addrlen = dev_parse_header(entry->skb,
                                                    pmsg->hw_addr);
index 065fe405fb58486430a1f81209d9d4b6ec31abdf..249394863284bcb2edcb3228183a953393df1a26 100644 (file)
@@ -204,7 +204,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
        else
                pmsg->outdev_name[0] = '\0';
 
-       if (entry->indev && entry->skb->dev) {
+       if (entry->indev && entry->skb->dev &&
+           entry->skb->mac_header != entry->skb->network_header) {
                pmsg->hw_type = entry->skb->dev->type;
                pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr);
        }
index e0ee010935e7008a8730b2c87a2c9c689226fb8a..2e7ccbb43ddb563b7491eafe197ec0e91d8c4b4b 100644 (file)
@@ -456,7 +456,8 @@ __build_packet_message(struct nfulnl_instance *inst,
        if (skb->mark)
                NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark));
 
-       if (indev && skb->dev) {
+       if (indev && skb->dev &&
+           skb->mac_header != skb->network_header) {
                struct nfulnl_msg_packet_hw phw;
                int len = dev_parse_header(skb, phw.hw_addr);
                if (len > 0) {
index b83123f12b42e30612481796bc6c9a4d3bacab60..fdd2fafe0a14ed8810181aae57168f841d5b3f1e 100644 (file)
@@ -335,7 +335,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
        if (entskb->mark)
                NLA_PUT_BE32(skb, NFQA_MARK, htonl(entskb->mark));
 
-       if (indev && entskb->dev) {
+       if (indev && entskb->dev &&
+           entskb->mac_header != entskb->network_header) {
                struct nfqnl_msg_packet_hw phw;
                int len = dev_parse_header(entskb, phw.hw_addr);
                if (len) {