summaryrefslogtreecommitdiffstats
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.c9
-rw-r--r--net/ax25/sysctl_net_ax25.c2
-rw-r--r--net/bluetooth/hci_sock.c10
-rw-r--r--net/bluetooth/rfcomm/core.c13
-rw-r--r--net/bridge/br_if.c121
-rw-r--r--net/bridge/br_input.c19
-rw-r--r--net/bridge/br_netfilter.c58
-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.c6
-rw-r--r--net/bridge/br_sysfs_if.c50
-rw-r--r--net/bridge/netfilter/Makefile2
-rw-r--r--net/bridge/netfilter/ebt_log.c7
-rw-r--r--net/bridge/netfilter/ebt_ulog.c10
-rw-r--r--net/bridge/netfilter/ebtables.c7
-rw-r--r--net/core/datagram.c81
-rw-r--r--net/core/dev.c2
-rw-r--r--net/core/request_sock.c1
-rw-r--r--net/core/rtnetlink.c2
-rw-r--r--net/core/skbuff.c10
-rw-r--r--net/core/utils.c4
-rw-r--r--net/dccp/ccids/ccid3.c10
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c1
-rw-r--r--net/ethernet/eth.c12
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c2
-rw-r--r--net/ieee80211/ieee80211_rx.c20
-rw-r--r--net/ipv4/devinet.c2
-rw-r--r--net/ipv4/esp4.c185
-rw-r--r--net/ipv4/fib_semantics.c2
-rw-r--r--net/ipv4/icmp.c4
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/ip_gre.c3
-rw-r--r--net/ipv4/ip_output.c23
-rw-r--r--net/ipv4/ipip.c3
-rw-r--r--net/ipv4/netfilter.c41
-rw-r--r--net/ipv4/netfilter/arp_tables.c9
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c3
-rw-r--r--net/ipv4/netfilter/ip_conntrack_tftp.c1
-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/ip_queue.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c7
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c7
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c26
-rw-r--r--net/ipv4/netfilter/ipt_policy.c11
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c5
-rw-r--r--net/ipv4/proc.c2
-rw-r--r--net/ipv4/route.c2
-rw-r--r--net/ipv4/tcp_highspeed.c2
-rw-r--r--net/ipv4/tcp_input.c3
-rw-r--r--net/ipv4/tcp_output.c4
-rw-r--r--net/ipv4/xfrm4_output.c13
-rw-r--r--net/ipv4/xfrm4_policy.c6
-rw-r--r--net/ipv6/addrconf.c5
-rw-r--r--net/ipv6/ah6.c2
-rw-r--r--net/ipv6/icmp.c6
-rw-r--r--net/ipv6/inet6_hashtables.c6
-rw-r--r--net/ipv6/ip6_output.c22
-rw-r--r--net/ipv6/ip6_tunnel.c3
-rw-r--r--net/ipv6/mcast.c2
-rw-r--r--net/ipv6/netfilter/ip6_queue.c2
-rw-r--r--net/ipv6/netfilter/ip6_tables.c7
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c7
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c2
-rw-r--r--net/ipv6/netfilter/ip6t_policy.c7
-rw-r--r--net/ipv6/proc.c2
-rw-r--r--net/ipv6/raw.c6
-rw-r--r--net/ipv6/xfrm6_policy.c1
-rw-r--r--net/irda/irda_device.c4
-rw-r--r--net/irda/irnet/irnet_irda.c2
-rw-r--r--net/key/af_key.c2
-rw-r--r--net/netfilter/Kconfig10
-rw-r--r--net/netfilter/nf_conntrack_core.c7
-rw-r--r--net/netfilter/nf_conntrack_ftp.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c3
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c4
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c4
-rw-r--r--net/netfilter/nf_queue.c42
-rw-r--r--net/netfilter/nfnetlink_log.c20
-rw-r--r--net/netfilter/nfnetlink_queue.c9
-rw-r--r--net/netlink/af_netlink.c12
-rw-r--r--net/netlink/genetlink.c11
-rw-r--r--net/sched/act_api.c2
-rw-r--r--net/socket.c2
-rw-r--r--net/sunrpc/clnt.c3
-rw-r--r--net/sunrpc/sched.c13
-rw-r--r--net/unix/af_unix.c2
-rw-r--r--net/xfrm/xfrm_policy.c21
-rw-r--r--net/xfrm/xfrm_state.c8
-rw-r--r--net/xfrm/xfrm_user.c2
91 files changed, 651 insertions, 519 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..31d98b57e1d 100644
--- a/net/atm/signaling.c
+++ b/net/atm/signaling.c
@@ -39,24 +39,19 @@ static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);
static void sigd_put_skb(struct sk_buff *skb)
{
#ifdef WAIT_FOR_DEMON
- static unsigned long silence;
DECLARE_WAITQUEUE(wait,current);
add_wait_queue(&sigd_sleep,&wait);
while (!sigd) {
set_current_state(TASK_UNINTERRUPTIBLE);
- if (time_after(jiffies, silence) || silence == 0) {
- printk(KERN_INFO "atmsvc: waiting for signaling demon "
- "...\n");
- silence = (jiffies+30*HZ)|1;
- }
+ DPRINTK("atmsvc: waiting for signaling demon...\n");
schedule();
}
current->state = TASK_RUNNING;
remove_wait_queue(&sigd_sleep,&wait);
#else
if (!sigd) {
- printk(KERN_WARNING "atmsvc: no signaling demon\n");
+ DPRINTK("atmsvc: no signaling demon\n");
kfree_skb(skb);
return;
}
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index f67711f2ee9..894a22558d9 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -24,7 +24,7 @@ static int min_t3[1], max_t3[] = {3600 * HZ};
static int min_idle[1], max_idle[] = {65535 * HZ};
static int min_n2[] = {1}, max_n2[] = {31};
static int min_paclen[] = {1}, max_paclen[] = {512};
-static int min_proto[1], max_proto[] = {3};
+static int min_proto[1], max_proto[] = { AX25_PROTO_MAX };
static int min_ds_timeout[1], max_ds_timeout[] = {65535 * HZ};
static struct ctl_table_header *ax25_table_header;
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..f36b35edd60 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -79,37 +79,57 @@ 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;
+ struct net_bridge *br;
rtnl_lock();
- if (netif_carrier_ok(p->dev)) {
- u32 cost = port_cost(p->dev);
+ p = dev->br_port;
+ if (!p)
+ goto done;
+ br = p->br;
- spin_lock_bh(&p->br->lock);
- if (p->state == BR_STATE_DISABLED) {
- p->path_cost = cost;
- br_stp_enable_port(p);
+ if (netif_carrier_ok(dev))
+ p->path_cost = port_cost(dev);
+
+ if (br->dev->flags & IFF_UP) {
+ spin_lock_bh(&br->lock);
+ if (netif_carrier_ok(dev)) {
+ if (p->state == BR_STATE_DISABLED)
+ br_stp_enable_port(p);
+ } else {
+ if (p->state != BR_STATE_DISABLED)
+ br_stp_disable_port(p);
}
- spin_unlock_bh(&p->br->lock);
- } else {
- spin_lock_bh(&p->br->lock);
- if (p->state != BR_STATE_DISABLED)
- br_stp_disable_port(p);
- spin_unlock_bh(&p->br->lock);
+ spin_unlock_bh(&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 +153,25 @@ 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_uevent(&p->kobj, KOBJ_REMOVE);
+ kobject_del(&p->kobj);
+
call_rcu(&p->rcu, destroy_nbp_rcu);
}
@@ -160,7 +181,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,12 +274,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);
+ br_stp_port_timer_init(p);
+
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 +413,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 +461,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..e060aad8624 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;
@@ -93,11 +90,18 @@ static struct rtable __fake_rtable = {
.dev = &__fake_net_device,
.path = &__fake_rtable.u.dst,
.metrics = {[RTAX_MTU - 1] = 1500},
+ .flags = DST_NOXFRM,
}
},
.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 +193,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 +278,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 +290,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 +386,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 +476,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 +551,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 +581,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 +705,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 +720,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 +764,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 +806,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..23dea1422c9 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -39,8 +39,6 @@ void br_init_port(struct net_bridge_port *p)
p->state = BR_STATE_BLOCKING;
p->topology_change_ack = 0;
p->config_pending = 0;
-
- br_stp_port_timer_init(p);
}
/* called under bridge lock */
@@ -67,7 +65,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 +74,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/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile
index 8bf6d9f6e9d..905087e0d48 100644
--- a/net/bridge/netfilter/Makefile
+++ b/net/bridge/netfilter/Makefile
@@ -29,4 +29,4 @@ obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o
# watchers
obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o
-obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_ulog.o
+obj-$(CONFIG_BRIDGE_EBT_ULOG) += ebt_ulog.o
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 0128fbbe232..288ff1d4ccc 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -166,7 +166,12 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
li.u.log.level = info->loglevel;
li.u.log.logflags = info->bitmask;
- nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, info->prefix);
+ if (info->bitmask & EBT_LOG_NFLOG)
+ nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
+ info->prefix);
+ else
+ ebt_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
+ info->prefix);
}
static struct ebt_watcher log =
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index ce617b3dbbb..802baf755ef 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -46,7 +46,7 @@
#define PRINTR(format, args...) do { if (net_ratelimit()) \
printk(format , ## args); } while (0)
-static unsigned int nlbufsiz = 4096;
+static unsigned int nlbufsiz = NLMSG_GOODSIZE;
module_param(nlbufsiz, uint, 0600);
MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) "
"(defaults to 4096)");
@@ -98,12 +98,14 @@ static void ulog_timer(unsigned long data)
static struct sk_buff *ulog_alloc_skb(unsigned int size)
{
struct sk_buff *skb;
+ unsigned int n;
- skb = alloc_skb(nlbufsiz, GFP_ATOMIC);
+ n = max(size, nlbufsiz);
+ skb = alloc_skb(n, GFP_ATOMIC);
if (!skb) {
PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer "
- "of size %ub!\n", nlbufsiz);
- if (size < nlbufsiz) {
+ "of size %ub!\n", n);
+ if (n > size) {
/* try to allocate only as much as we need for
* current packet */
skb = alloc_skb(size, GFP_ATOMIC);
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 00729b3604f..cbd4020cc84 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -934,6 +934,13 @@ static int do_replace(void __user *user, unsigned int len)
BUGPRINT("Entries_size never zero\n");
return -EINVAL;
}
+ /* overflow check */
+ if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
+ SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
+ return -ENOMEM;
+ if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
+ return -ENOMEM;
+
countersize = COUNTER_OFFSET(tmp.nentries) *
(highest_possible_processor_id()+1);
newinfo = (struct ebt_table_info *)
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/dev.c b/net/core/dev.c
index ffb82073056..2afb0de9532 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3237,7 +3237,7 @@ static int __init net_dev_init(void)
* Initialise the packet receive queues.
*/
- for (i = 0; i < NR_CPUS; i++) {
+ for_each_cpu(i) {
struct softnet_data *queue;
queue = &per_cpu(softnet_data, i);
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index b8203de5ff0..98f0fc923f9 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -52,7 +52,6 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
rwlock_init(&queue->syn_wait_lock);
queue->rskq_accept_head = queue->rskq_accept_head = NULL;
- queue->rskq_defer_accept = 0;
lopt->nr_table_entries = nr_table_entries;
write_lock_bh(&queue->syn_wait_lock);
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
#ifdef CONFIG_BRIDGE_NETFILTER
C(nf_bridge);
nf_bridge_get(skb->nf_bridge);
diff --git a/net/core/utils.c b/net/core/utils.c
index ac1d1fcf867..fdc4f38bc46 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -121,7 +121,7 @@ void __init net_random_init(void)
{
int i;
- for (i = 0; i < NR_CPUS; i++) {
+ for_each_cpu(i) {
struct nrnd_state *state = &per_cpu(net_rand_state,i);
__net_srandom(state, i+jiffies);
}
@@ -133,7 +133,7 @@ static int net_random_reseed(void)
unsigned long seed[NR_CPUS];
get_random_bytes(seed, sizeof(seed));
- for (i = 0; i < NR_CPUS; i++) {
+ for_each_cpu(i) {
struct nrnd_state *state = &per_cpu(net_rand_state,i);
__net_srandom(state, seed[i]);
}
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index aa68e0ab274..35d1d347541 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -2,7 +2,7 @@
* net/dccp/ccids/ccid3.c
*
* Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005-6 Ian McDonald <imcdnzl@gmail.com>
*
* An implementation of the DCCP protocol
*
@@ -1033,9 +1033,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
p_prev = hcrx->ccid3hcrx_p;
/* Calculate loss event rate */
- if (!list_empty(&hcrx->ccid3hcrx_li_hist))
+ if (!list_empty(&hcrx->ccid3hcrx_li_hist)) {
+ u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);
+
/* Scaling up by 1000000 as fixed decimal */
- hcrx->ccid3hcrx_p = 1000000 / dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);
+ if (i_mean != 0)
+ hcrx->ccid3hcrx_p = 1000000 / i_mean;
+ }
if (hcrx->ccid3hcrx_p > p_prev) {
ccid3_hc_rx_send_feedback(sk);
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index d2b5933b451..add3cae65e2 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -15,7 +15,6 @@
#include <linux/config.h>
#include <linux/module.h>
-#include <asm/bug.h>
#include <asm/div64.h>
#include "tfrc.h"
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 9890fd97e53..c971f14712e 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -95,6 +95,12 @@ int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
saddr = dev->dev_addr;
memcpy(eth->h_source,saddr,dev->addr_len);
+ if(daddr)
+ {
+ memcpy(eth->h_dest,daddr,dev->addr_len);
+ return ETH_HLEN;
+ }
+
/*
* Anyway, the loopback-device should never use this function...
*/
@@ -105,12 +111,6 @@ int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
return ETH_HLEN;
}
- if(daddr)
- {
- memcpy(eth->h_dest,daddr,dev->addr_len);
- return ETH_HLEN;
- }
-
return -ETH_HLEN;
}
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 47022172850..3840d1911f2 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -131,7 +131,7 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
- (WLAN_FC_GET_STYPE(fc) & 0x08));
+ (WLAN_FC_GET_STYPE(fc) & IEEE80211_STYPE_QOS_DATA));
aad_len = 22;
if (a4_included)
aad_len += 6;
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 960aa78cdb9..7ac6a7165d9 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -1301,7 +1301,7 @@ static void update_network(struct ieee80211_network *dst,
/* dst->last_associate is not overwritten */
}
-static inline int is_beacon(int fc)
+static inline int is_beacon(__le16 fc)
{
return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
}
@@ -1348,9 +1348,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
escape_essid(info_element->data,
info_element->len),
MAC_ARG(beacon->header.addr3),
- is_beacon(le16_to_cpu
- (beacon->header.
- frame_ctl)) ?
+ is_beacon(beacon->header.frame_ctl) ?
"BEACON" : "PROBE RESPONSE");
return;
}
@@ -1400,9 +1398,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
escape_essid(network.ssid,
network.ssid_len),
MAC_ARG(network.bssid),
- is_beacon(le16_to_cpu
- (beacon->header.
- frame_ctl)) ?
+ is_beacon(beacon->header.frame_ctl) ?
"BEACON" : "PROBE RESPONSE");
#endif
memcpy(target, &network, sizeof(*target));
@@ -1412,21 +1408,19 @@ static void ieee80211_process_probe_response(struct ieee80211_device
escape_essid(target->ssid,
target->ssid_len),
MAC_ARG(target->bssid),
- is_beacon(le16_to_cpu
- (beacon->header.
- frame_ctl)) ?
+ is_beacon(beacon->header.frame_ctl) ?
"BEACON" : "PROBE RESPONSE");
update_network(target, &network);
}
spin_unlock_irqrestore(&ieee->lock, flags);
- if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) {
+ if (is_beacon(beacon->header.frame_ctl)) {
if (ieee->handle_beacon != NULL)
- ieee->handle_beacon(dev, beacon, &network);
+ ieee->handle_beacon(dev, beacon, target);
} else {
if (ieee->handle_probe_response != NULL)
- ieee->handle_probe_response(dev, beacon, &network);
+ ieee->handle_probe_response(dev, beacon, target);
}
}
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 95b9d81ac48..3ffa60dadc0 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -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 {
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 73bfcae8af9..09590f35608 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -12,13 +12,6 @@
#include <net/protocol.h>
#include <net/udp.h>
-/* decapsulation data for use when post-processing */
-struct esp_decap_data {
- xfrm_address_t saddr;
- __u16 sport;
- __u8 proto;
-};
-
static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
@@ -150,6 +143,10 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
int nfrags;
int encap_len = 0;
+ u8 nexthdr[2];
+ struct scatterlist *sg;
+ u8 workbuf[60];
+ int padlen;
if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
goto out;
@@ -185,122 +182,82 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
if (esp->conf.ivlen)
crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm));
- {
- u8 nexthdr[2];
- struct scatterlist *sg = &esp->sgbuf[0];
- u8 workbuf[60];
- int padlen;
-
- if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
- sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
- if (!sg)
- goto out;
- }
- skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen);
- crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
- if (unlikely(sg != &esp->sgbuf[0]))
- kfree(sg);
-
- if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
- BUG();
+ sg = &esp->sgbuf[0];
- padlen = nexthdr[0];
- if (padlen+2 >= elen)
+ if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
+ sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
+ if (!sg)
goto out;
-
- /* ... check padding bits here. Silly. :-) */
-
- if (x->encap && decap && decap->decap_type) {
- struct esp_decap_data *encap_data;
- struct udphdr *uh = (struct udphdr *) (iph+1);
-
- encap_data = (struct esp_decap_data *) (decap->decap_data);
- encap_data->proto = 0;
-
- switch (decap->decap_type) {
- case UDP_ENCAP_ESPINUDP:
- case UDP_ENCAP_ESPINUDP_NON_IKE:
- encap_data->proto = AF_INET;
- encap_data->saddr.a4 = iph->saddr;
- encap_data->sport = uh->source;
- encap_len = (void*)esph - (void*)uh;
- break;
-
- default:
- goto out;
- }
- }
-
- iph->protocol = nexthdr[1];
- pskb_trim(skb, skb->len - alen - padlen - 2);
- memcpy(workbuf, skb->nh.raw, iph->ihl*4);
- skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
- skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
- memcpy(skb->nh.raw, workbuf, iph->ihl*4);
- skb->nh.iph->tot_len = htons(skb->len);
}
+ skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen);
+ crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
+ if (unlikely(sg != &esp->sgbuf[0]))
+ kfree(sg);
- return 0;
+ if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
+ BUG();
-out:
- return -EINVAL;
-}
+ padlen = nexthdr[0];
+ if (padlen+2 >= elen)
+ goto out;
-static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
-{
-
- if (x->encap) {
- struct xfrm_encap_tmpl *encap;
- struct esp_decap_data *decap_data;
+ /* ... check padding bits here. Silly. :-) */
- encap = x->encap;
- decap_data = (struct esp_decap_data *)(decap->decap_data);
+ if (x->encap) {
+ struct xfrm_encap_tmpl *encap = x->encap;
+ struct udphdr *uh;
- /* first, make sure that the decap type == the encap type */
if (encap->encap_type != decap->decap_type)
- return -EINVAL;
+ goto out;
- switch (encap->encap_type) {
- default:
- case UDP_ENCAP_ESPINUDP:
- case UDP_ENCAP_ESPINUDP_NON_IKE:
- /*
- * 1) if the NAT-T peer's IP or port changed then
- * advertize the change to the keying daemon.
- * This is an inbound SA, so just compare
- * SRC ports.
- */
- if (decap_data->proto == AF_INET &&
- (decap_data->saddr.a4 != x->props.saddr.a4 ||
- decap_data->sport != encap->encap_sport)) {
- xfrm_address_t ipaddr;
-
- ipaddr.a4 = decap_data->saddr.a4;
- km_new_mapping(x, &ipaddr, decap_data->sport);
-
- /* XXX: perhaps add an extra
- * policy check here, to see
- * if we should allow or
- * reject a packet from a
- * different source
- * address/port.
- */
- }
-
- /*
- * 2) ignore UDP/TCP checksums in case
- * of NAT-T in Transport Mode, or
- * perform other post-processing fixes
- * as per * draft-ietf-ipsec-udp-encaps-06,
- * section 3.1.2
+ uh = (struct udphdr *)(iph + 1);
+ encap_len = (void*)esph - (void*)uh;
+
+ /*
+ * 1) if the NAT-T peer's IP or port changed then
+ * advertize the change to the keying daemon.
+ * This is an inbound SA, so just compare
+ * SRC ports.
+ */
+ if (iph->saddr != x->props.saddr.a4 ||
+ uh->source != encap->encap_sport) {
+ xfrm_address_t ipaddr;
+
+ ipaddr.a4 = iph->saddr;
+ km_new_mapping(x, &ipaddr, uh->source);
+
+ /* XXX: perhaps add an extra
+ * policy check here, to see
+ * if we should allow or
+ * reject a packet from a
+ * different source
+ * address/port.
*/
- if (!x->props.mode)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
-
- break;
}
+
+ /*
+ * 2) ignore UDP/TCP checksums in case
+ * of NAT-T in Transport Mode, or
+ * perform other post-processing fixes
+ * as per draft-ietf-ipsec-udp-encaps-06,
+ * section 3.1.2
+ */
+ if (!x->props.mode)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
}
+
+ iph->protocol = nexthdr[1];
+ pskb_trim(skb, skb->len - alen - padlen - 2);
+ memcpy(workbuf, skb->nh.raw, iph->ihl*4);
+ skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
+ skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
+ memcpy(skb->nh.raw, workbuf, iph->ihl*4);
+ skb->nh.iph->tot_len = htons(skb->len);
+
return 0;
+
+out:
+ return -EINVAL;
}
static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
@@ -458,7 +415,6 @@ static struct xfrm_type esp_type =
.destructor = esp_destroy,
.get_max_size = esp4_get_max_size,
.input = esp_input,
- .post_input = esp_post_input,
.output = esp_output
};
@@ -470,15 +426,6 @@ static struct net_protocol esp4_protocol = {
static int __init esp4_init(void)
{
- struct xfrm_decap_state decap;
-
- if (sizeof(struct esp_decap_data) >
- sizeof(decap.decap_data)) {
- extern void decap_data_too_small(void);
-
- decap_data_too_small();
- }
-
if (xfrm_register_type(&esp_type, AF_INET) < 0) {
printk(KERN_INFO "ip esp init: can't add xfrm type\n");
return -EAGAIN;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index ef4724de735..0f4145babb1 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -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) {
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 6bc0887b083..e7bbff4340b 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -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.
@@ -524,7 +524,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
iph->tos;
if (ip_options_echo(&icmp_param.replyopts, skb_in))
- goto ende;
+ goto out_unlock;
/*
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 0b4e95f93da..64ce52bf048 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1578,7 +1578,7 @@ static int sf_setstate(struct ip_mc_list *pmc)
new_in = psf->sf_count[MCAST_INCLUDE] != 0;
if (new_in) {
if (!psf->sf_oldin) {
- struct ip_sf_list *prev = 0;
+ struct ip_sf_list *prev = NULL;
for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next) {
if (dpsf->sf_inaddr == psf->sf_inaddr)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index abe23923e4e..9981dcd68f1 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -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;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 3324fbfe528..8ee4d016740 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -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)
@@ -843,10 +847,11 @@ int ip_append_data(struct sock *sk,
if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
(rt->u.dst.dev->features & NETIF_F_UFO)) {
- if(ip_ufo_append_data(sk, getfrag, from, length, hh_len,
- fragheaderlen, transhdrlen, mtu, flags))
+ err = ip_ufo_append_data(sk, getfrag, from, length, hh_len,
+ fragheaderlen, transhdrlen, mtu,
+ flags);
+ if (err)
goto error;
-
return 0;
}
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index e5cbe72c6b8..03d13742a4b 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -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;
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 52a3d7c5790..ed42cdc57cd 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -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);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index afe3d8f8177..7d7ab94a7a2 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -771,7 +771,7 @@ static int get_entries(const struct arpt_get_entries *entries,
struct arpt_table *t;
t = xt_find_table_lock(NF_ARP, entries->name);
- if (t || !IS_ERR(t)) {
+ if (t && !IS_ERR(t)) {
struct xt_table_info *private = t->private;
duprintf("t->private->number = %u\n",
private->number);
@@ -807,6 +807,13 @@ static int do_replace(void __user *user, unsigned int len)
if (len != sizeof(tmp) + tmp.size)
return -ENOPROTOOPT;
+ /* overflow check */
+ if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+ SMP_CACHE_BYTES)
+ return -ENOMEM;
+ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+ return -ENOMEM;
+
newinfo = xt_alloc_table_info(tmp.size);
if (!newinfo)
return -ENOMEM;
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index c9ebbe0d2d9..e0b5926c76f 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1216,7 +1216,7 @@ static int ctnetlink_expect_event(struct notifier_block *this,
b = skb->tail;
- type |= NFNL_SUBSYS_CTNETLINK << 8;
+ type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
nfmsg = NLMSG_DATA(nlh);
@@ -1567,6 +1567,7 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = {
};
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
static int __init ctnetlink_init(void)
{
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index d3c5a371f99..4ba4463cec2 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -71,6 +71,7 @@ static int tftp_help(struct sk_buff **pskb,
exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
exp->mask.src.ip = 0xffffffff;
+ exp->mask.src.u.udp.port = 0;
exp->mask.dst.ip = 0xffffffff;
exp->mask.dst.u.udp.port = 0xffff;
exp->mask.dst.protonum = 0xff;
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index c1a61462507..1741d555ad0 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -434,6 +434,7 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
} *inside;
struct ip_conntrack_tuple inner, target;
int hdrlen = (*pskb)->nh.iph->ihl * 4;
+ unsigned long statusbit;
if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
return 0;
@@ -495,17 +496,16 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
/* Change outer to look the reply to an incoming packet
* (proto 0 means don't invert per-proto part). */
+ if (manip == IP_NAT_MANIP_SRC)
+ statusbit = IPS_SRC_NAT;
+ else
+ statusbit = IPS_DST_NAT;
- /* Obviously, we need to NAT destination IP, but source IP
- should be NAT'ed only if it is from a NAT'd host.
+ /* Invert if this is reply dir. */
+ if (dir == IP_CT_DIR_REPLY)
+ statusbit ^= IPS_NAT_MASK;
- Explanation: some people use NAT for anonymizing. Also,
- CERT recommends dropping all packets from private IP
- addresses (although ICMP errors from internal links with
- such addresses are not too uncommon, as Alan Cox points
- out) */
- if (manip != IP_NAT_MANIP_SRC
- || ((*pskb)->nh.iph->saddr == ct->tuplehash[dir].tuple.src.ip)) {
+ if (ct->status & statusbit) {
invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
if (!manip_pkt(0, pskb, 0, &target, manip))
return 0;
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index ad438fb185b..ab1f88fa21e 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -200,20 +200,14 @@ ip_nat_in(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct ip_conntrack *ct;
- enum ip_conntrack_info ctinfo;
unsigned int ret;
+ u_int32_t daddr = (*pskb)->nh.iph->daddr;
ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
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) {
- dst_release((*pskb)->dst);
- (*pskb)->dst = NULL;
- }
+ && daddr != (*pskb)->nh.iph->daddr) {
+ dst_release((*pskb)->dst);
+ (*pskb)->dst = NULL;
}
return ret;
}
@@ -235,19 +229,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;
}
@@ -276,7 +270,7 @@ ip_nat_local_fn(unsigned int hooknum,
ct->tuplehash[!dir].tuple.src.ip
#ifdef CONFIG_XFRM
|| ct->tuplehash[dir].tuple.dst.u.all !=
- ct->tuplehash[dir].tuple.src.u.all
+ ct->tuplehash[!dir].tuple.src.u.all
#endif
)
return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 36339eb39e1..08f80e2ea2a 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -524,7 +524,7 @@ ipq_rcv_skb(struct sk_buff *skb)
write_unlock_bh(&queue_lock);
status = ipq_receive_peer(NLMSG_DATA(nlh), type,
- skblen - NLMSG_LENGTH(0));
+ nlmsglen - NLMSG_LENGTH(0));
if (status < 0)
RCV_SKB_FAIL(status);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 2371b2062c2..16f47c675fe 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -921,6 +921,13 @@ do_replace(void __user *user, unsigned int len)
if (len != sizeof(tmp) + tmp.size)
return -ENOPROTOOPT;
+ /* overflow check */
+ if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+ SMP_CACHE_BYTES)
+ return -ENOMEM;
+ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+ return -ENOMEM;
+
newinfo = xt_alloc_table_info(tmp.size);
if (!newinfo)
return -ENOMEM;
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 6606ddb66a2..cc27545ff97 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -425,7 +425,12 @@ ipt_log_target(struct sk_buff **pskb,
li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags;
- nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, loginfo->prefix);
+ if (loginfo->logflags & IPT_LOG_NFLOG)
+ nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
+ loginfo->prefix);
+ else
+ ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
+ loginfo->prefix);
return IPT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 641dbc47765..180a9ea57b6 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -35,6 +35,10 @@
* each nlgroup you are using, so the total kernel memory usage increases
* by that factor.
*
+ * Actually you should use nlbufsiz a bit smaller than PAGE_SIZE, since
+ * nlbufsiz is used with alloc_skb, which adds another
+ * sizeof(struct skb_shared_info). Use NLMSG_GOODSIZE instead.
+ *
* flushtimeout:
* Specify, after how many hundredths of a second the queue should be
* flushed even if it is not full yet.
@@ -76,7 +80,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG);
#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
-static unsigned int nlbufsiz = 4096;
+static unsigned int nlbufsiz = NLMSG_GOODSIZE;
module_param(nlbufsiz, uint, 0400);
MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
@@ -143,22 +147,26 @@ static void ulog_timer(unsigned long data)
static struct sk_buff *ulog_alloc_skb(unsigned int size)
{
struct sk_buff *skb;
+ unsigned int n;
/* alloc skb which should be big enough for a whole
* multipart message. WARNING: has to be <= 131000
* due to slab allocator restrictions */
- skb = alloc_skb(nlbufsiz, GFP_ATOMIC);
+ n = max(size, nlbufsiz);
+ skb = alloc_skb(n, GFP_ATOMIC);
if (!skb) {
- PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n",
- nlbufsiz);
+ PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", n);
- /* try to allocate only as much as we need for
- * current packet */
+ if (n > size) {
+ /* try to allocate only as much as we need for
+ * current packet */
- skb = alloc_skb(size, GFP_ATOMIC);
- if (!skb)
- PRINTR("ipt_ULOG: can't even allocate %ub\n", size);
+ skb = alloc_skb(size, GFP_ATOMIC);
+ if (!skb)
+ PRINTR("ipt_ULOG: can't even allocate %ub\n",
+ size);
+ }
}
return skb;
diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c
index 18ca8258a1c..5a7a265280f 100644
--- a/net/ipv4/netfilter/ipt_policy.c
+++ b/net/ipv4/netfilter/ipt_policy.c
@@ -26,10 +26,13 @@ MODULE_LICENSE("GPL");
static inline int
match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
{
-#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
+#define MATCH_ADDR(x,y,z) (!e->match.x || \
+ ((e->x.a4.s_addr == (e->y.a4.s_addr & (z))) \
+ ^ e->invert.x))
+#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
- return MATCH(saddr, x->props.saddr.a4 & e->smask) &&
- MATCH(daddr, x->id.daddr.a4 & e->dmask) &&
+ return MATCH_ADDR(saddr, smask, x->props.saddr.a4) &&
+ MATCH_ADDR(daddr, dmask, x->id.daddr.a4) &&
MATCH(proto, x->id.proto) &&
MATCH(mode, x->props.mode) &&
MATCH(spi, x->id.spi) &&
@@ -89,7 +92,7 @@ match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
return 0;
}
- return strict ? 1 : 0;
+ return strict ? i == info->len : 0;
}
static int match(const struct sk_buff *skb,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 167619f638c..6c8624a5493 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -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:
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 39d49dc333a..1b167c4bb3b 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -49,7 +49,7 @@ static int fold_prot_inuse(struct proto *proto)
int res = 0;
int cpu;
- for (cpu = 0; cpu < NR_CPUS; cpu++)
+ for_each_cpu(cpu)
res += proto->stats[cpu].inuse;
return res;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d82c242ea70..fca5fe0cf94 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -835,7 +835,7 @@ static int rt_garbage_collect(void)
int r;
rthp = rt_remove_balanced_route(
- &rt_hash_table[i].chain,
+ &rt_hash_table[k].chain,
rth,
&r);
goal -= r;
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index 63cf7e54084..e0e9d1383c7 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -125,7 +125,7 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
/* Update AIMD parameters */
if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
- ca->ai < HSTCP_AIMD_MAX)
+ ca->ai < HSTCP_AIMD_MAX - 1)
ca->ai++;
} else if (tp->snd_cwnd < hstcp_aimd_vals[ca->ai].cwnd) {
while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index a97ed5416c2..e9a54ae7d69 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -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
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index a7623ead39a..9f498a6c889 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1036,6 +1036,10 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
limit = min(send_win, cong_win);
+ /* If a full-sized TSO skb can be sent, do it. */
+ if (limit >= 65536)
+ return 0;
+
if (sysctl_tcp_tso_win_divisor) {
u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index d4df0ddd424..32ad229b4fe 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -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));
}
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 42196ba3b0b..f285bbf296e 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -8,7 +8,6 @@
*
*/
-#include <asm/bug.h>
#include <linux/compiler.h>
#include <linux/config.h>
#include <linux/inetdevice.h>
@@ -36,6 +35,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
if (xdst->u.rt.fl.oif == fl->oif && /*XXX*/
xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
xdst->u.rt.fl.fl4_src == fl->fl4_src &&
+ xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
xfrm_bundle_ok(xdst, fl, AF_INET)) {
dst_clone(dst);
break;
@@ -62,7 +62,8 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
.nl_u = {
.ip4_u = {
.saddr = local,
- .daddr = remote
+ .daddr = remote,
+ .tos = fl->fl4_tos
}
}
};
@@ -231,6 +232,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
fl->proto = iph->protocol;
fl->fl4_dst = iph->daddr;
fl->fl4_src = iph->saddr;
+ fl->fl4_tos = iph->tos;
}
static inline int xfrm4_garbage_collect(void)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1db50487916..19727d94196 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -822,7 +822,7 @@ struct ipv6_saddr_score {
int addr_type;
unsigned int attrs;
int matchlen;
- unsigned int scope;
+ int scope;
unsigned int rule;
};
@@ -2165,6 +2165,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
dev->name);
break;
}
+
+ if (idev)
+ idev->if_flags |= IF_READY;
} else {
if (!netif_carrier_ok(dev)) {
/* device is still not ready. */
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index c7932cb420a..84963749ab7 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -279,7 +279,7 @@ static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
goto out;
memcpy(tmp_hdr, skb->nh.raw, hdr_len);
if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len))
- goto out;
+ goto free_out;
skb->nh.ipv6h->priority = 0;
skb->nh.ipv6h->flow_lbl[0] = 0;
skb->nh.ipv6h->flow_lbl[1] = 0;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index fcf883183ce..21eb725e885 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -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,
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 4154f3a8b6c..bb8ffb8a14c 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -87,7 +87,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
struct inet_timewait_sock **twp)
{
struct inet_hashinfo *hinfo = death_row->hashinfo;
- const struct inet_sock *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
const struct ipv6_pinfo *np = inet6_sk(sk);
const struct in6_addr *daddr = &np->rcv_saddr;
const struct in6_addr *saddr = &np->daddr;
@@ -129,6 +129,10 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
}
unique:
+ /* Must record num and sport now. Otherwise we will see
+ * in hash table socket with a funny identity. */
+ inet->num = lport;
+ inet->sport = htons(lport);
BUG_TRAP(sk_unhashed(sk));
__sk_add_node(sk, &head->chain);
sk->sk_hash = hash;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index efa3e72cfcf..5bf70b1442e 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -494,6 +494,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
struct net_device *dev;
struct sk_buff *frag;
struct rt6_info *rt = (struct rt6_info*)skb->dst;
+ struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL;
struct ipv6hdr *tmp_hdr;
struct frag_hdr *fh;
unsigned int mtu, hlen, left, len;
@@ -505,7 +506,12 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
hlen = ip6_find_1stfragopt(skb, &prevhdr);
nexthdr = *prevhdr;
- mtu = dst_mtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr);
+ mtu = dst_mtu(&rt->u.dst);
+ if (np && np->frag_size < mtu) {
+ if (np->frag_size)
+ mtu = np->frag_size;
+ }
+ mtu -= hlen + sizeof(struct frag_hdr);
if (skb_shinfo(skb)->frag_list) {
int first_len = skb_pagelen(skb);
@@ -882,7 +888,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
inet->cork.fl = *fl;
np->cork.hop_limit = hlimit;
np->cork.tclass = tclass;
- inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path);
+ mtu = dst_mtu(rt->u.dst.path);
+ if (np && np->frag_size < mtu) {
+ if (np->frag_size)
+ mtu = np->frag_size;
+ }
+ inet->cork.fragsize = mtu;
if (dst_allfrag(rt->u.dst.path))
inet->cork.flags |= IPCORK_ALLFRAG;
inet->cork.length = 0;
@@ -933,10 +944,11 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
(rt->u.dst.dev->features & NETIF_F_UFO)) {
- if(ip6_ufo_append_data(sk, getfrag, from, length, hh_len,
- fragheaderlen, transhdrlen, mtu, flags))
+ err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len,
+ fragheaderlen, transhdrlen, mtu,
+ flags);
+ if (err)
goto error;
-
return 0;
}
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 92ead3cf956..48597538db3 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -458,7 +458,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
mtu = IPV6_MIN_MTU;
t->dev->mtu = mtu;
- if ((len = sizeof (*ipv6h) + ipv6h->payload_len) > mtu) {
+ if ((len = sizeof (*ipv6h) + ntohs(ipv6h->payload_len)) > mtu) {
rel_type = ICMPV6_PKT_TOOBIG;
rel_code = 0;
rel_info = mtu;
@@ -884,6 +884,7 @@ ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p)
t->parms.encap_limit = p->encap_limit;
t->parms.flowinfo = p->flowinfo;
t->parms.link = p->link;
+ ip6_tnl_dst_reset(t);
ip6ip6_tnl_link_config(t);
return 0;
}
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 4420948a1bf..807c021d64a 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1978,7 +1978,7 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
new_in = psf->sf_count[MCAST_INCLUDE] != 0;
if (new_in) {
if (!psf->sf_oldin) {
- struct ip6_sf_list *prev = 0;
+ struct ip6_sf_list *prev = NULL;
for (dpsf=pmc->mca_tomb; dpsf;
dpsf=dpsf->sf_next) {
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 5027bbe6415..af0635084df 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -522,7 +522,7 @@ ipq_rcv_skb(struct sk_buff *skb)
write_unlock_bh(&queue_lock);
status = ipq_receive_peer(NLMSG_DATA(nlh), type,
- skblen - NLMSG_LENGTH(0));
+ nlmsglen - NLMSG_LENGTH(0));
if (status < 0)
RCV_SKB_FAIL(status);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 847068fd336..74ff56c322f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -978,6 +978,13 @@ do_replace(void __user *user, unsigned int len)
if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
return -EFAULT;
+ /* overflow check */
+ if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+ SMP_CACHE_BYTES)
+ return -ENOMEM;
+ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+ return -ENOMEM;
+
newinfo = xt_alloc_table_info(tmp.size);
if (!newinfo)
return -ENOMEM;
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 77c725832de..6b930efa9fb 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -436,7 +436,12 @@ ip6t_log_target(struct sk_buff **pskb,
li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags;
- nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, loginfo->prefix);
+ if (loginfo->logflags & IP6T_LOG_NFLOG)
+ nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
+ loginfo->prefix);
+ else
+ ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
+ loginfo->prefix);
return IP6T_CONTINUE;
}
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index c745717b4ce..0e6d1d4bbd5 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -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);
}
diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c
index afe1cc4c18a..3d39ec92404 100644
--- a/net/ipv6/netfilter/ip6t_policy.c
+++ b/net/ipv6/netfilter/ip6t_policy.c
@@ -26,8 +26,9 @@ MODULE_LICENSE("GPL");
static inline int
match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
{
-#define MATCH_ADDR(x,y,z) (!e->match.x || \
- ((ip6_masked_addrcmp((z), &e->x, &e->y)) == 0) ^ e->invert.x)
+#define MATCH_ADDR(x,y,z) (!e->match.x || \
+ ((!ip6_masked_addrcmp(&e->x.a6, &e->y.a6, z)) \
+ ^ e->invert.x))
#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
return MATCH_ADDR(saddr, smask, (struct in6_addr *)&x->props.saddr.a6) &&
@@ -91,7 +92,7 @@ match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
return 0;
}
- return strict ? 1 : 0;
+ return strict ? i == info->len : 0;
}
static int match(const struct sk_buff *skb,
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 50a13e75d70..4238b1ed886 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -38,7 +38,7 @@ static int fold_prot_inuse(struct proto *proto)
int res = 0;
int cpu;
- for (cpu=0; cpu<NR_CPUS; cpu++)
+ for_each_cpu(cpu)
res += proto->stats[cpu].inuse;
return res;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 66f1d12ea57..ae20a0ec9bd 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -35,7 +35,6 @@
#include <linux/skbuff.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
-#include <asm/bug.h>
#include <net/ip.h>
#include <net/sock.h>
@@ -804,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);
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 69bd957380e..91cce8b2d7a 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -11,7 +11,6 @@
*
*/
-#include <asm/bug.h>
#include <linux/compiler.h>
#include <linux/config.h>
#include <linux/netdevice.h>
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index 890bac0d4a5..e3debbdb67f 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -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;
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
index 07ec326c71f..f65c7a83bc5 100644
--- a/net/irda/irnet/irnet_irda.c
+++ b/net/irda/irnet/irnet_irda.c
@@ -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);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ae86d237a45..b2d4d1dd211 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1423,7 +1423,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
if (err < 0) {
x->km.state = XFRM_STATE_DEAD;
- xfrm_state_put(x);
+ __xfrm_state_put(x);
goto out;
}
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 99c0a0fa4a9..a8e5544da93 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -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
+
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 62bb509f05d..d622ddf08bb 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -188,7 +188,7 @@ extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
struct nf_conntrack_protocol *
__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol)
{
- if (unlikely(nf_ct_protos[l3proto] == NULL))
+ if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL))
return &nf_conntrack_generic_protocol;
return nf_ct_protos[l3proto][protocol];
@@ -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);
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index ab0c920f0d3..6f210f39976 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -657,8 +657,6 @@ static int __init init(void)
/* FIXME should be configurable whether IPv4 and IPv6 FTP connections
are tracked or not - YK */
for (i = 0; i < ports_c; i++) {
- memset(&ftp[i], 0, sizeof(struct nf_conntrack_helper));
-
ftp[i][0].tuple.src.l3num = PF_INET;
ftp[i][1].tuple.src.l3num = PF_INET6;
for (j = 0; j < 2; j++) {
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 73ab16bc7d4..9ff3463037e 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1232,7 +1232,7 @@ static int ctnetlink_expect_event(struct notifier_block *this,
b = skb->tail;
- type |= NFNL_SUBSYS_CTNETLINK << 8;
+ type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
nfmsg = NLMSG_DATA(nlh);
@@ -1589,6 +1589,7 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = {
};
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
static int __init ctnetlink_init(void)
{
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index df99138c3b3..6492ed66fb3 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -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));
}
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 4264dd079a1..831d206344e 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -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));
}
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index d3a4f30a7f2..d9f0d7ef103 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -6,6 +6,7 @@
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/seq_file.h>
+#include <linux/rcupdate.h>
#include <net/protocol.h>
#include "nf_internals.h"
@@ -16,7 +17,7 @@
* for queueing and must reinject all packets it receives, no matter what.
*/
static struct nf_queue_handler *queue_handler[NPROTO];
-static struct nf_queue_rerouter *queue_rerouter;
+static struct nf_queue_rerouter *queue_rerouter[NPROTO];
static DEFINE_RWLOCK(queue_handler_lock);
@@ -64,7 +65,7 @@ int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
return -EINVAL;
write_lock_bh(&queue_handler_lock);
- memcpy(&queue_rerouter[pf], rer, sizeof(queue_rerouter[pf]));
+ rcu_assign_pointer(queue_rerouter[pf], rer);
write_unlock_bh(&queue_handler_lock);
return 0;
@@ -77,8 +78,9 @@ int nf_unregister_queue_rerouter(int pf)
return -EINVAL;
write_lock_bh(&queue_handler_lock);
- memset(&queue_rerouter[pf], 0, sizeof(queue_rerouter[pf]));
+ rcu_assign_pointer(queue_rerouter[pf], NULL);
write_unlock_bh(&queue_handler_lock);
+ synchronize_rcu();
return 0;
}
EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
@@ -114,16 +116,17 @@ int nf_queue(struct sk_buff **skb,
struct net_device *physindev = NULL;
struct net_device *physoutdev = NULL;
#endif
+ struct nf_queue_rerouter *rerouter;
/* QUEUE == DROP if noone is waiting, to be safe. */
read_lock(&queue_handler_lock);
- if (!queue_handler[pf] || !queue_handler[pf]->outfn) {
+ if (!queue_handler[pf]) {
read_unlock(&queue_handler_lock);
kfree_skb(*skb);
return 1;
}
- info = kmalloc(sizeof(*info)+queue_rerouter[pf].rer_size, GFP_ATOMIC);
+ info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC);
if (!info) {
if (net_ratelimit())
printk(KERN_ERR "OOM queueing packet %p\n",
@@ -155,15 +158,13 @@ int nf_queue(struct sk_buff **skb,
if (physoutdev) dev_hold(physoutdev);
}
#endif
- if (queue_rerouter[pf].save)
- queue_rerouter[pf].save(*skb, info);
+ rerouter = rcu_dereference(queue_rerouter[pf]);
+ if (rerouter)
+ rerouter->save(*skb, info);
status = queue_handler[pf]->outfn(*skb, info, queuenum,
queue_handler[pf]->data);
- if (status >= 0 && queue_rerouter[pf].reroute)
- status = queue_rerouter[pf].reroute(skb, info);
-
read_unlock(&queue_handler_lock);
if (status < 0) {
@@ -189,6 +190,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
{
struct list_head *elem = &info->elem->list;
struct list_head *i;
+ struct nf_queue_rerouter *rerouter;
rcu_read_lock();
@@ -212,7 +214,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
break;
}
- if (elem == &nf_hooks[info->pf][info->hook]) {
+ if (i == &nf_hooks[info->pf][info->hook]) {
/* The module which sent it to userspace is gone. */
NFDEBUG("%s: module disappeared, dropping packet.\n",
__FUNCTION__);
@@ -226,6 +228,12 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
}
if (verdict == NF_ACCEPT) {
+ rerouter = rcu_dereference(queue_rerouter[info->pf]);
+ if (rerouter && rerouter->reroute(&skb, info) < 0)
+ verdict = NF_DROP;
+ }
+
+ if (verdict == NF_ACCEPT) {
next_hook:
verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
&skb, info->hook,
@@ -322,22 +330,12 @@ int __init netfilter_queue_init(void)
{
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *pde;
-#endif
- queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter),
- GFP_KERNEL);
- if (!queue_rerouter)
- return -ENOMEM;
-#ifdef CONFIG_PROC_FS
pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter);
- if (!pde) {
- kfree(queue_rerouter);
+ if (!pde)
return -1;
- }
pde->proc_fops = &nfqueue_file_ops;
#endif
- memset(queue_rerouter, 0, NPROTO * sizeof(struct nf_queue_rerouter));
-
return 0;
}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index e10512e229b..3b3c781b40c 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -37,7 +37,7 @@
#include "../bridge/br_private.h"
#endif
-#define NFULNL_NLBUFSIZ_DEFAULT 4096
+#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE
#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */
#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */
@@ -314,24 +314,28 @@ static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size,
unsigned int pkt_size)
{
struct sk_buff *skb;
+ unsigned int n;
UDEBUG("entered (%u, %u)\n", inst_size, pkt_size);
/* alloc skb which should be big enough for a whole multipart
* message. WARNING: has to be <= 128k due to slab restrictions */
- skb = alloc_skb(inst_size, GFP_ATOMIC);
+ n = max(inst_size, pkt_size);
+ skb = alloc_skb(n, GFP_ATOMIC);
if (!skb) {
PRINTR("nfnetlink_log: can't alloc whole buffer (%u bytes)\n",
inst_size);
- /* try to allocate only as much as we need for current
- * packet */
+ if (n > pkt_size) {
+ /* try to allocate only as much as we need for current
+ * packet */
- skb = alloc_skb(pkt_size, GFP_ATOMIC);
- if (!skb)
- PRINTR("nfnetlink_log: can't even alloc %u bytes\n",
- pkt_size);
+ skb = alloc_skb(pkt_size, GFP_ATOMIC);
+ if (!skb)
+ PRINTR("nfnetlink_log: can't even alloc %u "
+ "bytes\n", pkt_size);
+ }
}
return skb;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 18ed9c5d209..2cf5fb8322c 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -825,7 +825,8 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
}
if (nfqa[NFQA_MARK-1])
- skb->nfmark = ntohl(*(u_int32_t *)NFA_DATA(nfqa[NFQA_MARK-1]));
+ entry->skb->nfmark = ntohl(*(u_int32_t *)
+ NFA_DATA(nfqa[NFQA_MARK-1]));
issue_verdict(entry, verdict);
instance_put(queue);
@@ -927,8 +928,12 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
if (nfqa[NFQA_CFG_PARAMS-1]) {
struct nfqnl_msg_config_params *params;
- params = NFA_DATA(nfqa[NFQA_CFG_PARAMS-1]);
+ if (!queue) {
+ ret = -ENOENT;
+ goto out_put;
+ }
+ params = NFA_DATA(nfqa[NFQA_CFG_PARAMS-1]);
nfqnl_set_mode(queue, params->copy_mode,
ntohl(params->copy_range));
}
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2101b45d2ec..59dc7d14060 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -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)
@@ -1193,6 +1194,9 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
msg->msg_namelen = sizeof(*addr);
}
+ if (nlk->flags & NETLINK_RECV_PKTINFO)
+ netlink_cmsg_recv_pktinfo(msg, skb);
+
if (NULL == siocb->scm) {
memset(&scm, 0, sizeof(scm));
siocb->scm = &scm;
@@ -1204,8 +1208,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
netlink_dump(sk);
scm_recv(sock, msg, siocb->scm, flags);
- if (nlk->flags & NETLINK_RECV_PKTINFO)
- netlink_cmsg_recv_pktinfo(msg, skb);
out:
netlink_rcv_wake(sk);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 4ae1538c54a..43e72419c86 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -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);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 792ce59940e..2ffa11c6e8d 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -707,7 +707,7 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
rtattr_failure:
nlmsg_failure:
- skb_trim(skb, b - skb->data);
+ kfree_skb(skb);
return -1;
}
diff --git a/net/socket.c b/net/socket.c
index b38a263853c..a00851f981d 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2078,7 +2078,7 @@ void socket_seq_show(struct seq_file *seq)
int cpu;
int counter = 0;
- for (cpu = 0; cpu < NR_CPUS; cpu++)
+ for_each_cpu(cpu)
counter += per_cpu(sockets_in_use, cpu);
/* It can be negative, by the way. 8) */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d2f0550c4ba..d7847978204 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -113,7 +113,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
err = -EINVAL;
if (!xprt)
- goto out_err;
+ goto out_no_xprt;
if (vers >= program->nrvers || !(version = program->version[vers]))
goto out_err;
@@ -182,6 +182,7 @@ out_no_path:
kfree(clnt);
out_err:
xprt_destroy(xprt);
+out_no_xprt:
return ERR_PTR(err);
}
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 802d4fe0f55..e838d042f7f 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -515,16 +515,14 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue)
*/
void rpc_wake_up(struct rpc_wait_queue *queue)
{
- struct rpc_task *task;
-
+ struct rpc_task *task, *next;
struct list_head *head;
+
spin_lock_bh(&queue->lock);
head = &queue->tasks[queue->maxpriority];
for (;;) {
- while (!list_empty(head)) {
- task = list_entry(head->next, struct rpc_task, u.tk_wait.list);
+ list_for_each_entry_safe(task, next, head, u.tk_wait.list)
__rpc_wake_up_task(task);
- }
if (head == &queue->tasks[0])
break;
head--;
@@ -541,14 +539,13 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
*/
void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
{
+ struct rpc_task *task, *next;
struct list_head *head;
- struct rpc_task *task;
spin_lock_bh(&queue->lock);
head = &queue->tasks[queue->maxpriority];
for (;;) {
- while (!list_empty(head)) {
- task = list_entry(head->next, struct rpc_task, u.tk_wait.list);
+ list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
task->tk_status = status;
__rpc_wake_up_task(task);
}
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 1b5989b1b67..c323cc6a28b 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -547,7 +547,7 @@ static struct sock * unix_create1(struct socket *sock)
struct sock *sk = NULL;
struct unix_sock *u;
- if (atomic_read(&unix_nr_socks) >= 2*files_stat.max_files)
+ if (atomic_read(&unix_nr_socks) >= 2*get_max_files())
goto out;
sk = sk_alloc(PF_UNIX, GFP_KERNEL, &unix_proto, 1);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 077bbf9fb9b..ae62054a9fc 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -13,7 +13,6 @@
*
*/
-#include <asm/bug.h>
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/kmod.h>
@@ -783,7 +782,7 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
int nx = 0;
int err;
u32 genid;
- u16 family = dst_orig->ops->family;
+ u16 family;
u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
u32 sk_sid = security_sk_sid(sk, fl, dir);
restart:
@@ -797,13 +796,14 @@ restart:
if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
return 0;
- policy = flow_cache_lookup(fl, sk_sid, family, dir,
- xfrm_policy_lookup);
+ policy = flow_cache_lookup(fl, sk_sid, dst_orig->ops->family,
+ dir, xfrm_policy_lookup);
}
if (!policy)
return 0;
+ family = dst_orig->ops->family;
policy->curlft.use_time = (unsigned long)xtime.tv_sec;
switch (policy->action) {
@@ -886,11 +886,11 @@ restart:
* We can't enlist stable bundles either.
*/
write_unlock_bh(&policy->lock);
-
- xfrm_pol_put(policy);
if (dst)
dst_free(dst);
- goto restart;
+
+ err = -EHOSTUNREACH;
+ goto error;
}
dst->next = policy->bundles;
policy->bundles = dst;
@@ -996,13 +996,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
struct sec_decap_state *xvec = &(skb->sp->x[i]);
if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
return 0;
-
- /* If there is a post_input processor, try running it */
- if (xvec->xvec->type->post_input &&
- (xvec->xvec->type->post_input)(xvec->xvec,
- &(xvec->decap),
- skb) != 0)
- return 0;
}
}
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index e12d0be5f97..c656cbaf35e 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -220,14 +220,14 @@ static int __xfrm_state_delete(struct xfrm_state *x)
x->km.state = XFRM_STATE_DEAD;
spin_lock(&xfrm_state_lock);
list_del(&x->bydst);
- atomic_dec(&x->refcnt);
+ __xfrm_state_put(x);
if (x->id.spi) {
list_del(&x->byspi);
- atomic_dec(&x->refcnt);
+ __xfrm_state_put(x);
}
spin_unlock(&xfrm_state_lock);
if (del_timer(&x->timer))
- atomic_dec(&x->refcnt);
+ __xfrm_state_put(x);
/* The number two in this test is the reference
* mentioned in the comment below plus the reference
@@ -243,7 +243,7 @@ static int __xfrm_state_delete(struct xfrm_state *x)
* The xfrm_state_alloc call gives a reference, and that
* is what we are dropping here.
*/
- atomic_dec(&x->refcnt);
+ __xfrm_state_put(x);
err = 0;
}
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index ac87a09ba83..7de17559249 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -345,7 +345,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
if (err < 0) {
x->km.state = XFRM_STATE_DEAD;
- xfrm_state_put(x);
+ __xfrm_state_put(x);
goto out;
}