diff options
Diffstat (limited to 'net')
53 files changed, 609 insertions, 644 deletions
diff --git a/net/Makefile b/net/Makefile index 29f66733f..44f47fabc 100644 --- a/net/Makefile +++ b/net/Makefile @@ -1,217 +1,70 @@ # # Makefile for the linux networking. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). +# 2 Sep 2000, Christoph Hellwig <hch@caldera.de> +# Rewritten to use lists instead of if-statements. # -# Note 2! The CFLAGS definition is now in the main makefile... -MOD_SUB_DIRS := ipv4 -ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \ - netrom rose lapb x25 wanrouter netlink sched packet sunrpc \ - econet irda decnet atm khttpd ipv4/netfilter ipv6/netfilter -SUB_DIRS := core ethernet +O_TARGET := network.o -ifeq ($(CONFIG_NET),y) -SUB_DIRS += 802 sched -endif - -ifeq ($(CONFIG_INET),y) -SUB_DIRS += ipv4 -ifeq ($(CONFIG_NETFILTER),y) -SUB_DIRS += ipv4/netfilter -MOD_SUB_DIRS += ipv4/netfilter -endif -endif +mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm +export-objs := netsyms.o -ifeq ($(CONFIG_UNIX),y) -SUB_DIRS += unix -else - ifeq ($(CONFIG_UNIX),m) - MOD_SUB_DIRS += unix - endif -endif +subdir-y := core ethernet +subdir-m := ipv4 # hum? -ifeq ($(CONFIG_IPV6),y) -SUB_DIRS += ipv6 -ifeq ($(CONFIG_NETFILTER),y) -SUB_DIRS += ipv6/netfilter -MOD_SUB_DIRS += ipv6/netfilter -endif -else - ifeq ($(CONFIG_IPV6),m) - MOD_SUB_DIRS += ipv6 - ifeq ($(CONFIG_NETFILTER),y) - MOD_SUB_DIRS += ipv6/netfilter - endif - endif -endif -ifeq ($(CONFIG_KHTTPD),y) -SUB_DIRS += khttpd -else - ifeq ($(CONFIG_KHTTPD),m) - MOD_SUB_DIRS += khttpd - endif -endif +subdir-$(CONFIG_NET) += 802 sched +subdir-$(CONFIG_INET) += ipv4 +subdir-$(CONFIG_NETFILTER) += ipv4/netfilter +subdir-$(CONFIG_UNIX) += unix +subdir-$(CONFIG_IPV6) += ipv6 -ifeq ($(CONFIG_NETLINK),y) -SUB_DIRS += netlink - ifeq ($(CONFIG_NETLINK_DEV),m) - MOD_SUB_DIRS += netlink - endif +ifneq ($(CONFIG_IPV6),n) +ifneq ($(CONFIG_IPV6),) +subdir-$(CONFIG_NETFILTER) += ipv6/netfilter endif - -ifeq ($(CONFIG_PACKET),y) -SUB_DIRS += packet -else - ifeq ($(CONFIG_PACKET),m) - MOD_SUB_DIRS += packet - endif endif -ifeq ($(CONFIG_NET_SCHED),y) - MOD_SUB_DIRS += sched -endif +subdir-$(CONFIG_KHTTPD) += khttpd +subdir-$(CONFIG_NETLINK) += netlink +subdir-$(CONFIG_PACKET) += packet +subdir-$(CONFIG_NET_SCHED) += sched +subdir-$(CONFIG_BRIDGE) += bridge +subdir-$(CONFIG_IPX) += ipx +subdir-$(CONFIG_ATALK) += appletalk +subdir-$(CONFIG_WAN_ROUTER) += wanrouter +subdir-$(CONFIG_X25) += x25 +subdir-$(CONFIG_LAPB) += lapb +subdir-$(CONFIG_NETROM) += netrom +subdir-$(CONFIG_ROSE) += rose +subdir-$(CONFIG_AX25) += ax25 +subdir-$(CONFIG_IRDA) += irda +subdir-$(CONFIG_SUNRPC) += sunrpc +subdir-$(CONFIG_ATM) += atm +subdir-$(CONFIG_DECNET) += decnet +subdir-$(CONFIG_ECONET) += econet -ifeq ($(CONFIG_BRIDGE),y) -SUB_DIRS += bridge -else - ifeq ($(CONFIG_BRIDGE),m) - MOD_SUB_DIRS += bridge - endif -endif -ifeq ($(CONFIG_IPX),y) -SUB_DIRS += ipx -# SPX can be still a module -MOD_SUB_DIRS += ipx -else - ifeq ($(CONFIG_IPX),m) - MOD_SUB_DIRS += ipx - endif -endif - -ifeq ($(CONFIG_ATALK),y) -SUB_DIRS += appletalk -else - ifeq ($(CONFIG_ATALK),m) - MOD_SUB_DIRS += appletalk - endif -endif - -ifeq ($(CONFIG_WAN_ROUTER),y) -SUB_DIRS += wanrouter -else - ifeq ($(CONFIG_WAN_ROUTER),m) - MOD_SUB_DIRS += wanrouter - endif -endif - -ifeq ($(CONFIG_X25),y) -SUB_DIRS += x25 -else - ifeq ($(CONFIG_X25),m) - MOD_SUB_DIRS += x25 - endif -endif - -ifeq ($(CONFIG_LAPB),y) -SUB_DIRS += lapb -else - ifeq ($(CONFIG_LAPB),m) - MOD_SUB_DIRS += lapb - endif -endif - -ifeq ($(CONFIG_NETROM),y) -SUB_DIRS += netrom -else - ifeq ($(CONFIG_NETROM),m) - MOD_SUB_DIRS += netrom - endif -endif - -ifeq ($(CONFIG_ROSE),y) -SUB_DIRS += rose -else - ifeq ($(CONFIG_ROSE),m) - MOD_SUB_DIRS += rose - endif -endif - -ifeq ($(CONFIG_AX25),y) -SUB_DIRS += ax25 -else - ifeq ($(CONFIG_AX25),m) - MOD_SUB_DIRS += ax25 - endif -endif - -ifeq ($(CONFIG_IRDA),y) -SUB_DIRS += irda -# There might be some irda features that are compiled as modules -MOD_IN_SUB_DIRS += irda -else - ifeq ($(CONFIG_IRDA),m) - MOD_SUB_DIRS += irda - endif -endif - -ifeq ($(CONFIG_SUNRPC),y) -SUB_DIRS += sunrpc -else - ifeq ($(CONFIG_SUNRPC),m) - MOD_SUB_DIRS += sunrpc - endif -endif - -ifeq ($(CONFIG_ATM),y) -SUB_DIRS += atm -ifeq ($(CONFIG_ATM_LANE),m) - MOD_ATM = atm -endif -ifeq ($(CONFIG_ATM_MPOA),m) - MOD_ATM = atm -endif -MOD_SUB_DIRS += $(MOD_ATM) +obj-y := socket.o protocols.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y)))) +ifeq ($(CONFIG_NET),y) +obj-$(CONFIG_MODULES) += netsyms.o +obj-$(CONFIG_SYSCTL) += sysctl_net.o endif -ifeq ($(CONFIG_DECNET),y) -SUB_DIRS += decnet -else - ifeq ($(CONFIG_DECNET),m) - MOD_SUB_DIRS += decnet - endif -endif -ifeq ($(CONFIG_ECONET),y) -SUB_DIRS += econet -else - ifeq ($(CONFIG_ECONET),m) - MOD_SUB_DIRS += econet - endif -endif +# Subdirectories that should be entered when MAKING_MODULES=1, even if set to 'y'. +both-m := $(filter $(mod-subdirs), $(subdir-y)) -# We must attach netsyms.o to socket.o, as otherwise there is nothing -# to pull the object file from the archive. +# Translate to Rules.make lists. +O_OBJS := $(filter-out $(export-objs), $(obj-y)) +OX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) -ifeq ($(CONFIG_NET),y) -ifeq ($(CONFIG_MODULES),y) -OX_OBJS := netsyms.o -endif -endif +SUB_DIRS := $(subdir-y) +MOD_SUB_DIRS := $(sort $(subdir-m) $(both-m)) +ALL_SUB_DIRS := $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-)) -O_TARGET := network.o -O_OBJS := socket.o protocols.o $(join $(SUB_DIRS), $(patsubst %,/%.o,$(notdir $(SUB_DIRS)))) - -M_OBJS := - -ifeq ($(CONFIG_SYSCTL),y) -ifeq ($(CONFIG_NET),y) -O_OBJS += sysctl_net.o -endif -endif include $(TOPDIR)/Rules.make diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index f89f777ce..c67e3fdd0 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -1017,7 +1017,10 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_t * cycle during probing of a slow to respond host addr. */ if (a != NULL) + { a->expires_at = jiffies - 1; + mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time); + } } if (sa.s_node != ma->s_node) diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 1c79056bb..bc04ecc67 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -155,7 +155,10 @@ static ssize_t proc_mpc_read(struct file *file, char *buff, if (*pos >= length) length = 0; else { if ((count + *pos) > length) count = length - *pos; - copy_to_user(buff, (char *)page , count); + if (copy_to_user(buff, (char *)page , count)) { + free_page(page); + return -EFAULT; + } *pos += count; } @@ -198,7 +201,7 @@ static ssize_t proc_mpc_write(struct file *file, const char *buff, *ppos += incoming; page[incoming] = '\0'; - retval = parse_qos(buff, incoming); + retval = parse_qos(page, incoming); if (retval == 0) printk("mpoa: proc_mpc_write: could not parse '%s'\n", page); diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 57718cf00..fc8910f2d 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -100,6 +100,7 @@ * with only 6 digipeaters and sockaddr_ax25 in ax25_bind(), * ax25_connect() and ax25_sendmsg() * Joerg(DL1BKE) Added support for SO_BINDTODEVICE + * Arnaldo C. Melo s/suser/capable(CAP_NET_ADMIN)/, some more cleanups */ #include <linux/config.h> @@ -817,10 +818,7 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op if (put_user(length, optlen)) return -EFAULT; - if (copy_to_user(optval, valptr, length)) - return -EFAULT; - - return 0; + return copy_to_user(optval, valptr, length) ? -EFAULT : 0; } static int ax25_listen(struct socket *sock, int backlog) @@ -1070,7 +1068,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL; call = ax25_findbyuid(current->euid); - if (call == NULL && ax25_uid_policy && !suser()) + if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN)) return -EACCES; if (call == NULL) @@ -1584,9 +1582,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) amount = 0; - if (put_user(amount, (int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (int *)arg); } case TIOCINQ: { @@ -1595,19 +1591,15 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->receive_queue)) != NULL) amount = skb->len; - if (put_user(amount, (int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (int *)arg); } case SIOCGSTAMP: if (sk != NULL) { if (sk->stamp.tv_sec == 0) return -ENOENT; - if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - return -EFAULT; - return 0; - } + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; + } return -EINVAL; case SIOCAX25ADDUID: /* Add a uid to the uid/call map table */ @@ -1621,7 +1613,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCAX25NOUID: { /* Set the default policy (default/bar) */ long amount; - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (get_user(amount, (long *)arg)) return -EFAULT; @@ -1634,12 +1626,12 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCADDRT: case SIOCDELRT: case SIOCAX25OPTRT: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; return ax25_rt_ioctl(cmd, (void *)arg); case SIOCAX25CTLCON: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; return ax25_ctl_ioctl(cmd, (void *)arg); @@ -1688,7 +1680,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCAX25ADDFWD: case SIOCAX25DELFWD: { struct ax25_fwd_struct ax25_fwd; - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd))) return -EFAULT; diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 6d58c5d04..32a7ab515 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -38,6 +38,7 @@ * Joerg(DL1BKE) Moved BPQ Ethernet driver to separate device. * AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating. * Jonathan(G4KLX) Support for packet forwarding. + * Arnaldo C. Melo s/suser/capable/ */ #include <linux/config.h> @@ -363,7 +364,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) return -EHOSTUNREACH; if ((call = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !suser()) + if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) return -EPERM; call = (ax25_address *)ax25->ax25_dev->dev->dev_addr; } diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 1cce0dd6d..eb226b14c 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -78,7 +78,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) return -ENOENT; case SIOCAX25ADDUID: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (ax25_findbyuid(sax->sax25_uid)) return -EEXIST; @@ -95,7 +95,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) return 0; case SIOCAX25DELUID: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) { if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) diff --git a/net/core/dev.c b/net/core/dev.c index a6ee7367a..e6f440cf4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -295,37 +295,20 @@ int netdev_boot_setup_add(char *name, struct ifmap *map) * netdev_boot_setup_check - check boot time settings * @dev: the netdevice * - * Check boot time settings for the device. If device's name is a - * mask (eg. eth%d) and settings are found then this will allocate - * name for the device. The found settings are set for the device - * to be used later in the device probing. Returns 0 if no settings - * found, 1 if they are. + * Check boot time settings for the device. + * The found settings are set for the device to be used + * later in the device probing. + * Returns 0 if no settings found, 1 if they are. */ int netdev_boot_setup_check(struct net_device *dev) { struct netdev_boot_setup *s; - char buf[IFNAMSIZ + 1]; - int i, mask = 0; - - memset(buf, 0, sizeof(buf)); - strcpy(buf, dev->name); - if (strchr(dev->name, '%')) { - *strchr(buf, '%') = '\0'; - mask = 1; - } + int i; s = dev_boot_setup; for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) { if (s[i].name[0] != '\0' && s[i].name[0] != ' ' && - !strncmp(buf, s[i].name, mask ? strlen(buf) : - strlen(s[i].name))) { - if (__dev_get_by_name(s[i].name)) { - if (!mask) - return 0; - continue; - } - memset(dev->name, 0, IFNAMSIZ); - strcpy(dev->name, s[i].name); + !strncmp(dev->name, s[i].name, strlen(s[i].name))) { dev->irq = s[i].map.irq; dev->base_addr = s[i].map.base_addr; dev->mem_start = s[i].map.mem_start; @@ -333,7 +316,6 @@ int netdev_boot_setup_check(struct net_device *dev) return 1; } } - return 0; } @@ -868,25 +850,6 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) br_read_unlock(BR_NETPROTO_LOCK); } -/* - * Fast path for loopback frames. - */ - -void dev_loopback_xmit(struct sk_buff *skb) -{ - struct sk_buff *newskb=skb_clone(skb, GFP_ATOMIC); - if (newskb==NULL) - return; - - newskb->mac.raw = newskb->data; - skb_pull(newskb, newskb->nh.raw - newskb->data); - newskb->pkt_type = PACKET_LOOPBACK; - newskb->ip_summed = CHECKSUM_UNNECESSARY; - if (newskb->dst==NULL) - printk(KERN_DEBUG "BUG: packet without dst looped back 1\n"); - netif_rx(newskb); -} - /** * dev_queue_xmit - transmit a buffer * @skb: buffer to transmit @@ -1178,6 +1141,7 @@ static void net_tx_action(struct softirq_action *h) struct net_device *dev = head; head = head->next_sched; + smp_mb__before_clear_bit(); clear_bit(__LINK_STATE_SCHED, &dev->state); if (spin_trylock(&dev->queue_lock)) { @@ -2482,27 +2446,26 @@ int __init net_dev_init(void) dev->iflink = -1; dev_hold(dev); + /* + * Allocate name. If the init() fails + * the name will be reissued correctly. + */ + if (strchr(dev->name, '%')) + dev_alloc_name(dev, dev->name); + /* * Check boot time settings for the device. */ - if (!netdev_boot_setup_check(dev)) { - /* - * No settings found - allocate name. If the init() - * fails the name will be reissued correctly. - */ - if (strchr(dev->name, '%')) - dev_alloc_name(dev, dev->name); - } + netdev_boot_setup_check(dev); if (dev->init && dev->init(dev)) { /* - * It failed to come up. Unhook it. + * It failed to come up. It will be unhooked later. + * dev_alloc_name can now advance to next suitable + * name that is checked next. */ - write_lock_bh(&dev_base_lock); - *dp = dev->next; dev->deadbeaf = 1; - write_unlock_bh(&dev_base_lock); - dev_put(dev); + dp = &dev->next; } else { dp = &dev->next; dev->ifindex = dev_new_index(); @@ -2515,6 +2478,21 @@ int __init net_dev_init(void) } } + /* + * Unhook devices that failed to come up + */ + dp = &dev_base; + while ((dev = *dp) != NULL) { + if (dev->deadbeaf) { + write_lock_bh(&dev_base_lock); + *dp = dev->next; + write_unlock_bh(&dev_base_lock); + dev_put(dev); + } else { + dp = &dev->next; + } + } + #ifdef CONFIG_PROC_FS proc_net_create("dev", 0, dev_get_info); create_proc_read_entry("net/softnet_stat", 0, 0, dev_proc_stats, NULL); diff --git a/net/core/sock.c b/net/core/sock.c index 1afd0619c..8503e364f 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -7,7 +7,7 @@ * handler for protocols to use and generic option handler. * * - * Version: $Id: sock.c,v 1.98 2000/08/16 16:09:15 davem Exp $ + * Version: $Id: sock.c,v 1.100 2000/09/18 05:59:48 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -609,7 +609,9 @@ void __init sk_init(void) { sk_cachep = kmem_cache_create("sock", sizeof(struct sock), 0, SLAB_HWCACHE_ALIGN, 0, 0); - + if (!sk_cachep) + printk(KERN_CRIT "sk_init: Cannot create sock SLAB cache!"); + if (num_physpages <= 4096) { sysctl_wmem_max = 32767; sysctl_rmem_max = 32767; @@ -1142,6 +1144,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) } else sk->sleep = NULL; + sk->dst_lock = RW_LOCK_UNLOCKED; sk->callback_lock = RW_LOCK_UNLOCKED; sk->state_change = sock_def_wakeup; diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 5322b3a89..348c30fce 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -32,6 +32,7 @@ * Patrick Caulfield: Fixes to delayed acceptance logic. * David S. Miller: New socket locking * Steve Whitehouse: Socket list hashing/locking + * Arnaldo C. Melo: use capable, not suser */ @@ -688,7 +689,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (dn_ntohs(saddr->sdn_nodeaddrl) && (dn_ntohs(saddr->sdn_nodeaddrl) != 2)) return -EINVAL; - if (saddr->sdn_objnum && !suser()) + if (saddr->sdn_objnum && !capable(CAP_NET_BIND_SERVICE)) return -EPERM; if (dn_ntohs(saddr->sdn_objnamel) > DN_MAXOBJL) @@ -698,7 +699,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL; if (saddr->sdn_flags & SDF_WILD) { - if (!suser()) + if (!capable(CAP_NET_BIND_SERVICE)) return -EPERM; } else { if (dn_ntohs(saddr->sdn_nodeaddrl)) { @@ -1101,7 +1102,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) #if 0 case SIOCSIFADDR: - if (!suser()) return -EPERM; + if (!capable(CAP_NET_ADMIN)) return -EPERM; if ((err = copy_from_user(devname, ioarg->devname, 5)) != 0) break; @@ -1143,7 +1144,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) #if 0 case SIOCSNETADDR: - if (!suser()) { + if (!capable(CAP_NET_ADMIN)) { err = -EPERM; break; } @@ -1174,7 +1175,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; #endif case OSIOCSNETADDR: - if (!suser()) { + if (!capable(CAP_NET_ADMIN)) { err = -EPERM; break; } @@ -1189,8 +1190,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; case OSIOCGNETADDR: - if ((err = put_user(decnet_address, (unsigned short *)arg)) != 0) - break; + err = put_user(decnet_address, (unsigned short *)arg); break; case SIOCGIFCONF: case SIOCGIFFLAGS: diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index cb9b3d11e..7a2a815ce 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -641,17 +641,15 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void *arg) static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; - int err; int pid; switch(cmd) { case FIOSETOWN: case SIOCSPGRP: - err = get_user(pid, (int *) arg); - if (err) - return err; - if (current->pid != pid && current->pgrp != -pid && !suser()) + if (get_user(pid, (int *) arg)) + return -EFAULT; + if (current->pid != pid && current->pgrp != -pid && !capable(CAP_NET_ADMIN)) return -EPERM; sk->proc = pid; return(0); @@ -661,10 +659,7 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg case SIOCGSTAMP: if(sk->stamp.tv_sec==0) return -ENOENT; - err = -EFAULT; - if (!copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - err = 0; - return err; + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; case SIOCGIFFLAGS: case SIOCSIFFLAGS: case SIOCGIFCONF: diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 6e80ed912..69c6ff036 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.112 2000/08/16 16:20:56 davem Exp $ + * Version: $Id: af_inet.c,v 1.114 2000/09/18 05:59:48 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -258,7 +258,6 @@ static int inet_autobind(struct sock *sk) return -EAGAIN; } sk->sport = htons(sk->num); - sk->prot->hash(sk); } release_sock(sk); return 0; @@ -390,7 +389,6 @@ static int inet_create(struct socket *sock, int protocol) if (sk->prot->init) { int err = sk->prot->init(sk); if (err != 0) { - sk->dead = 1; inet_sock_release(sk); return(err); } @@ -460,7 +458,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len < sizeof(struct sockaddr_in)) return -EINVAL; - + chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr); snum = ntohs(addr->sin_port); @@ -495,10 +493,11 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (sk->rcv_saddr) sk->userlocks |= SOCK_BINDADDR_LOCK; + if (snum) + sk->userlocks |= SOCK_BINDPORT_LOCK; sk->sport = htons(sk->num); sk->daddr = 0; sk->dport = 0; - sk->prot->hash(sk); sk_dst_reset(sk); err = 0; out: diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 2dfd1763c..c173b9eb3 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1066,16 +1066,13 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) { char tbuf[16]; sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key)); - - size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s", + size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s" + " * %s\n", tbuf, hatype, arp_state_to_flags(n), - hbuffer); - - size += sprintf(buffer+len+size, - " %-8s %s\n", - "*", dev->name); + hbuffer, + dev->name); } read_unlock(&n->lock); @@ -1099,15 +1096,17 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) struct net_device *dev = n->dev; int hatype = dev ? dev->type : 0; - size = sprintf(buffer+len, - "%u.%u.%u.%u0x%-10x0x%-10x%s", - NIPQUAD(*(u32*)n->key), - hatype, - ATF_PUBL|ATF_PERM, - "00:00:00:00:00:00"); - size += sprintf(buffer+len+size, - " %-17s %s\n", - "*", dev ? dev->name : "*"); + { + char tbuf[16]; + sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key)); + size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s" + " * %s\n", + tbuf, + hatype, + ATF_PUBL|ATF_PERM, + "00:00:00:00:00:00", + dev ? dev->name : "*"); + } len += size; pos += size; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 0af9ec321..1d8002bdd 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -8,7 +8,7 @@ * the older version didn't come out right using gcc 2.5.8, the newer one * seems to fall out with gcc 2.6.2. * - * Version: $Id: igmp.c,v 1.40 2000/07/26 01:04:16 davem Exp $ + * Version: $Id: igmp.c,v 1.41 2000/08/31 23:39:12 davem Exp $ * * Authors: * Alan Cox <Alan.Cox@linux.org> @@ -184,7 +184,10 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay) #define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4) -static inline int igmp_send_report2(struct sk_buff *skb) +/* Don't just hand NF_HOOK skb->dst->output, in case netfilter hook + changes route */ +static inline int +output_maybe_reroute(struct sk_buff *skb) { return skb->dst->output(skb); } @@ -247,7 +250,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type) ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr)); return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, - igmp_send_report2); + output_maybe_reroute); } diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index 40bf288ac..cda89659c 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -82,12 +82,12 @@ static struct inet_peer *peer_root = peer_avl_empty; static rwlock_t peer_pool_lock = RW_LOCK_UNLOCKED; #define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */ -static volatile int peer_total = 0; +static volatile int peer_total; int inet_peer_threshold = 65536 + 128; /* start to throw entries more * aggressively at this stage */ int inet_peer_minttl = 120 * HZ; /* TTL under high load: 120 sec */ int inet_peer_maxttl = 10 * 60 * HZ; /* usual time to live: 10 min */ -struct inet_peer *inet_peer_unused_head = NULL, +struct inet_peer *inet_peer_unused_head, **inet_peer_unused_tailp = &inet_peer_unused_head; spinlock_t inet_peer_unused_lock = SPIN_LOCK_UNLOCKED; #define PEER_MAX_CLEANUP_WORK 30 diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3d0e2b4aa..056767890 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.84 2000/08/25 02:15:47 davem Exp $ + * Version: $Id: ip_output.c,v 1.85 2000/08/31 23:39:12 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -107,42 +107,11 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb) return 0; } -#ifdef CONFIG_NETFILTER -/* To preserve the cute illusion that a locally-generated packet can - be mangled before routing, we actually reroute if a hook altered - the packet. -RR */ -static int route_me_harder(struct sk_buff *skb) -{ - struct iphdr *iph = skb->nh.iph; - struct rtable *rt; - - if (ip_route_output(&rt, iph->daddr, iph->saddr, - RT_TOS(iph->tos) | RTO_CONN, - skb->sk ? skb->sk->bound_dev_if : 0)) { - printk("route_me_harder: No more route.\n"); - return -EINVAL; - } - - /* Drop old route. */ - dst_release(skb->dst); - - skb->dst = &rt->u.dst; - return 0; -} -#endif - -/* Do route recalc if netfilter changes skb. */ +/* Don't just hand NF_HOOK skb->dst->output, in case netfilter hook + changes route */ static inline int output_maybe_reroute(struct sk_buff *skb) { -#ifdef CONFIG_NETFILTER - if (skb->nfcache & NFC_ALTERED) { - if (route_me_harder(skb) != 0) { - kfree_skb(skb); - return -EINVAL; - } - } -#endif return skb->dst->output(skb); } @@ -312,25 +281,6 @@ static inline int ip_queue_xmit2(struct sk_buff *skb) struct net_device *dev; struct iphdr *iph = skb->nh.iph; -#ifdef CONFIG_NETFILTER - /* BLUE-PEN-FOR-ALEXEY. I don't understand; you mean I can't - hold the route as I pass the packet to userspace? -- RR - - You may hold it, if you really hold it. F.e. if netfilter - does not destroy handed skb with skb->dst attached, it - will be held. When it was stored in info->arg, then - it was not held apparently. Now (without second arg) it is evident, - that it is clean. --ANK - */ - if (rt==NULL || (skb->nfcache & NFC_ALTERED)) { - if (route_me_harder(skb) != 0) { - kfree_skb(skb); - return -EHOSTUNREACH; - } - rt = (struct rtable *)skb->dst; - } -#endif - dev = rt->u.dst.dev; /* This can happen when the transport layer has segments queued diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 4287c7525..a82e4be1f 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.51 2000/08/09 11:59:04 davem Exp $ + * Version: $Id: ip_sockglue.c,v 1.52 2000/09/09 08:26:04 davem Exp $ * * Authors: see ip.c * @@ -380,31 +380,39 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt { int val=0,err; - if(optlen>=sizeof(int)) { - if(get_user(val, (int *) optval)) - return -EFAULT; - } else if(optlen>=sizeof(char)) { - unsigned char ucval; - if(get_user(ucval, (unsigned char *) optval)) - return -EFAULT; - val = (int)ucval; + 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 (optlen >= sizeof(int)) { + if (get_user(val, (int *) optval)) + return -EFAULT; + } else if (optlen >= sizeof(char)) { + unsigned char ucval; + + if (get_user(ucval, (unsigned char *) optval)) + return -EFAULT; + val = (int) ucval; + } } + /* If optlen==0, it is equivalent to val == 0 */ - if(level!=SOL_IP) + if (level != SOL_IP) return -ENOPROTOOPT; + #ifdef CONFIG_IP_MROUTE - if(optname>=MRT_BASE && optname <=MRT_BASE+10) - { + if (optname >= MRT_BASE && optname <= (MRT_BASE + 10)) return ip_mroute_setsockopt(sk,optname,optval,optlen); - } #endif err = 0; lock_sock(sk); - switch(optname) - { + switch (optname) { case IP_OPTIONS: { struct ip_options * opt = NULL; diff --git a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c index 6bb1b240c..cc3d2fb9c 100644 --- a/net/ipv4/netfilter/ip_fw_compat.c +++ b/net/ipv4/netfilter/ip_fw_compat.c @@ -15,6 +15,10 @@ struct notifier_block; #include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack_core.h> +/* Theoretically, we could one day use 2.4 helpers, but for now it + just confuses depmod --RR */ +EXPORT_NO_SYMBOLS; + static struct firewall_ops *fwops; /* From ip_fw_compat_redir.c */ diff --git a/net/ipv4/netfilter/ip_fw_compat_masq.c b/net/ipv4/netfilter/ip_fw_compat_masq.c index ce3180d39..e68804d65 100644 --- a/net/ipv4/netfilter/ip_fw_compat_masq.c +++ b/net/ipv4/netfilter/ip_fw_compat_masq.c @@ -85,7 +85,12 @@ do_masquerade(struct sk_buff **pskb, const struct net_device *dev) newsrc, newsrc, { htons(61000) }, { htons(65095) } } } }); - ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); + ret = ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); + if (ret != NF_ACCEPT) { + WRITE_UNLOCK(&ip_nat_lock); + return ret; + } + place_in_hashes(ct, info); info->initialized = 1; } else diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c index c3d8ccab0..54f89f765 100644 --- a/net/ipv4/netfilter/ip_nat_ftp.c +++ b/net/ipv4/netfilter/ip_nat_ftp.c @@ -372,8 +372,9 @@ static unsigned int help(struct ip_conntrack *ct, newseq = ntohl(tcph->seq) + ftp[dir].syn_offset_before; newseq = htonl(newseq); - /* Ack adjust */ - if (after(ntohl(tcph->ack_seq), ftp[!dir].syn_correction_pos)) + /* Ack adjust: other dir sees offset seq numbers */ + if (after(ntohl(tcph->ack_seq) - ftp[!dir].syn_offset_before, + ftp[!dir].syn_correction_pos)) newack = ntohl(tcph->ack_seq) - ftp[!dir].syn_offset_after; else newack = ntohl(tcph->ack_seq) - ftp[!dir].syn_offset_before; diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 3334a64c2..10d09a6bd 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -7,6 +7,7 @@ /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General Public Licence. */ +#include <linux/config.h> #include <linux/types.h> #include <linux/ip.h> #include <linux/netfilter.h> @@ -161,6 +162,34 @@ ip_nat_out(unsigned int hooknum, return ip_nat_fn(hooknum, pskb, in, out, okfn); } +/* FIXME: change in oif may mean change in hh_len. Check and realloc + --RR */ +static int +route_me_harder(struct sk_buff *skb) +{ + struct iphdr *iph = skb->nh.iph; + struct rtable *rt; + struct rt_key key = { dst:iph->daddr, + src:iph->saddr, + oif:skb->sk ? skb->sk->bound_dev_if : 0, + tos:RT_TOS(iph->tos)|RTO_CONN, +#ifdef CONFIG_IP_ROUTE_FWMARK + fwmark:skb->nfmark +#endif + }; + + if (ip_route_output_key(&rt, &key) != 0) { + printk("route_me_harder: No more route.\n"); + return -EINVAL; + } + + /* Drop old route. */ + dst_release(skb->dst); + + skb->dst = &rt->u.dst; + return 0; +} + static unsigned int ip_nat_local_fn(unsigned int hooknum, struct sk_buff **pskb, @@ -168,12 +197,23 @@ ip_nat_local_fn(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { + u_int32_t saddr, daddr; + unsigned int ret; + /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) return NF_ACCEPT; - return ip_nat_fn(hooknum, pskb, in, out, okfn); + saddr = (*pskb)->nh.iph->saddr; + daddr = (*pskb)->nh.iph->daddr; + + ret = ip_nat_fn(hooknum, pskb, in, out, okfn); + if (ret != NF_DROP && ret != NF_STOLEN + && ((*pskb)->nh.iph->saddr != saddr + || (*pskb)->nh.iph->daddr != daddr)) + return route_me_harder(*pskb) == 0 ? ret : NF_DROP; + return ret; } /* We must be after connection tracking and before packet filtering. */ diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 85787ed88..73fd4eaf7 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -414,7 +414,7 @@ static struct sk_buff *netlink_build_message(ipq_queue_element_t *e, int *errp) return skb; nlmsg_failure: if (skb) - kfree(skb); + kfree_skb(skb); *errp = 0; printk(KERN_ERR "ip_queue: error creating netlink message\n"); return NULL; diff --git a/net/ipv4/netfilter/ipt_MIRROR.c b/net/ipv4/netfilter/ipt_MIRROR.c index d7718b557..cb5362dc2 100644 --- a/net/ipv4/netfilter/ipt_MIRROR.c +++ b/net/ipv4/netfilter/ipt_MIRROR.c @@ -89,7 +89,7 @@ static void ip_direct_send(struct sk_buff *skb) dst->neighbour->output(skb); else { printk(KERN_DEBUG "khm in MIRROR\n"); - kfree(skb); + kfree_skb(skb); } } diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 2d8ad255f..9c1088e76 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -21,12 +21,13 @@ struct in_device; #endif /* Send RST reply */ -static void send_reset(struct sk_buff *oldskb) +static void send_reset(struct sk_buff *oldskb, int local) { struct sk_buff *nskb; struct tcphdr *otcph, *tcph; struct rtable *rt; unsigned int otcplen; + u_int16_t tmp; int needs_ack; /* IP header checks: fragment, too short. */ @@ -64,8 +65,11 @@ static void send_reset(struct sk_buff *oldskb) tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); + /* Swap source and dest */ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr); - tcph->source = xchg(&tcph->dest, tcph->source); + tmp = tcph->source; + tcph->source = tcph->dest; + tcph->dest = tmp; /* Truncate to length (no data) */ tcph->doff = sizeof(struct tcphdr)/4; @@ -110,8 +114,9 @@ static void send_reset(struct sk_buff *oldskb) nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, nskb->nh.iph->ihl); - /* Routing */ - if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr, + /* Routing: if not headed for us, route won't like source */ + if (ip_route_output(&rt, nskb->nh.iph->daddr, + local ? nskb->nh.iph->saddr : 0, RT_TOS(nskb->nh.iph->tos) | RTO_CONN, 0) != 0) goto free_nskb; @@ -184,7 +189,7 @@ static unsigned int reject(struct sk_buff **pskb, } break; case IPT_TCP_RESET: - send_reset(*pskb); + send_reset(*pskb, hooknum == NF_IP_LOCAL_IN); break; } diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index cb9f18da3..c52ada64e 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -3,8 +3,14 @@ * * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling */ +#include <linux/config.h> #include <linux/module.h> #include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <net/sock.h> +#include <net/route.h> +#include <linux/ip.h> #define MANGLE_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT)) @@ -86,6 +92,34 @@ ipt_hook(unsigned int hook, return ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL); } +/* FIXME: change in oif may mean change in hh_len. Check and realloc + --RR */ +static int +route_me_harder(struct sk_buff *skb) +{ + struct iphdr *iph = skb->nh.iph; + struct rtable *rt; + struct rt_key key = { dst:iph->daddr, + src:iph->saddr, + oif:skb->sk ? skb->sk->bound_dev_if : 0, + tos:RT_TOS(iph->tos)|RTO_CONN, +#ifdef CONFIG_IP_ROUTE_FWMARK + fwmark:skb->nfmark +#endif + }; + + if (ip_route_output_key(&rt, &key) != 0) { + printk("route_me_harder: No more route.\n"); + return -EINVAL; + } + + /* Drop old route. */ + dst_release(skb->dst); + + skb->dst = &rt->u.dst; + return 0; +} + static unsigned int ipt_local_out_hook(unsigned int hook, struct sk_buff **pskb, @@ -93,6 +127,11 @@ ipt_local_out_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { + unsigned int ret; + u_int8_t tos; + u_int32_t saddr, daddr; + unsigned long nfmark; + /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { @@ -101,7 +140,22 @@ ipt_local_out_hook(unsigned int hook, return NF_ACCEPT; } - return ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL); + /* Save things which could affect route */ + nfmark = (*pskb)->nfmark; + saddr = (*pskb)->nh.iph->saddr; + daddr = (*pskb)->nh.iph->daddr; + tos = (*pskb)->nh.iph->tos; + + ret = ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL); + /* Reroute for ANY change. */ + if (ret != NF_DROP && ret != NF_STOLEN + && ((*pskb)->nh.iph->saddr != saddr + || (*pskb)->nh.iph->daddr != daddr + || (*pskb)->nfmark != nfmark + || (*pskb)->nh.iph->tos != tos)) + return route_me_harder(*pskb) == 0 ? ret : NF_DROP; + + return ret; } static struct nf_hook_ops ipt_ops[] diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c index 4839764e8..db57fedb9 100644 --- a/net/ipv4/protocol.c +++ b/net/ipv4/protocol.c @@ -112,10 +112,7 @@ static struct inet_protocol icmp_protocol = struct inet_protocol *inet_protocol_base = IPPROTO_PREVIOUS; -struct inet_protocol *inet_protos[MAX_INET_PROTOS] = -{ - NULL -}; +struct inet_protocol *inet_protos[MAX_INET_PROTOS]; /* * Add a protocol handler to the hash tables diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d4e9806a0..4734d8087 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.89 2000/08/09 11:59:04 davem Exp $ + * Version: $Id: route.c,v 1.90 2000/08/31 23:39:12 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -117,7 +117,7 @@ int ip_rt_mtu_expires = 10*60*HZ; int ip_rt_min_pmtu = 512+20+20; int ip_rt_min_advmss = 536; -static unsigned long rt_deadline = 0; +static unsigned long rt_deadline; #define RTprint(a...) printk(KERN_DEBUG a) @@ -1610,7 +1610,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr, * Major route resolver routine. */ -int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif) +int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey) { struct rt_key key; struct fib_result res; @@ -1620,25 +1620,31 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int unsigned hash; int free_res = 0; int err; + u32 tos; - tos &= IPTOS_RT_MASK|RTO_ONLINK; - key.dst = daddr; - key.src = saddr; + tos = oldkey->tos & (IPTOS_RT_MASK|RTO_ONLINK); + key.dst = oldkey->dst; + key.src = oldkey->src; key.tos = tos&IPTOS_RT_MASK; key.iif = loopback_dev.ifindex; - key.oif = oif; + key.oif = oldkey->oif; +#ifdef CONFIG_IP_ROUTE_FWMARK + key.fwmark = oldkey->fwmark; +#endif key.scope = (tos&RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE; res.fi = NULL; #ifdef CONFIG_IP_MULTIPLE_TABLES res.r = NULL; #endif - if (saddr) { - if (MULTICAST(saddr) || BADCLASS(saddr) || ZERONET(saddr)) + if (oldkey->src) { + if (MULTICAST(oldkey->src) + || BADCLASS(oldkey->src) + || ZERONET(oldkey->src)) return -EINVAL; /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ - dev_out = ip_dev_find(saddr); + dev_out = ip_dev_find(oldkey->src); if (dev_out == NULL) return -EINVAL; @@ -1650,8 +1656,8 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int of another iface. --ANK */ - if (oif == 0 && - (MULTICAST(daddr) || daddr == 0xFFFFFFFF)) { + if (oldkey->oif == 0 + && (MULTICAST(oldkey->dst) || oldkey->dst == 0xFFFFFFFF)) { /* Special hack: user can direct multicasts and limited broadcast via necessary interface without fiddling with IP_MULTICAST_IF or IP_PKTINFO. @@ -1674,8 +1680,8 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int dev_put(dev_out); dev_out = NULL; } - if (oif) { - dev_out = dev_get_by_index(oif); + if (oldkey->oif) { + dev_out = dev_get_by_index(oldkey->oif); if (dev_out == NULL) return -ENODEV; if (__in_dev_get(dev_out) == NULL) { @@ -1683,15 +1689,15 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int return -ENODEV; /* Wrong error code */ } - if (LOCAL_MCAST(daddr) || daddr == 0xFFFFFFFF) { + if (LOCAL_MCAST(oldkey->dst) || oldkey->dst == 0xFFFFFFFF) { if (!key.src) key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK); goto make_route; } if (!key.src) { - if (MULTICAST(daddr)) + if (MULTICAST(oldkey->dst)) key.src = inet_select_addr(dev_out, 0, key.scope); - else if (!daddr) + else if (!oldkey->dst) key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST); } } @@ -1712,7 +1718,7 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int if (fib_lookup(&key, &res)) { res.fi = NULL; - if (oif) { + if (oldkey->oif) { /* Apparently, routing tables are wrong. Assume, that the destination is on link. @@ -1800,7 +1806,7 @@ make_route: } else if (res.type == RTN_MULTICAST) { flags |= RTCF_MULTICAST|RTCF_LOCAL; read_lock(&inetdev_lock); - if (!__in_dev_get(dev_out) || !ip_check_mc(__in_dev_get(dev_out), daddr)) + if (!__in_dev_get(dev_out) || !ip_check_mc(__in_dev_get(dev_out), oldkey->dst)) flags &= ~RTCF_LOCAL; read_unlock(&inetdev_lock); /* If multicast route do not exist use @@ -1819,18 +1825,21 @@ make_route: atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; - rth->key.dst = daddr; + rth->key.dst = oldkey->dst; rth->key.tos = tos; - rth->key.src = saddr; + rth->key.src = oldkey->src; rth->key.iif = 0; - rth->key.oif = oif; + rth->key.oif = oldkey->oif; +#ifdef CONFIG_IP_ROUTE_FWMARK + rth->key.fwmark = oldkey->fwmark; +#endif rth->rt_dst = key.dst; rth->rt_src = key.src; #ifdef CONFIG_IP_ROUTE_NAT rth->rt_dst_map = key.dst; rth->rt_src_map = key.src; #endif - rth->rt_iif = oif ? : dev_out->ifindex; + rth->rt_iif = oldkey->oif ? : dev_out->ifindex; rth->u.dst.dev = dev_out; dev_hold(dev_out); rth->rt_gateway = key.dst; @@ -1850,7 +1859,7 @@ make_route: if (res.type == RTN_MULTICAST) { struct in_device *in_dev = in_dev_get(dev_out); if (in_dev) { - if (IN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(daddr)) { + if (IN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(oldkey->dst)) { rth->u.dst.input = ip_mr_input; rth->u.dst.output = ip_mc_output; } @@ -1864,7 +1873,7 @@ make_route: rth->rt_flags = flags; - hash = rt_hash_code(daddr, saddr^(oif<<5), tos); + hash = rt_hash_code(oldkey->dst, oldkey->src^(oldkey->oif<<5), tos); err = rt_intern_hash(hash, rth, rp); done: if (free_res) @@ -1881,21 +1890,24 @@ e_nobufs: goto done; } -int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif) +int ip_route_output_key(struct rtable **rp, const struct rt_key *key) { unsigned hash; struct rtable *rth; - hash = rt_hash_code(daddr, saddr^(oif<<5), tos); + hash = rt_hash_code(key->dst, key->src^(key->oif<<5), key->tos); read_lock_bh(&rt_hash_table[hash].lock); for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) { - if (rth->key.dst == daddr && - rth->key.src == saddr && + if (rth->key.dst == key->dst && + rth->key.src == key->src && rth->key.iif == 0 && - rth->key.oif == oif && - !((rth->key.tos^tos)&(IPTOS_RT_MASK|RTO_ONLINK)) && - ((tos&RTO_TPROXY) || !(rth->rt_flags&RTCF_TPROXY)) + rth->key.oif == key->oif && +#ifdef CONFIG_IP_ROUTE_FWMARK + rth->key.fwmark == key->fwmark && +#endif + !((rth->key.tos^key->tos)&(IPTOS_RT_MASK|RTO_ONLINK)) && + ((key->tos&RTO_TPROXY) || !(rth->rt_flags&RTCF_TPROXY)) ) { rth->u.dst.lastuse = jiffies; dst_hold(&rth->u.dst); @@ -1907,8 +1919,8 @@ int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif) } read_unlock_bh(&rt_hash_table[hash].lock); - return ip_route_output_slow(rp, daddr, saddr, tos, oif); -} + return ip_route_output_slow(rp, key); +} #ifdef CONFIG_RTNETLINK diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 4274045e8..d9f05c671 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.44 2000/08/09 11:59:04 davem Exp $ + * $Id: sysctl_net_ipv4.c,v 1.46 2000/09/16 09:38:30 davem Exp $ * * Begun April 1, 1996, Mike Shaver. * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS] @@ -15,19 +15,6 @@ #include <net/route.h> #include <net/tcp.h> -/* - * TCP configuration parameters - */ - -#define TCP_PMTU_DISC 0x00000001 /* perform PMTU discovery */ -#define TCP_CONG_AVOID 0x00000002 /* congestion avoidance algorithm */ -#define TCP_DELAY_ACKS 0x00000003 /* delayed ack stategy */ - -#if 0 -static int boolean_min = 0; -static int boolean_max = 1; -#endif - /* From icmp.c */ extern int sysctl_icmp_echo_ignore_all; extern int sysctl_icmp_echo_ignore_broadcasts; @@ -57,7 +44,10 @@ extern int inet_peer_maxttl; extern int inet_peer_gc_mintime; extern int inet_peer_gc_maxtime; -int tcp_retr1_max = 255; +static int tcp_retr1_max = 255; + +static int ip_local_port_range_min[] = { 1, 1 }; +static int ip_local_port_range_max[] = { 65535, 65535 }; struct ipv4_config ipv4_config; @@ -170,7 +160,8 @@ ctl_table ipv4_table[] = { sizeof(int), 0644, NULL, &proc_dointvec}, {NET_IPV4_LOCAL_PORT_RANGE, "ip_local_port_range", &sysctl_local_port_range, sizeof(sysctl_local_port_range), 0644, - NULL, &proc_dointvec}, + NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL, + ip_local_port_range_min, ip_local_port_range_max }, {NET_IPV4_ICMP_ECHO_IGNORE_ALL, "icmp_echo_ignore_all", &sysctl_icmp_echo_ignore_all, sizeof(int), 0644, NULL, &proc_dointvec}, @@ -213,8 +204,10 @@ ctl_table ipv4_table[] = { &sysctl_tcp_fack, sizeof(int), 0644, NULL, &proc_dointvec}, {NET_TCP_REORDERING, "tcp_reordering", &sysctl_tcp_reordering, sizeof(int), 0644, NULL, &proc_dointvec}, +#ifdef CONFIG_INET_ECN {NET_TCP_ECN, "tcp_ecn", &sysctl_tcp_ecn, sizeof(int), 0644, NULL, &proc_dointvec}, +#endif {NET_TCP_DSACK, "tcp_dsack", &sysctl_tcp_dsack, sizeof(int), 0644, NULL, &proc_dointvec}, {NET_TCP_MEM, "tcp_mem", diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index d828a7f3f..05027bc93 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.173 2000/08/15 20:15:23 davem Exp $ + * Version: $Id: tcp.c,v 1.174 2000/09/18 05:59:48 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -436,7 +436,7 @@ kmem_cache_t *tcp_timewait_cachep; atomic_t tcp_orphan_count = ATOMIC_INIT(0); -int sysctl_tcp_mem[3] = { 0, }; +int sysctl_tcp_mem[3]; int sysctl_tcp_wmem[3] = { 4*1024, 16*1024, 128*1024 }; int sysctl_tcp_rmem[3] = { 4*1024, 87380, 87380*2 }; @@ -1952,12 +1952,14 @@ int tcp_disconnect(struct sock *sk, int flags) sk->dport = 0; - sk->rcv_saddr = 0; - sk->saddr = 0; + if (!(sk->userlocks&SOCK_BINDADDR_LOCK)) { + sk->rcv_saddr = 0; + sk->saddr = 0; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - memset(&sk->net_pinfo.af_inet6.saddr, 0, 16); - memset(&sk->net_pinfo.af_inet6.rcv_saddr, 0, 16); + memset(&sk->net_pinfo.af_inet6.saddr, 0, 16); + memset(&sk->net_pinfo.af_inet6.rcv_saddr, 0, 16); #endif + } sk->shutdown = 0; sk->done = 0; @@ -2281,6 +2283,68 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, case TCP_WINDOW_CLAMP: val = tp->window_clamp; break; + case TCP_INFO: + { + struct tcp_info info; + u32 now = tcp_time_stamp; + + if(get_user(len,optlen)) + return -EFAULT; + info.tcpi_state = sk->state; + info.tcpi_ca_state = tp->ca_state; + info.tcpi_retransmits = tp->retransmits; + info.tcpi_probes = tp->probes_out; + info.tcpi_backoff = tp->backoff; + info.tcpi_options = 0; + if (tp->tstamp_ok) + info.tcpi_options |= TCPI_OPT_TIMESTAMPS; + if (tp->sack_ok) + info.tcpi_options |= TCPI_OPT_SACK; + if (tp->wscale_ok) { + info.tcpi_options |= TCPI_OPT_WSCALE; + info.tcpi_snd_wscale = tp->snd_wscale; + info.tcpi_rcv_wscale = tp->rcv_wscale; + } else { + info.tcpi_snd_wscale = 0; + info.tcpi_rcv_wscale = 0; + } +#ifdef CONFIG_INET_ECN + if (tp->ecn_flags&TCP_ECN_OK) + info.tcpi_options |= TCPI_OPT_ECN; +#endif + + info.tcpi_rto = (1000000*tp->rto)/HZ; + info.tcpi_ato = (1000000*tp->ack.ato)/HZ; + info.tcpi_snd_mss = tp->mss_cache; + info.tcpi_rcv_mss = tp->ack.rcv_mss; + + info.tcpi_unacked = tp->packets_out; + info.tcpi_sacked = tp->sacked_out; + info.tcpi_lost = tp->lost_out; + info.tcpi_retrans = tp->retrans_out; + info.tcpi_fackets = tp->fackets_out; + + info.tcpi_last_data_sent = ((now - tp->lsndtime)*1000)/HZ; + info.tcpi_last_ack_sent = 0; + info.tcpi_last_data_recv = ((now - tp->ack.lrcvtime)*1000)/HZ; + info.tcpi_last_ack_recv = ((now - tp->rcv_tstamp)*1000)/HZ; + + info.tcpi_pmtu = tp->pmtu_cookie; + info.tcpi_rcv_ssthresh = tp->rcv_ssthresh; + info.tcpi_rtt = ((1000000*tp->srtt)/HZ)>>3; + info.tcpi_rttvar = ((1000000*tp->mdev)/HZ)>>2; + info.tcpi_snd_ssthresh = tp->snd_ssthresh; + info.tcpi_snd_cwnd = tp->snd_cwnd; + info.tcpi_advmss = tp->advmss; + info.tcpi_reordering = tp->reordering; + + len = min(len, sizeof(info)); + if(put_user(len, optlen)) + return -EFAULT; + if(copy_to_user(optval, &info,len)) + return -EFAULT; + return 0; + } default: return -ENOPROTOOPT; }; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 76791d724..ea9d18d97 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.198 2000/08/15 20:15:23 davem Exp $ + * Version: $Id: tcp_input.c,v 1.202 2000/09/21 01:05:38 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -58,6 +58,7 @@ * J Hadi Salim: ECN support */ +#include <linux/config.h> #include <linux/mm.h> #include <linux/sysctl.h> #include <net/tcp.h> @@ -73,7 +74,11 @@ int sysctl_tcp_window_scaling = 1; int sysctl_tcp_sack = 1; int sysctl_tcp_fack = 1; int sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH; +#ifdef CONFIG_INET_ECN int sysctl_tcp_ecn = 1; +#else +int sysctl_tcp_ecn = 0; +#endif int sysctl_tcp_dsack = 1; int sysctl_tcp_app_win = 31; int sysctl_tcp_adv_win_scale = 2; @@ -1488,10 +1493,8 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, case TCP_CA_Disorder: tcp_try_undo_dsack(sk, tp); - if (IsReno(tp) || !tp->undo_marker) { - tp->undo_marker = 0; - tp->ca_state = TCP_CA_Open; - } + tp->undo_marker = 0; + tp->ca_state = TCP_CA_Open; break; case TCP_CA_Recovery: @@ -1819,7 +1822,9 @@ static int tcp_ack_update_window(struct sock *sk, struct tcp_opt *tp, #ifdef TCP_DEBUG if (before(tp->snd_una + tp->snd_wnd, tp->snd_nxt)) { if (net_ratelimit()) - printk(KERN_DEBUG "TCP: peer shrinks window. Bad, what else can I say?\n"); + printk(KERN_DEBUG "TCP: peer %u.%u.%u.%u:%u/%u shrinks window %u:%u:%u. Bad, what else can I say?\n", + NIPQUAD(sk->daddr), htons(sk->dport), sk->num, + tp->snd_una, tp->snd_wnd, tp->snd_nxt); } #endif @@ -1948,7 +1953,7 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp) if (opsize < 2) /* "silly options" */ return; if (opsize > length) - break; /* don't parse partial options */ + return; /* don't parse partial options */ switch(opcode) { case TCPOPT_MSS: if(opsize==TCPOLEN_MSS && th->syn) { diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0c1e678ef..d2a79b4b1 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.212 2000/08/18 17:10:04 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.213 2000/09/18 05:59:48 davem Exp $ * * IPv4 specific functions * @@ -82,21 +82,21 @@ void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, * 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 = NULL; +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 = NULL; +struct tcp_bind_hashbucket *tcp_bhash; -int tcp_bhash_size = 0; -int tcp_ehash_size = 0; +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. */ -struct sock *tcp_listening_hash[TCP_LHTABLE_SIZE] = { NULL, }; +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, }; @@ -300,6 +300,7 @@ __inline__ void __tcp_put_port(struct sock *sk) sk->bind_next->bind_pprev = sk->bind_pprev; *(sk->bind_pprev) = sk->bind_next; sk->prev = NULL; + sk->num = 0; if (tb->owners == NULL) { if (tb->next) tb->next->pprev = tb->pprev; diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index ef7fc36cb..fea27faea 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_minisocks.c,v 1.1 2000/08/09 11:59:04 davem Exp $ + * Version: $Id: tcp_minisocks.c,v 1.4 2000/09/18 05:59:48 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -662,6 +662,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, sock_lock_init(newsk); bh_lock_sock(newsk); + newsk->dst_lock = RW_LOCK_UNLOCKED; atomic_set(&newsk->rmem_alloc, 0); skb_queue_head_init(&newsk->receive_queue); atomic_set(&newsk->wmem_alloc, 0); @@ -671,8 +672,10 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, newsk->forward_alloc = 0; newsk->done = 0; + newsk->userlocks = sk->userlocks & ~SOCK_BINDPORT_LOCK; newsk->proc = 0; newsk->backlog.head = newsk->backlog.tail = NULL; + newsk->callback_lock = RW_LOCK_UNLOCKED; skb_queue_head_init(&newsk->error_queue); newsk->write_space = tcp_write_space; #ifdef CONFIG_FILTER @@ -742,7 +745,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, /* Back to base struct sock members. */ newsk->err = 0; newsk->priority = 0; - atomic_set(&newsk->refcnt, 1); + atomic_set(&newsk->refcnt, 2); #ifdef INET_REFCNT_DEBUG atomic_inc(&inet_sock_nr); #endif @@ -966,5 +969,6 @@ int tcp_child_process(struct sock *parent, struct sock *child, } bh_unlock_sock(child); + sock_put(child); return ret; } diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index d98376840..5e5af83c2 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -29,7 +29,7 @@ int sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES; int sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL; int sysctl_tcp_retries1 = TCP_RETR1; int sysctl_tcp_retries2 = TCP_RETR2; -int sysctl_tcp_orphan_retries = 0; +int sysctl_tcp_orphan_retries; static void tcp_write_timer(unsigned long); static void tcp_delack_timer(unsigned long); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 59afc3cee..ff8a3d109 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.85 2000/08/09 11:59:04 davem Exp $ + * Version: $Id: udp.c,v 1.87 2000/09/20 02:11:34 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -126,7 +126,7 @@ struct sock *udp_hash[UDP_HTABLE_SIZE]; rwlock_t udp_hash_lock = RW_LOCK_UNLOCKED; /* Shared by v4/v6 udp. */ -int udp_port_rover = 0; +int udp_port_rover; static int udp_v4_get_port(struct sock *sk, unsigned short snum) { @@ -188,6 +188,15 @@ gotit: } } sk->num = snum; + if (sk->pprev == NULL) { + struct sock **skp = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; + if ((sk->next = *skp) != NULL) + (*skp)->pprev = &sk->next; + *skp = sk; + sk->pprev = skp; + sock_prot_inc_use(sk->prot); + sock_hold(sk); + } write_unlock_bh(&udp_hash_lock); return 0; @@ -198,16 +207,7 @@ fail: static void udp_v4_hash(struct sock *sk) { - struct sock **skp = &udp_hash[sk->num & (UDP_HTABLE_SIZE - 1)]; - - write_lock_bh(&udp_hash_lock); - if ((sk->next = *skp) != NULL) - (*skp)->pprev = &sk->next; - *skp = sk; - sk->pprev = skp; - sock_prot_inc_use(sk->prot); - sock_hold(sk); - write_unlock_bh(&udp_hash_lock); + BUG(); } static void udp_v4_unhash(struct sock *sk) @@ -218,6 +218,7 @@ static void udp_v4_unhash(struct sock *sk) sk->next->pprev = sk->pprev; *sk->pprev = sk->next; sk->pprev = NULL; + sk->num = 0; sock_prot_dec_use(sk->prot); __sock_put(sk); } @@ -493,8 +494,6 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len) if (usin->sin_family != AF_INET) { if (usin->sin_family != AF_UNSPEC) return -EINVAL; - if (net_ratelimit()) - printk("Remind Kuznetsov, he has to repair %s eventually\n", current->comm); } ufh.daddr = usin->sin_addr.s_addr; @@ -678,6 +677,8 @@ 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! @@ -733,26 +734,21 @@ out: csum_copy_err: UDP_INC_STATS_BH(UdpInErrors); - /* Clear queue. */ - if (flags&MSG_PEEK) { - int clear = 0; + if (flags&(MSG_PEEK|MSG_DONTWAIT)) { + struct sk_buff *skb2; + spin_lock_irq(&sk->receive_queue.lock); - if (skb == skb_peek(&sk->receive_queue)) { + skb2 = skb_peek(&sk->receive_queue); + if ((flags & MSG_PEEK) && skb == skb2) { __skb_unlink(skb, &sk->receive_queue); - clear = 1; } spin_unlock_irq(&sk->receive_queue.lock); - if (clear) - kfree_skb(skb); - } - - skb_free_datagram(sk, skb); - - /* - * Error for blocking case is chosen to masquerade - * as some normal condition. - */ - return (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH; + skb_free_datagram(sk, skb); + if ((flags & MSG_DONTWAIT) && !skb2) + return -EAGAIN; + } else + skb_free_datagram(sk, skb); + goto retry; } int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) @@ -797,10 +793,21 @@ int udp_disconnect(struct sock *sk, int flags) */ sk->state = TCP_CLOSE; - sk->rcv_saddr = 0; sk->daddr = 0; sk->dport = 0; sk->bound_dev_if = 0; + if (!(sk->userlocks&SOCK_BINDADDR_LOCK)) { + sk->rcv_saddr = 0; + sk->saddr = 0; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + memset(&sk->net_pinfo.af_inet6.saddr, 0, 16); + memset(&sk->net_pinfo.af_inet6.rcv_saddr, 0, 16); +#endif + } + if (!(sk->userlocks&SOCK_BINDPORT_LOCK)) { + sk->prot->unhash(sk); + sk->sport = 0; + } sk_dst_reset(sk); return 0; } diff --git a/net/ipv4/utils.c b/net/ipv4/utils.c index 5992cbc55..c6494d87f 100644 --- a/net/ipv4/utils.c +++ b/net/ipv4/utils.c @@ -57,12 +57,6 @@ char *in_ntoa(__u32 in) return(buff); } -char *in_ntoa2(__u32 in, char *buff) -{ - sprintf(buff, "%d.%d.%d.%d", NIPQUAD(in)); - return buff; -} - /* * Convert an ASCII string to binary IP. */ diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 8b039a658..869cac689 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -7,10 +7,11 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.56 2000/04/25 04:13:34 davem Exp $ + * $Id: af_inet6.c,v 1.58 2000/09/18 05:59:48 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support + * Arnaldo Melo : check proc_net_create return, cleanups * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -189,7 +190,7 @@ static int inet6_create(struct socket *sock, int protocol) if (sk->prot->init) { int err = sk->prot->init(sk); if (err != 0) { - sk->dead = 1; + MOD_DEC_USE_COUNT; inet_sock_release(sk); return(err); } @@ -295,10 +296,13 @@ static int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EADDRINUSE; } + if (addr_type != IPV6_ADDR_ANY) + sk->userlocks |= SOCK_BINDADDR_LOCK; + if (snum) + sk->userlocks |= SOCK_BINDPORT_LOCK; sk->sport = ntohs(sk->num); sk->dport = 0; sk->daddr = 0; - sk->prot->hash(sk); release_sock(sk); return 0; @@ -395,10 +399,8 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { case FIOSETOWN: case SIOCSPGRP: - err = get_user(pid, (int *) arg); - if(err) - return err; - + if (get_user(pid, (int *) arg)) + return -EFAULT; /* see sock_no_fcntl */ if (current->pid != pid && current->pgrp != -pid && !capable(CAP_NET_ADMIN)) @@ -407,10 +409,7 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return(0); case FIOGETOWN: case SIOCGPGRP: - err = put_user(sk->proc,(int *)arg); - if(err) - return err; - return(0); + return put_user(sk->proc,(int *)arg); case SIOCGSTAMP: if(sk->stamp.tv_sec==0) return -ENOENT; @@ -550,6 +549,20 @@ void __init inet6_proto_init(struct net_proto *pro) err = igmp6_init(&inet6_family_ops); if (err) goto igmp_fail; + /* Create /proc/foo6 entries. */ +#ifdef CONFIG_PROC_FS + err = -ENOMEM; + if (!proc_net_create("raw6", 0, raw6_get_info)) + goto proc_raw6_fail; + if (!proc_net_create("tcp6", 0, tcp6_get_info)) + goto proc_tcp6_fail; + if (!proc_net_create("udp6", 0, udp6_get_info)) + goto proc_udp6_fail; + if (!proc_net_create("sockstat6", 0, afinet6_get_info)) + goto proc_sockstat6_fail; + if (!proc_net_create("snmp6", 0, afinet6_get_snmp)) + goto proc_snmp6_fail; +#endif ipv6_netdev_notif_init(); ipv6_packet_init(); ip6_route_init(); @@ -561,15 +574,6 @@ void __init inet6_proto_init(struct net_proto *pro) udpv6_init(); tcpv6_init(); - /* Create /proc/foo6 entries. */ -#ifdef CONFIG_PROC_FS - proc_net_create("raw6", 0, raw6_get_info); - proc_net_create("tcp6", 0, tcp6_get_info); - proc_net_create("udp6", 0, udp6_get_info); - proc_net_create("sockstat6", 0, afinet6_get_info); - proc_net_create("snmp6", 0, afinet6_get_snmp); -#endif - /* Now the userspace is allowed to create INET6 sockets. */ (void) sock_register(&inet6_family_ops); @@ -579,6 +583,18 @@ void __init inet6_proto_init(struct net_proto *pro) return; #endif +#ifdef CONFIG_PROC_FS +proc_snmp6_fail: + proc_net_remove("sockstat6"); +proc_sockstat6_fail: + proc_net_remove("udp6"); +proc_udp6_fail: + proc_net_remove("tcp6"); +proc_tcp6_fail: + proc_net_remove("raw6"); +proc_raw6_fail: + igmp6_cleanup(); +#endif igmp_fail: ndisc_cleanup(); ndisc_fail: diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 3edc09a64..49fc32f59 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque <roque@di.fc.ul.pt> * - * $Id: ip6_fib.c,v 1.21 2000/05/03 06:37:07 davem Exp $ + * $Id: ip6_fib.c,v 1.22 2000/09/12 00:38:34 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -638,10 +638,8 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, if (narg->addr) { st = fib6_lookup_1(fn->subtree, narg); - if (!(st->fn_flags & RTN_ROOT)) - { + if (st && !(st->fn_flags & RTN_ROOT)) return st; - } } } #endif diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 62b89af5c..6121e2d24 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque <roque@di.fc.ul.pt> * - * $Id: mcast.c,v 1.32 2000/07/26 01:04:21 davem Exp $ + * $Id: mcast.c,v 1.33 2000/09/18 05:59:48 davem Exp $ * * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c * @@ -766,7 +766,6 @@ int __init igmp6_init(struct net_proto_family *ops) return 0; } -#ifdef MODULE void igmp6_cleanup(void) { sock_release(igmp6_socket); @@ -775,4 +774,3 @@ void igmp6_cleanup(void) remove_proc_entry("net/igmp6", 0); #endif } -#endif diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index accc87cbe..43ac35004 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c @@ -32,11 +32,8 @@ #include <net/ipv6.h> #include <net/protocol.h> -struct inet6_protocol *inet6_protocol_base = NULL; -struct inet6_protocol *inet6_protos[MAX_INET_PROTOS] = -{ - NULL -}; +struct inet6_protocol *inet6_protocol_base; +struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; void inet6_add_protocol(struct inet6_protocol *prot) { diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b4a00b171..4d95aa40b 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.56 2000/08/09 11:59:04 davem Exp $ + * $Id: udp.c,v 1.57 2000/09/18 05:59:48 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -119,6 +119,15 @@ gotit: } sk->num = snum; + if (sk->pprev == NULL) { + struct sock **skp = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; + if ((sk->next = *skp) != NULL) + (*skp)->pprev = &sk->next; + *skp = sk; + sk->pprev = skp; + sock_prot_inc_use(sk->prot); + sock_hold(sk); + } write_unlock_bh(&udp_hash_lock); return 0; @@ -129,16 +138,7 @@ fail: static void udp_v6_hash(struct sock *sk) { - struct sock **skp = &udp_hash[sk->num & (UDP_HTABLE_SIZE - 1)]; - - write_lock_bh(&udp_hash_lock); - if ((sk->next = *skp) != NULL) - (*skp)->pprev = &sk->next; - *skp = sk; - sk->pprev = skp; - sock_prot_inc_use(sk->prot); - sock_hold(sk); - write_unlock_bh(&udp_hash_lock); + BUG(); } static void udp_v6_unhash(struct sock *sk) @@ -149,6 +149,7 @@ static void udp_v6_unhash(struct sock *sk) sk->next->pprev = sk->pprev; *sk->pprev = sk->next; sk->pprev = NULL; + sk->num = 0; sock_prot_dec_use(sk->prot); __sock_put(sk); } diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index d4e4802b9..27d95703b 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -30,6 +30,7 @@ * Jonathan(G4KLX) Removed hdrincl. * NET/ROM 007 Jonathan(G4KLX) New timer architecture. * Impmented Idle timer. + * Arnaldo C. Melo s/suser/capable/, micro cleanups */ #include <linux/config.h> @@ -437,10 +438,7 @@ static int nr_getsockopt(struct socket *sock, int level, int optname, if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, &val, len)) - return -EFAULT; - - return 0; + return copy_to_user(optval, &val, len) ? -EFAULT : 0; } static int nr_listen(struct socket *sock, int backlog) @@ -616,7 +614,7 @@ full_sockaddr_ax25)) * Only the super user can set an arbitrary user callsign. */ if (addr->fsa_ax25.sax25_ndigis == 1) { - if (!suser()) + if (!capable(CAP_NET_BIND_SERVICE)) return -EACCES; sk->protinfo.nr->user_addr = addr->fsa_digipeater[0]; sk->protinfo.nr->source_addr = addr->fsa_ax25.sax25_call; @@ -624,7 +622,7 @@ full_sockaddr_ax25)) source = &addr->fsa_ax25.sax25_call; if ((user = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !suser()) + if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) return -EPERM; user = source; } @@ -680,7 +678,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, source = (ax25_address *)dev->dev_addr; if ((user = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !suser()) + if (ax25_uid_policy && !capable(CAP_NET_ADMIN)) return -EPERM; user = source; } @@ -1111,9 +1109,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) amount = 0; - if (put_user(amount, (int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (int *)arg); } case TIOCINQ: { @@ -1122,18 +1118,14 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->receive_queue)) != NULL) amount = skb->len; - if (put_user(amount, (int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (int *)arg); } case SIOCGSTAMP: if (sk != NULL) { if (sk->stamp.tv_sec == 0) return -ENOENT; - if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; } return -EINVAL; @@ -1152,7 +1144,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCADDRT: case SIOCDELRT: case SIOCNRDECOBS: - if (!suser()) return -EPERM; + if (!capable(CAP_NET_ADMIN)) return -EPERM; return nr_rt_ioctl(cmd, (void *)arg); default: diff --git a/net/netsyms.c b/net/netsyms.c index a7be82cbd..8579c5b2f 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -212,7 +212,7 @@ EXPORT_SYMBOL(br_ioctl_hook); EXPORT_SYMBOL(inetdev_lock); EXPORT_SYMBOL(inet_add_protocol); EXPORT_SYMBOL(inet_del_protocol); -EXPORT_SYMBOL(ip_route_output); +EXPORT_SYMBOL(ip_route_output_key); EXPORT_SYMBOL(ip_route_input); EXPORT_SYMBOL(icmp_send); EXPORT_SYMBOL(icmp_reply); @@ -364,7 +364,6 @@ EXPORT_SYMBOL(tcp_cwnd_application_limited); EXPORT_SYMBOL(xrlim_allow); EXPORT_SYMBOL(tcp_write_xmit); -EXPORT_SYMBOL(dev_loopback_xmit); EXPORT_SYMBOL(tcp_v4_remember_stamp); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 990431eb8..b7827f09f 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.41 2000/08/10 01:21:14 davem Exp $ + * Version: $Id: af_packet.c,v 1.42 2000/08/29 03:44:56 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 1bf9f7ab6..f61d9cd34 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -21,6 +21,7 @@ * Implemented idle timer. * Added use count to neighbour. * Tomi(OH2BNS) Fixed rose_getname(). + * Arnaldo C. Melo s/suser/capable/ + micro cleanups */ #include <linux/config.h> @@ -510,10 +511,7 @@ static int rose_getsockopt(struct socket *sock, int level, int optname, if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, &val, len)) - return -EFAULT; - - return 0; + return copy_to_user(optval, &val, len) ? -EFAULT : 0; } static int rose_listen(struct socket *sock, int backlog) @@ -695,7 +693,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) source = &addr->srose_call; if ((user = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !suser()) + if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) return -EACCES; user = source; } @@ -1236,9 +1234,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) amount = 0; - if (put_user(amount, (unsigned int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (unsigned int *)arg); } case TIOCINQ: { @@ -1247,18 +1243,14 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->receive_queue)) != NULL) amount = skb->len; - if (put_user(amount, (unsigned int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (unsigned int *)arg); } case SIOCGSTAMP: if (sk != NULL) { if (sk->stamp.tv_sec == 0) return -ENOENT; - if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; } return -EINVAL; @@ -1284,9 +1276,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) struct rose_cause_struct rose_cause; rose_cause.cause = sk->protinfo.rose->cause; rose_cause.diagnostic = sk->protinfo.rose->diagnostic; - if (copy_to_user((void *)arg, &rose_cause, sizeof(struct rose_cause_struct))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &rose_cause, sizeof(struct rose_cause_struct)) ? -EFAULT : 0; } case SIOCRSSCAUSE: { @@ -1299,7 +1289,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } case SIOCRSSL2CALL: - if (!suser()) return -EPERM; + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) ax25_listen_release(&rose_callsign, NULL); if (copy_from_user(&rose_callsign, (void *)arg, sizeof(ax25_address))) @@ -1309,9 +1299,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return 0; case SIOCRSGL2CALL: - if (copy_to_user((void *)arg, &rose_callsign, sizeof(ax25_address))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &rose_callsign, sizeof(ax25_address)) ? -EFAULT : 0; case SIOCRSACCEPT: if (sk->protinfo.rose->state == ROSE_STATE_5) { diff --git a/net/socket.c b/net/socket.c index 5691718c9..9fdc84fb5 100644 --- a/net/socket.c +++ b/net/socket.c @@ -822,7 +822,7 @@ int sock_create(int family, int type, int protocol, struct socket **res) * Check protocol is in range */ if(family<0 || family>=NPROTO) - return -EINVAL; + return -EAFNOSUPPORT; /* Compatibility. diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 8033ed6c1..3da9ff392 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -180,7 +180,8 @@ unx_marshal(struct rpc_task *task, u32 *p, int ruid) memcpy(p, clnt->cl_nodename, n); p += (n + 3) >> 2; - if (ruid) { + /* Note: we don't use real uid if it involves raising priviledge */ + if (ruid && cred->uc_uid != 0 && cred->uc_gid != 0) { *p++ = htonl((u32) cred->uc_uid); *p++ = htonl((u32) cred->uc_gid); } else { diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index a908812c5..b384b754c 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -708,7 +708,7 @@ call_decode(struct rpc_task *task) * The following is an NFS-specific hack to cater for setuid * processes whose uid is mapped to nobody on the server. */ - if (task->tk_client->cl_prog == NFS_PROGRAM && + if (task->tk_client->cl_droppriv && (ntohl(*p) == NFSERR_ACCES || ntohl(*p) == NFSERR_PERM)) { if (RPC_IS_SETUID(task) && task->tk_suid_retry) { dprintk("RPC: %4d retry squashed uid\n", task->tk_pid); @@ -824,6 +824,7 @@ call_verify(struct rpc_task *task) case RPC_AUTH_TOOWEAK: printk(KERN_NOTICE "call_verify: server requires stronger " "authentication.\n"); + break; default: printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n); error = -EIO; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index ce0c7fa04..de359d2f5 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -24,7 +24,7 @@ #ifdef RPC_DEBUG #define RPCDBG_FACILITY RPCDBG_SCHED -static int rpc_task_id = 0; +static int rpc_task_id; #endif /* @@ -56,7 +56,7 @@ static struct rpc_wait_queue delay_queue = RPC_INIT_WAITQ("delayq"); /* * All RPC tasks are linked into this list */ -static struct rpc_task * all_tasks = NULL; +static struct rpc_task * all_tasks; /* * rpciod-related stuff @@ -64,9 +64,9 @@ static struct rpc_task * all_tasks = NULL; static DECLARE_WAIT_QUEUE_HEAD(rpciod_idle); static DECLARE_WAIT_QUEUE_HEAD(rpciod_killer); static DECLARE_MUTEX(rpciod_sema); -static unsigned int rpciod_users = 0; -static pid_t rpciod_pid = 0; -static int rpc_inhibit = 0; +static unsigned int rpciod_users; +static pid_t rpciod_pid; +static int rpc_inhibit; /* * Spinlock for wait queues. Access to the latter also has to be @@ -82,7 +82,7 @@ spinlock_t rpc_sched_lock = SPIN_LOCK_UNLOCKED; * This is the last-ditch buffer for NFS swap requests */ static u32 swap_buffer[PAGE_SIZE >> 2]; -static int swap_buffer_used = 0; +static int swap_buffer_used; /* * Make allocation of the swap_buffer SMP-safe diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index be49a16a1..fe2e5389c 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -25,14 +25,14 @@ /* * Declare the debug flags here */ -unsigned int rpc_debug = 0; -unsigned int nfs_debug = 0; -unsigned int nfsd_debug = 0; -unsigned int nlm_debug = 0; +unsigned int rpc_debug; +unsigned int nfs_debug; +unsigned int nfsd_debug; +unsigned int nlm_debug; #ifdef RPC_DEBUG -static struct ctl_table_header *sunrpc_table_header = NULL; +static struct ctl_table_header *sunrpc_table_header; static ctl_table sunrpc_table[]; void diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index e4e06e9be..b614a1f14 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1037,7 +1037,7 @@ tcp_write_space(struct sock *sk) return; /* Wait until we have enough socket memory */ - if (sock_wspace(sk) < min(sk->sndbuf,XPRT_MIN_WRITE_SPACE)) + if (!sock_writeable(sk)) return; spin_lock_bh(&xprt_sock_lock); @@ -1212,9 +1212,6 @@ do_xprt_transmit(struct rpc_task *task) */ while (1) { xprt->write_space = 0; - status = -ENOMEM; - if (sock_wspace(xprt->inet) < req->rq_slen + SOCK_MIN_WRITE_SPACE) - break; status = xprt_sendmsg(xprt, req); if (status < 0) diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index ebaaa7242..9af3a0e3d 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -20,6 +20,9 @@ * 2000-22-03 Daniela Squassoni Allowed disabling/enabling of * facilities negotiation and increased * the throughput upper limit. + * 2000-27-08 Arnaldo C. Melo s/suser/capable/ + micro cleanups + * 2000-04-09 Henner Eisen Set sock->state in x25_accept(). + * Fixed x25_output() related skb leakage. */ #include <linux/config.h> @@ -402,10 +405,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, &val, len)) - return -EFAULT; - - return 0; + return copy_to_user(optval, &val, len) ? -EFAULT : 0; } static int x25_listen(struct socket *sock, int backlog) @@ -723,6 +723,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) kfree_skb(skb); sk->ack_backlog--; newsock->sk = newsk; + newsock->state = SS_CONNECTED; return 0; } @@ -973,7 +974,11 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct if (msg->msg_flags & MSG_OOB) { skb_queue_tail(&sk->protinfo.x25->interrupt_out_queue, skb); } else { - x25_output(sk, skb); + err = x25_output(sk, skb); + if(err){ + len = err; + kfree_skb(skb); + } } x25_kick(sk); @@ -1067,9 +1072,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) amount = 0; - if (put_user(amount, (unsigned int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (unsigned int *)arg); } case TIOCINQ: { @@ -1078,18 +1081,14 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->receive_queue)) != NULL) amount = skb->len; - if (put_user(amount, (unsigned int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (unsigned int *)arg); } case SIOCGSTAMP: if (sk != NULL) { if (sk->stamp.tv_sec == 0) return -ENOENT; - if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; } return -EINVAL; @@ -1114,15 +1113,13 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return x25_subscr_ioctl(cmd, (void *)arg); case SIOCX25SSUBSCRIP: - if (!suser()) return -EPERM; + if (!capable(CAP_NET_ADMIN)) return -EPERM; return x25_subscr_ioctl(cmd, (void *)arg); case SIOCX25GFACILITIES: { struct x25_facilities facilities; facilities = sk->protinfo.x25->facilities; - if (copy_to_user((void *)arg, &facilities, sizeof(facilities))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &facilities, sizeof(facilities)) ? -EFAULT : 0; } case SIOCX25SFACILITIES: { @@ -1148,9 +1145,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCX25GCALLUSERDATA: { struct x25_calluserdata calluserdata; calluserdata = sk->protinfo.x25->calluserdata; - if (copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)) ? -EFAULT : 0; } case SIOCX25SCALLUSERDATA: { @@ -1166,9 +1161,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCX25GCAUSEDIAG: { struct x25_causediag causediag; causediag = sk->protinfo.x25->causediag; - if (copy_to_user((void *)arg, &causediag, sizeof(causediag))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &causediag, sizeof(causediag)) ? -EFAULT : 0; } default: diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index 1808361a6..d986022fb 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c @@ -14,6 +14,7 @@ * * History * X.25 001 Jonathan Naylor Started coding. + * 2000-09-04 Henner Eisen Prevent freeing a dangling skb. */ #include <linux/config.h> @@ -78,12 +79,13 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh) return x25_rx_call_request(skb, neigh, lci); /* - * Its not a Call Request, nor is it a control frame, throw it awa + * Its not a Call Request, nor is it a control frame. + * Let caller throw it away. */ /* x25_transmit_clear_request(neigh, lci, 0x0D); */ - kfree_skb(skb); + printk(KERN_DEBUG "x25_receive_data(): unknown frame type %2x\n",frametype); return 0; } diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index 34d065b83..d6b878371 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c @@ -17,6 +17,7 @@ * X.25 002 Jonathan Naylor New timer architecture. * mar/20/00 Daniela Squassoni Disabling/enabling of facilities * negotiation. + * 2000-09-04 Henner Eisen dev_hold() / dev_put() for x25_neigh. */ #include <linux/config.h> @@ -292,6 +293,7 @@ void x25_link_device_up(struct net_device *dev) init_timer(&x25_neigh->t20timer); + dev_hold(dev); x25_neigh->dev = dev; x25_neigh->state = X25_LINK_STATE_0; x25_neigh->extended = 0; @@ -349,8 +351,10 @@ void x25_link_device_down(struct net_device *dev) neigh = x25_neigh; x25_neigh = x25_neigh->next; - if (neigh->dev == dev) + if (neigh->dev == dev){ x25_remove_neigh(neigh); + dev_put(dev); + } } } diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c index 24fdf4d47..077f2c0b4 100644 --- a/net/x25/x25_out.c +++ b/net/x25/x25_out.c @@ -15,6 +15,7 @@ * History * X.25 001 Jonathan Naylor Started coding. * X.25 002 Jonathan Naylor New timer architecture. + * 2000-09-04 Henner Eisen Prevented x25_output() skb leakage. */ #include <linux/config.h> @@ -56,7 +57,7 @@ static int x25_pacsize_to_bytes(unsigned int pacsize) /* * This is where all X.25 information frames pass; */ -void x25_output(struct sock *sk, struct sk_buff *skb) +int x25_output(struct sock *sk, struct sk_buff *skb) { struct sk_buff *skbn; unsigned char header[X25_EXT_MIN_LEN]; @@ -73,9 +74,12 @@ void x25_output(struct sock *sk, struct sk_buff *skb) frontlen = skb_headroom(skb); while (skb->len > 0) { - if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL) - return; - + if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL){ + int unsent = skb->len - header_len; + SOCK_DEBUG(sk, "x25_output: framgent allocation failed, err=%d, %d bytes unsent\n", err, unsent); + return err; + } + skb_reserve(skbn, frontlen); len = (max_len > skb->len) ? skb->len : max_len; @@ -102,6 +106,7 @@ void x25_output(struct sock *sk, struct sk_buff *skb) } else { skb_queue_tail(&sk->write_queue, skb); } + return 0; } /* |