Merge branch 'upstream-fixes'

This commit is contained in:
Jeff Garzik
2006-02-17 16:20:30 -05:00
436 changed files with 6443 additions and 4219 deletions

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
/* insert into forwarding database after filtering to avoid spoofing */
br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
if (!p || p->state == BR_STATE_DISABLED)
goto drop;
if (p->state == BR_STATE_LEARNING) {
kfree_skb(skb);
goto out;
}
/* insert into forwarding database after filtering to avoid spoofing */
br = p->br;
br_fdb_update(br, p, eth_hdr(skb)->h_source);
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;
}
/*

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -1135,7 +1135,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa)
if (!skb)
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);
netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL);
} else {

View File

@@ -1045,7 +1045,7 @@ fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
}
nl->nlmsg_flags = NLM_F_REQUEST;
nl->nlmsg_pid = current->pid;
nl->nlmsg_pid = 0;
nl->nlmsg_seq = 0;
nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm));
if (cmd == SIOCDELRT) {

View File

@@ -192,7 +192,7 @@ int sysctl_icmp_echo_ignore_all;
int sysctl_icmp_echo_ignore_broadcasts = 1;
/* Control parameter - ignore bogus broadcast responses? */
int sysctl_icmp_ignore_bogus_error_responses;
int sysctl_icmp_ignore_bogus_error_responses = 1;
/*
* Configurable global rate limit.

View File

@@ -830,7 +830,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
skb->h.raw = skb->nh.raw;
skb->nh.raw = skb_push(skb, gre_hlen);
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED);
IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
IPSKB_REROUTED);
dst_release(skb->dst);
skb->dst = &rt->u.dst;

View File

@@ -207,8 +207,10 @@ static inline int ip_finish_output(struct sk_buff *skb)
{
#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
/* Policy lookup after SNAT yielded a new policy */
if (skb->dst->xfrm != NULL)
return xfrm4_output_finish(skb);
if (skb->dst->xfrm != NULL) {
IPCB(skb)->flags |= IPSKB_REROUTED;
return dst_output(skb);
}
#endif
if (skb->len > dst_mtu(skb->dst) &&
!(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
@@ -271,8 +273,9 @@ int ip_mc_output(struct sk_buff *skb)
newskb->dev, ip_dev_loopback_xmit);
}
return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev,
ip_finish_output);
return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev,
ip_finish_output,
!(IPCB(skb)->flags & IPSKB_REROUTED));
}
int ip_output(struct sk_buff *skb)
@@ -284,8 +287,9 @@ int ip_output(struct sk_buff *skb)
skb->dev = dev;
skb->protocol = htons(ETH_P_IP);
return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
ip_finish_output);
return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
ip_finish_output,
!(IPCB(skb)->flags & IPSKB_REROUTED));
}
int ip_queue_xmit(struct sk_buff *skb, int ipfragok)

View File

@@ -622,7 +622,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
skb->h.raw = skb->nh.raw;
skb->nh.raw = skb_push(skb, sizeof(struct iphdr));
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED);
IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
IPSKB_REROUTED);
dst_release(skb->dst);
skb->dst = &rt->u.dst;

View File

@@ -78,6 +78,47 @@ int ip_route_me_harder(struct sk_buff **pskb)
}
EXPORT_SYMBOL(ip_route_me_harder);
#ifdef CONFIG_XFRM
int ip_xfrm_me_harder(struct sk_buff **pskb)
{
struct flowi fl;
unsigned int hh_len;
struct dst_entry *dst;
if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)
return 0;
if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0)
return -1;
dst = (*pskb)->dst;
if (dst->xfrm)
dst = ((struct xfrm_dst *)dst)->route;
dst_hold(dst);
if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0)
return -1;
dst_release((*pskb)->dst);
(*pskb)->dst = dst;
/* Change in oif may mean change in hh_len. */
hh_len = (*pskb)->dst->dev->hard_header_len;
if (skb_headroom(*pskb) < hh_len) {
struct sk_buff *nskb;
nskb = skb_realloc_headroom(*pskb, hh_len);
if (!nskb)
return -1;
if ((*pskb)->sk)
skb_set_owner_w(nskb, (*pskb)->sk);
kfree_skb(*pskb);
*pskb = nskb;
}
return 0;
}
EXPORT_SYMBOL(ip_xfrm_me_harder);
#endif
void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
EXPORT_SYMBOL(ip_nat_decode_session);

View File

