diff options
author | Linus Torvalds <torvalds@cc.helsinki.fi> | 1994-01-17 13:18:10 +0000 |
---|---|---|
committer | Nicolas Pitre <nico@cam.org> | 2007-08-19 14:19:27 -0400 |
commit | e3e62943752a4c7960c04d452718a9b247fe185d (patch) | |
tree | d1c19ba60a81b8f63a013f529770e9d43ba26083 | |
parent | 5f295b33cf4ea277617047421018a6cd75cc5dff (diff) | |
download | archive-e3e62943752a4c7960c04d452718a9b247fe185d.tar.gz |
ALPHA-pl14q
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | drivers/FPU-emu/reg_div.S | 2 | ||||
-rw-r--r-- | drivers/char/tty_ioctl.c | 2 | ||||
-rw-r--r-- | net/inet/dev.c | 35 | ||||
-rw-r--r-- | net/inet/ip.c | 4 | ||||
-rw-r--r-- | net/inet/route.c | 83 | ||||
-rw-r--r-- | net/inet/tcp.c | 66 |
7 files changed, 124 insertions, 70 deletions
@@ -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); |