static void
do_port_input(struct net_bridge_port *p, struct sk_buff *skb)
{
+ /* Make our own copy of the packet. Otherwise we will mangle the
+ * packet for anyone who came before us (e.g. tcpdump via AF_PACKET).
+ * (No one comes after us, since we tell handle_bridge() that we took
+ * the packet.) */
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (!skb)
+ return;
+
#ifdef SUPPORT_SNAT
/* Check if this packet needs early SNAT processing. */
if (snat_pre_route(skb)) {
- kfree_skb(skb);
return;
}
#endif
/* Push the Ethernet header back on. */
skb_push(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
fwd_port_input(p->dp->chain, skb, p);
}
* forward the whole packet? */
struct sk_buff *f_skb;
struct ofp_packet_in *opi;
- struct net_bridge_port *p;
size_t fwd_len, opi_len;
int err;
}
opi->buffer_id = htonl(buffer_id);
opi->total_len = htons(skb->len);
- p = skb->dev->br_port;
- opi->in_port = htons(p ? p->port_no : OFPP_LOCAL);
+ opi->in_port = htons(skb->dev && skb->dev->br_port
+ ? skb->dev->br_port->port_no
+ : OFPP_LOCAL);
opi->reason = reason;
opi->pad = 0;
- memcpy(opi->data, skb_mac_header(skb), fwd_len);
+ skb_copy_bits(skb, 0, opi->data, fwd_len);
err = send_openflow_skb(f_skb, NULL);
out:
genlmsg_end(ans_skb, data);
err = genlmsg_reply(ans_skb, info);
- if (!err)
- ans_skb = NULL;
+ ans_skb = NULL;
}
err:
nla_put_failure:
- if (ans_skb)
- kfree_skb(ans_skb);
+ kfree_skb(ans_skb);
rcu_read_unlock();
return err;
}