summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-10-05 01:18:40 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-10-05 01:18:40 +0000
commit012bb3e61e5eced6c610f9e036372bf0c8def2d1 (patch)
tree87efc733f9b164e8c85c0336f92c8fb7eff6d183 /net
parent625a1589d3d6464b5d90b8a0918789e3afffd220 (diff)
Merge with Linux 2.4.0-test9. Please check DECstation, I had a number
of rejects to fixup while integrating Linus patches. I also found that this kernel will only boot SMP on Origin; the UP kernel freeze soon after bootup with SCSI timeout messages. I commit this anyway since I found that the last CVS versions had the same problem.
Diffstat (limited to 'net')
-rw-r--r--net/Makefile241
-rw-r--r--net/appletalk/aarp.c3
-rw-r--r--net/atm/mpoa_proc.c7
-rw-r--r--net/ax25/af_ax25.c30
-rw-r--r--net/ax25/ax25_route.c3
-rw-r--r--net/ax25/ax25_uid.c4
-rw-r--r--net/core/dev.c90
-rw-r--r--net/core/sock.c7
-rw-r--r--net/decnet/af_decnet.c14
-rw-r--r--net/econet/af_econet.c13
-rw-r--r--net/ipv4/af_inet.c9
-rw-r--r--net/ipv4/arp.c31
-rw-r--r--net/ipv4/igmp.c9
-rw-r--r--net/ipv4/inetpeer.c4
-rw-r--r--net/ipv4/ip_output.c56
-rw-r--r--net/ipv4/ip_sockglue.c38
-rw-r--r--net/ipv4/netfilter/ip_fw_compat.c4
-rw-r--r--net/ipv4/netfilter/ip_fw_compat_masq.c7
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c42
-rw-r--r--net/ipv4/netfilter/ip_queue.c2
-rw-r--r--net/ipv4/netfilter/ipt_MIRROR.c2
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c15
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c56
-rw-r--r--net/ipv4/protocol.c5
-rw-r--r--net/ipv4/route.c80
-rw-r--r--net/ipv4/sysctl_net_ipv4.c25
-rw-r--r--net/ipv4/tcp.c76
-rw-r--r--net/ipv4/tcp_input.c19
-rw-r--r--net/ipv4/tcp_ipv4.c13
-rw-r--r--net/ipv4/tcp_minisocks.c8
-rw-r--r--net/ipv4/tcp_timer.c2
-rw-r--r--net/ipv4/udp.c69
-rw-r--r--net/ipv4/utils.c6
-rw-r--r--net/ipv6/af_inet6.c56
-rw-r--r--net/ipv6/ip6_fib.c6
-rw-r--r--net/ipv6/mcast.c4
-rw-r--r--net/ipv6/protocol.c7
-rw-r--r--net/ipv6/udp.c23
-rw-r--r--net/netrom/af_netrom.c26
-rw-r--r--net/netsyms.c3
-rw-r--r--net/packet/af_packet.c2
-rw-r--r--net/rose/af_rose.c30
-rw-r--r--net/socket.c2
-rw-r--r--net/sunrpc/auth_unix.c3
-rw-r--r--net/sunrpc/clnt.c3
-rw-r--r--net/sunrpc/sched.c12
-rw-r--r--net/sunrpc/sysctl.c10
-rw-r--r--net/sunrpc/xprt.c5
-rw-r--r--net/x25/af_x25.c41
-rw-r--r--net/x25/x25_dev.c6
-rw-r--r--net/x25/x25_link.c6
-rw-r--r--net/x25/x25_out.c13
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;
}
/*