summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.osdl.org>2003-12-30 00:06:58 -0800
committerLinus Torvalds <torvalds@home.osdl.org>2003-12-30 00:06:58 -0800
commitd027a95f37ec012ca4c8d5e42419c8eb7338dbbf (patch)
treedb8b856ed3dac472606fd68737e7e3a01f13c073 /net
parentb2e95563794f81a3b2ccbeffcb59af1090fa00ef (diff)
parent09fa6bcea48db8d55e9789585773cf367a899a75 (diff)
Merge bk://kernel.bkbits.net/davem/net-2.6
into home.osdl.org:/home/torvalds/v2.5/linux
Diffstat (limited to 'net')
-rw-r--r--net/appletalk/sysctl_net_atalk.c3
-rw-r--r--net/bridge/br_netfilter.c40
-rw-r--r--net/core/dev.c2
-rw-r--r--net/core/neighbour.c4
-rw-r--r--net/core/sock.c25
-rw-r--r--net/core/sysctl_net_core.c6
-rw-r--r--net/ipv4/netfilter/ipt_recent.c4
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/ndisc.c39
-rw-r--r--net/sctp/associola.c1
-rw-r--r--net/sctp/outqueue.c1
-rw-r--r--net/sctp/socket.c1
-rw-r--r--net/sctp/transport.c1
-rw-r--r--net/xfrm/xfrm_policy.c85
-rw-r--r--net/xfrm/xfrm_state.c2
15 files changed, 141 insertions, 75 deletions
diff --git a/net/appletalk/sysctl_net_atalk.c b/net/appletalk/sysctl_net_atalk.c
index edddd3291f70..25b33f670499 100644
--- a/net/appletalk/sysctl_net_atalk.c
+++ b/net/appletalk/sysctl_net_atalk.c
@@ -23,6 +23,7 @@ static struct ctl_table atalk_table[] = {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_ATALK_AARP_TICK_TIME,
@@ -31,6 +32,7 @@ static struct ctl_table atalk_table[] = {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_ATALK_AARP_RETRANSMIT_LIMIT,
@@ -47,6 +49,7 @@ static struct ctl_table atalk_table[] = {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{ 0 },
};
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 932f3ae2bbea..359555cd35b6 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -356,6 +356,7 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
return NF_ACCEPT;
}
+
/* PF_BRIDGE/FORWARD *************************************************/
static int br_nf_forward_finish(struct sk_buff *skb)
{
@@ -466,6 +467,7 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
return NF_STOLEN;
}
+
/* PF_BRIDGE/LOCAL_OUT ***********************************************/
static int br_nf_local_out_finish(struct sk_buff *skb)
{
@@ -531,9 +533,7 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
return NF_ACCEPT;
nf_bridge = skb->nf_bridge;
-
nf_bridge->physoutdev = skb->dev;
-
realindev = nf_bridge->physindev;
/* Bridged, take PF_BRIDGE/FORWARD.
@@ -601,18 +601,15 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
struct net_device *realoutdev = bridge_parent(skb->dev);
- /* Be very paranoid. Must be a device driver bug. */
+#ifdef CONFIG_NETFILTER_DEBUG
+ /* Be very paranoid. This probably won't happen anymore, but let's
+ * keep the check just to be sure... */
if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) {
printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: "
"bad mac.raw pointer.");
- if (skb->dev != NULL) {
- printk("[%s]", skb->dev->name);
- if (has_bridge_parent(skb->dev))
- printk("[%s]", bridge_parent(skb->dev)->name);
- }
- printk(" head:%p, raw:%p\n", skb->head, skb->mac.raw);
- return NF_ACCEPT;
+ goto print_error;
}
+#endif
#ifdef CONFIG_SYSCTL
if (!nf_bridge)
@@ -622,13 +619,16 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
return NF_ACCEPT;
+#ifdef CONFIG_NETFILTER_DEBUG
/* Sometimes we get packets with NULL ->dst here (for example,
- * running a dhcp client daemon triggers this).
+ * running a dhcp client daemon triggers this). This should now
+ * be fixed, but let's keep the check around.
*/
- if (skb->dst == NULL)
- return NF_ACCEPT;
+ if (skb->dst == NULL) {
+ printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
+ goto print_error;
+ }
-#ifdef CONFIG_NETFILTER_DEBUG
skb->nf_debug ^= (1 << NF_IP_POST_ROUTING);
#endif
@@ -655,6 +655,18 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
realoutdev, br_dev_queue_push_xmit);
return NF_STOLEN;
+
+#ifdef CONFIG_NETFILTER_DEBUG
+print_error:
+ if (skb->dev != NULL) {
+ printk("[%s]", skb->dev->name);
+ if (has_bridge_parent(skb->dev))
+ printk("[%s]", bridge_parent(skb->dev)->name);
+ }
+ printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw,
+ skb->data);
+ return NF_ACCEPT;
+#endif
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 47fff21ea3b2..30cba1e1c633 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1543,7 +1543,7 @@ static inline int __handle_bridge(struct sk_buff *skb,
struct packet_type **pt_prev, int *ret)
{
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
- if (skb->dev->br_port) {
+ if (skb->dev->br_port && skb->pkt_type != PACKET_LOOPBACK) {
*ret = handle_bridge(skb, *pt_prev);
if (br_handle_frame_hook(skb) == 0)
return 1;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 247b6d6e661d..4b194b6be05a 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1518,6 +1518,7 @@ struct neigh_sysctl_table {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_NEIGH_DELAY_PROBE_TIME,
@@ -1525,6 +1526,7 @@ struct neigh_sysctl_table {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_NEIGH_GC_STALE_TIME,
@@ -1532,6 +1534,7 @@ struct neigh_sysctl_table {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_NEIGH_UNRES_QLEN,
@@ -1574,6 +1577,7 @@ struct neigh_sysctl_table {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_NEIGH_GC_THRESH1,
diff --git a/net/core/sock.c b/net/core/sock.c
index 9d51516eaa56..d549d519482d 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1119,6 +1119,31 @@ void sock_init_data(struct socket *sock, struct sock *sk)
atomic_set(&sk->sk_refcnt, 1);
}
+void lock_sock(struct sock *sk)
+{
+ might_sleep();
+ spin_lock_bh(&(sk->sk_lock.slock));
+ if (sk->sk_lock.owner)
+ __lock_sock(sk);
+ sk->sk_lock.owner = (void *)1;
+ spin_unlock_bh(&(sk->sk_lock.slock));
+}
+
+EXPORT_SYMBOL(lock_sock);
+
+void release_sock(struct sock *sk)
+{
+ spin_lock_bh(&(sk->sk_lock.slock));
+ if (sk->sk_backlog.tail)
+ __release_sock(sk);
+ sk->sk_lock.owner = NULL;
+ if (waitqueue_active(&(sk->sk_lock.wq)))
+ wake_up(&(sk->sk_lock.wq));
+ spin_unlock_bh(&(sk->sk_lock.slock));
+}
+
+EXPORT_SYMBOL(release_sock);
+
EXPORT_SYMBOL(__lock_sock);
EXPORT_SYMBOL(__release_sock);
EXPORT_SYMBOL(sk_alloc);
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 46c0c78b196d..642ef77a2824 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -146,7 +146,8 @@ ctl_table core_table[] = {
.data = &net_msg_cost,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_jiffies
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_CORE_MSG_BURST,
@@ -154,7 +155,8 @@ ctl_table core_table[] = {
.data = &net_msg_burst,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_jiffies
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_CORE_OPTMEM_MAX,
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 3e03fe295529..eda86a22accd 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -91,8 +91,10 @@ static struct recent_ip_tables *r_tables = NULL;
*/
static spinlock_t recent_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_PROC_FS
/* Our /proc/net/ipt_recent entry */
static struct proc_dir_entry *proc_net_ipt_recent = NULL;
+#endif
/* Function declaration for later. */
static int
@@ -959,8 +961,10 @@ static int __init init(void)
int count;
printk(version);
+#ifdef CONFIG_PROC_FS
proc_net_ipt_recent = proc_mkdir("ipt_recent",proc_net);
if(!proc_net_ipt_recent) return -ENOMEM;
+#endif
if(ip_list_hash_size && ip_list_hash_size <= ip_list_tot) {
printk(KERN_WARNING RECENT_NAME ": ip_list_hash_size too small, resetting to default.\n");
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b08ba41c5356..0d4b1688a801 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2946,6 +2946,7 @@ static struct addrconf_sysctl_table
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_IPV6_RTR_SOLICIT_DELAY,
@@ -2954,6 +2955,7 @@ static struct addrconf_sysctl_table
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
#ifdef CONFIG_IPV6_PRIVACY
{
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0309a24a367e..f2e7c8bb7fe9 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -75,6 +75,9 @@
#include <net/checksum.h>
#include <linux/proc_fs.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
+
static struct socket *ndisc_socket;
static u32 ndisc_hash(const void *pkey, const struct net_device *dev);
@@ -497,10 +500,11 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
skb->dst = dst;
idev = in6_dev_get(dst->dev);
- dst_output(skb);
-
- ICMP6_INC_STATS(idev, Icmp6OutNeighborAdvertisements);
- ICMP6_INC_STATS(idev, Icmp6OutMsgs);
+ err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
+ if (!err) {
+ ICMP6_INC_STATS(idev, Icmp6OutNeighborAdvertisements);
+ ICMP6_INC_STATS(idev, Icmp6OutMsgs);
+ }
if (likely(idev != NULL))
in6_dev_put(idev);
@@ -576,10 +580,11 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
/* send it! */
skb->dst = dst;
idev = in6_dev_get(dst->dev);
- dst_output(skb);
-
- ICMP6_INC_STATS(idev, Icmp6OutNeighborSolicits);
- ICMP6_INC_STATS(idev, Icmp6OutMsgs);
+ err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
+ if (!err) {
+ ICMP6_INC_STATS(idev, Icmp6OutNeighborSolicits);
+ ICMP6_INC_STATS(idev, Icmp6OutMsgs);
+ }
if (likely(idev != NULL))
in6_dev_put(idev);
@@ -644,10 +649,11 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
/* send it! */
skb->dst = dst;
idev = in6_dev_get(dst->dev);
- dst_output(skb);
-
- ICMP6_INC_STATS(idev, Icmp6OutRouterSolicits);
- ICMP6_INC_STATS(idev, Icmp6OutMsgs);
+ err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
+ if (!err) {
+ ICMP6_INC_STATS(idev, Icmp6OutRouterSolicits);
+ ICMP6_INC_STATS(idev, Icmp6OutMsgs);
+ }
if (likely(idev != NULL))
in6_dev_put(idev);
@@ -1404,10 +1410,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
buff->dst = dst;
idev = in6_dev_get(dst->dev);
- dst_output(buff);
-
- ICMP6_INC_STATS(idev, Icmp6OutRedirects);
- ICMP6_INC_STATS(idev, Icmp6OutMsgs);
+ err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
+ if (!err) {
+ ICMP6_INC_STATS(idev, Icmp6OutRedirects);
+ ICMP6_INC_STATS(idev, Icmp6OutMsgs);
+ }
if (likely(idev != NULL))
in6_dev_put(idev);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index dba3d149e499..44b30efb17a9 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -58,6 +58,7 @@
#include <linux/in.h>
#include <net/ipv6.h>
#include <net/sctp/sctp.h>
+#include <net/sctp/sm.h>
/* Forward declarations for internal functions. */
static void sctp_assoc_bh_rcv(struct sctp_association *asoc);
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index d26292af9ff1..dc4cb1a5a739 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -53,6 +53,7 @@
#include <net/sock.h> /* For skb_set_owner_w */
#include <net/sctp/sctp.h>
+#include <net/sctp/sm.h>
/* Declare internal functions here. */
static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 0ac8c9bf5363..36b2ec11a3a8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -77,6 +77,7 @@
#include <linux/socket.h> /* for sa_family_t */
#include <net/sock.h>
#include <net/sctp/sctp.h>
+#include <net/sctp/sm.h>
/* WARNING: Please do not remove the SCTP_STATIC attribute to
* any of the functions below as they are used to export functions
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 485d77015399..026ffebb61d4 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -50,6 +50,7 @@
#include <linux/types.h>
#include <net/sctp/sctp.h>
+#include <net/sctp/sm.h>
/* 1st Level Abstractions. */
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 85f626d20c4a..0f970906c9ef 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -19,6 +19,8 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
+#include <linux/notifier.h>
+#include <linux/netdevice.h>
#include <net/xfrm.h>
#include <net/ip.h>
@@ -690,6 +692,8 @@ static inline int policy_to_flow_dir(int dir)
};
}
+static int stale_bundle(struct dst_entry *dst);
+
/* Main function: finds/creates a bundle for given flow.
*
* At the moment we eat a raw IP route. Mostly to speed up lookups
@@ -814,10 +818,11 @@ restart:
}
write_lock_bh(&policy->lock);
- if (unlikely(policy->dead)) {
+ if (unlikely(policy->dead || stale_bundle(dst))) {
/* Wow! While we worked on resolving, this
* policy has gone. Retry. It is not paranoia,
* we just cannot enlist new bundle to dead object.
+ * We can't enlist stable bundles either.
*/
write_unlock_bh(&policy->lock);
@@ -985,18 +990,27 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
{
+ if (!stale_bundle(dst))
+ return dst;
+
+ dst_release(dst);
+ return NULL;
+}
+
+static int stale_bundle(struct dst_entry *dst)
+{
struct dst_entry *child = dst;
while (child) {
if (child->obsolete > 0 ||
+ (child->dev && !netif_running(child->dev)) ||
(child->xfrm && child->xfrm->km.state != XFRM_STATE_VALID)) {
- dst_release(dst);
- return NULL;
+ return 1;
}
child = child->child;
}
- return dst;
+ return 0;
}
static void xfrm_dst_destroy(struct dst_entry *dst)
@@ -1022,7 +1036,7 @@ static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst)
return dst;
}
-static void __xfrm_garbage_collect(void)
+static void xfrm_prune_bundles(int (*func)(struct dst_entry *))
{
int i;
struct xfrm_policy *pol;
@@ -1034,7 +1048,7 @@ static void __xfrm_garbage_collect(void)
write_lock(&pol->lock);
dstp = &pol->bundles;
while ((dst=*dstp) != NULL) {
- if (atomic_read(&dst->__refcnt) == 0) {
+ if (func(dst)) {
*dstp = dst->next;
dst->next = gc_list;
gc_list = dst;
@@ -1054,46 +1068,19 @@ static void __xfrm_garbage_collect(void)
}
}
-static int bundle_depends_on(struct dst_entry *dst, struct xfrm_state *x)
+static int unused_bundle(struct dst_entry *dst)
{
- do {
- if (dst->xfrm == x)
- return 1;
- } while ((dst = dst->child) != NULL);
- return 0;
+ return !atomic_read(&dst->__refcnt);
}
-int xfrm_flush_bundles(struct xfrm_state *x)
+static void __xfrm_garbage_collect(void)
{
- int i;
- struct xfrm_policy *pol;
- struct dst_entry *dst, **dstp, *gc_list = NULL;
-
- read_lock_bh(&xfrm_policy_lock);
- for (i=0; i<2*XFRM_POLICY_MAX; i++) {
- for (pol = xfrm_policy_list[i]; pol; pol = pol->next) {
- write_lock(&pol->lock);
- dstp = &pol->bundles;
- while ((dst=*dstp) != NULL) {
- if (bundle_depends_on(dst, x)) {
- *dstp = dst->next;
- dst->next = gc_list;
- gc_list = dst;
- } else {
- dstp = &dst->next;
- }
- }
- write_unlock(&pol->lock);
- }
- }
- read_unlock_bh(&xfrm_policy_lock);
-
- while (gc_list) {
- dst = gc_list;
- gc_list = dst->next;
- dst_free(dst);
- }
+ xfrm_prune_bundles(unused_bundle);
+}
+int xfrm_flush_bundles(void)
+{
+ xfrm_prune_bundles(stale_bundle);
return 0;
}
@@ -1216,6 +1203,21 @@ void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
read_unlock(&afinfo->lock);
}
+static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ switch (event) {
+ case NETDEV_DOWN:
+ xfrm_flush_bundles();
+ }
+ return NOTIFY_DONE;
+}
+
+struct notifier_block xfrm_dev_notifier = {
+ xfrm_dev_event,
+ NULL,
+ 0
+};
+
void __init xfrm_policy_init(void)
{
xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache",
@@ -1226,6 +1228,7 @@ void __init xfrm_policy_init(void)
panic("XFRM: failed to allocate xfrm_dst_cache\n");
INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL);
+ register_netdevice_notifier(&xfrm_dev_notifier);
}
void __init xfrm_init(void)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index ab1c1ec1aa12..dc70df79f9cb 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -219,7 +219,7 @@ static void __xfrm_state_delete(struct xfrm_state *x)
* there are DSTs attached to this xfrm_state.
*/
if (atomic_read(&x->refcnt) > 2)
- xfrm_flush_bundles(x);
+ xfrm_flush_bundles();
/* All xfrm_state objects are created by one of two possible
* paths: