aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/802/p8023.c2
-rw-r--r--net/atm/signaling.c3
-rw-r--r--net/bluetooth/hci_sock.c10
-rw-r--r--net/bluetooth/rfcomm/core.c13
-rw-r--r--net/bridge/br_if.c94
-rw-r--r--net/bridge/br_input.c19
-rw-r--r--net/bridge/br_netfilter.c57
-rw-r--r--net/bridge/br_private.h6
-rw-r--r--net/bridge/br_stp_bpdu.c30
-rw-r--r--net/bridge/br_stp_if.c4
-rw-r--r--net/bridge/br_sysfs_if.c50
-rw-r--r--net/core/datagram.c81
-rw-r--r--net/core/rtnetlink.c2
-rw-r--r--net/core/skbuff.c10
-rw-r--r--net/ipv4/devinet.c2
-rw-r--r--net/ipv4/fib_semantics.c2
-rw-r--r--net/ipv4/icmp.c2
-rw-r--r--net/ipv4/ip_gre.c3
-rw-r--r--net/ipv4/ip_output.c16
-rw-r--r--net/ipv4/ipip.c3
-rw-r--r--net/ipv4/netfilter.c41
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c18
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c22
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c5
-rw-r--r--net/ipv4/tcp_input.c3
-rw-r--r--net/ipv4/xfrm4_output.c13
-rw-r--r--net/ipv6/icmp.c6
-rw-r--r--net/ipv6/ip6_tunnel.c2
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c2
-rw-r--r--net/ipv6/raw.c5
-rw-r--r--net/irda/irda_device.c4
-rw-r--r--net/irda/irnet/irnet_irda.c2
-rw-r--r--net/netfilter/Kconfig10
-rw-r--r--net/netfilter/nf_conntrack_core.c5
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c4
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c4
-rw-r--r--net/netlink/af_netlink.c7
-rw-r--r--net/netlink/genetlink.c11
-rw-r--r--net/xfrm/xfrm_policy.c6
39 files changed, 345 insertions, 234 deletions
diff --git a/net/802/p8023.c b/net/802/p8023.c
index d23e906456e..53cf0570928 100644
--- a/net/802/p8023.c
+++ b/net/802/p8023.c
@@ -59,3 +59,5 @@ void destroy_8023_client(struct datalink_proto *dl)
EXPORT_SYMBOL(destroy_8023_client);
EXPORT_SYMBOL(make_8023_client);
+
+MODULE_LICENSE("GPL");
diff --git a/net/atm/signaling.c b/net/atm/signaling.c
index e7211a7f382..93ad59a28ef 100644
--- a/net/atm/signaling.c
+++ b/net/atm/signaling.c
@@ -56,7 +56,8 @@ static void sigd_put_skb(struct sk_buff *skb)
remove_wait_queue(&sigd_sleep,&wait);
#else
if (!sigd) {
- printk(KERN_WARNING "atmsvc: no signaling demon\n");
+ if (net_ratelimit())
+ printk(KERN_WARNING "atmsvc: no signaling demon\n");
kfree_skb(skb);
return;
}
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index bdb6458c6bd..97bdec73d17 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -143,13 +143,15 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
static int hci_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct hci_dev *hdev = hci_pi(sk)->hdev;
+ struct hci_dev *hdev;
BT_DBG("sock %p sk %p", sock, sk);
if (!sk)
return 0;
+ hdev = hci_pi(sk)->hdev;
+
bt_sock_unlink(&hci_sk_list, sk);
if (hdev) {
@@ -311,14 +313,18 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *add
{
struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
struct sock *sk = sock->sk;
+ struct hci_dev *hdev = hci_pi(sk)->hdev;
BT_DBG("sock %p sk %p", sock, sk);
+ if (!hdev)
+ return -EBADFD;
+
lock_sock(sk);
*addr_len = sizeof(*haddr);
haddr->hci_family = AF_BLUETOOTH;
- haddr->hci_dev = hci_pi(sk)->hdev->id;
+ haddr->hci_dev = hdev->id;
release_sock(sk);
return 0;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 0d89d643413..5b4253c61f6 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -46,13 +46,15 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
-#define VERSION "1.6"
-
#ifndef CONFIG_BT_RFCOMM_DEBUG
#undef BT_DBG
#define BT_DBG(D...)
#endif
+#define VERSION "1.7"
+
+static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
+
static struct task_struct *rfcomm_thread;
static DECLARE_MUTEX(rfcomm_sem);
@@ -623,7 +625,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
/* Set L2CAP options */
sk = sock->sk;
lock_sock(sk);
- l2cap_pi(sk)->imtu = RFCOMM_MAX_L2CAP_MTU;
+ l2cap_pi(sk)->imtu = l2cap_mtu;
release_sock(sk);
s = rfcomm_session_add(sock, BT_BOUND);
@@ -1868,7 +1870,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Set L2CAP options */
sk = sock->sk;
lock_sock(sk);
- l2cap_pi(sk)->imtu = RFCOMM_MAX_L2CAP_MTU;
+ l2cap_pi(sk)->imtu = l2cap_mtu;
release_sock(sk);
/* Start listening on the socket */
@@ -2070,6 +2072,9 @@ static void __exit rfcomm_exit(void)
module_init(rfcomm_init);
module_exit(rfcomm_exit);
+module_param(l2cap_mtu, uint, 0644);
+MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection");
+
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index da687c8dc6f..7fa3a5a9971 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -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);
@@ -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)
@@ -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);
}
@@ -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);
}
@@ -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;
}
@@ -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;
}
@@ -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);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index e3a73cead6b..4eef8375531 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -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;
@@ -93,6 +95,9 @@ int br_handle_frame_finish(struct sk_buff *skb)
out:
return 0;
+drop:
+ kfree_skb(skb);
+ goto out;
}
/*
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 7cac3fb9f80..6bb0c7eb1ef 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -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;
@@ -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
@@ -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;
}
@@ -270,7 +277,7 @@ bridged_dnat:
}
/* 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;
@@ -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 */
@@ -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);
@@ -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,
@@ -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
@@ -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;
}
@@ -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 */
@@ -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,
@@ -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
@@ -782,8 +805,8 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
print_error:
if (skb->dev != NULL) {
printk("[%s]", skb->dev->name);
- if (has_bridge_parent(skb->dev))
- printk("[%s]", bridge_parent(skb->dev)->name);
+ if (realoutdev)
+ printk("[%s]", realoutdev->name);
}
printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw,
skb->data);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e330b17b6d8..8f10e09f251 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -68,7 +68,6 @@ struct net_bridge_port
/* STP */
u8 priority;
u8 state;
- u8 deleted;
u16 port_no;
unsigned char topology_change_ack;
unsigned char config_pending;
@@ -233,9 +232,8 @@ extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
#ifdef CONFIG_SYSFS
/* br_sysfs_if.c */
+extern struct sysfs_ops brport_sysfs_ops;
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 */
extern int br_sysfs_addbr(struct net_device *dev);
@@ -244,8 +242,6 @@ extern void br_sysfs_delbr(struct net_device *dev);
#else
#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_delbr(dev) do { } while(0)
#endif /* CONFIG_SYSFS */
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index d071f1c9ad0..296f6a487c5 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -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};
-/* NO locks */
+/* NO locks, but rcu_read_lock (preempt_disabled) */
int br_stp_handle_bpdu(struct sk_buff *skb)
{
- 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;
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 */
- 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 */
if (!pskb_may_pull(skb, sizeof(header)+1) ||
memcmp(skb->data, header, sizeof(header)))
- goto err;
+ goto out;
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) {
struct br_config_bpdu bpdu;
@@ -201,7 +207,7 @@ int br_stp_handle_bpdu(struct sk_buff *skb)
br_received_tcn_bpdu(p);
}
out:
- spin_unlock_bh(&br->lock);
+ spin_unlock(&br->lock);
err:
kfree_skb(skb);
return 0;
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index cc047f7fb6e..35cf3a07408 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -67,7 +67,7 @@ void br_stp_disable_bridge(struct net_bridge *br)
{
struct net_bridge_port *p;
- spin_lock(&br->lock);
+ spin_lock_bh(&br->lock);
list_for_each_entry(p, &br->port_list, list) {
if (p->state != BR_STATE_DISABLED)
br_stp_disable_port(p);
@@ -76,7 +76,7 @@ void br_stp_disable_bridge(struct net_bridge *br)
br->topology_change = 0;
br->topology_change_detected = 0;
- spin_unlock(&br->lock);
+ spin_unlock_bh(&br->lock);
del_timer_sync(&br->hello_timer);
del_timer_sync(&br->topology_change_timer);
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 0ac0355d16d..c51c9e42aeb 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -195,23 +195,11 @@ static ssize_t brport_store(struct kobject * kobj,
return ret;
}
-/* called from kobject_put when port ref count goes to zero. */
-static void brport_release(struct kobject *kobj)
-{
- kfree(container_of(kobj, struct net_bridge_port, kobj));
-}
-
-static struct sysfs_ops brport_sysfs_ops = {
+struct sysfs_ops brport_sysfs_ops = {
.show = brport_show,
.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.
* Creates a brport subdirectory with bridge attributes.
@@ -223,17 +211,6 @@ int br_sysfs_addif(struct net_bridge_port *p)
struct brport_attribute **a;
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,
SYSFS_BRIDGE_PORT_LINK);
if (err)
@@ -245,28 +222,7 @@ int br_sysfs_addif(struct net_bridge_port *p)
goto out2;
}
- err = sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name);
- if (err)
- goto out2;
-
- kobject_uevent(&p->kobj, KOBJ_ADD);
- return 0;
- out2:
- kobject_del(&p->kobj);
- out1:
+ err= sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name);
+out2:
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);
-}
diff --git a/net/core/datagram.c b/net/core/datagram.c
index f8d322e1ea9..b8ce6bf8118 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -247,49 +247,74 @@ EXPORT_SYMBOL(skb_kill_datagram);
int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
struct iovec *to, int len)
{
- int i, err, fraglen, end = 0;
- struct sk_buff *next = skb_shinfo(skb)->frag_list;
+ int start = skb_headlen(skb);
+ int i, copy = start - offset;
- if (!len)
- return 0;
+ /* Copy header. */
+ if (copy > 0) {
+ if (copy > len)
+ copy = len;
+ if (memcpy_toiovec(to, skb->data + offset, copy))
+ goto fault;
+ if ((len -= copy) == 0)
+ return 0;
+ offset += copy;
+ }
-next_skb:
- fraglen = skb_headlen(skb);
- i = -1;
+ /* Copy paged appendix. Hmm... why does this look so complicated? */
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ int end;
- while (1) {
- int start = end;
+ BUG_TRAP(start <= offset + len);
- if ((end += fraglen) > offset) {
- int copy = end - offset, o = offset - start;
+ end = start + skb_shinfo(skb)->frags[i].size;
+ if ((copy = end - offset) > 0) {
+ int err;
+ u8 *vaddr;
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ struct page *page = frag->page;
if (copy > len)
copy = len;
- if (i == -1)
- err = memcpy_toiovec(to, skb->data + o, copy);
- else {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- struct page *page = frag->page;
- void *p = kmap(page) + frag->page_offset + o;
- err = memcpy_toiovec(to, p, copy);
- kunmap(page);
- }
+ vaddr = kmap(page);
+ err = memcpy_toiovec(to, vaddr + frag->page_offset +
+ offset - start, copy);
+ kunmap(page);
if (err)
goto fault;
if (!(len -= copy))
return 0;
offset += copy;
}
- if (++i >= skb_shinfo(skb)->nr_frags)
- break;
- fraglen = skb_shinfo(skb)->frags[i].size;
+ start = end;
}
- if (next) {
- skb = next;
- BUG_ON(skb_shinfo(skb)->frag_list);
- next = skb->next;
- goto next_skb;
+
+ if (skb_shinfo(skb)->frag_list) {
+ struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+ for (; list; list = list->next) {
+ int end;
+
+ BUG_TRAP(start <= offset + len);
+
+ end = start + list->len;
+ if ((copy = end - offset) > 0) {
+ if (copy > len)
+ copy = len;
+ if (skb_copy_datagram_iovec(list,
+ offset - start,
+ to, copy))
+ goto fault;
+ if ((len -= copy) == 0)
+ return 0;
+ offset += copy;
+ }
+ start = end;
+ }
}
+ if (!len)
+ return 0;
+
fault:
return -EFAULT;
}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 8700379685e..eca2976abb2 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -455,7 +455,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
if (!skb)
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);
return;
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 6766f118f07..2144952d1c6 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -411,6 +411,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
C(pkt_type);
C(ip_summed);
C(priority);
+#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
+ C(ipvs_property);
+#endif
C(protocol);
n->destructor = NULL;
#ifdef CONFIG_NETFILTER
@@ -422,13 +425,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
C(nfct_reasm);
nf_conntrack_get_reasm(skb->nfct_reasm);
#endif
-#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
- C(ipvs_property);
-#endif
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
- C(nfct_reasm);
- nf_conntrack_get_reasm(skb->nfct_reasm);
-#endif
#ifde