Skip to content

Commit

Permalink
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Browse files Browse the repository at this point in the history
  • Loading branch information
Linus Torvalds committed Feb 10, 2006
2 parents 5bc159e + bab1dee commit 4b0955a
Show file tree
Hide file tree
Showing 16 changed files with 155 additions and 128 deletions.
3 changes: 2 additions & 1 deletion include/linux/netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ extern int netlink_unregister_notifier(struct notifier_block *nb);

/* finegrained unicast helpers: */
struct sock *netlink_getsockbyfilp(struct file *filp);
int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo);
int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
long timeo, struct sock *ssk);
void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);

Expand Down
3 changes: 3 additions & 0 deletions include/net/irda/irlap.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
/* May be different when we get VFIR */
#define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER)

/* Each IrDA device gets a random 32 bits IRLAP device address */
#define LAP_ALEN 4

#define BROADCAST 0xffffffff /* Broadcast device address */
#define CBROADCAST 0xfe /* Connection broadcast address */
#define XID_FORMAT 0x01 /* Discovery XID format */
Expand Down
3 changes: 2 additions & 1 deletion ipc/mqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,8 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
goto out;
}

ret = netlink_attachskb(sock, nc, 0, MAX_SCHEDULE_TIMEOUT);
ret = netlink_attachskb(sock, nc, 0,
MAX_SCHEDULE_TIMEOUT, NULL);
if (ret == 1)
goto retry;
if (ret) {
Expand Down
94 changes: 64 additions & 30 deletions net/bridge/br_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,14 @@ static int port_cost(struct net_device *dev)
*/
static void port_carrier_check(void *arg)
{
struct net_bridge_port *p = arg;
struct net_device *dev = arg;
struct net_bridge_port *p;

rtnl_lock();
p = dev->br_port;
if (!p)
goto done;

if (netif_carrier_ok(p->dev)) {
u32 cost = port_cost(p->dev);

Expand All @@ -97,19 +102,33 @@ static void port_carrier_check(void *arg)
br_stp_disable_port(p);
spin_unlock_bh(&p->br->lock);
}
done:
rtnl_unlock();
}

static void release_nbp(struct kobject *kobj)
{
struct net_bridge_port *p
= container_of(kobj, struct net_bridge_port, kobj);
kfree(p);
}

static struct kobj_type brport_ktype = {
#ifdef CONFIG_SYSFS
.sysfs_ops = &brport_sysfs_ops,
#endif
.release = release_nbp,
};

static void destroy_nbp(struct net_bridge_port *p)
{
struct net_device *dev = p->dev;

dev->br_port = NULL;
p->br = NULL;
p->dev = NULL;
dev_put(dev);

br_sysfs_freeif(p);
kobject_put(&p->kobj);
}

static void destroy_nbp_rcu(struct rcu_head *head)
Expand All @@ -133,24 +152,24 @@ static void del_nbp(struct net_bridge_port *p)
struct net_bridge *br = p->br;
struct net_device *dev = p->dev;

/* Race between RTNL notify and RCU callback */
if (p->deleted)
return;
sysfs_remove_link(&br->ifobj, dev->name);

dev_set_promiscuity(dev, -1);

cancel_delayed_work(&p->carrier_check);
flush_scheduled_work();

spin_lock_bh(&br->lock);
br_stp_disable_port(p);
p->deleted = 1;
spin_unlock_bh(&br->lock);

br_fdb_delete_by_port(br, p);

list_del_rcu(&p->list);

rcu_assign_pointer(dev->br_port, NULL);

kobject_del(&p->kobj);

call_rcu(&p->rcu, destroy_nbp_rcu);
}

Expand All @@ -160,7 +179,6 @@ static void del_br(struct net_bridge *br)
struct net_bridge_port *p, *n;

list_for_each_entry_safe(p, n, &br->port_list, list) {
br_sysfs_removeif(p);
del_nbp(p);
}

Expand Down Expand Up @@ -254,13 +272,17 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
p->dev = dev;
p->path_cost = port_cost(dev);
p->priority = 0x8000 >> BR_PORT_BITS;
dev->br_port = p;
p->port_no = index;
br_init_port(p);
p->state = BR_STATE_DISABLED;
INIT_WORK(&p->carrier_check, port_carrier_check, p);
INIT_WORK(&p->carrier_check, port_carrier_check, dev);
kobject_init(&p->kobj);

kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
p->kobj.ktype = &brport_ktype;
p->kobj.parent = &(dev->class_dev.kobj);
p->kobj.kset = NULL;

return p;
}

Expand Down Expand Up @@ -388,30 +410,43 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
if (dev->br_port != NULL)
return -EBUSY;

if (IS_ERR(p = new_nbp(br, dev)))
p = new_nbp(br, dev);
if (IS_ERR(p))
return PTR_ERR(p);

if ((err = br_fdb_insert(br, p, dev->dev_addr)))
destroy_nbp(p);

else if ((err = br_sysfs_addif(p)))
del_nbp(p);
else {
dev_set_promiscuity(dev, 1);
err = kobject_add(&p->kobj);
if (err)
goto err0;

list_add_rcu(&p->list, &br->port_list);
err = br_fdb_insert(br, p, dev->dev_addr);
if (err)
goto err1;

spin_lock_bh(&br->lock);
br_stp_recalculate_bridge_id(br);
br_features_recompute(br);
if ((br->dev->flags & IFF_UP)
&& (dev->flags & IFF_UP) && netif_carrier_ok(dev))
br_stp_enable_port(p);
spin_unlock_bh(&br->lock);
err = br_sysfs_addif(p);
if (err)
goto err2;

dev_set_mtu(br->dev, br_min_mtu(br));
}
rcu_assign_pointer(dev->br_port, p);
dev_set_promiscuity(dev, 1);

list_add_rcu(&p->list, &br->port_list);

spin_lock_bh(&br->lock);
br_stp_recalculate_bridge_id(br);
br_features_recompute(br);
schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
spin_unlock_bh(&br->lock);

dev_set_mtu(br->dev, br_min_mtu(br));
kobject_uevent(&p->kobj, KOBJ_ADD);

return 0;
err2:
br_fdb_delete_by_port(br, p);
err1:
kobject_del(&p->kobj);
err0:
kobject_put(&p->kobj);
return err;
}

Expand All @@ -423,7 +458,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
if (!p || p->br != br)
return -EINVAL;

br_sysfs_removeif(p);
del_nbp(p);

