aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@cc.helsinki.fi>1994-01-17 13:18:10 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:27 -0400
commite3e62943752a4c7960c04d452718a9b247fe185d (patch)
treed1c19ba60a81b8f63a013f529770e9d43ba26083
parent5f295b33cf4ea277617047421018a6cd75cc5dff (diff)
downloadarchive-e3e62943752a4c7960c04d452718a9b247fe185d.tar.gz
ALPHA-pl14q
-rw-r--r--Makefile2
-rw-r--r--drivers/FPU-emu/reg_div.S2
-rw-r--r--drivers/char/tty_ioctl.c2
-rw-r--r--net/inet/dev.c35
-rw-r--r--net/inet/ip.c4
-rw-r--r--net/inet/route.c83
-rw-r--r--net/inet/tcp.c66
7 files changed, 124 insertions, 70 deletions
diff --git a/Makefile b/Makefile
index 1ebcf6e..7028cdf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 0.99
PATCHLEVEL = 14
-ALPHA = p
+ALPHA = q
all: Version zImage
diff --git a/drivers/FPU-emu/reg_div.S b/drivers/FPU-emu/reg_div.S
index 558c594..570e4e0 100644
--- a/drivers/FPU-emu/reg_div.S
+++ b/drivers/FPU-emu/reg_div.S
@@ -237,7 +237,7 @@ L_return_zero:
#ifdef PARANOID
L_unknown_tags:
- push EX_INTERNAL | 0x208
+ pushl EX_INTERNAL | 0x208
call EXCEPTION
/* Generate a NaN for unknown tags */
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 49d8514..b6d7b48 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -584,6 +584,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
(unsigned long *) arg);
return 0;
case TIOCSTI:
+ if ((current->tty != dev) && !suser())
+ return -EACCES;
put_tty_queue(get_fs_byte((char *) arg), &tty->read_q);
return 0;
case TIOCGWINSZ:
diff --git a/net/inet/dev.c b/net/inet/dev.c
index 0ce0e7b..42a37e0 100644
--- a/net/inet/dev.c
+++ b/net/inet/dev.c
@@ -350,22 +350,29 @@ dev_get(char *name)
/* Find an interface that can handle addresses for a certain address. */
-struct device *
-dev_check(unsigned long addr)
+struct device * dev_check(unsigned long addr)
{
- struct device *dev;
-
- for (dev = dev_base; dev; dev = dev->next)
- if ((dev->flags & IFF_UP) && (dev->flags & IFF_POINTOPOINT) &&
- (addr == dev->pa_dstaddr))
+ struct device *dev;
+
+ for (dev = dev_base; dev; dev = dev->next) {
+ if (!(dev->flags & IFF_UP))
+ continue;
+ if (!(dev->flags & IFF_POINTOPOINT))
+ continue;
+ if (addr != dev->pa_dstaddr)
+ continue;
return dev;
- for (dev = dev_base; dev; dev = dev->next)
- if ((dev->flags & IFF_UP) && !(dev->flags & IFF_POINTOPOINT) &&
- (dev->flags & IFF_LOOPBACK ? (addr == dev->pa_addr) :
- (dev->pa_mask & addr) == (dev->pa_addr & dev->pa_mask)))
- break;
- /* no need to check broadcast addresses */
- return dev;
+ }
+ for (dev = dev_base; dev; dev = dev->next) {
+ if (!(dev->flags & IFF_UP))
+ continue;
+ if (dev->flags & IFF_POINTOPOINT)
+ continue;
+ if (dev->pa_mask & (addr ^ dev->pa_addr))
+ continue;
+ return dev;
+ }
+ return NULL;
}
diff --git a/net/inet/ip.c b/net/inet/ip.c
index 091998c..761f5f1 100644
--- a/net/inet/ip.c
+++ b/net/inet/ip.c
@@ -1295,6 +1295,10 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
continue;
memcpy(skb2, skb, skb->mem_len);
skb2->mem_addr = skb2;
+ skb2->ip_hdr = (struct iphdr *)(
+ (unsigned long)skb2 +
+ (unsigned long) skb->ip_hdr -
+ (unsigned long)skb);
skb2->h.raw = (unsigned char *)(
(unsigned long)skb2 +
(unsigned long) skb->h.raw -
diff --git a/net/inet/route.c b/net/inet/route.c
index c6bcdce..8fd88a0 100644
--- a/net/inet/route.c
+++ b/net/inet/route.c
@@ -15,6 +15,7 @@
* Alan Cox : cli() protects routing changes
* Rui Oliveira : ICMP routing table updates
* (rco@di.uminho.pt) Routing table insertion and update
+ * Linus Torvalds : Rewrote bits to be sensible
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -133,17 +134,11 @@ static inline unsigned long default_mask(unsigned long dst)
static unsigned long guess_mask(unsigned long dst, struct device * dev)
{
- unsigned long mask = 0xffffffff;
-
-/* this is a rather ugly optimization: works only on little-endian machines */
- while (mask & dst)
- mask <<= 8;
- if (mask)
- return ~mask;
-/* ok, no more hacks.. */
+ unsigned long mask;
+
+ if (!dst)
+ return 0;
mask = default_mask(dst);
- if (dev->flags & IFF_POINTOPOINT)
- return mask;
if ((dst ^ dev->pa_addr) & mask)
return mask;
return dev->pa_mask;
@@ -168,8 +163,8 @@ static inline struct device * get_gw_dev(unsigned long gw)
/*
* rewrote rt_add(), as the old one was weird. Linus
*/
-void
-rt_add(short flags, unsigned long dst, unsigned long mask, unsigned long gw, struct device *dev)
+void rt_add(short flags, unsigned long dst, unsigned long mask,
+ unsigned long gw, struct device *dev)
{
struct rtable *r, *rt;
struct rtable **rp;
@@ -267,12 +262,14 @@ static int rt_new(struct rtentry *r)
daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
mask = r->rt_genmask;
gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
+ dev = (struct device *) r->rt_dev;
if (flags & RTF_GATEWAY) {
if (r->rt_gateway.sa_family != AF_INET)
return -EAFNOSUPPORT;
- dev = get_gw_dev(gw);
- } else
+ if (!dev)
+ dev = get_gw_dev(gw);
+ } else if (!dev)
dev = dev_check(daddr);
if (dev == NULL)
@@ -286,15 +283,13 @@ static int rt_new(struct rtentry *r)
}
-static int
-rt_kill(struct rtentry *r)
+static int rt_kill(struct rtentry *r)
{
- struct sockaddr_in *trg;
+ struct sockaddr_in *trg;
- trg = (struct sockaddr_in *) &r->rt_dst;
- rt_del(trg->sin_addr.s_addr);
-
- return(0);
+ trg = (struct sockaddr_in *) &r->rt_dst;
+ rt_del(trg->sin_addr.s_addr);
+ return 0;
}
@@ -337,8 +332,10 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt)
rt->rt_dev->pa_brdaddr == daddr)
break;
}
- if (daddr == rt->rt_dev->pa_addr)
- rt = rt_loopback;
+ if (daddr == rt->rt_dev->pa_addr) {
+ if ((rt = rt_loopback) == NULL)
+ goto no_route;
+ }
rt->rt_use++;
return rt;
no_route:
@@ -346,39 +343,41 @@ no_route:
}
-int
-rt_ioctl(unsigned int cmd, void *arg)
+int rt_ioctl(unsigned int cmd, void *arg)
{
- struct device *dev;
- struct rtentry rt;
- char namebuf[32];
- int ret;
- int err;
+ struct device *dev;
+ struct rtentry rt;
+ char *devname;
+ int ret;
+ int err;
- switch(cmd) {
+ switch(cmd) {
case DDIOCSDBG:
ret = dbg_ioctl(arg, DBG_RT);
break;
case SIOCADDRT:
case SIOCDELRT:
- if (!suser()) return(-EPERM);
+ if (!suser())
+ return -EPERM;
err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
- if(err)
+ if (err)
return err;
memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
- if (rt.rt_dev) {
- err=verify_area(VERIFY_READ, rt.rt_dev, sizeof namebuf);
- if(err)
- return err;
- memcpy_fromfs(&namebuf, rt.rt_dev, sizeof namebuf);
- dev = dev_get(namebuf);
- rt.rt_dev = dev;
+ if ((devname = (char *) rt.rt_dev) != NULL) {
+ err = getname(devname, &devname);
+ if (err)
+ return err;
+ dev = dev_get(devname);
+ putname(devname);
+ if (!dev)
+ return -EINVAL;
+ rt.rt_dev = dev;
}
ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
break;
default:
ret = -EINVAL;
- }
+ }
- return(ret);
+ return ret;
}
diff --git a/net/inet/tcp.c b/net/inet/tcp.c
index 9160821..15d2d13 100644
--- a/net/inet/tcp.c
+++ b/net/inet/tcp.c
@@ -54,6 +54,9 @@
* Alan Cox : Handle FIN (more) properly (we hope).
* Alan Cox : RST frames sent on unsynchronised state ack error/
* Alan Cox : Put in missing check for SYN bit.
+ * Alan Cox : Added tcp_select_window() aka NET2E
+ * window non shrink trick.
+ * Alan Cox : Added a couple of small NET2E timer fixes
*
*
* To Fix:
@@ -61,7 +64,6 @@
* it causes a select. Linux can - given the official select semantics I
* feel that _really_ its the BSD network programs that are bust (notably
* inetd, which hangs occasionally because of this).
- * Proper processing of piggybacked data on connect.
* Add VJ Fastrecovery algorithm ?
* Protocol closedown badly messed up.
* Incompatiblity with spider ports (tcp hangs on that
@@ -154,6 +156,31 @@ diff(unsigned long seq1, unsigned long seq2)
return(~d+1);
}
+/* This routine picks a TCP windows for a socket based on
+ the following constraints
+
+ 1. The window can never be shrunk once it is offered (RFC 793)
+ 2. We limit memory per socket
+
+ For now we use NET2E3's heuristic of offering half the memory
+ we have handy. All is not as bad as this seems however because
+ of two things. Firstly we will bin packets even within the window
+ in order to get the data we are waiting for into the memory limit.
+ Secondly we bin common duplicate forms at receive time
+
+ Better heuristics welcome
+*/
+
+static int tcp_select_window(struct sock *sk)
+{
+ int new_window=sk->prot->rspace(sk)/2;
+
+ /* Enforce RFC793 - we've offered it we must live with it */
+ if(new_window<sk->window)
+ return(sk->window);
+
+ return(new_window);
+}
/* Enter the time wait state. */
@@ -308,7 +335,7 @@ tcp_readable(struct sock *sk)
if (skb->h.th->syn) amount--;
counted += sum;
}
-/* if (amount && skb->h.th->psh) break;*/
+ if (amount && skb->h.th->psh) break;
skb =(struct sk_buff *)skb->next; /* Move along */
} while(skb != sk->rqueue);
restore_flags(flags);
@@ -660,7 +687,7 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n");
t1->source = th->dest;
t1->seq = ntohl(sequence);
t1->ack = 1;
- sk->window = sk->prot->rspace(sk);
+ sk->window = tcp_select_window(sk);/*sk->prot->rspace(sk);*/
t1->window = ntohs(sk->window);
t1->res1 = 0;
t1->res2 = 0;
@@ -673,8 +700,12 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n");
sk->ack_backlog = 0;
sk->bytes_rcv = 0;
sk->ack_timed = 0;
- if (sk->send_head == NULL && sk->wfront == NULL) {
-/* delete_timer(sk);*/
+ if (sk->send_head == NULL && sk->wfront == NULL && sk->timeout == TIME_WRITE)
+ {
+ if(sk->keepopen)
+ reset_timer(sk,TIME_KEEPOPEN,TCP_TIMEOUT_LEN);
+ else
+ delete_timer(sk);
}
}
t1->ack_seq = ntohl(ack);
@@ -702,7 +733,7 @@ tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
sk->bytes_rcv = 0;
sk->ack_timed = 0;
th->ack_seq = htonl(sk->acked_seq);
- sk->window = sk->prot->rspace(sk);
+ sk->window = tcp_select_window(sk)/*sk->prot->rspace(sk)*/;
th->window = htons(sk->window);
return(sizeof(*th));
@@ -1049,7 +1080,7 @@ tcp_read_wakeup(struct sock *sk)
t1->psh = 0;
sk->ack_backlog = 0;
sk->bytes_rcv = 0;
- sk->window = sk->prot->rspace(sk);
+ sk->window = tcp_select_window(sk);/*sk->prot->rspace(sk);*/
t1->window = ntohs(sk->window);
t1->ack_seq = ntohl(sk->acked_seq);
t1->doff = sizeof(*t1)/4;
@@ -1225,7 +1256,7 @@ tcp_read_urg(struct sock * sk, int nonblock,
skb =(struct sk_buff *)skb->next;
} while(skb != sk->rqueue);
}
- sk->urg = 0;
+/*sk->urg = 0;*/
release_sock(sk);
return(0);
}
@@ -1522,7 +1553,7 @@ tcp_shutdown(struct sock *sk, int how)
buff->h.seq = sk->send_seq;
t1->ack = 1;
t1->ack_seq = ntohl(sk->acked_seq);
- t1->window = ntohs(sk->prot->rspace(sk));
+ t1->window = ntohs(sk->window=tcp_select_window(sk)/*sk->prot->rspace(sk)*/);
t1->fin = 1;
t1->rst = 0;
t1->doff = sizeof(*t1)/4;
@@ -1871,7 +1902,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
t1->source = newsk->dummy_th.source;
t1->seq = ntohl(newsk->send_seq++);
t1->ack = 1;
- newsk->window = newsk->prot->rspace(newsk);
+ newsk->window = tcp_select_window(newsk);/*newsk->prot->rspace(newsk);*/
t1->window = ntohs(newsk->window);
t1->res1 = 0;
t1->res2 = 0;
@@ -2017,7 +2048,7 @@ tcp_close(struct sock *sk, int timeout)
/* Ack everything immediately from now on. */
sk->delay_acks = 0;
t1->ack_seq = ntohl(sk->acked_seq);
- t1->window = ntohs(sk->prot->rspace(sk));
+ t1->window = ntohs(sk->window=tcp_select_window(sk)/*sk->prot->rspace(sk)*/);
t1->fin = 1;
t1->rst = need_reset;
t1->doff = sizeof(*t1)/4;
@@ -2508,7 +2539,18 @@ tcp_data(struct sk_buff *skb, struct sock *sk,
skb2 = (struct sk_buff *)skb2->next) {
if (before(skb2->h.th->seq, sk->acked_seq+1)) {
if (after(skb2->h.th->ack_seq, sk->acked_seq))
+ {
+ long old_acked_seq = sk->acked_seq;
sk->acked_seq = skb2->h.th->ack_seq;
+ if((int)(sk->acked_seq - old_acked_seq) >0)
+ {
+ int new_window=sk->window-sk->acked_seq+
+ old_acked_seq;
+ if(new_window<0)
+ new_window=0;
+ sk->window = new_window;
+ }
+ }
skb2->acked = 1;
/*
@@ -3369,7 +3411,7 @@ tcp_write_wakeup(struct sock *sk)
t1->fin = 0;
t1->syn = 0;
t1->ack_seq = ntohl(sk->acked_seq);
- t1->window = ntohs(sk->prot->rspace(sk));
+ t1->window = ntohs(tcp_select_window(sk)/*sk->prot->rspace(sk)*/);
t1->doff = sizeof(*t1)/4;
tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);