Commit ac27c05b authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.14q

parent 36f4514a
VERSION = 0.99
PATCHLEVEL = 14
ALPHA = p
ALPHA = q
all: Version zImage
......
......@@ -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 */
......
......@@ -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:
......
......@@ -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;
}
......
......@@ -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 -
......
......@@ -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 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt)
}
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;
}
......@@ -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);
......
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