diff options
| author | Linus Torvalds <torvalds@home.osdl.org> | 2003-12-30 00:06:58 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-12-30 00:06:58 -0800 |
| commit | d027a95f37ec012ca4c8d5e42419c8eb7338dbbf (patch) | |
| tree | db8b856ed3dac472606fd68737e7e3a01f13c073 /net | |
| parent | b2e95563794f81a3b2ccbeffcb59af1090fa00ef (diff) | |
| parent | 09fa6bcea48db8d55e9789585773cf367a899a75 (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.c | 3 | ||||
| -rw-r--r-- | net/bridge/br_netfilter.c | 40 | ||||
| -rw-r--r-- | net/core/dev.c | 2 | ||||
| -rw-r--r-- | net/core/neighbour.c | 4 | ||||
| -rw-r--r-- | net/core/sock.c | 25 | ||||
| -rw-r--r-- | net/core/sysctl_net_core.c | 6 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ipt_recent.c | 4 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ndisc.c | 39 | ||||
| -rw-r--r-- | net/sctp/associola.c | 1 | ||||
| -rw-r--r-- | net/sctp/outqueue.c | 1 | ||||
| -rw-r--r-- | net/sctp/socket.c | 1 | ||||
| -rw-r--r-- | net/sctp/transport.c | 1 | ||||
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 85 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 2 |
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: |
