Commit 4b0955a6 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

parents 5bc159e6 bab1deea
...@@ -160,7 +160,8 @@ extern int netlink_unregister_notifier(struct notifier_block *nb); ...@@ -160,7 +160,8 @@ extern int netlink_unregister_notifier(struct notifier_block *nb);
/* finegrained unicast helpers: */ /* finegrained unicast helpers: */
struct sock *netlink_getsockbyfilp(struct file *filp); 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); void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol); int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
......
...@@ -50,6 +50,9 @@ ...@@ -50,6 +50,9 @@
/* May be different when we get VFIR */ /* May be different when we get VFIR */
#define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER) #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 BROADCAST 0xffffffff /* Broadcast device address */
#define CBROADCAST 0xfe /* Connection broadcast address */ #define CBROADCAST 0xfe /* Connection broadcast address */
#define XID_FORMAT 0x01 /* Discovery XID format */ #define XID_FORMAT 0x01 /* Discovery XID format */
......
...@@ -1018,7 +1018,8 @@ retry: ...@@ -1018,7 +1018,8 @@ retry:
goto out; goto out;
} }
ret = netlink_attachskb(sock, nc, 0, MAX_SCHEDULE_TIMEOUT); ret = netlink_attachskb(sock, nc, 0,
MAX_SCHEDULE_TIMEOUT, NULL);
if (ret == 1) if (ret == 1)
goto retry; goto retry;
if (ret) { if (ret) {
......
...@@ -79,9 +79,14 @@ static int port_cost(struct net_device *dev) ...@@ -79,9 +79,14 @@ static int port_cost(struct net_device *dev)
*/ */
static void port_carrier_check(void *arg) 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(); rtnl_lock();
p = dev->br_port;
if (!p)
goto done;
if (netif_carrier_ok(p->dev)) { if (netif_carrier_ok(p->dev)) {
u32 cost = port_cost(p->dev); u32 cost = port_cost(p->dev);
...@@ -97,19 +102,33 @@ static void port_carrier_check(void *arg) ...@@ -97,19 +102,33 @@ static void port_carrier_check(void *arg)
br_stp_disable_port(p); br_stp_disable_port(p);
spin_unlock_bh(&p->br->lock); spin_unlock_bh(&p->br->lock);
} }
done:
rtnl_unlock(); 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) static void destroy_nbp(struct net_bridge_port *p)
{ {
struct net_device *dev = p->dev; struct net_device *dev = p->dev;
dev->br_port = NULL;
p->br = NULL; p->br = NULL;
p->dev = NULL; p->dev = NULL;
dev_put(dev); dev_put(dev);
br_sysfs_freeif(p); kobject_put(&p->kobj);
} }
static void destroy_nbp_rcu(struct rcu_head *head) static void destroy_nbp_rcu(struct rcu_head *head)
...@@ -133,24 +152,24 @@ static void del_nbp(struct net_bridge_port *p) ...@@ -133,24 +152,24 @@ static void del_nbp(struct net_bridge_port *p)
struct net_bridge *br = p->br; struct net_bridge *br = p->br;
struct net_device *dev = p->dev; struct net_device *dev = p->dev;
/* Race between RTNL notify and RCU callback */ sysfs_remove_link(&br->ifobj, dev->name);
if (p->deleted)
return;
dev_set_promiscuity(dev, -1); dev_set_promiscuity(dev, -1);
cancel_delayed_work(&p->carrier_check); cancel_delayed_work(&p->carrier_check);
flush_scheduled_work();
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br_stp_disable_port(p); br_stp_disable_port(p);
p->deleted = 1;
spin_unlock_bh(&br->lock); spin_unlock_bh(&br->lock);
br_fdb_delete_by_port(br, p); br_fdb_delete_by_port(br, p);
list_del_rcu(&p->list); list_del_rcu(&p->list);
rcu_assign_pointer(dev->br_port, NULL);
kobject_del(&p->kobj);
call_rcu(&p->rcu, destroy_nbp_rcu); call_rcu(&p->rcu, destroy_nbp_rcu);
} }
...@@ -160,7 +179,6 @@ static void del_br(struct net_bridge *br) ...@@ -160,7 +179,6 @@ static void del_br(struct net_bridge *br)
struct net_bridge_port *p, *n; struct net_bridge_port *p, *n;
list_for_each_entry_safe(p, n, &br->port_list, list) { list_for_each_entry_safe(p, n, &br->port_list, list) {
br_sysfs_removeif(p);
del_nbp(p); del_nbp(p);
} }
...@@ -254,13 +272,17 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, ...@@ -254,13 +272,17 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
p->dev = dev; p->dev = dev;
p->path_cost = port_cost(dev); p->path_cost = port_cost(dev);
p->priority = 0x8000 >> BR_PORT_BITS; p->priority = 0x8000 >> BR_PORT_BITS;
dev->br_port = p;
p->port_no = index; p->port_no = index;
br_init_port(p); br_init_port(p);
p->state = BR_STATE_DISABLED; 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_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; return p;
} }
...@@ -388,30 +410,43 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) ...@@ -388,30 +410,43 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
if (dev->br_port != NULL) if (dev->br_port != NULL)
return -EBUSY; return -EBUSY;
if (IS_ERR(p = new_nbp(br, dev))) p = new_nbp(br, dev);
if (IS_ERR(p))
return PTR_ERR(p); return PTR_ERR(p);
if ((err = br_fdb_insert(br, p, dev->dev_addr))) err = kobject_add(&p->kobj);
destroy_nbp(p); if (err)
goto err0;
else if ((err = br_sysfs_addif(p)))
del_nbp(p);
else {
dev_set_promiscuity(dev, 1);
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); err = br_sysfs_addif(p);
br_stp_recalculate_bridge_id(br); if (err)
br_features_recompute(br); goto err2;
if ((br->dev->flags & IFF_UP)
&& (dev->flags & IFF_UP) && netif_carrier_ok(dev))
br_stp_enable_port(p);
spin_unlock_bh(&br->lock);
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; return err;
} }
...@@ -423,7 +458,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) ...@@ -423,7 +458,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
if (!p || p->br != br) if (!p || p->br != br)
return -EINVAL; return -EINVAL;
br_sysfs_removeif(p);
del_nbp(p); del_nbp(p);
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
......
...@@ -45,18 +45,20 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) ...@@ -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) int br_handle_frame_finish(struct sk_buff *skb)
{ {
const unsigned char *dest = eth_hdr(skb)->h_dest; const unsigned char *dest = eth_hdr(skb)->h_dest;
struct net_bridge_port *p = skb->dev->br_port; struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
struct net_bridge *br = p->br; struct net_bridge *br;
struct net_bridge_fdb_entry *dst; struct net_bridge_fdb_entry *dst;
int passedup = 0; int passedup = 0;
if (!p || p->state == BR_STATE_DISABLED)
goto drop;
/* insert into forwarding database after filtering to avoid spoofing */ /* 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) { if (p->state == BR_STATE_LEARNING)
kfree_skb(skb); goto drop;
goto out;
}
if (br->dev->flags & IFF_PROMISC) { if (br->dev->flags & IFF_PROMISC) {
struct sk_buff *skb2; struct sk_buff *skb2;
...@@ -93,6 +95,9 @@ int br_handle_frame_finish(struct sk_buff *skb) ...@@ -93,6 +95,9 @@ int br_handle_frame_finish(struct sk_buff *skb)
out: out:
return 0; return 0;
drop:
kfree_skb(skb);
goto out;
} }
/* /*
......
...@@ -51,9 +51,6 @@ ...@@ -51,9 +51,6 @@
#define store_orig_dstaddr(skb) (skb_origaddr(skb) = (skb)->nh.iph->daddr) #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 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 #ifdef CONFIG_SYSCTL
static struct ctl_table_header *brnf_sysctl_header; static struct ctl_table_header *brnf_sysctl_header;
static int brnf_call_iptables = 1; static int brnf_call_iptables = 1;
...@@ -98,6 +95,12 @@ static struct rtable __fake_rtable = { ...@@ -98,6 +95,12 @@ static struct rtable __fake_rtable = {
.rt_flags = 0, .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 *********************************************/ /* PF_BRIDGE/PRE_ROUTING *********************************************/
/* Undo the changes made for ip6tables PREROUTING and continue the /* Undo the changes made for ip6tables PREROUTING and continue the
...@@ -189,11 +192,15 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) ...@@ -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->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
skb->dev = bridge_parent(skb->dev); skb->dev = bridge_parent(skb->dev);
if (skb->protocol == __constant_htons(ETH_P_8021Q)) { if (!skb->dev)
skb_pull(skb, VLAN_HLEN); kfree_skb(skb);
skb->nh.raw += VLAN_HLEN; 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; return 0;
} }
...@@ -270,7 +277,7 @@ bridged_dnat: ...@@ -270,7 +277,7 @@ bridged_dnat:
} }
/* Some common code for IPv4/IPv6 */ /* 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; struct nf_bridge_info *nf_bridge = skb->nf_bridge;
...@@ -282,6 +289,8 @@ static void setup_pre_routing(struct sk_buff *skb) ...@@ -282,6 +289,8 @@ static void setup_pre_routing(struct sk_buff *skb)
nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
nf_bridge->physindev = skb->dev; nf_bridge->physindev = skb->dev;
skb->dev = bridge_parent(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 */ /* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */
...@@ -376,7 +385,8 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, ...@@ -376,7 +385,8 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
nf_bridge_put(skb->nf_bridge); nf_bridge_put(skb->nf_bridge);
if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
return NF_DROP; 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, NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
br_nf_pre_routing_finish_ipv6); br_nf_pre_routing_finish_ipv6);
...@@ -465,7 +475,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, ...@@ -465,7 +475,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
nf_bridge_put(skb->nf_bridge); nf_bridge_put(skb->nf_bridge);
if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
return NF_DROP; return NF_DROP;
setup_pre_routing(skb); if (!setup_pre_routing(skb))
return NF_DROP;
store_orig_dstaddr(skb); store_orig_dstaddr(skb);
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
...@@ -539,11 +550,16 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, ...@@ -539,11 +550,16 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
struct nf_bridge_info *nf_bridge; struct nf_bridge_info *nf_bridge;
struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
struct net_device *parent;
int pf; int pf;
if (!skb->nf_bridge) if (!skb->nf_bridge)
return NF_ACCEPT; return NF_ACCEPT;
parent = bridge_parent(out);
if (!parent)
return NF_DROP;
if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
pf = PF_INET; pf = PF_INET;
else else
...@@ -564,8 +580,8 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, ...@@ -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->mask |= BRNF_BRIDGED;
nf_bridge->physoutdev = skb->dev; nf_bridge->physoutdev = skb->dev;
NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), parent,
bridge_parent(out), br_nf_forward_finish); br_nf_forward_finish);
return NF_STOLEN; return NF_STOLEN;
} }
...@@ -688,6 +704,8 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, ...@@ -688,6 +704,8 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
goto out; goto out;
} }
realoutdev = bridge_parent(skb->dev); realoutdev = bridge_parent(skb->dev);
if (!realoutdev)
return NF_DROP;
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
/* iptables should match -o br0.x */ /* iptables should match -o br0.x */
...@@ -701,9 +719,11 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, ...@@ -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 /* IP forwarded traffic has a physindev, locally
* generated traffic hasn't. */ * generated traffic hasn't. */
if (realindev != NULL) { if (realindev != NULL) {
if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) && if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) ) {
has_bridge_parent(realindev)) struct net_device *parent = bridge_parent(realindev);
realindev = bridge_parent(realindev); if (parent)
realindev = parent;
}
NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev, NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
realoutdev, br_nf_local_out_finish, realoutdev, br_nf_local_out_finish,
...@@ -743,6 +763,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, ...@@ -743,6 +763,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
if (!nf_bridge) if (!nf_bridge)
return NF_ACCEPT; return NF_ACCEPT;
if (!realoutdev)
return NF_DROP;
if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
pf = PF_INET; pf = PF_INET;
else else
......
...@@ -68,7 +68,6 @@ struct net_bridge_port ...@@ -68,7 +68,6 @@ struct net_bridge_port
/* STP */ /* STP */
u8 priority; u8 priority;
u8 state; u8 state;
u8 deleted;
u16 port_no; u16 port_no;
unsigned char topology_change_ack; unsigned char topology_change_ack;
unsigned char config_pending; unsigned char config_pending;
...@@ -233,9 +232,8 @@ extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); ...@@ -233,9 +232,8 @@ extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
#ifdef CONFIG_SYSFS #ifdef CONFIG_SYSFS
/* br_sysfs_if.c */ /* br_sysfs_if.c */
extern struct sysfs_ops brport_sysfs_ops;
extern int br_sysfs_addif(struct net_bridge_port *p); extern int br_sysfs_addif(struct net_bridge_port *p);
extern void br_sysfs_removeif(struct net_bridge_port *p);
extern void br_sysfs_freeif(struct net_bridge_port *p);
/* br_sysfs_br.c */ /* br_sysfs_br.c */
extern int br_sysfs_addbr(struct net_device *dev); extern int br_sysfs_addbr(struct net_device *dev);
...@@ -244,8 +242,6 @@ extern void br_sysfs_delbr(struct net_device *dev); ...@@ -244,8 +242,6 @@ extern void br_sysfs_delbr(struct net_device *dev);
#else #else
#define br_sysfs_addif(p) (0) #define br_sysfs_addif(p) (0)
#define br_sysfs_removeif(p) do { } while(0)
#define br_sysfs_freeif(p) kfree(p)
#define br_sysfs_addbr(dev) (0) #define br_sysfs_addbr(dev) (0)
#define br_sysfs_delbr(dev) do { } while(0) #define br_sysfs_delbr(dev) do { } while(0)
#endif /* CONFIG_SYSFS */ #endif /* CONFIG_SYSFS */
......
...@@ -133,29 +133,35 @@ void br_send_tcn_bpdu(struct net_bridge_port *p) ...@@ -133,29 +133,35 @@ void br_send_tcn_bpdu(struct net_bridge_port *p)
static const unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00}; static const unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
/* NO locks */ /* NO locks, but rcu_read_lock (preempt_disabled) */
int br_stp_handle_bpdu(struct sk_buff *skb) int br_stp_handle_bpdu(struct sk_buff *skb)
{ {
struct net_bridge_port *p = skb->dev->br_port; struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
struct net_bridge *br = p->br; struct net_bridge *br;
unsigned char *buf; unsigned char *buf;
if (!p)
goto err;
br = p->br;
spin_lock(&br->lock);
if (p->state == BR_STATE_DISABLED || !(br->dev->flags & IFF_UP))
goto out;
/* insert into forwarding database after filtering to avoid spoofing */ /* insert into forwarding database after filtering to avoid spoofing */
br_fdb_update(p->br, p, eth_hdr(skb)->h_source); br_fdb_update(br, p, eth_hdr(skb)->h_source);
if (!br->stp_enabled)
goto out;
/* need at least the 802 and STP headers */ /* need at least the 802 and STP headers */
if (!pskb_may_pull(skb, sizeof(header)+1) || if (!pskb_may_pull(skb, sizeof(header)+1) ||
memcmp(skb->data, header, sizeof(header))) memcmp(skb->data, header, sizeof(header)))
goto err; goto out;
buf = skb_pull(skb, sizeof(header)); buf = skb_pull(skb, sizeof(header));
spin_lock_bh(&br->lock);
if (p->state == BR_STATE_DISABLED
|| !(br->dev->flags & IFF_UP)
|| !br->stp_enabled)
goto out;
if (buf[0] == BPDU_TYPE_CONFIG) { if (buf[0] == BPDU_TYPE_CONFIG) {
struct br_config_bpdu bpdu; struct br_config_bpdu bpdu;
...@@ -201,7 +207,7 @@ int br_stp_handle_bpdu(struct sk_buff *skb) ...@@ -201,7 +207,7 @@ int br_stp_handle_bpdu(struct sk_buff *skb)
br_received_tcn_bpdu(p); br_received_tcn_bpdu(p);
} }
out: out:
spin_unlock_bh(&br->lock); spin_unlock(&br->lock);
err: err:
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
......
...@@ -195,23 +195,11 @@ static ssize_t brport_store(struct kobject * kobj, ...@@ -195,23 +195,11 @@ static ssize_t brport_store(struct kobject * kobj,
return ret; return ret;
} }
/* called from kobject_put when port ref count goes to zero. */ struct sysfs_ops brport_sysfs_ops = {
static void brport_release(struct kobject *kobj)
{
kfree(container_of(kobj, struct net_bridge_port, kobj));
}
static struct sysfs_ops brport_sysfs_ops = {
.show = brport_show, .show = brport_show,
.store = brport_store, .store = brport_store,
}; };
static struct kobj_type brport_ktype = {
.sysfs_ops = &brport_sysfs_ops,
.release = brport_release,
};
/* /*
* Add sysfs entries to ethernet device added to a bridge. * Add sysfs entries to ethernet device added to a bridge.
* Creates a brport subdirectory with bridge attributes. * Creates a brport subdirectory with bridge attributes.
...@@ -223,17 +211,6 @@ int br_sysfs_addif(struct net_bridge_port *p) ...@@ -223,17 +211,6 @@ int br_sysfs_addif(struct net_bridge_port *p)
struct brport_attribute **a; struct brport_attribute **a;
int err; int err;
ASSERT_RTNL();
kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
p->kobj.ktype = &brport_ktype;
p->kobj.parent = &(p->dev->class_dev.kobj);
p->kobj.kset = NULL;
err = kobject_add(&p->kobj);
if(err)
goto out1;
err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj,
SYSFS_BRIDGE_PORT_LINK); SYSFS_BRIDGE_PORT_LINK);
if (err) if (err)
...@@ -245,28 +222,7 @@ int br_sysfs_addif(struct net_bridge_port *p) ...@@ -245,28 +222,7 @@ int br_sysfs_addif(struct net_bridge_port *p)
goto out2; goto out2;
} }
err = sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name); err= sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name);
if (err) out2:
goto out2;
kobject_uevent(&p->kobj, KOBJ_ADD);
return 0;
out2:
kobject_del(&p->kobj);
out1:
return err; return err;
} }
void br_sysfs_removeif(struct net_bridge_port *p)
{
pr_debug("br_sysfs_removeif\n");
sysfs_remove_link(&p->br->ifobj, p->dev->name);
kobject_uevent(&p->kobj, KOBJ_REMOVE);
kobject_del(&p->kobj);
}
void br_sysfs_freeif(struct net_bridge_port *p)
{
pr_debug("br_sysfs_freeif\n");
kobject_put(&p->kobj);
}
...@@ -455,7 +455,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) ...@@ -455,7 +455,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
if (!skb) if (!skb)
return; return;
if (rtnetlink_fill_ifinfo(skb, dev, type, current->pid, 0, change, 0) < 0) { if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change, 0) < 0) {
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
......
...@@ -1135,7 +1135,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa) ...@@ -1135,7 +1135,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa)
if (!skb) if (!skb)
netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS);
else if (inet_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) { else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
kfree_skb(skb); kfree_skb(skb);
netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL);
} else { } else {
......
...@@ -1045,7 +1045,7 @@ fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, ...@@ -1045,7 +1045,7 @@ fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
} }
nl->nlmsg_flags = NLM_F_REQUEST; nl->nlmsg_flags = NLM_F_REQUEST;
nl->nlmsg_pid = current->pid; nl->nlmsg_pid = 0;
nl->nlmsg_seq = 0; nl->nlmsg_seq = 0;
nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm)); nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm));
if (cmd == SIOCDELRT) { if (cmd == SIOCDELRT) {
......
...@@ -456,7 +456,8 @@ void tcp_rcv_space_adjust(struct sock *sk) ...@@ -456,7 +456,8 @@ void tcp_rcv_space_adjust(struct sock *sk)
tp->rcvq_space.space = space; tp->rcvq_space.space = space;
if (sysctl_tcp_moderate_rcvbuf) { if (sysctl_tcp_moderate_rcvbuf &&
!(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) {
int new_clamp = space; int new_clamp = space;
/* Receive space grows, normalize in order to /* Receive space grows, normalize in order to
......
...@@ -343,12 +343,12 @@ static void irda_task_timer_expired(void *data) ...@@ -343,12 +343,12 @@ static void irda_task_timer_expired(void *data)
static void irda_device_setup(struct net_device *dev) static void irda_device_setup(struct net_device *dev)
{ {
dev->hard_header_len = 0; dev->hard_header_len = 0;
dev->addr_len = 0; dev->addr_len = LAP_ALEN;
dev->type = ARPHRD_IRDA; dev->type = ARPHRD_IRDA;
dev->tx_queue_len = 8; /* Window size + 1 s-frame */ dev->tx_queue_len = 8; /* Window size + 1 s-frame */
memset(dev->broadcast, 0xff, 4); memset(dev->broadcast, 0xff, LAP_ALEN);
dev->mtu = 2048; dev->mtu = 2048;
dev->flags = IFF_NOARP; dev->flags = IFF_NOARP;
......
...@@ -696,7 +696,7 @@ irnet_daddr_to_dname(irnet_socket * self) ...@@ -696,7 +696,7 @@ irnet_daddr_to_dname(irnet_socket * self)
{ {
/* Yes !!! Get it.. */ /* Yes !!! Get it.. */
strlcpy(self->rname, discoveries[i].info, sizeof(self->rname)); strlcpy(self->rname, discoveries[i].info, sizeof(self->rname));
self->rname[NICKNAME_MAX_LEN + 1] = '\0'; self->rname[sizeof(self->rname) - 1] = '\0';
DEBUG(IRDA_SERV_INFO, "Device 0x%08x is in fact ``%s''.\n", DEBUG(IRDA_SERV_INFO, "Device 0x%08x is in fact ``%s''.\n",
self->daddr, self->rname); self->daddr, self->rname);
kfree(discoveries); kfree(discoveries);
......
...@@ -702,7 +702,8 @@ struct sock *netlink_getsockbyfilp(struct file *filp) ...@@ -702,7 +702,8 @@ struct sock *netlink_getsockbyfilp(struct file *filp)
* 0: continue * 0: continue
* 1: repeat lookup - reference dropped while waiting for socket memory. * 1: repeat lookup - reference dropped while waiting for socket memory.
*/ */
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)
{ {
struct netlink_sock *nlk; struct netlink_sock *nlk;
...@@ -712,7 +713,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t ...@@ -712,7 +713,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t
test_bit(0, &nlk->state)) { test_bit(0, &nlk->state)) {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
if (!timeo) { if (!timeo) {
if (!nlk->pid) if (!ssk || nlk_sk(ssk)->pid == 0)
netlink_overrun(sk); netlink_overrun(sk);
sock_put(sk); sock_put(sk);
kfree_skb(skb); kfree_skb(skb);
...@@ -797,7 +798,7 @@ retry: ...@@ -797,7 +798,7 @@ retry:
kfree_skb(skb); kfree_skb(skb);
return PTR_ERR(sk); return PTR_ERR(sk);
} }
err = netlink_attachskb(sk, skb, nonblock, timeo); err = netlink_attachskb(sk, skb, nonblock, timeo, ssk);
if (err == 1) if (err == 1)
goto retry; goto retry;
if (err) if (err)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment