diff options
Diffstat (limited to 'net')
68 files changed, 1150 insertions, 623 deletions
diff --git a/net/802/llc_macinit.c b/net/802/llc_macinit.c index 792bfd5e8..987d8a5c4 100644 --- a/net/802/llc_macinit.c +++ b/net/802/llc_macinit.c @@ -204,24 +204,11 @@ EXPORT_SYMBOL(llc_cancel_timers); #define ALL_TYPES_8022 0 -void __init llc_init(struct net_proto *proto) +static int __init llc_init(void) { printk(KERN_NOTICE "IEEE 802.2 LLC for Linux 2.1 (c) 1996 Tim Alpaerts\n"); - return; -} - -#ifdef MODULE - - -int init_module(void) -{ - llc_init(NULL); return 0; } -void cleanup_module(void) -{ - -} -#endif +module_init(llc_init); diff --git a/net/802/p8022.c b/net/802/p8022.c index 9be3100dd..41a755e88 100644 --- a/net/802/p8022.c +++ b/net/802/p8022.c @@ -90,12 +90,15 @@ static struct packet_type p8022_packet_type = EXPORT_SYMBOL(register_8022_client); EXPORT_SYMBOL(unregister_8022_client); -void __init p8022_proto_init(struct net_proto *pro) +static int __init p8022_init(void) { p8022_packet_type.type=htons(ETH_P_802_2); dev_add_pack(&p8022_packet_type); + return 0; } +module_init(p8022_init); + struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *)) { struct datalink_proto *proto; diff --git a/net/802/psnap.c b/net/802/psnap.c index 3c493d7d9..907ac1b54 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -89,12 +89,14 @@ static void snap_datalink_header(struct datalink_proto *dl, struct sk_buff *skb, EXPORT_SYMBOL(register_snap_client); EXPORT_SYMBOL(unregister_snap_client); -void __init snap_proto_init(struct net_proto *pro) +static int __init snap_init(void) { snap_dl=register_8022_client(0xAA, snap_rcv); if(snap_dl==NULL) printk("SNAP - unable to register with 802.2\n"); + return 0; } +module_init(snap_init); /* * Register SNAP clients. We don't yet use this for IP. diff --git a/net/802/tr.c b/net/802/tr.c index 097929257..73c938486 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -540,7 +540,7 @@ static int rif_get_info(char *buffer,char **start, off_t offset, int length) * too much for this. */ -void __init rif_init(struct net_proto *unused) +static int __init rif_init(void) { rif_timer.expires = RIF_TIMEOUT; rif_timer.data = 0L; @@ -549,4 +549,7 @@ void __init rif_init(struct net_proto *unused) add_timer(&rif_timer); proc_net_create("tr_rif",0,rif_get_info); + return 0; } + +module_init(rif_init); diff --git a/net/Config.in b/net/Config.in index f383bbbd2..4d4f6c373 100644 --- a/net/Config.in +++ b/net/Config.in @@ -63,6 +63,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25 tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC + bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT # if [ "$CONFIG_LLC" = "y" ]; then # bool ' Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI # fi diff --git a/net/Makefile b/net/Makefile index 44f47fabc..ff79d8584 100644 --- a/net/Makefile +++ b/net/Makefile @@ -7,7 +7,7 @@ O_TARGET := network.o -mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm +mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm netlink export-objs := netsyms.o subdir-y := core ethernet @@ -46,7 +46,7 @@ subdir-$(CONFIG_DECNET) += decnet subdir-$(CONFIG_ECONET) += econet -obj-y := socket.o protocols.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y)))) +obj-y := socket.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y)))) ifeq ($(CONFIG_NET),y) obj-$(CONFIG_MODULES) += netsyms.o obj-$(CONFIG_SYSCTL) += sysctl_net.o diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 260a5e530..e7784dabd 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -2120,7 +2120,7 @@ EXPORT_SYMBOL(atalk_find_dev_addr); /* Called by proto.c on kernel start up */ -void __init atalk_proto_init(struct net_proto *pro) +static int __init atalk_init(void) { (void) sock_register(&atalk_family_ops); if((ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv)) == NULL) @@ -2148,16 +2148,11 @@ void __init atalk_proto_init(struct net_proto *pro) #endif /* CONFIG_SYSCTL */ printk(KERN_INFO "NET4: AppleTalk 0.18 for Linux NET4.0\n"); + return 0; } +module_init(atalk_init); #ifdef MODULE - -int init_module(void) -{ - atalk_proto_init(NULL); - return (0); -} - /* * Note on MOD_{INC,DEC}_USE_COUNT: * @@ -2171,7 +2166,7 @@ int init_module(void) * sockets be closed from user space. */ -void cleanup_module(void) +static void __exit atalk_exit(void) { #ifdef CONFIG_SYSCTL atalk_unregister_sysctl(); @@ -2195,6 +2190,7 @@ void cleanup_module(void) return; } - +module_exit(atalk_exit); #endif /* MODULE */ + #endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */ diff --git a/net/atm/pvc.c b/net/atm/pvc.c index fc71c2435..ff28ed551 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -123,7 +123,7 @@ static struct net_proto_family pvc_family_ops = { */ -void __init atmpvc_proto_init(struct net_proto *pro) +static int __init atmpvc_init(void) { int error; @@ -139,4 +139,7 @@ void __init atmpvc_proto_init(struct net_proto *pro) error = atm_proc_init(); if (error) printk("atm_proc_init fails with %d\n",error); #endif + return 0; } + +module_init(atmpvc_init); diff --git a/net/atm/svc.c b/net/atm/svc.c index bffe7aac5..7984cb22a 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -442,10 +442,13 @@ static struct net_proto_family svc_family_ops = { * Initialize the ATM SVC protocol family */ -void __init atmsvc_proto_init(struct net_proto *pro) +static int __init atmsvc_init(void) { if (sock_register(&svc_family_ops) < 0) { printk(KERN_ERR "ATMSVC: can't register"); - return; + return -1; } + return 0; } + +module_init(atmsvc_init); diff --git a/net/ax25/Config.in b/net/ax25/Config.in index 2670528b3..b8e5d7333 100644 --- a/net/ax25/Config.in +++ b/net/ax25/Config.in @@ -3,7 +3,7 @@ # # 19971130 Now in an own category to make correct compilation of the # AX.25 stuff easier... -# Joerg Reuter DL1BKE <jreuter@poboxes.com> +# Joerg Reuter DL1BKE <jreuter@yaina.de> # 19980129 Moved to net/ax25/Config.in, sourcing device drivers. mainmenu_option next_comment diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index fc8910f2d..8e34e42e2 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -101,6 +101,7 @@ * ax25_connect() and ax25_sendmsg() * Joerg(DL1BKE) Added support for SO_BINDTODEVICE * Arnaldo C. Melo s/suser/capable(CAP_NET_ADMIN)/, some more cleanups + * Michal Ostrowski Module initialization cleanup. */ #include <linux/config.h> @@ -137,6 +138,8 @@ #include <net/ip.h> #include <net/arp.h> + + ax25_cb *volatile ax25_list = NULL; static struct proto_ops ax25_proto_ops; @@ -1193,7 +1196,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le */ if (sk->zapped) { /* check if we can remove this feature. It is broken. */ - printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@poboxes.com\n", + printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@yaina.de\n", current->comm); if ((err = ax25_rt_autobind(sk->protinfo.ax25, &fsa->fsa_ax25.sax25_call)) < 0) return err; @@ -1844,7 +1847,7 @@ EXPORT_SYMBOL(asc2ax); EXPORT_SYMBOL(null_ax25_address); EXPORT_SYMBOL(ax25_display_timer); -void __init ax25_proto_init(struct net_proto *pro) +static int __init ax25_init(void) { sock_register(&ax25_family_ops); ax25_packet_type.type = htons(ETH_P_AX25); @@ -1861,20 +1864,16 @@ void __init ax25_proto_init(struct net_proto *pro) #endif printk(KERN_INFO "NET4: G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET4.0\n"); + return 0; } +module_init(ax25_init); + #ifdef MODULE MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>"); MODULE_DESCRIPTION("The amateur radio AX.25 link layer protocol"); -int init_module(void) -{ - ax25_proto_init(NULL); - - return 0; -} - -void cleanup_module(void) +static void __exit ax25_exit(void) { #ifdef CONFIG_PROC_FS proc_net_remove("ax25_route"); @@ -1895,6 +1894,7 @@ void cleanup_module(void) sock_unregister(PF_AX25); } -#endif +module_exit(ax25_exit); +#endif /* MODULE */ #endif diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c index 464122823..3354206df 100644 --- a/net/ax25/ax25_ds_in.c +++ b/net/ax25/ax25_ds_in.c @@ -89,10 +89,8 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet ax25_dama_on(ax25); /* according to DK4EG´s spec we are required to - * send a RR RESPONSE FINAL NR=0. Please mail - * <jreuter@poboxes.com> if this causes problems - * with the TheNetNode DAMA Master implementation. - */ + * send a RR RESPONSE FINAL NR=0. + */ ax25_std_enquiry_response(ax25); break; diff --git a/net/bridge/br.c b/net/bridge/br.c index 3c6c9b72d..cda2e570a 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br.c,v 1.44 2000/08/04 06:08:32 davem Exp $ + * $Id: br.c,v 1.45 2000/10/22 18:26:07 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -38,7 +38,7 @@ void br_inc_use_count() MOD_INC_USE_COUNT; } -int __init br_init(void) +static int __init br_init(void) { printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 86355509d..295cfc973 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_if.c,v 1.3 2000/05/05 02:17:17 davem Exp $ + * $Id: br_if.c,v 1.4 2000/10/05 01:58:16 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -14,6 +14,7 @@ */ #include <linux/kernel.h> +#include <linux/if_arp.h> #include <linux/if_bridge.h> #include <linux/inetdevice.h> #include <linux/rtnetlink.h> @@ -222,7 +223,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (dev->br_port != NULL) return -EBUSY; - if (dev->flags & IFF_LOOPBACK) + if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER) return -EINVAL; dev_hold(dev); diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index dad96fb99..4d04aec66 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_ioctl.c,v 1.2 2000/02/21 15:51:34 davem Exp $ + * $Id: br_ioctl.c,v 1.3 2000/10/05 01:58:16 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -138,7 +138,7 @@ static int br_ioctl_device(struct net_bridge *br, p.hold_timer_value = br_timer_get_residue(&pt->hold_timer); if (copy_to_user((void *)arg0, &p, sizeof(p))) - return -EINVAL; + return -EFAULT; return 0; } diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h index 91faafff5..2857d5c91 100644 --- a/net/bridge/br_private_stp.h +++ b/net/bridge/br_private_stp.h @@ -4,7 +4,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_private_stp.h,v 1.1 2000/02/18 16:47:13 davem Exp $ + * $Id: br_private_stp.h,v 1.2 2000/10/30 22:03:20 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -16,7 +16,7 @@ #define _BR_PRIVATE_STP_H #define BPDU_TYPE_CONFIG 0 -#define BPDU_TYPE_TCN 1 +#define BPDU_TYPE_TCN 0x80 struct br_config_bpdu { diff --git a/net/core/Makefile b/net/core/Makefile index 7ee0db3fd..af3c74091 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -29,6 +29,10 @@ ifdef CONFIG_NETFILTER OX_OBJS += netfilter.o endif +ifeq ($(CONFIG_NET_DIVERT),y) +O_OBJS += dv.o +endif + endif ifdef CONFIG_NET_PROFILE diff --git a/net/core/dev.c b/net/core/dev.c index e6f440cf4..17fae7a1e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -59,6 +59,8 @@ * Paul Rusty Russell : SIOCSIFNAME * Pekka Riikonen : Netdev boot-time settings code * Andrew Morton : Make unregister_netdevice wait indefinitely on dev->refcnt + * J Hadi Salim : - Backlog queue sampling + * - netif_rx() feedback */ #include <asm/uaccess.h> @@ -85,6 +87,7 @@ #include <linux/proc_fs.h> #include <linux/stat.h> #include <linux/if_bridge.h> +#include <linux/divert.h> #include <net/dst.h> #include <net/pkt_sched.h> #include <net/profile.h> @@ -97,6 +100,18 @@ extern int plip_init(void); #endif +/* This define, if set, will randomly drop a packet when congestion + * is more than moderate. It helps fairness in the multi-interface + * case when one of them is a hog, but it kills performance for the + * single interface case so it is off now by default. + */ +#undef RAND_LIE + +/* Setting this will sample the queue lengths and thus congestion + * via a timer instead of as each packet is received. + */ +#undef OFFLINE_SAMPLE + NET_PROFILE_DEFINE(dev_queue_xmit) NET_PROFILE_DEFINE(softnet_process) @@ -133,6 +148,11 @@ const char *if_port_text[] = { static struct packet_type *ptype_base[16]; /* 16 way hashed list */ static struct packet_type *ptype_all = NULL; /* Taps */ +#ifdef OFFLINE_SAMPLE +static void sample_queue(unsigned long dummy); +static struct timer_list samp_timer = { function: sample_queue }; +#endif + /* * Our notifier list */ @@ -933,12 +953,20 @@ int dev_queue_xmit(struct sk_buff *skb) =======================================================================*/ int netdev_max_backlog = 300; +/* These numbers are selected based on intuition and some + * experimentatiom, if you have more scientific way of doing this + * please go ahead and fix things. + */ +int no_cong_thresh = 10; +int no_cong = 20; +int lo_cong = 100; +int mod_cong = 290; struct netif_rx_stats netdev_rx_stat[NR_CPUS]; #ifdef CONFIG_NET_HW_FLOWCONTROL -static atomic_t netdev_dropping = ATOMIC_INIT(0); +atomic_t netdev_dropping = ATOMIC_INIT(0); static unsigned long netdev_fc_mask = 1; unsigned long netdev_fc_xoff = 0; spinlock_t netdev_fc_lock = SPIN_LOCK_UNLOCKED; @@ -996,6 +1024,56 @@ static void netdev_wakeup(void) } #endif +static void get_sample_stats(int cpu) +{ +#ifdef RAND_LIE + unsigned long rd; + int rq; +#endif + int blog = softnet_data[cpu].input_pkt_queue.qlen; + int avg_blog = softnet_data[cpu].avg_blog; + + avg_blog = (avg_blog >> 1)+ (blog >> 1); + + if (avg_blog > mod_cong) { + /* Above moderate congestion levels. */ + softnet_data[cpu].cng_level = NET_RX_CN_HIGH; +#ifdef RAND_LIE + rd = net_random(); + rq = rd % netdev_max_backlog; + if (rq < avg_blog) /* unlucky bastard */ + softnet_data[cpu].cng_level = NET_RX_DROP; +#endif + } else if (avg_blog > lo_cong) { + softnet_data[cpu].cng_level = NET_RX_CN_MOD; +#ifdef RAND_LIE + rd = net_random(); + rq = rd % netdev_max_backlog; + if (rq < avg_blog) /* unlucky bastard */ + softnet_data[cpu].cng_level = NET_RX_CN_HIGH; +#endif + } else if (avg_blog > no_cong) + softnet_data[cpu].cng_level = NET_RX_CN_LOW; + else /* no congestion */ + softnet_data[cpu].cng_level = NET_RX_SUCCESS; + + softnet_data[cpu].avg_blog = avg_blog; +} + +#ifdef OFFLINE_SAMPLE +static void sample_queue(unsigned long dummy) +{ +/* 10 ms 0r 1ms -- i dont care -- JHS */ + int next_tick = 1; + int cpu = smp_processor_id(); + + get_sample_stats(cpu); + next_tick += jiffies; + mod_timer(&samp_timer, next_tick); +} +#endif + + /** * netif_rx - post buffer to the network code * @skb: buffer to post @@ -1004,9 +1082,18 @@ static void netdev_wakeup(void) * the upper (protocol) levels to process. It always succeeds. The buffer * may be dropped during processing for congestion control or by the * protocol layers. + * + * return values: + * NET_RX_SUCCESS (no congestion) + * NET_RX_CN_LOW (low congestion) + * NET_RX_CN_MOD (moderate congestion) + * NET_RX_CN_HIGH (high congestion) + * NET_RX_DROP (packet was dropped) + * + * */ -void netif_rx(struct sk_buff *skb) +int netif_rx(struct sk_buff *skb) { int this_cpu = smp_processor_id(); struct softnet_data *queue; @@ -1036,7 +1123,10 @@ enqueue: __skb_queue_tail(&queue->input_pkt_queue,skb); __cpu_raise_softirq(this_cpu, NET_RX_SOFTIRQ); local_irq_restore(flags); - return; +#ifndef OFFLINE_SAMPLE + get_sample_stats(this_cpu); +#endif + return softnet_data[this_cpu].cng_level; } if (queue->throttle) { @@ -1062,19 +1152,22 @@ drop: local_irq_restore(flags); kfree_skb(skb); + return NET_RX_DROP; } /* Deliver skb to an old protocol, which is not threaded well or which do not understand shared skbs. */ -static void deliver_to_old_ones(struct packet_type *pt, struct sk_buff *skb, int last) +static int deliver_to_old_ones(struct packet_type *pt, struct sk_buff *skb, int last) { static spinlock_t net_bh_lock = SPIN_LOCK_UNLOCKED; + int ret = NET_RX_DROP; + if (!last) { skb = skb_clone(skb, GFP_ATOMIC); if (skb == NULL) - return; + return ret; } /* The assumption (correct one) is that old protocols @@ -1087,10 +1180,11 @@ static void deliver_to_old_ones(struct packet_type *pt, struct sk_buff *skb, int /* Disable timers and wait for all timers completion */ tasklet_disable(bh_task_vec+TIMER_BH); - pt->func(skb, skb->dev, pt); + ret = pt->func(skb, skb->dev, pt); tasklet_enable(bh_task_vec+TIMER_BH); spin_unlock(&net_bh_lock); + return ret; } /* Reparent skb to master device. This function is called @@ -1173,22 +1267,35 @@ void net_call_rx_atomic(void (*fn)(void)) void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; #endif -static void __inline__ handle_bridge(struct sk_buff *skb, +static int __inline__ handle_bridge(struct sk_buff *skb, struct packet_type *pt_prev) { + int ret = NET_RX_DROP; + if (pt_prev) { if (!pt_prev->data) - deliver_to_old_ones(pt_prev, skb, 0); + ret = deliver_to_old_ones(pt_prev, skb, 0); else { atomic_inc(&skb->users); - pt_prev->func(skb, skb->dev, pt_prev); + ret = pt_prev->func(skb, skb->dev, pt_prev); } } br_handle_frame_hook(skb); + return ret; } +#ifdef CONFIG_NET_DIVERT +static inline void handle_diverter(struct sk_buff *skb) +{ + /* if diversion is supported on device, then divert */ + if (skb->dev->divert && skb->dev->divert->divert) + divert_frame(skb); +} +#endif /* CONFIG_NET_DIVERT */ + + static void net_rx_action(struct softirq_action *h) { int this_cpu = smp_processor_id(); @@ -1239,6 +1346,12 @@ static void net_rx_action(struct softirq_action *h) } } +#ifdef CONFIG_NET_DIVERT + if (skb->dev->divert && skb->dev->divert->divert) + handle_diverter(skb); +#endif /* CONFIG_NET_DIVERT */ + + #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) if (skb->dev->br_port != NULL && br_handle_frame_hook != NULL) { @@ -1275,6 +1388,17 @@ static void net_rx_action(struct softirq_action *h) if (bugdet-- < 0 || jiffies - start_time > 1) goto softnet_break; + +#ifdef CONFIG_NET_HW_FLOWCONTROL + if (queue->throttle && queue->input_pkt_queue.qlen < no_cong_thresh ) { + if (atomic_dec_and_test(&netdev_dropping)) { + queue->throttle = 0; + netdev_wakeup(); + goto softnet_break; + } + } +#endif + } br_read_unlock(BR_NETPROTO_LOCK); @@ -2113,9 +2237,9 @@ int dev_ioctl(unsigned int cmd, void *arg) /** * dev_new_index - allocate an ifindex * - * Returns a suitable unique value for a new device interface number. - * The caller must hold the rtnl semaphore to be sure it remains - * unique. + * Returns a suitable unique value for a new device interface + * number. The caller must hold the rtnl semaphore or the + * dev_base_lock to be sure it remains unique. */ int dev_new_index(void) @@ -2140,6 +2264,10 @@ static int dev_boot_phase = 1; * chain. 0 is returned on success. A negative errno code is returned * on a failure to set up the device, or if the name is a duplicate. * + * Callers must hold the rtnl semaphore. See the comment at the + * end of Space.c for details about the locking. You may want + * register_netdev() instead of this. + * * BUGS: * The locking appears insufficient to guarantee two parallel registers * will not get the same name. @@ -2148,6 +2276,9 @@ static int dev_boot_phase = 1; int register_netdevice(struct net_device *dev) { struct net_device *d, **dp; +#ifdef CONFIG_NET_DIVERT + int ret; +#endif spin_lock_init(&dev->queue_lock); spin_lock_init(&dev->xmit_lock); @@ -2182,6 +2313,12 @@ int register_netdevice(struct net_device *dev) dev_hold(dev); write_unlock_bh(&dev_base_lock); +#ifdef CONFIG_NET_DIVERT + ret = alloc_divert_blk(dev); + if (ret) + return ret; +#endif /* CONFIG_NET_DIVERT */ + /* * Default initial state at registry is that the * device is present. @@ -2231,6 +2368,12 @@ int register_netdevice(struct net_device *dev) dev->deadbeaf = 0; write_unlock_bh(&dev_base_lock); +#ifdef CONFIG_NET_DIVERT + ret = alloc_divert_blk(dev); + if (ret) + return ret; +#endif /* CONFIG_NET_DIVERT */ + /* Notify protocols, that a new device appeared. */ notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); @@ -2272,6 +2415,10 @@ int netdev_finish_unregister(struct net_device *dev) * This function shuts down a device interface and removes it * from the kernel tables. On success 0 is returned, on a failure * a negative errno code is returned. + * + * Callers must hold the rtnl semaphore. See the comment at the + * end of Space.c for details about the locking. You may want + * unregister_netdev() instead of this. */ int unregister_netdevice(struct net_device *dev) @@ -2325,6 +2472,10 @@ int unregister_netdevice(struct net_device *dev) /* Notifier chain MUST detach us from master device. */ BUG_TRAP(dev->master==NULL); +#ifdef CONFIG_NET_DIVERT + free_divert_blk(dev); +#endif + if (dev->new_style) { #ifdef NET_REFCNT_DEBUG if (atomic_read(&dev->refcnt) != 1) @@ -2397,7 +2548,15 @@ int unregister_netdevice(struct net_device *dev) extern void net_device_init(void); extern void ip_auto_config(void); +#ifdef CONFIG_NET_DIVERT +extern void dv_init(void); +#endif /* CONFIG_NET_DIVERT */ + +/* + * Callers must hold the rtnl semaphore. See the comment at the + * end of Space.c for details about the locking. + */ int __init net_dev_init(void) { struct net_device *dev, **dp; @@ -2407,6 +2566,10 @@ int __init net_dev_init(void) pktsched_init(); #endif +#ifdef CONFIG_NET_DIVERT + dv_init(); +#endif /* CONFIG_NET_DIVERT */ + /* * Initialise the packet receive queues. */ @@ -2417,6 +2580,8 @@ int __init net_dev_init(void) queue = &softnet_data[i]; skb_queue_head_init(&queue->input_pkt_queue); queue->throttle = 0; + queue->cng_level = 0; + queue->avg_blog = 10; /* arbitrary non-zero */ queue->completion_queue = NULL; } @@ -2425,6 +2590,12 @@ int __init net_dev_init(void) NET_PROFILE_REGISTER(dev_queue_xmit); NET_PROFILE_REGISTER(softnet_process); #endif + +#ifdef OFFLINE_SAMPLE + samp_timer.expires = jiffies + (10 * HZ); + add_timer(&samp_timer); +#endif + /* * Add the devices. * If the call to dev->init fails, the dev is removed diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index cf590db04..6b24a1416 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -13,6 +13,7 @@ * rather than any time but... * Alan Cox : IFF_ALLMULTI support. * Alan Cox : New format set_multicast_list() calls. + * Gleb Natapov : Remove dev_mc_lock. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -59,16 +60,14 @@ * Device mc lists are changed by bh at least if IPv6 is enabled, * so that it must be bh protected. * - * We protect all mc lists with global rw lock - * and block accesses to device mc filters with dev->xmit_lock. + * We block accesses to device mc filters with dev->xmit_lock. */ -static rwlock_t dev_mc_lock = RW_LOCK_UNLOCKED; /* * Update the multicast list into the physical NIC controller. */ -void dev_mc_upload(struct net_device *dev) +static void __dev_mc_upload(struct net_device *dev) { /* Don't do anything till we up the interface * [dev_open will call this function so the list will @@ -87,13 +86,14 @@ void dev_mc_upload(struct net_device *dev) !netif_device_present(dev)) return; - read_lock_bh(&dev_mc_lock); - spin_lock(&dev->xmit_lock); - dev->xmit_lock_owner = smp_processor_id(); dev->set_multicast_list(dev); - dev->xmit_lock_owner = -1; - spin_unlock(&dev->xmit_lock); - read_unlock_bh(&dev_mc_lock); +} + +void dev_mc_upload(struct net_device *dev) +{ + spin_lock_bh(&dev->xmit_lock); + __dev_mc_upload(dev); + spin_unlock_bh(&dev->xmit_lock); } /* @@ -105,7 +105,8 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) int err = 0; struct dev_mc_list *dmi, **dmip; - write_lock_bh(&dev_mc_lock); + spin_lock_bh(&dev->xmit_lock); + for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) { /* * Find the entry we want to delete. The device could @@ -127,7 +128,6 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) */ *dmip = dmi->next; dev->mc_count--; - write_unlock_bh(&dev_mc_lock); kfree(dmi); @@ -135,13 +135,15 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) * We have altered the list, so the card * loaded filter is now wrong. Fix it */ - dev_mc_upload(dev); + __dev_mc_upload(dev); + + spin_unlock_bh(&dev->xmit_lock); return 0; } } err = -ENOENT; done: - write_unlock_bh(&dev_mc_lock); + spin_unlock_bh(&dev->xmit_lock); return err; } @@ -156,7 +158,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) dmi1 = (struct dev_mc_list *)kmalloc(sizeof(*dmi), GFP_ATOMIC); - write_lock_bh(&dev_mc_lock); + spin_lock_bh(&dev->xmit_lock); for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && dmi->dmi_addrlen == alen) { @@ -172,7 +174,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) } if ((dmi = dmi1) == NULL) { - write_unlock_bh(&dev_mc_lock); + spin_unlock_bh(&dev->xmit_lock); return -ENOMEM; } memcpy(dmi->dmi_addr, addr, alen); @@ -182,12 +184,14 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) dmi->dmi_gusers = glbl ? 1 : 0; dev->mc_list = dmi; dev->mc_count++; - write_unlock_bh(&dev_mc_lock); - dev_mc_upload(dev); + + __dev_mc_upload(dev); + + spin_unlock_bh(&dev->xmit_lock); return 0; done: - write_unlock_bh(&dev_mc_lock); + spin_unlock_bh(&dev->xmit_lock); if (dmi1) kfree(dmi1); return err; @@ -199,7 +203,8 @@ done: void dev_mc_discard(struct net_device *dev) { - write_lock_bh(&dev_mc_lock); + spin_lock_bh(&dev->xmit_lock); + while (dev->mc_list != NULL) { struct dev_mc_list *tmp = dev->mc_list; dev->mc_list = tmp->next; @@ -208,7 +213,8 @@ void dev_mc_discard(struct net_device *dev) kfree(tmp); } dev->mc_count = 0; - write_unlock_bh(&dev_mc_lock); + + spin_unlock_bh(&dev->xmit_lock); } #ifdef CONFIG_PROC_FS @@ -222,7 +228,7 @@ static int dev_mc_read_proc(char *buffer, char **start, off_t offset, read_lock(&dev_base_lock); for (dev = dev_base; dev; dev = dev->next) { - read_lock_bh(&dev_mc_lock); + spin_lock_bh(&dev->xmit_lock); for (m = dev->mc_list; m; m = m->next) { int i; @@ -240,11 +246,11 @@ static int dev_mc_read_proc(char *buffer, char **start, off_t offset, begin = pos; } if (pos > offset + length) { - read_unlock_bh(&dev_mc_lock); + spin_unlock_bh(&dev->xmit_lock); goto done; } } - read_unlock_bh(&dev_mc_lock); + spin_unlock_bh(&dev->xmit_lock); } *eof = 1; diff --git a/net/core/dv.c b/net/core/dv.c new file mode 100644 index 000000000..4df7747b8 --- /dev/null +++ b/net/core/dv.c @@ -0,0 +1,551 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Generic frame diversion + * + * Version: @(#)eth.c 0.41 09/09/2000 + * + * Authors: + * Benoit LOCHER: initial integration within the kernel with support for ethernet + * Dave Miller: improvement on the code (correctness, performance and source files) + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/socket.h> +#include <linux/in.h> +#include <linux/inet.h> +#include <linux/ip.h> +#include <linux/udp.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <net/dst.h> +#include <net/arp.h> +#include <net/sock.h> +#include <net/ipv6.h> +#include <net/ip.h> +#include <asm/uaccess.h> +#include <asm/system.h> +#include <asm/checksum.h> +#include <linux/divert.h> +#include <linux/sockios.h> + +const char sysctl_divert_version[32]="0.46"; /* Current version */ + +int __init dv_init(void) +{ + printk(KERN_INFO "NET4: Frame Diverter %s\n", sysctl_divert_version); + return 0; +} + +/* + * Allocate a divert_blk for a device. This must be an ethernet nic. + */ +int alloc_divert_blk(struct net_device *dev) +{ + int alloc_size = (sizeof(struct divert_blk) + 3) & ~3; + + if (!strncmp(dev->name, "eth", 3)) { + printk(KERN_DEBUG "divert: allocating divert_blk for %s\n", + dev->name); + + dev->divert = (struct divert_blk *) + kmalloc(alloc_size, GFP_KERNEL); + if (dev->divert == NULL) { + printk(KERN_DEBUG "divert: unable to allocate divert_blk for %s\n", + dev->name); + return -EFAULT; + } else { + memset(dev->divert, 0, sizeof(struct divert_blk)); + } + } else { + printk(KERN_DEBUG "divert: not allocating divert_blk for non-ethernet device %s\n", + dev->name); + + dev->divert = NULL; + } + return 0; +} + +/* + * Free a divert_blk allocated by the above function, if it was + * allocated on that device. + */ +void free_divert_blk(struct net_device *dev) +{ + if (dev->divert) { + kfree(dev->divert); + dev->divert=NULL; + printk(KERN_DEBUG "divert: freeing divert_blk for %s\n", + dev->name); + } else { + printk(KERN_DEBUG "divert: no divert_blk to free, %s not ethernet\n", + dev->name); + } +} + +/* + * Adds a tcp/udp (source or dest) port to an array + */ +int add_port(u16 ports[], u16 port) +{ + int i; + + if (port == 0) + return -EINVAL; + + /* Storing directly in network format for performance, + * thanks Dave :) + */ + port = htons(port); + + for (i = 0; i < MAX_DIVERT_PORTS; i++) { + if (ports[i] == port) + return -EALREADY; + } + + for (i = 0; i < MAX_DIVERT_PORTS; i++) { + if (ports[i] == 0) { + ports[i] = port; + return 0; + } + } + + return -ENOBUFS; +} + +/* + * Removes a port from an array tcp/udp (source or dest) + */ +int remove_port(u16 ports[], u16 port) +{ + int i; + + if (port == 0) + return -EINVAL; + + /* Storing directly in network format for performance, + * thanks Dave ! + */ + port = htons(port); + + for (i = 0; i < MAX_DIVERT_PORTS; i++) { + if (ports[i] == port) { + ports[i] = 0; + return 0; + } + } + + return -EINVAL; +} + +/* Some basic sanity checks on the arguments passed to divert_ioctl() */ +int check_args(struct divert_cf *div_cf, struct net_device **dev) +{ + char devname[32]; + + if (dev == NULL) + return -EFAULT; + + /* GETVERSION: all other args are unused */ + if (div_cf->cmd == DIVCMD_GETVERSION) + return 0; + + /* Network device index should reasonably be between 0 and 1000 :) */ + if (div_cf->dev_index < 0 || div_cf->dev_index > 1000) + return -EINVAL; + + /* Let's try to find the ifname */ + sprintf(devname, "eth%d", div_cf->dev_index); + *dev = dev_get_by_name(devname); + + /* dev should NOT be null */ + if (*dev == NULL) + return -EINVAL; + + /* user issuing the ioctl must be a super one :) */ + if (!suser()) + return -EPERM; + + /* Device must have a divert_blk member NOT null */ + if ((*dev)->divert == NULL) + return -EFAULT; + + return 0; +} + +/* + * control function of the diverter + */ +#define DVDBG(a) \ + printk(KERN_DEBUG "divert_ioctl() line %d %s\n", __LINE__, (a)) + +int divert_ioctl(unsigned int cmd, struct divert_cf *arg) +{ + struct divert_cf div_cf; + struct divert_blk *div_blk; + struct net_device *dev; + int ret; + + switch (cmd) { + case SIOCGIFDIVERT: + DVDBG("SIOCGIFDIVERT, copy_from_user"); + if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf))) + return -EFAULT; + DVDBG("before check_args"); + ret = check_args(&div_cf, &dev); + if (ret) + return ret; + DVDBG("after checkargs"); + div_blk = dev->divert; + + DVDBG("befre switch()"); + switch (div_cf.cmd) { + case DIVCMD_GETSTATUS: + /* Now, just give the user the raw divert block + * for him to play with :) + */ + if (copy_to_user(div_cf.arg1.ptr, dev->divert, + sizeof(struct divert_blk))) + return -EFAULT; + break; + + case DIVCMD_GETVERSION: + DVDBG("GETVERSION: checking ptr"); + if (div_cf.arg1.ptr == NULL) + return -EINVAL; + DVDBG("GETVERSION: copying data to userland"); + if (copy_to_user(div_cf.arg1.ptr, + sysctl_divert_version, 32)) + return -EFAULT; + DVDBG("GETVERSION: data copied"); + break; + + default: + return -EINVAL; + }; + + break; + + case SIOCSIFDIVERT: + if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf))) + return -EFAULT; + + ret = check_args(&div_cf, &dev); + if (ret) + return ret; + + div_blk = dev->divert; + + switch(div_cf.cmd) { + case DIVCMD_RESET: + div_blk->divert = 0; + div_blk->protos = DIVERT_PROTO_NONE; + memset(div_blk->tcp_dst, 0, + MAX_DIVERT_PORTS * sizeof(u16)); + memset(div_blk->tcp_src, 0, + MAX_DIVERT_PORTS * sizeof(u16)); + memset(div_blk->udp_dst, 0, + MAX_DIVERT_PORTS * sizeof(u16)); + memset(div_blk->udp_src, 0, + MAX_DIVERT_PORTS * sizeof(u16)); + return 0; + + case DIVCMD_DIVERT: + switch(div_cf.arg1.int32) { + case DIVARG1_ENABLE: + if (div_blk->divert) + return -EALREADY; + div_blk->divert = 1; + break; + + case DIVARG1_DISABLE: + if (!div_blk->divert) + return -EALREADY; + div_blk->divert = 0; + break; + + default: + return -EINVAL; + }; + + break; + + case DIVCMD_IP: + switch(div_cf.arg1.int32) { + case DIVARG1_ENABLE: + if (div_blk->protos & DIVERT_PROTO_IP) + return -EALREADY; + div_blk->protos |= DIVERT_PROTO_IP; + break; + + case DIVARG1_DISABLE: + if (!(div_blk->protos & DIVERT_PROTO_IP)) + return -EALREADY; + div_blk->protos &= ~DIVERT_PROTO_IP; + break; + + default: + return -EINVAL; + }; + + break; + + case DIVCMD_TCP: + switch(div_cf.arg1.int32) { + case DIVARG1_ENABLE: + if (div_blk->protos & DIVERT_PROTO_TCP) + return -EALREADY; + div_blk->protos |= DIVERT_PROTO_TCP; + break; + + case DIVARG1_DISABLE: + if (!(div_blk->protos & DIVERT_PROTO_TCP)) + return -EALREADY; + div_blk->protos &= ~DIVERT_PROTO_TCP; + break; + + default: + return -EINVAL; + }; + + break; + + case DIVCMD_TCPDST: + switch(div_cf.arg1.int32) { + case DIVARG1_ADD: + return add_port(div_blk->tcp_dst, + div_cf.arg2.uint16); + + case DIVARG1_REMOVE: + return remove_port(div_blk->tcp_dst, + div_cf.arg2.uint16); + + default: + return -EINVAL; + }; + + break; + + case DIVCMD_TCPSRC: + switch(div_cf.arg1.int32) { + case DIVARG1_ADD: + return add_port(div_blk->tcp_src, + div_cf.arg2.uint16); + + case DIVARG1_REMOVE: + return remove_port(div_blk->tcp_src, + div_cf.arg2.uint16); + + default: + return -EINVAL; + }; + + break; + + case DIVCMD_UDP: + switch(div_cf.arg1.int32) { + case DIVARG1_ENABLE: + if (div_blk->protos & DIVERT_PROTO_UDP) + return -EALREADY; + div_blk->protos |= DIVERT_PROTO_UDP; + break; + + case DIVARG1_DISABLE: + if (!(div_blk->protos & DIVERT_PROTO_UDP)) + return -EALREADY; + div_blk->protos &= ~DIVERT_PROTO_UDP; + break; + + default: + return -EINVAL; + }; + + break; + + case DIVCMD_UDPDST: + switch(div_cf.arg1.int32) { + case DIVARG1_ADD: + return add_port(div_blk->udp_dst, + div_cf.arg2.uint16); + + case DIVARG1_REMOVE: + return remove_port(div_blk->udp_dst, + div_cf.arg2.uint16); + + default: + return -EINVAL; + }; + + break; + + case DIVCMD_UDPSRC: + switch(div_cf.arg1.int32) { + case DIVARG1_ADD: + return add_port(div_blk->udp_src, + div_cf.arg2.uint16); + + case DIVARG1_REMOVE: + return remove_port(div_blk->udp_src, + div_cf.arg2.uint16); + + default: + return -EINVAL; + }; + + break; + + case DIVCMD_ICMP: + switch(div_cf.arg1.int32) { + case DIVARG1_ENABLE: + if (div_blk->protos & DIVERT_PROTO_ICMP) + return -EALREADY; + div_blk->protos |= DIVERT_PROTO_ICMP; + break; + + case DIVARG1_DISABLE: + if (!(div_blk->protos & DIVERT_PROTO_ICMP)) + return -EALREADY; + div_blk->protos &= ~DIVERT_PROTO_ICMP; + break; + + default: + return -EINVAL; + }; + + break; + + default: + return -EINVAL; + }; + + break; + + default: + return -EINVAL; + }; + + return 0; +} + + +/* + * Check if packet should have its dest mac address set to the box itself + * for diversion + */ + +#define ETH_DIVERT_FRAME(skb) \ + memcpy(skb->mac.ethernet, skb->dev->dev_addr, ETH_ALEN); \ + skb->pkt_type=PACKET_HOST + +void divert_frame(struct sk_buff *skb) +{ + struct ethhdr *eth = skb->mac.ethernet; + struct iphdr *iph; + struct tcphdr *tcph; + struct udphdr *udph; + struct divert_blk *divert = skb->dev->divert; + int i, src, dst; + unsigned char *skb_data_end = skb->data + skb->len; + + /* Packet is already aimed at us, return */ + if (!memcmp(eth, skb->dev->dev_addr, ETH_ALEN)) + return; + + /* proto is not IP, do nothing */ + if (eth->h_proto != htons(ETH_P_IP)) + return; + + /* Divert all IP frames ? */ + if (divert->protos & DIVERT_PROTO_IP) { + ETH_DIVERT_FRAME(skb); + return; + } + + /* Check for possible (maliciously) malformed IP frame (thanks Dave) */ + iph = (struct iphdr *) skb->data; + if (((iph->ihl<<2)+(unsigned char*)(iph)) >= skb_data_end) { + printk(KERN_INFO "divert: malformed IP packet !\n"); + return; + } + + switch (iph->protocol) { + /* Divert all ICMP frames ? */ + case IPPROTO_ICMP: + if (divert->protos & DIVERT_PROTO_ICMP) { + ETH_DIVERT_FRAME(skb); + return; + } + break; + + /* Divert all TCP frames ? */ + case IPPROTO_TCP: + if (divert->protos & DIVERT_PROTO_TCP) { + ETH_DIVERT_FRAME(skb); + return; + } + + /* Check for possible (maliciously) malformed IP + * frame (thanx Dave) + */ + tcph = (struct tcphdr *) + (((unsigned char *)iph) + (iph->ihl<<2)); + if (((unsigned char *)(tcph+1)) >= skb_data_end) { + printk(KERN_INFO "divert: malformed TCP packet !\n"); + return; + } + + /* Divert some tcp dst/src ports only ?*/ + for (i = 0; i < MAX_DIVERT_PORTS; i++) { + dst = divert->tcp_dst[i]; + src = divert->tcp_src[i]; + if ((dst && dst == tcph->dest) || + (src && src == tcph->source)) { + ETH_DIVERT_FRAME(skb); + return; + } + } + break; + + /* Divert all UDP frames ? */ + case IPPROTO_UDP: + if (divert->protos & DIVERT_PROTO_UDP) { + ETH_DIVERT_FRAME(skb); + return; + } + + /* Check for possible (maliciously) malformed IP + * packet (thanks Dave) + */ + udph = (struct udphdr *) + (((unsigned char *)iph) + (iph->ihl<<2)); + if (((unsigned char *)(udph+1)) >= skb_data_end) { + printk(KERN_INFO + "divert: malformed UDP packet !\n"); + return; + } + + /* Divert some udp dst/src ports only ? */ + for (i = 0; i < MAX_DIVERT_PORTS; i++) { + dst = divert->udp_dst[i]; + src = divert->udp_src[i]; + if ((dst && dst == udph->dest) || + (src && src == udph->source)) { + ETH_DIVERT_FRAME(skb); + return; + } + } + break; + }; + + return; +} + diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 4ea599a88..2f6090a2f 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -12,6 +12,10 @@ #ifdef CONFIG_SYSCTL extern int netdev_max_backlog; +extern int no_cong_thresh; +extern int no_cong; +extern int lo_cong; +extern int mod_cong; extern int netdev_fastroute; extern int net_msg_cost; extern int net_msg_burst; @@ -25,6 +29,10 @@ extern int sysctl_core_destroy_delay; extern int sysctl_optmem_max; extern int sysctl_hot_list_len; +#ifdef CONFIG_NET_DIVERT +extern char sysctl_divert_version[]; +#endif /* CONFIG_NET_DIVERT */ + ctl_table core_table[] = { #ifdef CONFIG_NET {NET_CORE_WMEM_MAX, "wmem_max", @@ -42,6 +50,18 @@ ctl_table core_table[] = { {NET_CORE_MAX_BACKLOG, "netdev_max_backlog", &netdev_max_backlog, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_CORE_NO_CONG_THRESH, "no_cong_thresh", + &no_cong, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_CORE_NO_CONG, "no_cong", + &no_cong, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_CORE_LO_CONG, "lo_cong", + &lo_cong, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_CORE_MOD_CONG, "mod_cong", + &mod_cong, sizeof(int), 0644, NULL, + &proc_dointvec}, #ifdef CONFIG_NET_FASTROUTE {NET_CORE_FASTROUTE, "netdev_fastroute", &netdev_fastroute, sizeof(int), 0644, NULL, @@ -59,6 +79,11 @@ ctl_table core_table[] = { {NET_CORE_HOT_LIST_LENGTH, "hot_list_length", &sysctl_hot_list_len, sizeof(int), 0644, NULL, &proc_dointvec}, +#ifdef CONFIG_NET_DIVERT + {NET_CORE_DIVERT_VERSION, "divert_version", + (void *)sysctl_divert_version, 32, 0444, NULL, + &proc_dostring}, +#endif /* CONFIG_NET_DIVERT */ #endif /* CONFIG_NET */ { 0 } }; diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 348c30fce..8de443979 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -2053,8 +2053,36 @@ void dn_register_sysctl(void); void dn_unregister_sysctl(void); #endif -void __init decnet_proto_init(struct net_proto *pro) + +#ifdef MODULE +EXPORT_NO_SYMBOLS; +MODULE_DESCRIPTION("The Linux DECnet Network Protocol"); +MODULE_AUTHOR("Linux DECnet Project Team"); + +static int addr[2] = {0, 0}; + +MODULE_PARM(addr, "2i"); +MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node"); +#endif + + +static int __init decnet_init(void) { +#ifdef MODULE + if (addr[0] > 63 || addr[0] < 0) { + printk(KERN_ERR "DECnet: Area must be between 0 and 63"); + return 1; + } + + if (addr[1] > 1023 || addr[1] < 0) { + printk(KERN_ERR "DECnet: Node must be between 0 and 1023"); + return 1; + } + + decnet_address = dn_htons((addr[0] << 10) | addr[1]); + dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address)); +#endif + printk(KERN_INFO "NET4: DECnet for Linux: V.2.3.49s (C) 1995-2000 Linux DECnet Project Team\n"); sock_register(&dn_family_ops); @@ -2074,6 +2102,7 @@ void __init decnet_proto_init(struct net_proto *pro) #ifdef CONFIG_SYSCTL dn_register_sysctl(); #endif /* CONFIG_SYSCTL */ + return 0; } @@ -2093,37 +2122,7 @@ static int __init decnet_setup(char *str) __setup("decnet=", decnet_setup); #endif -#ifdef MODULE -EXPORT_NO_SYMBOLS; -MODULE_DESCRIPTION("The Linux DECnet Network Protocol"); -MODULE_AUTHOR("Linux DECnet Project Team"); - -static int addr[2] = {0, 0}; - -MODULE_PARM(addr, "2i"); -MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node"); - -int __init init_module(void) -{ - if (addr[0] > 63 || addr[0] < 0) { - printk(KERN_ERR "DECnet: Area must be between 0 and 63"); - return 1; - } - - if (addr[1] > 1023 || addr[1] < 0) { - printk(KERN_ERR "DECnet: Node must be between 0 and 1023"); - return 1; - } - - decnet_address = dn_htons((addr[0] << 10) | addr[1]); - dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address)); - - decnet_proto_init(NULL); - - return 0; -} - -void __exit cleanup_module(void) +static void __exit decnet_exit(void) { #ifdef CONFIG_SYSCTL dn_unregister_sysctl(); @@ -2145,4 +2144,5 @@ void __exit cleanup_module(void) sock_unregister(AF_DECnet); } -#endif +module_init(decnet_init); +module_exit(decnet_exit); diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 7a2a815ce..5d44e1f12 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -1143,7 +1143,5 @@ int __init econet_proto_init(void) return 0; } -#ifdef MODULE module_init(econet_proto_init); module_exit(econet_proto_exit); -#endif diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 69c6ff036..584814ad8 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -5,7 +5,7 @@ * * PF_INET protocol family socket handler. * - * Version: $Id: af_inet.c,v 1.114 2000/09/18 05:59:48 davem Exp $ + * Version: $Id: af_inet.c,v 1.121 2000/10/24 21:26:18 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -107,6 +107,9 @@ #ifdef CONFIG_KMOD #include <linux/kmod.h> #endif +#ifdef CONFIG_NET_DIVERT +#include <linux/divert.h> +#endif /* CONFIG_NET_DIVERT */ #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO) #include <linux/wireless.h> /* Note : will define WIRELESS_EXT */ #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */ @@ -444,6 +447,9 @@ int inet_release(struct socket *sock) return(0); } +/* It is off by default, see below. */ +int sysctl_ip_nonlocal_bind; + static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in *addr=(struct sockaddr_in *)uaddr; @@ -461,6 +467,21 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr); + /* Not specified by any standard per-se, however it breaks too + * many applications when removed. It is unfortunate since + * allowing applications to make a non-local bind solves + * several problems with systems using dynamic addressing. + * (ie. your servers still start up even if your ISDN link + * is temporarily down) + */ + if (sysctl_ip_nonlocal_bind == 0 && + sk->protinfo.af_inet.freebind == 0 && + addr->sin_addr.s_addr != INADDR_ANY && + chk_addr_ret != RTN_LOCAL && + chk_addr_ret != RTN_MULTICAST && + chk_addr_ret != RTN_BROADCAST) + return -EADDRNOTAVAIL; + snum = ntohs(addr->sin_port); if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) return -EACCES; @@ -750,14 +771,15 @@ int inet_shutdown(struct socket *sock, int how) } switch (sk->state) { - default: + case TCP_CLOSE: + err = -ENOTCONN; + /* Hack to wake up other listeners, who can poll for + POLLHUP, even on eg. unconnected UDP sockets -- RR */ + default: sk->shutdown |= how; if (sk->prot->shutdown) sk->prot->shutdown(sk, how); break; - case TCP_CLOSE: - err = -ENOTCONN; - break; /* Remaining two branches are temporary solution for missing * close() in multithreaded environment. It is _not_ a good idea, @@ -847,6 +869,13 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if (br_ioctl_hook != NULL) return br_ioctl_hook(arg); #endif + case SIOCGIFDIVERT: + case SIOCSIFDIVERT: +#ifdef CONFIG_NET_DIVERT + return(divert_ioctl(cmd, (struct divert_cf *) arg)); +#else + return -ENOPKG; +#endif /* CONFIG_NET_DIVERT */ return -ENOPKG; case SIOCADDDLCI: @@ -946,7 +975,7 @@ extern void tcp_v4_init(struct net_proto_family *); * Called by socket.c on kernel startup. */ -void __init inet_proto_init(struct net_proto *pro) +static int __init inet_init(void) { struct sk_buff *dummy_skb; struct inet_protocol *p; @@ -956,7 +985,7 @@ void __init inet_proto_init(struct net_proto *pro) if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "inet_proto_init: panic\n"); - return; + return -EINVAL; } /* @@ -1030,4 +1059,6 @@ void __init inet_proto_init(struct net_proto *pro) proc_net_create ("tcp", 0, tcp_get_info); proc_net_create ("udp", 0, udp_get_info); #endif /* CONFIG_PROC_FS */ + return 0; } +module_init(inet_init); diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index c173b9eb3..b410d1de4 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1,6 +1,6 @@ /* linux/net/inet/arp.c * - * Version: $Id: arp.c,v 1.88 2000/08/02 06:05:02 davem Exp $ + * Version: $Id: arp.c,v 1.90 2000/10/04 09:20:56 anton Exp $ * * Copyright (C) 1994 by Florian La Roche * diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index cda89659c..8c103857c 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -3,7 +3,7 @@ * * This source is covered by the GNU GPL, the same as all kernel sources. * - * Version: $Id: inetpeer.c,v 1.2 2000/05/03 06:37:06 davem Exp $ + * Version: $Id: inetpeer.c,v 1.3 2000/10/03 07:29:00 anton Exp $ * * Authors: Andrey V. Savochkin <saw@msu.ru> */ diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 7d8efb6dd..7df6e72e3 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -5,7 +5,7 @@ * * The IP forwarding functionality. * - * Version: $Id: ip_forward.c,v 1.46 2000/01/09 02:19:37 davem Exp $ + * Version: $Id: ip_forward.c,v 1.47 2000/10/24 22:54:26 davem Exp $ * * Authors: see ip.c * @@ -63,13 +63,11 @@ static inline int ip_forward_finish(struct sk_buff *skb) dst_release(old_dst); } #endif - ip_send(skb); - return 0; + return (ip_send(skb)); } ip_forward_options(skb); - ip_send(skb); - return 0; + return (ip_send(skb)); } int ip_forward(struct sk_buff *skb) @@ -81,7 +79,7 @@ int ip_forward(struct sk_buff *skb) unsigned short mtu; if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb)) - return 0; + return NET_RX_SUCCESS; if (skb->pkt_type != PACKET_HOST) goto drop; @@ -119,7 +117,7 @@ int ip_forward(struct sk_buff *skb) /* We are about to mangle packet. Copy it! */ if ((skb = skb_cow(skb, dev2->hard_header_len)) == NULL) - return -1; + return NET_RX_DROP; iph = skb->nh.iph; opt = &(IPCB(skb)->opt); @@ -138,7 +136,7 @@ int ip_forward(struct sk_buff *skb) if (rt->rt_flags & RTCF_NAT) { if (ip_do_nat(skb)) { kfree_skb(skb); - return -1; + return NET_RX_BAD; } } #endif @@ -163,5 +161,5 @@ too_many_hops: icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0); drop: kfree_skb(skb); - return -1; + return NET_RX_DROP; } diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index e7167aa65..f7b73adb8 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1266,7 +1266,9 @@ int __init ipgre_init(void) #ifdef MODULE register_netdev(&ipgre_fb_tunnel_dev); #else + rtnl_lock(); register_netdevice(&ipgre_fb_tunnel_dev); + rtnl_unlock(); #endif inet_add_protocol(&ipgre_protocol); diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index bb76f7ce5..873030d0a 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) module. * - * Version: $Id: ip_input.c,v 1.49 2000/08/21 20:41:55 davem Exp $ + * Version: $Id: ip_input.c,v 1.50 2000/10/24 22:54:26 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -341,7 +341,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb) skb = skb_cow(skb, skb_headroom(skb)); if (skb == NULL) - return 0; + return NET_RX_DROP; iph = skb->nh.iph; skb->ip_summed = 0; @@ -372,7 +372,7 @@ inhdr_error: IP_INC_STATS_BH(IpInHdrErrors); drop: kfree_skb(skb); - return(0); + return NET_RX_DROP; } /* @@ -429,6 +429,6 @@ inhdr_error: drop: kfree_skb(skb); out: - return(0); + return NET_RX_DROP; } diff --git a/net/ipv4/ip_nat_dumb.c b/net/ipv4/ip_nat_dumb.c index b45377af4..88e3ff9e2 100644 --- a/net/ipv4/ip_nat_dumb.c +++ b/net/ipv4/ip_nat_dumb.c @@ -5,7 +5,7 @@ * * Dumb Network Address Translation. * - * Version: $Id: ip_nat_dumb.c,v 1.9 1999/08/20 11:05:46 davem Exp $ + * Version: $Id: ip_nat_dumb.c,v 1.10 2000/10/24 22:54:26 davem Exp $ * * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * @@ -152,8 +152,9 @@ ip_do_nat(struct sk_buff *skb) break; } } - return 0; + return NET_RX_SUCCESS; truncated: + /* should be return NET_RX_BAD; */ return -EINVAL; } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 056767890..ce7618fe1 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) output module. * - * Version: $Id: ip_output.c,v 1.85 2000/08/31 23:39:12 davem Exp $ + * Version: $Id: ip_output.c,v 1.87 2000/10/25 20:07:22 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index a82e4be1f..f87921077 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -5,7 +5,7 @@ * * The IP to API glue. * - * Version: $Id: ip_sockglue.c,v 1.52 2000/09/09 08:26:04 davem Exp $ + * Version: $Id: ip_sockglue.c,v 1.53 2000/10/22 16:06:56 davem Exp $ * * Authors: see ip.c * @@ -372,21 +372,23 @@ out: /* * Socket option code for IP. This is the end of the line after any TCP,UDP etc options on * an IP socket. - * - * We implement IP_TOS (type of service), IP_TTL (time to live). */ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen) { int val=0,err; - if (optname == IP_PKTINFO || optname == IP_RECVTTL || - optname == IP_RECVTOS || optname == IP_RECVOPTS || - optname == IP_RETOPTS || optname == IP_TOS || - optname == IP_TTL || optname == IP_HDRINCL || - optname == IP_MTU_DISCOVER || optname == IP_RECVERR || - optname == IP_MULTICAST_TTL || optname == IP_MULTICAST_LOOP || - optname == IP_ROUTER_ALERT) { + if (level != SOL_IP) + return -ENOPROTOOPT; + + if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | + (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | + (1<<IP_RETOPTS) | (1<<IP_TOS) | + (1<<IP_TTL) | (1<<IP_HDRINCL) | + (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | + (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND))) || + optname == IP_MULTICAST_TTL || + optname == IP_MULTICAST_LOOP) { if (optlen >= sizeof(int)) { if (get_user(val, (int *) optval)) return -EFAULT; @@ -400,9 +402,6 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt } /* If optlen==0, it is equivalent to val == 0 */ - - if (level != SOL_IP) - return -ENOPROTOOPT; #ifdef CONFIG_IP_MROUTE if (optname >= MRT_BASE && optname <= (MRT_BASE + 10)) @@ -612,6 +611,12 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt case IP_ROUTER_ALERT: err = ip_ra_control(sk, val ? 1 : 0, NULL); break; + + case IP_FREEBIND: + if (optlen<1) + goto e_inval; + sk->protinfo.af_inet.freebind = !!val; + break; default: #ifdef CONFIG_NETFILTER @@ -771,6 +776,9 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op len -= msg.msg_controllen; return put_user(len, optlen); } + case IP_FREEBIND: + val = sk->protinfo.af_inet.freebind; + break; default: #ifdef CONFIG_NETFILTER val = nf_getsockopt(sk, PF_INET, optname, optval, diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index eae29c0b0..a8cb239a8 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -1,7 +1,7 @@ /* * Linux NET3: IP/IP protocol decoder. * - * Version: $Id: ipip.c,v 1.39 2000/08/25 02:15:47 davem Exp $ + * Version: $Id: ipip.c,v 1.40 2000/10/28 17:19:25 davem Exp $ * * Authors: * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 @@ -894,7 +894,9 @@ int __init ipip_init(void) #ifdef MODULE register_netdev(&ipip_fb_tunnel_dev); #else + rtnl_lock(); register_netdevice(&ipip_fb_tunnel_dev); + rtnl_unlock(); #endif inet_add_protocol(&ipip_protocol); diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 10d09a6bd..e5fbe41af 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -72,7 +72,7 @@ ip_nat_fn(unsigned int hooknum, unreliable. */ if (!ct) { if (net_ratelimit()) - printk("NAT: %u dropping untracked packet %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n", + printk(KERN_DEBUG "NAT: %u dropping untracked packet %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n", hooknum, *pskb, (*pskb)->nh.iph->protocol, diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c index db57fedb9..cacd7a3f8 100644 --- a/net/ipv4/protocol.c +++ b/net/ipv4/protocol.c @@ -5,7 +5,7 @@ * * INET protocol dispatch tables. * - * Version: $Id: protocol.c,v 1.11 2000/02/22 23:54:26 davem Exp $ + * Version: $Id: protocol.c,v 1.12 2000/10/03 07:29:00 anton Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 81f20361a..675154d91 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -5,7 +5,7 @@ * * RAW - implementation of IP "raw" sockets. * - * Version: $Id: raw.c,v 1.53 2000/08/09 11:59:04 davem Exp $ + * Version: $Id: raw.c,v 1.55 2000/10/24 22:54:26 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -227,11 +227,11 @@ static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb) { IP_INC_STATS(IpInDiscards); kfree_skb(skb); - return -1; + return NET_RX_DROP; } IP_INC_STATS(IpInDelivers); - return 0; + return NET_RX_SUCCESS; } /* @@ -653,7 +653,7 @@ int raw_get_info(char *buffer, char **start, off_t offset, int length) if (sk->family != PF_INET) continue; pos += 128; - if (pos < offset) + if (pos <= offset) continue; get_raw_sock(sk, tmpbuf, i); len += sprintf(buffer+len, "%-127s\n", tmpbuf); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 4734d8087..cacf36b71 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -5,7 +5,7 @@ * * ROUTE - implementation of the IP router. * - * Version: $Id: route.c,v 1.90 2000/08/31 23:39:12 davem Exp $ + * Version: $Id: route.c,v 1.91 2000/10/03 07:29:00 anton Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index d9f05c671..68d536e10 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -1,7 +1,7 @@ /* * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem. * - * $Id: sysctl_net_ipv4.c,v 1.46 2000/09/16 09:38:30 davem Exp $ + * $Id: sysctl_net_ipv4.c,v 1.47 2000/10/19 15:51:02 davem Exp $ * * Begun April 1, 1996, Mike Shaver. * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS] @@ -15,6 +15,9 @@ #include <net/route.h> #include <net/tcp.h> +/* From af_inet.c */ +extern int sysctl_ip_nonlocal_bind; + /* From icmp.c */ extern int sysctl_icmp_echo_ignore_all; extern int sysctl_icmp_echo_ignore_broadcasts; @@ -110,6 +113,9 @@ ctl_table ipv4_table[] = { {NET_IPV4_NO_PMTU_DISC, "ip_no_pmtu_disc", &ipv4_config.no_pmtu_disc, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_IPV4_NONLOCAL_BIND, "ip_nonlocal_bind", + &sysctl_ip_nonlocal_bind, sizeof(int), 0644, NULL, + &proc_dointvec}, {NET_IPV4_TCP_SYN_RETRIES, "tcp_syn_retries", &sysctl_tcp_syn_retries, sizeof(int), 0644, NULL, &proc_dointvec}, {NET_TCP_SYNACK_RETRIES, "tcp_synack_retries", diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 05027bc93..0f97c2d27 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.174 2000/09/18 05:59:48 davem Exp $ + * Version: $Id: tcp.c,v 1.176 2000/10/06 22:45:41 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -1026,7 +1026,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size) skb = NULL; if (tcp_memory_free(sk)) - skb = tcp_alloc_skb(sk, tmp, GFP_KERNEL); + skb = tcp_alloc_skb(sk, tmp, sk->allocation); if (skb == NULL) { /* If we didn't get any memory, we need to sleep. */ set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d2a79b4b1..1a0f278b4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.213 2000/09/18 05:59:48 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.218 2000/10/18 18:04:22 davem Exp $ * * IPv4 specific functions * @@ -75,37 +75,21 @@ static struct socket *tcp_socket=&tcp_inode.u.socket_i; void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, struct sk_buff *skb); -/* This is for sockets with full identity only. Sockets here will always - * be without wildcards and will have the following invariant: - * TCP_ESTABLISHED <= sk->state < TCP_CLOSE - * - * First half of the table is for sockets not in TIME_WAIT, second half - * is for TIME_WAIT sockets only. - */ -struct tcp_ehash_bucket *tcp_ehash; - -/* Ok, let's try this, I give up, we do need a local binding - * TCP hash as well as the others for fast bind/connect. - */ -struct tcp_bind_hashbucket *tcp_bhash; - -int tcp_bhash_size; -int tcp_ehash_size; - -/* All sockets in TCP_LISTEN state will be in here. This is the only table - * where wildcard'd TCP sockets can exist. Hash function here is just local - * port number. +/* + * ALL members must be initialised to prevent gcc-2.7.2.3 miscompilation */ -struct sock *tcp_listening_hash[TCP_LHTABLE_SIZE]; -char __tcp_clean_cacheline_pad[(SMP_CACHE_BYTES - - (((sizeof(void *) * (TCP_LHTABLE_SIZE + 2)) + - (sizeof(int) * 2)) % SMP_CACHE_BYTES))] = { 0, }; - -rwlock_t tcp_lhash_lock = RW_LOCK_UNLOCKED; -atomic_t tcp_lhash_users = ATOMIC_INIT(0); -DECLARE_WAIT_QUEUE_HEAD(tcp_lhash_wait); - -spinlock_t tcp_portalloc_lock = SPIN_LOCK_UNLOCKED; +struct tcp_hashinfo __cacheline_aligned tcp_hashinfo = { + __tcp_ehash: NULL, + __tcp_bhash: NULL, + __tcp_bhash_size: 0, + __tcp_ehash_size: 0, + __tcp_listening_hash: { NULL, }, + __tcp_lhash_lock: RW_LOCK_UNLOCKED, + __tcp_lhash_users: ATOMIC_INIT(0), + __tcp_lhash_wait: + __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.__tcp_lhash_wait), + __tcp_portalloc_lock: SPIN_LOCK_UNLOCKED +}; /* * This array holds the first and last local port number. @@ -2113,7 +2097,7 @@ skip_listen: continue; pos += TMPSZ; - if (pos < offset) + if (pos <= offset) continue; get_openreq(sk, req, tmpbuf, num, uid); len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf); @@ -2145,7 +2129,7 @@ skip_listen: if (!TCP_INET_FAMILY(sk->family)) continue; pos += TMPSZ; - if (pos < offset) + if (pos <= offset) continue; get_tcp_sock(sk, tmpbuf, num); len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf); @@ -2160,7 +2144,7 @@ skip_listen: if (!TCP_INET_FAMILY(tw->family)) continue; pos += TMPSZ; - if (pos < offset) + if (pos <= offset) continue; get_timewait_sock(tw, tmpbuf, num); len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8dca4474b..7b6f45428 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.127 2000/08/15 20:15:23 davem Exp $ + * Version: $Id: tcp_output.c,v 1.128 2000/10/29 01:51:09 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -318,7 +318,7 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb, int force_queue, unsigne if (!force_queue && tp->send_head == NULL && tcp_snd_test(tp, skb, cur_mss, 1)) { /* Send it out now. */ TCP_SKB_CB(skb)->when = tcp_time_stamp; - if (tcp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL)) == 0) { + if (tcp_transmit_skb(sk, skb_clone(skb, sk->allocation)) == 0) { tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; tcp_minshall_update(tp, cur_mss, skb); if (tp->packets_out++ == 0) diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 5e5af83c2..f57aeb32e 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_timer.c,v 1.79 2000/08/11 00:13:36 davem Exp $ + * Version: $Id: tcp_timer.c,v 1.80 2000/10/03 07:29:01 anton Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ff8a3d109..e098b9ff2 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -5,7 +5,7 @@ * * The User Datagram Protocol (UDP). * - * Version: $Id: udp.c,v 1.87 2000/09/20 02:11:34 davem Exp $ + * Version: $Id: udp.c,v 1.90 2000/10/18 18:04:22 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -677,8 +677,6 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len, if (flags & MSG_ERRQUEUE) return ip_recv_error(sk, msg, len); - - retry: /* * From here the generic datagram does a lot of the work. Come * the finished NET3, it will do _ALL_ the work! @@ -734,21 +732,22 @@ out: csum_copy_err: UDP_INC_STATS_BH(UdpInErrors); - if (flags&(MSG_PEEK|MSG_DONTWAIT)) { - struct sk_buff *skb2; - + /* Clear queue. */ + if (flags&MSG_PEEK) { + int clear = 0; spin_lock_irq(&sk->receive_queue.lock); - skb2 = skb_peek(&sk->receive_queue); - if ((flags & MSG_PEEK) && skb == skb2) { + if (skb == skb_peek(&sk->receive_queue)) { __skb_unlink(skb, &sk->receive_queue); + clear = 1; } spin_unlock_irq(&sk->receive_queue.lock); - skb_free_datagram(sk, skb); - if ((flags & MSG_DONTWAIT) && !skb2) - return -EAGAIN; - } else - skb_free_datagram(sk, skb); - goto retry; + if (clear) + kfree_skb(skb); + } + + skb_free_datagram(sk, skb); + + return -EAGAIN; } int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) @@ -1029,7 +1028,7 @@ int udp_get_info(char *buffer, char **start, off_t offset, int length) if (sk->family != PF_INET) continue; pos += 128; - if (pos < offset) + if (pos <= offset) continue; get_udp_sock(sk, tmpbuf, i); len += sprintf(buffer+len, "%-127s\n", tmpbuf); diff --git a/net/ipv4/utils.c b/net/ipv4/utils.c index c6494d87f..a5a9c3873 100644 --- a/net/ipv4/utils.c +++ b/net/ipv4/utils.c @@ -6,7 +6,7 @@ * Various kernel-resident INET utility functions; mainly * for format conversion and debugging output. * - * Version: $Id: utils.c,v 1.7 1999/06/09 10:11:05 davem Exp $ + * Version: $Id: utils.c,v 1.8 2000/10/03 07:29:01 anton Exp $ * * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> * diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 869cac689..c243a6ec9 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.58 2000/09/18 05:59:48 davem Exp $ + * $Id: af_inet6.c,v 1.60 2000/10/19 01:05:34 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -502,11 +502,7 @@ extern void ipv6_sysctl_register(void); extern void ipv6_sysctl_unregister(void); #endif -#ifdef MODULE -int init_module(void) -#else -void __init inet6_proto_init(struct net_proto *pro) -#endif +static int __init inet6_init(void) { struct sk_buff *dummy_skb; int err; @@ -523,11 +519,7 @@ void __init inet6_proto_init(struct net_proto *pro) if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "inet6_proto_init: size fault\n"); -#ifdef MODULE return -EINVAL; -#else - return; -#endif } /* @@ -577,11 +569,7 @@ void __init inet6_proto_init(struct net_proto *pro) /* Now the userspace is allowed to create INET6 sockets. */ (void) sock_register(&inet6_family_ops); -#ifdef MODULE return 0; -#else - return; -#endif #ifdef CONFIG_PROC_FS proc_snmp6_fail: @@ -603,15 +591,13 @@ icmp_fail: #if defined(MODULE) && defined(CONFIG_SYSCTL) ipv6_sysctl_unregister(); #endif -#ifdef MODULE return err; -#else - return; -#endif } +module_init(inet6_init); + #ifdef MODULE -void cleanup_module(void) +static void inet6_exit(void) { /* First of all disallow new sockets creation. */ sock_unregister(PF_INET6); @@ -636,4 +622,5 @@ void cleanup_module(void) ipv6_sysctl_unregister(); #endif } -#endif /* MODULE */ +module_exit(inet6_exit); +#endif /* MODULE */ diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index 43ac35004..df1e9324f 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c @@ -5,7 +5,7 @@ * * PF_INET6 protocol dispatch tables. * - * Version: $Id: protocol.c,v 1.8 2000/02/22 23:54:29 davem Exp $ + * Version: $Id: protocol.c,v 1.9 2000/10/03 07:29:01 anton Exp $ * * Authors: Pedro Roque <roque@di.fc.ul.pt> * diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 0b7e00252..43ef2e87d 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/raw.c * - * $Id: raw.c,v 1.40 2000/08/09 11:59:04 davem Exp $ + * $Id: raw.c,v 1.41 2000/10/18 18:04:23 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -793,7 +793,7 @@ int raw6_get_info(char *buffer, char **start, off_t offset, int length) if (sk->family != PF_INET6) continue; pos += LINE_LEN+1; - if (pos < offset) + if (pos <= offset) continue; get_raw6_sock(sk, tmpbuf, i); len += sprintf(buffer+len, LINE_FMT, tmpbuf); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 59048a22b..f263a3197 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -6,7 +6,7 @@ * Pedro Roque <roque@di.fc.ul.pt> * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> * - * $Id: sit.c,v 1.43 2000/08/25 02:15:47 davem Exp $ + * $Id: sit.c,v 1.45 2000/10/28 17:19:25 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -188,7 +188,7 @@ struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) } if (i==100) goto failed; - memcpy(parms->name, dev->name, IFNAMSIZ); + memcpy(nt->parms.name, dev->name, IFNAMSIZ); } if (register_netdevice(dev) < 0) goto failed; @@ -829,7 +829,9 @@ int __init sit_init(void) #ifdef MODULE register_netdev(&ipip6_fb_tunnel_dev); #else + rtnl_lock(); register_netdevice(&ipip6_fb_tunnel_dev); + rtnl_unlock(); #endif inet_add_protocol(&sit_protocol); return 0; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 952e24765..b830884e8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque <roque@di.fc.ul.pt> * - * $Id: tcp_ipv6.c,v 1.125 2000/08/09 11:59:04 davem Exp $ + * $Id: tcp_ipv6.c,v 1.126 2000/10/18 18:04:23 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -2009,7 +2009,7 @@ int tcp6_get_info(char *buffer, char **start, off_t offset, int length) if (req->class->family != PF_INET6) continue; pos += LINE_LEN+1; - if (pos < offset) + if (pos <= offset) continue; get_openreq6(sk, req, tmpbuf, num, uid); len += sprintf(buffer+len, LINE_FMT, tmpbuf); @@ -2041,7 +2041,7 @@ int tcp6_get_info(char *buffer, char **start, off_t offset, int length) if (sk->family != PF_INET6) continue; pos += LINE_LEN+1; - if (pos < offset) + if (pos <= offset) continue; get_tcp6_sock(sk, tmpbuf, num); len += sprintf(buffer+len, LINE_FMT, tmpbuf); @@ -2056,7 +2056,7 @@ int tcp6_get_info(char *buffer, char **start, off_t offset, int length) if (tw->family != PF_INET6) continue; pos += LINE_LEN+1; - if (pos < offset) + if (pos <= offset) continue; get_timewait6_sock(tw, tmpbuf, num); len += sprintf(buffer+len, LINE_FMT, tmpbuf); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 4d95aa40b..187db4414 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -7,7 +7,7 @@ * * Based on linux/ipv4/udp.c * - * $Id: udp.c,v 1.57 2000/09/18 05:59:48 davem Exp $ + * $Id: udp.c,v 1.58 2000/10/18 18:04:23 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -956,7 +956,7 @@ int udp6_get_info(char *buffer, char **start, off_t offset, int length) if (sk->family != PF_INET6) continue; pos += LINE_LEN+1; - if (pos < offset) + if (pos <= offset) continue; get_udp6_sock(sk, tmpbuf, i); len += sprintf(buffer+len, LINE_FMT, tmpbuf); diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index bbb2b2630..2fc3ea46c 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -2387,9 +2387,8 @@ static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; -/* Called by protocols.c on kernel start up */ -void ipx_proto_init(struct net_proto *pro) +static int __init ipx_init(void) { (void) sock_register(&ipx_family_ops); @@ -2415,7 +2414,9 @@ void ipx_proto_init(struct net_proto *pro) printk(KERN_INFO "NET4: Linux IPX 0.38 for NET4.0\n"); printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n"); + return 0; } +module_init(ipx_init); /* Higher layers need this info to prep tx pkts */ int ipx_if_offset(unsigned long ipx_net_number) @@ -2434,7 +2435,6 @@ EXPORT_SYMBOL(ipx_remove_socket); EXPORT_SYMBOL(ipx_register_spx); EXPORT_SYMBOL(ipx_unregister_spx); -#ifdef MODULE /* Note on MOD_{INC,DEC}_USE_COUNT: * * Use counts are incremented/decremented when @@ -2448,6 +2448,7 @@ EXPORT_SYMBOL(ipx_unregister_spx); * sockets be closed from user space. */ +#ifdef MODULE static void ipx_proto_finito(void) { ipx_interface *ifc; @@ -2486,18 +2487,7 @@ static void ipx_proto_finito(void) return; } - -int init_module(void) -{ - ipx_proto_init(NULL); - return (0); -} - -void cleanup_module(void) -{ - ipx_proto_finito(); - return; -} - +module_exit(ipx_proto_finito); #endif /* MODULE */ + #endif /* CONFIG_IPX || CONFIG_IPX_MODULE */ diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 2ba86afcc..69db79a0e 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -43,10 +43,10 @@ ********************************************************************/ #include <linux/config.h> +#include <linux/init.h> #include <linux/types.h> #include <linux/socket.h> #include <linux/sockios.h> -#include <linux/init.h> #include <linux/if_arp.h> #include <linux/net.h> #include <linux/irda.h> @@ -2155,17 +2155,19 @@ static struct notifier_block irda_dev_notifier = { * Initialize IrDA protocol layer * */ -void __init irda_proto_init(struct net_proto *pro) +static int __init irda_proto_init(void) { - sock_register(&irda_family_ops); - - irda_packet_type.type = htons(ETH_P_IRDA); + sock_register(&irda_family_ops); + + irda_packet_type.type = htons(ETH_P_IRDA); dev_add_pack(&irda_packet_type); - - register_netdevice_notifier(&irda_dev_notifier); - - irda_init(); + + register_netdevice_notifier(&irda_dev_notifier); + + irda_init(); + return 0; } +module_init(irda_proto_init); /* * Function irda_proto_cleanup (void) @@ -2186,4 +2188,5 @@ void irda_proto_cleanup(void) return; } +module_exit(irda_proto_cleanup); #endif /* MODULE */ diff --git a/net/irda/irmod.c b/net/irda/irmod.c index fde6788c3..39257f87a 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -545,28 +545,6 @@ void irda_proc_modcount(struct inode *inode, int fill) MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); MODULE_PARM(irda_debug, "1l"); - -/* - * Function init_module (void) - * - * Initialize the irda module - * - */ -int init_module(void) -{ - irda_proto_init(NULL); - - return 0; -} - -/* - * Function cleanup_module (void) - * - * Cleanup the irda module - * - */ -void cleanup_module(void) -{ - irda_proto_cleanup(); -} +module_exit(irda_proto_cleanup); #endif /* MODULE */ + diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index 587304bca..bdc84d72f 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c @@ -401,25 +401,18 @@ EXPORT_SYMBOL(lapb_disconnect_request); EXPORT_SYMBOL(lapb_data_request); EXPORT_SYMBOL(lapb_data_received); -void __init lapb_proto_init(struct net_proto *pro) +static int __init lapb_init(void) { printk(KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0\n"); + return 0; } #ifdef MODULE MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>"); MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol"); +#endif -int init_module(void) -{ - lapb_proto_init(NULL); - return 0; -} - -void cleanup_module(void) -{ -} -#endif +module_init(lapb_init); #endif diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index be011a234..3927d9c3a 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/init.h> #include <linux/major.h> #include <linux/signal.h> #include <linux/sched.h> @@ -968,16 +969,19 @@ struct net_proto_family netlink_family_ops = { netlink_create }; -void netlink_proto_init(struct net_proto *pro) +static int __init netlink_proto_init(void) { struct sk_buff *dummy_skb; if (sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb)) { - printk(KERN_CRIT "netlink_proto_init: panic\n"); - return; + printk(KERN_CRIT "netlink_init: panic\n"); + return -1; } sock_register(&netlink_family_ops); #ifdef CONFIG_PROC_FS create_proc_read_entry("net/netlink", 0, 0, netlink_read_proc, NULL); #endif + return 0; } + +module_init(netlink_proto_init); diff --git a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c index bc1b378fc..da7598a79 100644 --- a/net/netlink/netlink_dev.c +++ b/net/netlink/netlink_dev.c @@ -31,7 +31,7 @@ #include <asm/system.h> #include <asm/uaccess.h> -static unsigned open_map = 0; +static unsigned open_map; static struct socket *netlink_user[MAX_LINKS]; /* @@ -178,7 +178,7 @@ static struct file_operations netlink_fops = { release: netlink_release, }; -static devfs_handle_t devfs_handle = NULL; +static devfs_handle_t devfs_handle; static void __init make_devfs_entries (const char *name, int minor) { diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 27d95703b..a0c139b3a 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1261,13 +1261,13 @@ static struct notifier_block nr_dev_notifier = { static struct net_device *dev_nr; -void __init nr_proto_init(struct net_proto *pro) +static int __init nr_proto_init(void) { int i; if ((dev_nr = kmalloc(nr_ndevs * sizeof(struct net_device), GFP_KERNEL)) == NULL) { printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n"); - return; + return -1; } memset(dev_nr, 0x00, nr_ndevs * sizeof(struct net_device)); @@ -1296,8 +1296,12 @@ void __init nr_proto_init(struct net_proto *pro) proc_net_create("nr_neigh", 0, nr_neigh_get_info); proc_net_create("nr_nodes", 0, nr_nodes_get_info); #endif + return 0; } +module_init(nr_proto_init); + + #ifdef MODULE EXPORT_NO_SYMBOLS; @@ -1307,14 +1311,7 @@ MODULE_PARM_DESC(nr_ndevs, "number of NET/ROM devices"); MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>"); MODULE_DESCRIPTION("The amateur radio NET/ROM network and transport layer protocol"); -int init_module(void) -{ - nr_proto_init(NULL); - - return 0; -} - -void cleanup_module(void) +static void nr_exit(void) { int i; @@ -1348,7 +1345,9 @@ void cleanup_module(void) kfree(dev_nr); } +module_exit(nr_exit); +#endif /* MODULE */ + -#endif #endif diff --git a/net/netsyms.c b/net/netsyms.c index 8579c5b2f..ebe3bbe81 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -30,6 +30,9 @@ #include <net/scm.h> #include <linux/if_bridge.h> #include <linux/random.h> +#ifdef CONFIG_NET_DIVERT +#include <linux/divert.h> +#endif /* CONFIG_NET_DIVERT */ #ifdef CONFIG_NET extern __u32 sysctl_wmem_max; @@ -207,6 +210,12 @@ EXPORT_SYMBOL(br_ioctl_hook); #endif #endif +#ifdef CONFIG_NET_DIVERT +EXPORT_SYMBOL(alloc_divert_blk); +EXPORT_SYMBOL(free_divert_blk); +EXPORT_SYMBOL(divert_ioctl); +#endif /* CONFIG_NET_DIVERT */ + #ifdef CONFIG_INET /* Internet layer registration */ EXPORT_SYMBOL(inetdev_lock); @@ -276,16 +285,8 @@ EXPORT_SYMBOL(inet_sock_destruct); EXPORT_SYMBOL(inet_sock_release); /* Socket demultiplexing. */ -EXPORT_SYMBOL(tcp_ehash); -EXPORT_SYMBOL(tcp_ehash_size); -EXPORT_SYMBOL(tcp_listening_hash); -EXPORT_SYMBOL(tcp_lhash_lock); -EXPORT_SYMBOL(tcp_lhash_users); -EXPORT_SYMBOL(tcp_lhash_wait); +EXPORT_SYMBOL(tcp_hashinfo); EXPORT_SYMBOL(tcp_listen_wlock); -EXPORT_SYMBOL(tcp_bhash); -EXPORT_SYMBOL(tcp_bhash_size); -EXPORT_SYMBOL(tcp_portalloc_lock); EXPORT_SYMBOL(udp_hash); EXPORT_SYMBOL(udp_hash_lock); @@ -490,6 +491,7 @@ EXPORT_SYMBOL(dev_load); EXPORT_SYMBOL(dev_ioctl); EXPORT_SYMBOL(dev_queue_xmit); #ifdef CONFIG_NET_HW_FLOWCONTROL +EXPORT_SYMBOL(netdev_dropping); EXPORT_SYMBOL(netdev_register_fc); EXPORT_SYMBOL(netdev_unregister_fc); EXPORT_SYMBOL(netdev_fc_xoff); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index b7827f09f..6b4c77854 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -5,7 +5,7 @@ * * PACKET - implements raw packet sockets. * - * Version: $Id: af_packet.c,v 1.42 2000/08/29 03:44:56 davem Exp $ + * Version: $Id: af_packet.c,v 1.46 2000/10/24 21:26:19 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -33,6 +33,7 @@ * Alan Cox : Protocol setting support * Alexey Kuznetsov : Untied from IPv4 stack. * Cyrus Durgin : Fixed kerneld for kmod. + * Michal Ostrowski : Module initialization cleanup. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -67,6 +68,10 @@ #include <linux/init.h> #include <linux/if_bridge.h> +#ifdef CONFIG_NET_DIVERT +#include <linux/divert.h> +#endif /* CONFIG_NET_DIVERT */ + #ifdef CONFIG_INET #include <net/inet_common.h> #endif @@ -1484,6 +1489,14 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg #endif #endif + case SIOCGIFDIVERT: + case SIOCSIFDIVERT: +#ifdef CONFIG_NET_DIVERT + return(divert_ioctl(cmd, (struct divert_cf *) arg)); +#else + return -ENOPKG; +#endif /* CONFIG_NET_DIVERT */ + return -ENOPKG; #ifdef CONFIG_INET @@ -1860,8 +1873,8 @@ done: #endif -#ifdef MODULE -void cleanup_module(void) + +static void __exit packet_exit(void) { #ifdef CONFIG_PROC_FS remove_proc_entry("net/packet", 0); @@ -1872,17 +1885,16 @@ void cleanup_module(void) } -int init_module(void) -#else -void __init packet_proto_init(struct net_proto *pro) -#endif +static int __init packet_init(void) { sock_register(&packet_family_ops); register_netdevice_notifier(&packet_netdev_notifier); #ifdef CONFIG_PROC_FS create_proc_read_entry("net/packet", 0, 0, packet_read_proc, NULL); #endif -#ifdef MODULE return 0; -#endif } + + +module_init(packet_init); +module_exit(packet_exit); diff --git a/net/protocols.c b/net/protocols.c deleted file mode 100644 index 7de6a3bcb..000000000 --- a/net/protocols.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Protocol initializer table. Here separately for convenience - * - */ - - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/net.h> -#include <linux/fs.h> - -#ifdef CONFIG_UNIX -#include <linux/un.h> -#include <net/af_unix.h> -#endif - -#ifdef CONFIG_INET -#include <linux/inet.h> -#ifdef CONFIG_IPV6 -extern void inet6_proto_init(struct net_proto *pro); -#endif -#endif /* INET */ - -#ifdef CONFIG_ECONET -extern void econet_proto_init(struct net_proto *pro); -#endif - -#ifdef CONFIG_NETLINK -extern void netlink_proto_init(struct net_proto *pro); -#endif - -#ifdef CONFIG_PACKET -extern void packet_proto_init(struct net_proto *pro); -#endif - -#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE) -#define NEED_802 -#include <net/ipxcall.h> -#endif - -#ifdef CONFIG_X25 -#include <net/x25call.h> -#endif - -#ifdef CONFIG_LAPB -#include <net/lapbcall.h> -#endif - -#ifdef CONFIG_AX25 -#include <net/ax25call.h> -#ifdef CONFIG_NETROM -#include <net/nrcall.h> -#endif -#ifdef CONFIG_ROSE -#include <net/rosecall.h> -#endif -#endif - -#ifdef CONFIG_IRDA -#include <net/irda/irdacall.h> -#endif - -#if defined(CONFIG_DECNET) -#include <net/decnet_call.h> -#endif - -#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) -#define NEED_802 -#include <net/atalkcall.h> -#endif - -#if defined(CONFIG_NETBEUI) -#define NEED_LLC -#include <net/netbeuicall.h> -#endif - -#if defined(CONFIG_LLC) -#define NEED_LLC -#endif - -#include <net/psnapcall.h> - -#ifdef CONFIG_TR -#include <linux/netdevice.h> -#include <linux/trdevice.h> -extern void rif_init(struct net_proto *); -#endif - -#ifdef CONFIG_ATM -#include <linux/atm.h> -#endif - -#ifdef NEED_LLC -#define NEED_802 -#include <net/llccall.h> -#endif - -#ifdef NEED_802 -#include <net/p8022call.h> -#endif - - -#ifdef CONFIG_PPPOE -#include <linux/if_pppox.h> -#endif - -/* - * Protocol Table - */ - -struct net_proto protocols[] = { -#ifdef CONFIG_NETLINK - { "NETLINK", netlink_proto_init }, -#endif - -#ifdef CONFIG_PACKET - { "PACKET", packet_proto_init }, -#endif - -#ifdef CONFIG_UNIX - { "UNIX", unix_proto_init }, /* Unix domain socket family */ -#endif - -#ifdef NEED_802 - { "802.2", p8022_proto_init }, /* 802.2 demultiplexor */ - { "SNAP", snap_proto_init }, /* SNAP demultiplexor */ -#endif - -#ifdef CONFIG_TR - { "RIF", rif_init }, /* RIF for Token ring */ -#endif - -#ifdef CONFIG_ATM - { "ATMPVC", atmpvc_proto_init }, /* ATM PVCs */ - { "ATMSVC", atmsvc_proto_init }, /* ATM SVCs */ -#endif - -#ifdef NEED_LLC - { "802.2LLC", llc_init }, /* 802.2 LLC */ -#endif - -#ifdef CONFIG_AX25 - { "AX.25", ax25_proto_init }, /* Amateur Radio AX.25 */ -#ifdef CONFIG_NETROM - { "NET/ROM", nr_proto_init }, /* Amateur Radio NET/ROM */ -#endif -#ifdef CONFIG_ROSE - { "Rose", rose_proto_init }, /* Amateur Radio X.25 PLP */ -#endif -#endif -#ifdef CONFIG_DECNET - { "DECnet", decnet_proto_init }, /* DECnet */ -#endif -#ifdef CONFIG_INET - { "INET", inet_proto_init }, /* TCP/IP */ -#ifdef CONFIG_IPV6 - { "INET6", inet6_proto_init}, /* IPv6 */ -#endif -#endif - -#ifdef CONFIG_IPX - { "IPX", ipx_proto_init }, /* IPX */ -#endif - -#ifdef CONFIG_ATALK - { "DDP", atalk_proto_init }, /* Netatalk Appletalk driver */ -#endif - -#ifdef CONFIG_LAPB - { "LAPB", lapb_proto_init }, /* LAPB protocols */ -#endif - -#ifdef CONFIG_X25 - { "X.25", x25_proto_init }, /* CCITT X.25 Packet Layer */ -#endif - -#ifdef CONFIG_ECONET - { "Econet", econet_proto_init }, /* Acorn Econet */ -#endif - -#ifdef CONFIG_IRDA - { "IrDA", irda_proto_init }, /* IrDA protocols */ -#endif -#ifdef CONFIG_PPPOE - { "PPPoX", pppox_proto_init }, /* PPP over Ethernet */ -#endif - { NULL, NULL } /* End marker */ -}; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index f61d9cd34..f639e578a 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -27,6 +27,7 @@ #include <linux/config.h> #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include <linux/module.h> +#include <linux/init.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -56,7 +57,6 @@ #include <linux/proc_fs.h> #include <net/ip.h> #include <net/arp.h> -#include <linux/init.h> int rose_ndevs = 10; @@ -1427,7 +1427,7 @@ static struct notifier_block rose_dev_notifier = { static struct net_device *dev_rose; -void __init rose_proto_init(struct net_proto *pro) +static int __init rose_proto_init(void) { int i; @@ -1435,7 +1435,7 @@ void __init rose_proto_init(struct net_proto *pro) if ((dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device), GFP_KERNEL)) == NULL) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n"); - return; + return -1; } memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device)); @@ -1466,7 +1466,9 @@ void __init rose_proto_init(struct net_proto *pro) proc_net_create("rose_nodes", 0, rose_nodes_get_info); proc_net_create("rose_routes", 0, rose_routes_get_info); #endif + return 0; } +module_init(rose_proto_init); #ifdef MODULE EXPORT_NO_SYMBOLS; @@ -1477,14 +1479,7 @@ MODULE_PARM_DESC(rose_ndevs, "number of ROSE devices"); MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>"); MODULE_DESCRIPTION("The amateur radio ROSE network layer protocol"); -int init_module(void) -{ - rose_proto_init(NULL); - - return 0; -} - -void cleanup_module(void) +static void __exit rose_exit(void) { int i; @@ -1522,7 +1517,8 @@ void cleanup_module(void) kfree(dev_rose); } +module_exit(rose_exit); +#endif /* MODULE */ -#endif #endif diff --git a/net/socket.c b/net/socket.c index 9fdc84fb5..58df6d92e 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1490,7 +1490,7 @@ out: /* * Perform a file control on a socket file descriptor. * - * Doesn't aquire a fd lock, because no network fcntl + * Doesn't acquire a fd lock, because no network fcntl * function sleeps currently. */ @@ -1638,27 +1638,9 @@ int sock_unregister(int family) return 0; } -void __init proto_init(void) -{ - extern struct net_proto protocols[]; /* Network protocols */ - struct net_proto *pro; - - /* Kick all configured protocols. */ - pro = protocols; - while (pro->name != NULL) - { - (*pro->init_func)(pro); - pro++; - } - /* We're all done... */ -} extern void sk_init(void); -#ifdef CONFIG_BRIDGE -extern int br_init(void); -#endif - #ifdef CONFIG_WAN_ROUTER extern void wanrouter_init(void); #endif @@ -1691,14 +1673,6 @@ void __init sock_init(void) #endif /* - * Ethernet bridge layer. - */ - -#ifdef CONFIG_BRIDGE - br_init(); -#endif - - /* * Wan router layer. */ @@ -1712,10 +1686,13 @@ void __init sock_init(void) register_filesystem(&sock_fs_type); sock_mnt = kern_mount(&sock_fs_type); - proto_init(); + /* The real protocol initialization is performed when + * do_initcalls is run. + */ + /* - * The netlink device handler may be needed early. + * The netlink device handler may be needed early. */ #ifdef CONFIG_RTNETLINK diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 7eb578a60..a295ecaf7 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -159,7 +159,7 @@ rpcauth_insert_credcache(struct rpc_auth *auth, struct rpc_cred *cred) { int nr; - nr = (cred->cr_uid % RPC_CREDCACHE_NR); + nr = (cred->cr_uid & RPC_CREDCACHE_MASK); spin_lock(&rpc_credcache_lock); cred->cr_next = auth->au_credcache[nr]; auth->au_credcache[nr] = cred; @@ -178,7 +178,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, int taskflags) int nr = 0; if (!(taskflags & RPC_TASK_ROOTCREDS)) - nr = current->uid % RPC_CREDCACHE_NR; + nr = current->uid & RPC_CREDCACHE_MASK; if (time_before(auth->au_nextgc, jiffies)) rpcauth_gc_credcache(auth); @@ -218,7 +218,7 @@ rpcauth_remove_credcache(struct rpc_auth *auth, struct rpc_cred *cred) struct rpc_cred **q, *cr; int nr; - nr = (cred->cr_uid % RPC_CREDCACHE_NR); + nr = (cred->cr_uid & RPC_CREDCACHE_MASK); spin_lock(&rpc_credcache_lock); q = &auth->au_credcache[nr]; while ((cr = *q) != NULL) { diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c index d2e645acd..a9e42721a 100644 --- a/net/sunrpc/auth_null.c +++ b/net/sunrpc/auth_null.c @@ -54,6 +54,7 @@ nul_create_cred(int flags) return NULL; cred->cr_count = 0; cred->cr_flags = RPCAUTH_CRED_UPTODATE; + cred->cr_uid = current->uid; return cred; } diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index a036faef9..26a140771 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -800,7 +800,6 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout) "svc_recv: service %p, wait queue active!\n", rqstp); -again: /* Initialize the buffers */ rqstp->rq_argbuf = rqstp->rq_defbuf; rqstp->rq_resbuf = rqstp->rq_defbuf; @@ -846,7 +845,7 @@ again: /* No data, incomplete (TCP) read, or accept() */ if (len == 0 || len == -EAGAIN) { svc_sock_release(rqstp); - goto again; + return -EAGAIN; } rqstp->rq_secure = ntohs(rqstp->rq_addr.sin_port) < 1024; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 407f8f6b6..7603a9221 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version: $Id: af_unix.c,v 1.105 2000/08/16 10:58:22 davem Exp $ + * Version: $Id: af_unix.c,v 1.107 2000/10/19 01:05:36 davem Exp $ * * Fixes: * Linus Torvalds : Assorted bug cures. @@ -46,6 +46,7 @@ * Artur Skawina : Hash function optimizations * Alexey Kuznetsov : Full scale SMP. Lot of bugs are introduced 8) * Malcolm Beattie : Set peercred for socketpair + * Michal Ostrowski : Module initialization cleanup. * * * Known differences from reference BSD that was tested: @@ -1845,16 +1846,12 @@ struct net_proto_family unix_family_ops = { unix_create }; -#ifdef MODULE #ifdef CONFIG_SYSCTL extern void unix_sysctl_register(void); extern void unix_sysctl_unregister(void); #endif -int init_module(void) -#else -void __init unix_proto_init(struct net_proto *pro) -#endif +static int __init af_unix_init(void) { struct sk_buff *dummy_skb; @@ -1862,28 +1859,21 @@ void __init unix_proto_init(struct net_proto *pro) if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "unix_proto_init: panic\n"); -#ifdef MODULE return -1; -#else - return; -#endif } sock_register(&unix_family_ops); #ifdef CONFIG_PROC_FS create_proc_read_entry("net/unix", 0, 0, unix_read_proc, NULL); #endif -#ifdef MODULE #ifdef CONFIG_SYSCTL unix_sysctl_register(); #endif return 0; -#endif } -#ifdef MODULE -void cleanup_module(void) +static void __exit af_unix_exit(void) { sock_unregister(PF_UNIX); #ifdef CONFIG_SYSCTL @@ -1893,7 +1883,9 @@ void cleanup_module(void) remove_proc_entry("net/unix", 0); #endif } -#endif + +module_init(af_unix_init); +module_exit(af_unix_exit); /* * Local variables: diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c index 744a4446a..885119da3 100644 --- a/net/unix/sysctl_net_unix.c +++ b/net/unix/sysctl_net_unix.c @@ -26,7 +26,6 @@ ctl_table unix_table[] = { {0} }; -#ifdef MODULE static struct ctl_table_header * unix_sysctl_header; static struct ctl_table unix_root_table[]; static struct ctl_table unix_net_table[]; @@ -50,6 +49,5 @@ void unix_sysctl_unregister(void) { unregister_sysctl_table(unix_sysctl_header); } -#endif /* MODULE */ #endif /* CONFIG_SYSCTL */ diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 9af3a0e3d..320722c40 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1283,8 +1283,11 @@ void x25_kill_by_neigh(struct x25_neigh *neigh) } } -void __init x25_proto_init(struct net_proto *pro) +static int __init x25_init(void) { +#ifdef MODULE + struct net_device *dev; +#endif /* MODULE */ sock_register(&x25_family_ops); x25_packet_type.type = htons(ETH_P_X25); @@ -1302,20 +1305,8 @@ void __init x25_proto_init(struct net_proto *pro) proc_net_create("x25", 0, x25_get_info); proc_net_create("x25_routes", 0, x25_routes_get_info); #endif -} #ifdef MODULE -EXPORT_NO_SYMBOLS; - -MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>"); -MODULE_DESCRIPTION("The X.25 Packet Layer network layer protocol"); - -int init_module(void) -{ - struct net_device *dev; - - x25_proto_init(NULL); - /* * Register any pre existing devices. */ @@ -1329,11 +1320,20 @@ int init_module(void) x25_link_device_up(dev); } read_unlock(&dev_base_lock); - +#endif /* MODULE */ return 0; } +module_init(x25_init); + -void cleanup_module(void) + +#ifdef MODULE +EXPORT_NO_SYMBOLS; + +MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>"); +MODULE_DESCRIPTION("The X.25 Packet Layer network layer protocol"); + +static void __exit x25_exit(void) { #ifdef CONFIG_PROC_FS @@ -1354,7 +1354,7 @@ void cleanup_module(void) sock_unregister(AF_X25); } - +module_exit(x25_exit); #endif #endif |