Commit ac27c05b authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.14q

parent 36f4514a
VERSION = 0.99 VERSION = 0.99
PATCHLEVEL = 14 PATCHLEVEL = 14
ALPHA = p ALPHA = q
all: Version zImage all: Version zImage
......
...@@ -237,7 +237,7 @@ L_return_zero: ...@@ -237,7 +237,7 @@ L_return_zero:
#ifdef PARANOID #ifdef PARANOID
L_unknown_tags: L_unknown_tags:
push EX_INTERNAL | 0x208 pushl EX_INTERNAL | 0x208
call EXCEPTION call EXCEPTION
/* Generate a NaN for unknown tags */ /* Generate a NaN for unknown tags */
......
...@@ -584,6 +584,8 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -584,6 +584,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
(unsigned long *) arg); (unsigned long *) arg);
return 0; return 0;
case TIOCSTI: case TIOCSTI:
if ((current->tty != dev) && !suser())
return -EACCES;
put_tty_queue(get_fs_byte((char *) arg), &tty->read_q); put_tty_queue(get_fs_byte((char *) arg), &tty->read_q);
return 0; return 0;
case TIOCGWINSZ: case TIOCGWINSZ:
......
...@@ -350,22 +350,29 @@ dev_get(char *name) ...@@ -350,22 +350,29 @@ dev_get(char *name)
/* Find an interface that can handle addresses for a certain address. */ /* Find an interface that can handle addresses for a certain address. */
struct device * struct device * dev_check(unsigned long addr)
dev_check(unsigned long addr)
{ {
struct device *dev; struct device *dev;
for (dev = dev_base; dev; dev = dev->next) for (dev = dev_base; dev; dev = dev->next) {
if ((dev->flags & IFF_UP) && (dev->flags & IFF_POINTOPOINT) && if (!(dev->flags & IFF_UP))
(addr == dev->pa_dstaddr)) continue;
if (!(dev->flags & IFF_POINTOPOINT))
continue;
if (addr != dev->pa_dstaddr)
continue;
return dev; return dev;
for (dev = dev_base; dev; dev = dev->next) }
if ((dev->flags & IFF_UP) && !(dev->flags & IFF_POINTOPOINT) && for (dev = dev_base; dev; dev = dev->next) {
(dev->flags & IFF_LOOPBACK ? (addr == dev->pa_addr) : if (!(dev->flags & IFF_UP))
(dev->pa_mask & addr) == (dev->pa_addr & dev->pa_mask))) continue;
break; if (dev->flags & IFF_POINTOPOINT)
/* no need to check broadcast addresses */ continue;
return dev; if (dev->pa_mask & (addr ^ dev->pa_addr))
continue;
return dev;
}
return NULL;
} }
......
...@@ -1295,6 +1295,10 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) ...@@ -1295,6 +1295,10 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
continue; continue;
memcpy(skb2, skb, skb->mem_len); memcpy(skb2, skb, skb->mem_len);
skb2->mem_addr = skb2; 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 *)( skb2->h.raw = (unsigned char *)(
(unsigned long)skb2 + (unsigned long)skb2 +
(unsigned long) skb->h.raw - (unsigned long) skb->h.raw -
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
* Alan Cox : cli() protects routing changes * Alan Cox : cli() protects routing changes
* Rui Oliveira : ICMP routing table updates * Rui Oliveira : ICMP routing table updates
* (rco@di.uminho.pt) Routing table insertion and update * (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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -133,17 +134,11 @@ static inline unsigned long default_mask(unsigned long dst) ...@@ -133,17 +134,11 @@ static inline unsigned long default_mask(unsigned long dst)
static unsigned long guess_mask(unsigned long dst, struct device * dev) static unsigned long guess_mask(unsigned long dst, struct device * dev)
{ {
unsigned long mask = 0xffffffff; unsigned long mask;
/* this is a rather ugly optimization: works only on little-endian machines */ if (!dst)
while (mask & dst) return 0;
mask <<= 8;
if (mask)
return ~mask;
/* ok, no more hacks.. */
mask = default_mask(dst); mask = default_mask(dst);
if (dev->flags & IFF_POINTOPOINT)
return mask;
if ((dst ^ dev->pa_addr) & mask) if ((dst ^ dev->pa_addr) & mask)
return mask; return mask;
return dev->pa_mask; return dev->pa_mask;
...@@ -168,8 +163,8 @@ static inline struct device * get_gw_dev(unsigned long gw) ...@@ -168,8 +163,8 @@ static inline struct device * get_gw_dev(unsigned long gw)
/* /*
* rewrote rt_add(), as the old one was weird. Linus * rewrote rt_add(), as the old one was weird. Linus
*/ */
void void rt_add(short flags, unsigned long dst, unsigned long mask,
rt_add(short flags, unsigned long dst, unsigned long mask, unsigned long gw, struct device *dev) unsigned long gw, struct device *dev)
{ {
struct rtable *r, *rt; struct rtable *r, *rt;
struct rtable **rp; struct rtable **rp;
...@@ -267,12 +262,14 @@ static int rt_new(struct rtentry *r) ...@@ -267,12 +262,14 @@ static int rt_new(struct rtentry *r)
daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr; daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
mask = r->rt_genmask; mask = r->rt_genmask;
gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr; gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
dev = (struct device *) r->rt_dev;
if (flags & RTF_GATEWAY) { if (flags & RTF_GATEWAY) {
if (r->rt_gateway.sa_family != AF_INET) if (r->rt_gateway.sa_family != AF_INET)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
dev = get_gw_dev(gw); if (!dev)
} else dev = get_gw_dev(gw);
} else if (!dev)
dev = dev_check(daddr); dev = dev_check(daddr);
if (dev == NULL) if (dev == NULL)
...@@ -286,15 +283,13 @@ static int rt_new(struct rtentry *r) ...@@ -286,15 +283,13 @@ static int rt_new(struct rtentry *r)
} }
static int static int rt_kill(struct rtentry *r)
rt_kill(struct rtentry *r)
{ {
struct sockaddr_in *trg; struct sockaddr_in *trg;
trg = (struct sockaddr_in *) &r->rt_dst; trg = (struct sockaddr_in *) &r->rt_dst;
rt_del(trg->sin_addr.s_addr); rt_del(trg->sin_addr.s_addr);
return 0;
return(0);
} }
...@@ -337,8 +332,10 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt) ...@@ -337,8 +332,10 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt)
rt->rt_dev->pa_brdaddr == daddr) rt->rt_dev->pa_brdaddr == daddr)
break; break;
} }
if (daddr == rt->rt_dev->pa_addr) if (daddr == rt->rt_dev->pa_addr) {
rt = rt_loopback; if ((rt = rt_loopback) == NULL)
goto no_route;
}
rt->rt_use++; rt->rt_use++;
return rt; return rt;
no_route: no_route:
...@@ -346,39 +343,41 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt) ...@@ -346,39 +343,41 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt)
} }
int int rt_ioctl(unsigned int cmd, void *arg)
rt_ioctl(unsigned int cmd, void *arg)
{ {
struct device *dev; struct device *dev;
struct rtentry rt; struct rtentry rt;
char namebuf[32]; char *devname;
int ret; int ret;
int err; int err;
switch(cmd) { switch(cmd) {
case DDIOCSDBG: case DDIOCSDBG:
ret = dbg_ioctl(arg, DBG_RT); ret = dbg_ioctl(arg, DBG_RT);
break; break;
case SIOCADDRT: case SIOCADDRT:
case SIOCDELRT: case SIOCDELRT:
if (!suser()) return(-EPERM); if (!suser())
return -EPERM;
err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry)); err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
if(err) if (err)
return err; return err;
memcpy_fromfs(&rt, arg, sizeof(struct rtentry)); memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
if (rt.rt_dev) { if ((devname = (char *) rt.rt_dev) != NULL) {
err=verify_area(VERIFY_READ, rt.rt_dev, sizeof namebuf); err = getname(devname, &devname);
if(err) if (err)
return err; return err;
memcpy_fromfs(&namebuf, rt.rt_dev, sizeof namebuf); dev = dev_get(devname);
dev = dev_get(namebuf); putname(devname);
rt.rt_dev = dev; if (!dev)
return -EINVAL;
rt.rt_dev = dev;
} }
ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt); ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
} }
return(ret); return ret;
} }
...@@ -54,6 +54,9 @@ ...@@ -54,6 +54,9 @@
* Alan Cox : Handle FIN (more) properly (we hope). * Alan Cox : Handle FIN (more) properly (we hope).
* Alan Cox : RST frames sent on unsynchronised state ack error/ * Alan Cox : RST frames sent on unsynchronised state ack error/
* Alan Cox : Put in missing check for SYN bit. * 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: * To Fix:
...@@ -61,7 +64,6 @@ ...@@ -61,7 +64,6 @@
* it causes a select. Linux can - given the official select semantics I * it causes a select. Linux can - given the official select semantics I
* feel that _really_ its the BSD network programs that are bust (notably * feel that _really_ its the BSD network programs that are bust (notably
* inetd, which hangs occasionally because of this). * inetd, which hangs occasionally because of this).
* Proper processing of piggybacked data on connect.
* Add VJ Fastrecovery algorithm ? * Add VJ Fastrecovery algorithm ?
* Protocol closedown badly messed up. * Protocol closedown badly messed up.
* Incompatiblity with spider ports (tcp hangs on that * Incompatiblity with spider ports (tcp hangs on that
...@@ -154,6 +156,31 @@ diff(unsigned long seq1, unsigned long seq2) ...@@ -154,6 +156,31 @@ diff(unsigned long seq1, unsigned long seq2)
return(~d+1); 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. */ /* Enter the time wait state. */
...@@ -308,7 +335,7 @@ tcp_readable(struct sock *sk) ...@@ -308,7 +335,7 @@ tcp_readable(struct sock *sk)
if (skb->h.th->syn) amount--; if (skb->h.th->syn) amount--;
counted += sum; counted += sum;
} }
/* if (amount && skb->h.th->psh) break;*/ if (amount && skb->h.th->psh) break;
skb =(struct sk_buff *)skb->next; /* Move along */ skb =(struct sk_buff *)skb->next; /* Move along */
} while(skb != sk->rqueue); } while(skb != sk->rqueue);
restore_flags(flags); restore_flags(flags);
...@@ -660,7 +687,7 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n"); ...@@ -660,7 +687,7 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n");
t1->source = th->dest; t1->source = th->dest;
t1->seq = ntohl(sequence); t1->seq = ntohl(sequence);
t1->ack = 1; 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->window = ntohs(sk->window);
t1->res1 = 0; t1->res1 = 0;
t1->res2 = 0; t1->res2 = 0;
...@@ -673,8 +700,12 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n"); ...@@ -673,8 +700,12 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n");
sk->ack_backlog = 0; sk->ack_backlog = 0;
sk->bytes_rcv = 0; sk->bytes_rcv = 0;
sk->ack_timed = 0; sk->ack_timed = 0;
if (sk->send_head == NULL && sk->wfront == NULL) { if (sk->send_head == NULL && sk->wfront == NULL && sk->timeout == TIME_WRITE)
/* delete_timer(sk);*/ {
if(sk->keepopen)
reset_timer(sk,TIME_KEEPOPEN,TCP_TIMEOUT_LEN);
else
delete_timer(sk);
} }
} }
t1->ack_seq = ntohl(ack); t1->ack_seq = ntohl(ack);
...@@ -702,7 +733,7 @@ tcp_build_header(struct tcphdr *th, struct sock *sk, int push) ...@@ -702,7 +733,7 @@ tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
sk->bytes_rcv = 0; sk->bytes_rcv = 0;
sk->ack_timed = 0; sk->ack_timed = 0;
th->ack_seq = htonl(sk->acked_seq); 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); th->window = htons(sk->window);
return(sizeof(*th)); return(sizeof(*th));
...@@ -1049,7 +1080,7 @@ tcp_read_wakeup(struct sock *sk) ...@@ -1049,7 +1080,7 @@ tcp_read_wakeup(struct sock *sk)
t1->psh = 0; t1->psh = 0;
sk->ack_backlog = 0; sk->ack_backlog = 0;
sk->bytes_rcv = 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->window = ntohs(sk->window);
t1->ack_seq = ntohl(sk->acked_seq); t1->ack_seq = ntohl(sk->acked_seq);
t1->doff = sizeof(*t1)/4; t1->doff = sizeof(*t1)/4;
...@@ -1225,7 +1256,7 @@ tcp_read_urg(struct sock * sk, int nonblock, ...@@ -1225,7 +1256,7 @@ tcp_read_urg(struct sock * sk, int nonblock,
skb =(struct sk_buff *)skb->next; skb =(struct sk_buff *)skb->next;
} while(skb != sk->rqueue); } while(skb != sk->rqueue);
} }
sk->urg = 0; /*sk->urg = 0;*/
release_sock(sk); release_sock(sk);
return(0); return(0);
} }
...@@ -1522,7 +1553,7 @@ tcp_shutdown(struct sock *sk, int how) ...@@ -1522,7 +1553,7 @@ tcp_shutdown(struct sock *sk, int how)
buff->h.seq = sk->send_seq; buff->h.seq = sk->send_seq;
t1->ack = 1; t1->ack = 1;
t1->ack_seq = ntohl(sk->acked_seq); 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->fin = 1;
t1->rst = 0; t1->rst = 0;
t1->doff = sizeof(*t1)/4; t1->doff = sizeof(*t1)/4;
...@@ -1871,7 +1902,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -1871,7 +1902,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
t1->source = newsk->dummy_th.source; t1->source = newsk->dummy_th.source;
t1->seq = ntohl(newsk->send_seq++); t1->seq = ntohl(newsk->send_seq++);
t1->ack = 1; 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->window = ntohs(newsk->window);
t1->res1 = 0; t1->res1 = 0;
t1->res2 = 0; t1->res2 = 0;
...@@ -2017,7 +2048,7 @@ tcp_close(struct sock *sk, int timeout) ...@@ -2017,7 +2048,7 @@ tcp_close(struct sock *sk, int timeout)
/* Ack everything immediately from now on. */ /* Ack everything immediately from now on. */
sk->delay_acks = 0; sk->delay_acks = 0;
t1->ack_seq = ntohl(sk->acked_seq); 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->fin = 1;
t1->rst = need_reset; t1->rst = need_reset;
t1->doff = sizeof(*t1)/4; t1->doff = sizeof(*t1)/4;
...@@ -2508,7 +2539,18 @@ tcp_data(struct sk_buff *skb, struct sock *sk, ...@@ -2508,7 +2539,18 @@ tcp_data(struct sk_buff *skb, struct sock *sk,
skb2 = (struct sk_buff *)skb2->next) { skb2 = (struct sk_buff *)skb2->next) {
if (before(skb2->h.th->seq, sk->acked_seq+1)) { if (before(skb2->h.th->seq, sk->acked_seq+1)) {
if (after(skb2->h.th->ack_seq, sk->acked_seq)) 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; 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; skb2->acked = 1;
/* /*
...@@ -3369,7 +3411,7 @@ tcp_write_wakeup(struct sock *sk) ...@@ -3369,7 +3411,7 @@ tcp_write_wakeup(struct sock *sk)
t1->fin = 0; t1->fin = 0;
t1->syn = 0; t1->syn = 0;
t1->ack_seq = ntohl(sk->acked_seq); 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; t1->doff = sizeof(*t1)/4;
tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk); tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment