p->dev = dev;
if (port_no != ODPP_LOCAL)
rcu_assign_pointer(dev->br_port, p);
+ else {
+ /* For consistency it would make sense to assign dev->br_port
+ * here too, but we can't because that would cause packets
+ * received on the local port to get caught in
+ * dp_frame_hook(). On modern Linux kernels that's not a big
+ * deal--we would just return an appropriate value--but on
+ * Linux 2.4 there's no way for the frame hook to pass along
+ * the skbuff to the rest of the network stack. So we're
+ * stuck with the status quo. */
+ }
rcu_assign_pointer(dp->ports[port_no], p);
list_add_rcu(&p->node, &dp->port_list);
dp->n_ports++;
if (copy_from_user(&port, uport, sizeof port))
return -EFAULT;
if (port.devname[0]) {
- struct net_bridge_port *p;
struct net_device *dev;
int err;
if (!dev)
return -ENODEV;
- p = dev->br_port;
- err = p && p->dp == dp ? put_port(p, uport) : -ENOENT;
+ if (dev == dp->ports[ODPP_LOCAL]->dev) {
+ err = put_port(dp->ports[ODPP_LOCAL], uport);
+ } else {
+ struct net_bridge_port *p = dev->br_port;
+ err = p && p->dp == dp ? put_port(p, uport) : -ENOENT;
+ }
dev_put(dev);
return err;