spin_lock_bh(&br->lock);
Expand Down
19 changes: 12 additions & 7 deletions net/bridge/br_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,20 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
int br_handle_frame_finish(struct sk_buff *skb)
{
const unsigned char *dest = eth_hdr(skb)->h_dest;
struct net_bridge_port *p = skb->dev->br_port;
struct net_bridge *br = p->br;
struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
struct net_bridge *br;
struct net_bridge_fdb_entry *dst;
int passedup = 0;

if (!p || p->state == BR_STATE_DISABLED)
goto drop;

/* insert into forwarding database after filtering to avoid spoofing */
br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
br = p->br;
br_fdb_update(br, p, eth_hdr(skb)->h_source);

if (p->state == BR_STATE_LEARNING) {
kfree_skb(skb);
goto out;
}
if (p->state == BR_STATE_LEARNING)
goto drop;

if (br->dev->flags & IFF_PROMISC) {
struct sk_buff *skb2;
Expand Down Expand Up @@ -93,6 +95,9 @@ int br_handle_frame_finish(struct sk_buff *skb)

out:
return 0;
drop:
kfree_skb(skb);
goto out;
}

/*
Expand Down
53 changes: 38 additions & 15 deletions net/bridge/br_netfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@
#define store_orig_dstaddr(skb) (skb_origaddr(skb) = (skb)->nh.iph->daddr)
#define dnat_took_place(skb) (skb_origaddr(skb) != (skb)->nh.iph->daddr)

#define has_bridge_parent(device) ((device)->br_port != NULL)
#define bridge_parent(device) ((device)->br_port->br->dev)

#ifdef CONFIG_SYSCTL
static struct ctl_table_header *brnf_sysctl_header;
static int brnf_call_iptables = 1;
Expand Down Expand Up @@ -98,6 +95,12 @@ static struct rtable __fake_rtable = {
.rt_flags = 0,
};

static inline struct net_device *bridge_parent(const struct net_device *dev)
{
struct net_bridge_port *port = rcu_dereference(dev->br_port);

return port ? port->br->dev : NULL;
}

/* PF_BRIDGE/PRE_ROUTING *********************************************/
/* Undo the changes made for ip6tables PREROUTING and continue the
Expand Down Expand Up @@ -189,11 +192,15 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;

skb->dev = bridge_parent(skb->dev);
if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
skb_pull(skb, VLAN_HLEN);
skb->nh.raw += VLAN_HLEN;
if (!skb->dev)
kfree_skb(skb);
else {
if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
skb_pull(skb, VLAN_HLEN);
skb->nh.raw += VLAN_HLEN;
}
skb->dst->output(skb);
}
skb->dst->output(skb);
return 0;
}

Expand Down Expand Up @@ -270,7 +277,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
}

/* Some common code for IPv4/IPv6 */
static void setup_pre_routing(struct sk_buff *skb)
static struct net_device *setup_pre_routing(struct sk_buff *skb)
{
struct nf_bridge_info *nf_bridge = skb->nf_bridge;

Expand All @@ -282,6 +289,8 @@ static void setup_pre_routing(struct sk_buff *skb)
nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
nf_bridge->physindev = skb->dev;
skb->dev = bridge_parent(skb->dev);

return skb->dev;
}

/* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */
Expand Down Expand Up @@ -376,7 +385,8 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
nf_bridge_put(skb->nf_bridge);
if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
return NF_DROP;
setup_pre_routing(skb);
if (!setup_pre_routing(skb))
return NF_DROP;

NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
br_nf_pre_routing_finish_ipv6);
Expand Down Expand Up @@ -465,7 +475,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
nf_bridge_put(skb->nf_bridge);
if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
return NF_DROP;
setup_pre_routing(skb);
if (!setup_pre_routing(skb))
return NF_DROP;
store_orig_dstaddr(skb);

NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
Expand Down Expand Up @@ -539,11 +550,16 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
struct sk_buff *skb = *pskb;
struct nf_bridge_info *nf_bridge;
struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
struct net_device *parent;
int pf;

if (!skb->nf_bridge)
return NF_ACCEPT;

parent = bridge_parent(out);
if (!parent)
return NF_DROP;

if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
pf = PF_INET;
else
Expand All @@ -564,8 +580,8 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
nf_bridge->mask |= BRNF_BRIDGED;
nf_bridge->physoutdev = skb->dev;

NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in),
bridge_parent(out), br_nf_forward_finish);
NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), parent,
br_nf_forward_finish);

return NF_STOLEN;
}
Expand Down Expand Up @@ -688,6 +704,8 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
goto out;
}
realoutdev = bridge_parent(skb->dev);
if (!realoutdev)
return NF_DROP;

#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
/* iptables should match -o br0.x */
Expand All @@ -701,9 +719,11 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
/* IP forwarded traffic has a physindev, locally
* generated traffic hasn't. */
if (realindev != NULL) {
if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) &&
has_bridge_parent(realindev))
realindev = bridge_parent(realindev);
if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) ) {
struct net_device *parent = bridge_parent(realindev);
if (parent)
realindev = parent;
}

NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
realoutdev, br_nf_local_out_finish,
Expand Down Expand Up @@ -743,6 +763,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
if (!nf_bridge)
return NF_ACCEPT;

if (!realoutdev)
return NF_DROP;

if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
pf = PF_INET;
else
Expand Down
Loading

0 comments on commit 4b0955a

Please sign in to comment.