@@ -235,19 +235,19 @@ ip_nat_out(unsigned int hooknum,
return NF_ACCEPT;
ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
#ifdef CONFIG_XFRM
if (ret != NF_DROP && ret != NF_STOLEN
&& (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
if (ct->tuplehash[dir].tuple.src.ip !=
ct->tuplehash[!dir].tuple.dst.ip
#ifdef CONFIG_XFRM
|| ct->tuplehash[dir].tuple.src.u.all !=
ct->tuplehash[!dir].tuple.dst.u.all
#endif
)
return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP;
}
#endif
return ret;
}

View File

@@ -529,15 +529,10 @@ static int init_or_cleanup(int init)
goto cleanup_localinops;
}
#endif
/* For use by REJECT target */
ip_ct_attach = __nf_conntrack_attach;
return ret;
cleanup:
synchronize_net();
ip_ct_attach = NULL;
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
cleanup_localinops:

View File

@@ -456,7 +456,8 @@ void tcp_rcv_space_adjust(struct sock *sk)
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;
/* Receive space grows, normalize in order to

View File

@@ -152,10 +152,16 @@ error_nolock:
goto out_exit;
}
int xfrm4_output_finish(struct sk_buff *skb)
static int xfrm4_output_finish(struct sk_buff *skb)
{
int err;
#ifdef CONFIG_NETFILTER
if (!skb->dst->xfrm) {
IPCB(skb)->flags |= IPSKB_REROUTED;
return dst_output(skb);
}
#endif
while (likely((err = xfrm4_output_one(skb)) == 0)) {
nf_reset(skb);
@@ -178,6 +184,7 @@ int xfrm4_output_finish(struct sk_buff *skb)
int xfrm4_output(struct sk_buff *skb)
{
return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
xfrm4_output_finish);
return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
xfrm4_output_finish,
!(IPCB(skb)->flags & IPSKB_REROUTED));
}

View File

@@ -42,6 +42,7 @@
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/netfilter.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
@@ -255,6 +256,7 @@ out:
struct icmpv6_msg {
struct sk_buff *skb;
int offset;
uint8_t type;
};
static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
@@ -266,6 +268,8 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st
csum = skb_copy_and_csum_bits(org_skb, msg->offset + offset,
to, len, csum);
skb->csum = csum_block_add(skb->csum, csum, odd);
if (!(msg->type & ICMPV6_INFOMSG_MASK))
nf_ct_attach(skb, org_skb);
return 0;
}
@@ -403,6 +407,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
msg.skb = skb;
msg.offset = skb->nh.raw - skb->data;
msg.type = type;
len = skb->len - msg.offset;
len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) -sizeof(struct icmp6hdr));
@@ -500,6 +505,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
msg.skb = skb;
msg.offset = 0;
msg.type = ICMPV6_ECHO_REPLY;
err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl,

View File

@@ -160,6 +160,8 @@ static void send_reset(struct sk_buff *oldskb)
csum_partial((char *)tcph,
sizeof(struct tcphdr), 0));
nf_ct_attach(nskb, oldskb);
NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
dst_output);
}

View File

@@ -803,10 +803,7 @@ back_from_confirm:
err = rawv6_push_pending_frames(sk, &fl, rp);
}
done:
ip6_dst_store(sk, dst,
ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ?
&np->daddr : NULL);
dst_release(dst);
release_sock(sk);
out:
fl6_sock_release(flowlabel);

View File

@@ -343,12 +343,12 @@ static void irda_task_timer_expired(void *data)
static void irda_device_setup(struct net_device *dev)
{
dev->hard_header_len = 0;
dev->addr_len = 0;
dev->addr_len = LAP_ALEN;
dev->type = ARPHRD_IRDA;
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->flags = IFF_NOARP;

View File

@@ -696,7 +696,7 @@ irnet_daddr_to_dname(irnet_socket * self)
{
/* Yes !!! Get it.. */
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",
self->daddr, self->rname);
kfree(discoveries);

View File

@@ -102,8 +102,6 @@ config NF_CT_NETLINK
help
This option enables support for a netlink-based userspace interface
endmenu
config NETFILTER_XTABLES
tristate "Netfilter Xtables support (required for ip_tables)"
help
@@ -128,7 +126,7 @@ config NETFILTER_XT_TARGET_CONNMARK
tristate '"CONNMARK" target support'
depends on NETFILTER_XTABLES
depends on IP_NF_MANGLE || IP6_NF_MANGLE
depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK)
help
This option adds a `CONNMARK' target, which allows one to manipulate
the connection mark value. Similar to the MARK target, but
@@ -189,7 +187,7 @@ config NETFILTER_XT_MATCH_COMMENT
config NETFILTER_XT_MATCH_CONNBYTES
tristate '"connbytes" per-connection counter match support'
depends on NETFILTER_XTABLES
depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT
depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK)
help
This option adds a `connbytes' match, which allows you to match the
number of bytes and/or packets for each direction within a connection.
@@ -200,7 +198,7 @@ config NETFILTER_XT_MATCH_CONNBYTES
config NETFILTER_XT_MATCH_CONNMARK
tristate '"connmark" connection mark match support'
depends on NETFILTER_XTABLES
depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK
depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK)
help
This option adds a `connmark' match, which allows you to match the
connection mark value previously set for the session by `CONNMARK'.
@@ -361,3 +359,5 @@ config NETFILTER_XT_MATCH_TCPMSS
To compile it as a module, choose M here. If unsure, say N.
endmenu

View File

@@ -1556,6 +1556,8 @@ void nf_conntrack_cleanup(void)
{
int i;
ip_ct_attach = NULL;
/* This makes sure all current packets have passed through
netfilter framework. Roll on, two-stage module
delete... */
@@ -1715,6 +1717,9 @@ int __init nf_conntrack_init(void)
nf_ct_l3protos[i] = &nf_conntrack_generic_l3proto;
write_unlock_bh(&nf_conntrack_lock);
/* For use by REJECT target */
ip_ct_attach = __nf_conntrack_attach;
/* Set up fake conntrack:
- to never be deleted, not in any hashes */
atomic_set(&nf_conntrack_untracked.ct_general.use, 1);

View File

@@ -864,7 +864,9 @@ static int csum6(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
skb->len - dataoff, IPPROTO_TCP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
skb->ip_summed == CHECKSUM_HW
? csum_sub(skb->csum,
skb_checksum(skb, 0, dataoff, 0))
: skb_checksum(skb, dataoff, skb->len - dataoff,
0));
}

View File

@@ -161,7 +161,9 @@ static int csum6(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
skb->len - dataoff, IPPROTO_UDP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
skb->ip_summed == CHECKSUM_HW
? csum_sub(skb->csum,
skb_checksum(skb, 0, dataoff, 0))
: skb_checksum(skb, dataoff, skb->len - dataoff,
0));
}

View File

@@ -702,7 +702,8 @@ struct sock *netlink_getsockbyfilp(struct file *filp)
* 0: continue
* 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;
@@ -712,7 +713,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t
test_bit(0, &nlk->state)) {
DECLARE_WAITQUEUE(wait, current);
if (!timeo) {
if (!nlk->pid)
if (!ssk || nlk_sk(ssk)->pid == 0)
netlink_overrun(sk);
sock_put(sk);
kfree_skb(skb);
@@ -797,7 +798,7 @@ retry:
kfree_skb(skb);
return PTR_ERR(sk);
}
err = netlink_attachskb(sk, skb, nonblock, timeo);
err = netlink_attachskb(sk, skb, nonblock, timeo, ssk);
if (err == 1)
goto retry;
if (err)

View File

@@ -238,7 +238,7 @@ int genl_register_family(struct genl_family *family)
sizeof(struct nlattr *), GFP_KERNEL);
if (family->attrbuf == NULL) {
err = -ENOMEM;
goto errout;
goto errout_locked;
}
} else
family->attrbuf = NULL;
@@ -288,7 +288,7 @@ int genl_unregister_family(struct genl_family *family)
return -ENOENT;
}
static inline int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
int *errp)
{
struct genl_ops *ops;
@@ -375,7 +375,7 @@ static void genl_rcv(struct sock *sk, int len)
do {
if (genl_trylock())
return;
netlink_run_queue(sk, &qlen, &genl_rcv_msg);
netlink_run_queue(sk, &qlen, genl_rcv_msg);
genl_unlock();
} while (qlen && genl_sock && genl_sock->sk_receive_queue.qlen);
}
@@ -549,10 +549,8 @@ static int __init genl_init(void)
netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID,
genl_rcv, THIS_MODULE);
if (genl_sock == NULL) {
if (genl_sock == NULL)
panic("GENL: Cannot initialize generic netlink\n");
return -ENOMEM;
}
return 0;
@@ -560,7 +558,6 @@ errout_register:
genl_unregister_family(&genl_ctrl);
errout:
panic("GENL: Cannot register controller: %d\n", err);
return err;
}
subsys_initcall(genl_init);

View File

@@ -889,7 +889,9 @@ restart:
xfrm_pol_put(policy);
if (dst)
dst_free(dst);
goto restart;
err = -EHOSTUNREACH;
goto error;
}
dst->next = policy->bundles;
policy->bundles = dst;