Commit 95fda206 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.56

parent f4a818e0
VERSION = 1 VERSION = 1
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 55 SUBLEVEL = 56
ARCH = i386 ARCH = i386
......
/* /*
* linux/kernel/blk_dev/ll_rw.c * linux/drivers/block/ll_rw_blk.c
* *
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994, Karl Keyte: Added support for disk statistics
*/ */
/* /*
...@@ -149,6 +150,20 @@ void set_device_ro(int dev,int flag) ...@@ -149,6 +150,20 @@ void set_device_ro(int dev,int flag)
static void add_request(struct blk_dev_struct * dev, struct request * req) static void add_request(struct blk_dev_struct * dev, struct request * req)
{ {
struct request * tmp; struct request * tmp;
short disk_index;
switch (MAJOR(req->dev)) {
case SCSI_DISK_MAJOR: disk_index = (MINOR(req->dev) & 0x0070) >> 4;
if (disk_index < 4)
kstat.dk_drive[disk_index]++;
break;
case HD_MAJOR:
case XT_DISK_MAJOR: disk_index = (MINOR(req->dev) & 0x00C0) >> 6;
if (disk_index < 4)
kstat.dk_drive[disk_index]++;
break;
default: break;
}
req->next = NULL; req->next = NULL;
cli(); cli();
......
Tue Oct 18 10:02:43 1994 Theodore Y. Ts'o (tytso@rt-11)
* serial.c (rs_start): Removed an incorrect '!' that was
preventing transmit interrupts from being re-enabled in
rs_start(). Fortunately in most cases it would be
re-enabled elsewhere, but this still should be fixed
corectly.
Sun Oct 9 23:46:03 1994 Theodore Y. Ts'o (tytso@rt-11) Sun Oct 9 23:46:03 1994 Theodore Y. Ts'o (tytso@rt-11)
* tty_io.c (do_tty_hangup): If the tty driver flags * tty_io.c (do_tty_hangup): If the tty driver flags
......
...@@ -305,7 +305,7 @@ static void keyboard_interrupt(int int_pt_regs) ...@@ -305,7 +305,7 @@ static void keyboard_interrupt(int int_pt_regs)
} }
/* strange ... */ /* strange ... */
reply_expected = 1; reply_expected = 1;
#ifdef KBD_REPORT_ERR #if 0
printk("keyboard reply expected - got %02x\n", scancode); printk("keyboard reply expected - got %02x\n", scancode);
#endif #endif
} }
......
...@@ -313,8 +313,7 @@ static void rs_start(struct tty_struct *tty) ...@@ -313,8 +313,7 @@ static void rs_start(struct tty_struct *tty)
return; return;
save_flags(flags); cli(); save_flags(flags); cli();
if (info->xmit_cnt && !info->xmit_buf && if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
!(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI; info->IER |= UART_IER_THRI;
serial_out(info, UART_IER, info->IER); serial_out(info, UART_IER, info->IER);
} }
......
...@@ -631,12 +631,8 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs ...@@ -631,12 +631,8 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
bprm.e_uid = (i & S_ISUID) ? bprm.inode->i_uid : current->euid; bprm.e_uid = (i & S_ISUID) ? bprm.inode->i_uid : current->euid;
bprm.e_gid = (i & S_ISGID) ? bprm.inode->i_gid : current->egid; bprm.e_gid = (i & S_ISGID) ? bprm.inode->i_gid : current->egid;
} }
if (current->euid == bprm.inode->i_uid) if (!permission(bprm.inode, MAY_EXEC) ||
i >>= 6; (!(bprm.inode->i_mode & 0111) && fsuser())) {
else if (in_group_p(bprm.inode->i_gid))
i >>= 3;
if (!(i & 1) &&
!((bprm.inode->i_mode & 0111) && suser())) {
retval = -EACCES; retval = -EACCES;
goto exec_error2; goto exec_error2;
} }
......
...@@ -144,29 +144,36 @@ static int ext2_readdir (struct inode * inode, struct file * filp, ...@@ -144,29 +144,36 @@ static int ext2_readdir (struct inode * inode, struct file * filp,
revalidate: revalidate:
/* If the dir block has changed since the last call to /* If the dir block has changed since the last call to
readdir(2), then we might be pointing to an invalid dirent * readdir(2), then we might be pointing to an invalid
right now. Scan from the start of the block to make * dirent right now. Scan from the start of the block
sure. */ * to make sure. */
for (i = 0; i < sb->s_blocksize && i < offset; ) { if (filp->f_version != inode->i_version) {
de = (struct ext2_dir_entry *) (bh->b_data + i); for (i = 0; i < sb->s_blocksize && i < offset; ) {
/* It's too expensive to do a full dirent test de = (struct ext2_dir_entry *)
* each time round this loop, but we do have (bh->b_data + i);
* to test at least that it is non-zero. A /* It's too expensive to do a full
* failure will be detected in the dirent test * dirent test each time round this
* below. */ * loop, but we do have to test at
if (de->rec_len < EXT2_DIR_REC_LEN(1)) * least that it is non-zero. A
break; * failure will be detected in the
i += de->rec_len; * dirent test below. */
if (de->rec_len < EXT2_DIR_REC_LEN(1))
break;
i += de->rec_len;
}
offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
| offset;
filp->f_version = inode->i_version;
} }
offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | offset;
while (count > 0 && filp->f_pos < inode->i_size while (count > 0 && filp->f_pos < inode->i_size
&& offset < sb->s_blocksize) { && offset < sb->s_blocksize) {
de = (struct ext2_dir_entry *) (bh->b_data + offset); de = (struct ext2_dir_entry *) (bh->b_data + offset);
if (!ext2_check_dir_entry ("ext2_readdir", inode, de, if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
bh, offset)) { bh, offset)) {
/* On error, skip the f_pos to the next block. */ /* On error, skip the f_pos to the
next block. */
filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1))
+ sb->s_blocksize; + sb->s_blocksize;
brelse (bh); brelse (bh);
...@@ -175,7 +182,8 @@ static int ext2_readdir (struct inode * inode, struct file * filp, ...@@ -175,7 +182,8 @@ static int ext2_readdir (struct inode * inode, struct file * filp,
if (de->inode) { if (de->inode) {
dlen = ROUND_UP(NAME_OFFSET(dirent) dlen = ROUND_UP(NAME_OFFSET(dirent)
+ de->name_len + 1); + de->name_len + 1);
/* Old libc libraries always use a count of 1. */ /* Old libc libraries always use a
count of 1. */
if (count == 1 && !stored) if (count == 1 && !stored)
count = dlen; count = dlen;
if (count < dlen) { if (count < dlen) {
...@@ -184,11 +192,11 @@ static int ext2_readdir (struct inode * inode, struct file * filp, ...@@ -184,11 +192,11 @@ static int ext2_readdir (struct inode * inode, struct file * filp,
} }
/* We might block in the next section /* We might block in the next section
* if the data destination is * if the data destination is
* currently swapped out. So, use a * currently swapped out. So, use a
* version stamp to detect whether or * version stamp to detect whether or
* not the directory has been modified * not the directory has been modified
* during the copy operation. */ * during the copy operation. */
version = inode->i_version; version = inode->i_version;
i = de->name_len; i = de->name_len;
memcpy_tofs (dirent->d_name, de->name, i); memcpy_tofs (dirent->d_name, de->name, i);
......
...@@ -115,7 +115,24 @@ asmlinkage int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -115,7 +115,24 @@ asmlinkage int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
*/ */
return filp->f_owner; return filp->f_owner;
case F_SETOWN: case F_SETOWN:
filp->f_owner = arg; /* XXX security implications? */ /*
* Add the security checks - AC. Without this there is a massive
* Linux security hole here - consider what happens if you do
* something like
* fcntl(0,F_SETOWN,some_root_process);
* getchar();
* and input a line!
*
* BTW: Don't try this for fun. Several Unix systems I tried this on
* fall for the trick!
*
* I had to fix this botch job as Linux kill_fasync asserts
* priv making it a free all user process killer!
*/
if(!suser() && current->pgrp != -arg &&
current->pid != arg)
return -EPERM;
filp->f_owner = arg;
if (S_ISSOCK (filp->f_inode->i_mode)) if (S_ISSOCK (filp->f_inode->i_mode))
sock_fcntl (filp, F_SETOWN, arg); sock_fcntl (filp, F_SETOWN, arg);
return 0; return 0;
......
...@@ -79,6 +79,7 @@ struct file * get_empty_filp(void) ...@@ -79,6 +79,7 @@ struct file * get_empty_filp(void)
memset(f,0,sizeof(*f)); memset(f,0,sizeof(*f));
put_last_free(f); put_last_free(f);
f->f_count = 1; f->f_count = 1;
f->f_version = ++event;
return f; return f;
} }
if (nr_files < NR_FILE) { if (nr_files < NR_FILE) {
......
...@@ -71,6 +71,7 @@ asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin) ...@@ -71,6 +71,7 @@ asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
if (tmp != file->f_pos) { if (tmp != file->f_pos) {
file->f_pos = tmp; file->f_pos = tmp;
file->f_reada = 0; file->f_reada = 0;
file->f_version = ++event;
} }
return file->f_pos; return file->f_pos;
} }
...@@ -109,6 +110,7 @@ asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high, ...@@ -109,6 +110,7 @@ asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
return -EINVAL; return -EINVAL;
file->f_pos = tmp; file->f_pos = tmp;
file->f_reada = 0; file->f_reada = 0;
file->f_version = ++event;
memcpy_tofs(result, &file->f_pos, sizeof(loff_t)); memcpy_tofs(result, &file->f_pos, sizeof(loff_t));
return 0; return 0;
} }
......
...@@ -131,5 +131,5 @@ static int xiafs_readdir(struct inode * inode, ...@@ -131,5 +131,5 @@ static int xiafs_readdir(struct inode * inode,
inode->i_atime=CURRENT_TIME; inode->i_atime=CURRENT_TIME;
inode->i_dirt=1; inode->i_dirt=1;
} }
return 0; return ret;
} }
...@@ -233,6 +233,7 @@ struct file { ...@@ -233,6 +233,7 @@ struct file {
int f_owner; /* pid or -pgrp where SIGIO should be sent */ int f_owner; /* pid or -pgrp where SIGIO should be sent */
struct inode * f_inode; struct inode * f_inode;
struct file_operations * f_op; struct file_operations * f_op;
unsigned long f_version;
void *private_data; /* needed for tty driver, and maybe others */ void *private_data; /* needed for tty driver, and maybe others */
}; };
......
...@@ -52,6 +52,7 @@ struct arpreq { ...@@ -52,6 +52,7 @@ struct arpreq {
struct sockaddr arp_pa; /* protocol address */ struct sockaddr arp_pa; /* protocol address */
struct sockaddr arp_ha; /* hardware address */ struct sockaddr arp_ha; /* hardware address */
int arp_flags; /* flags */ int arp_flags; /* flags */
struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
}; };
/* ARP Flag values. */ /* ARP Flag values. */
...@@ -59,6 +60,8 @@ struct arpreq { ...@@ -59,6 +60,8 @@ struct arpreq {
#define ATF_PERM 0x04 /* permanent entry */ #define ATF_PERM 0x04 /* permanent entry */
#define ATF_PUBL 0x08 /* publish entry */ #define ATF_PUBL 0x08 /* publish entry */
#define ATF_USETRAILERS 0x10 /* has requested trailers */ #define ATF_USETRAILERS 0x10 /* has requested trailers */
#define ATF_NETMASK 0x20 /* want to use a netmask (only
for proxy entries) */
/* /*
* This structure defines an ethernet arp header. * This structure defines an ethernet arp header.
......
...@@ -77,6 +77,7 @@ struct socket { ...@@ -77,6 +77,7 @@ struct socket {
struct socket *next; struct socket *next;
struct wait_queue **wait; /* ptr to place to wait on */ struct wait_queue **wait; /* ptr to place to wait on */
struct inode *inode; struct inode *inode;
struct fasync_struct *fasync_list; /* Asynchronous wake up list */
}; };
#define SOCK_INODE(S) ((S)->inode) #define SOCK_INODE(S) ((S)->inode)
...@@ -128,7 +129,9 @@ struct net_proto { ...@@ -128,7 +129,9 @@ struct net_proto {
}; };
extern int sock_awaitconn(struct socket *mysock, struct socket *servsock); extern int sock_awaitconn(struct socket *mysock, struct socket *servsock);
extern int sock_wake_async(struct socket *sock);
extern int sock_register(int family, struct proto_ops *ops); extern int sock_register(int family, struct proto_ops *ops);
extern int sock_unregister(int family);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_NET_H */ #endif /* _LINUX_NET_H */
...@@ -81,9 +81,6 @@ struct linger { ...@@ -81,9 +81,6 @@ struct linger {
/* IPX options */ /* IPX options */
#define IPX_TYPE 1 #define IPX_TYPE 1
/* AX.25 options */
#define AX25_WINDOW 1
/* TCP options - this way around because someone left a set in the c library includes */ /* TCP options - this way around because someone left a set in the c library includes */
#define TCP_NODELAY 1 #define TCP_NODELAY 1
#define TCP_MAXSEG 2 #define TCP_MAXSEG 2
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/serial.h> #include <linux/serial.h>
#ifdef CONFIG_INET #ifdef CONFIG_INET
#include <linux/net.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#endif #endif
...@@ -169,6 +170,10 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */ ...@@ -169,6 +170,10 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
/* Miscellaneous access points */ /* Miscellaneous access points */
X(si_meminfo), X(si_meminfo),
/* socket layer registration */
X(sock_register),
X(sock_unregister),
#ifdef CONFIG_FTAPE #ifdef CONFIG_FTAPE
/* The next labels are needed for ftape driver. */ /* The next labels are needed for ftape driver. */
X(ftape_big_buffer), X(ftape_big_buffer),
...@@ -187,6 +192,12 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */ ...@@ -187,6 +192,12 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
X(dev_rint), X(dev_rint),
X(dev_tint), X(dev_tint),
X(irq2dev_map), X(irq2dev_map),
X(dev_add_pack),
X(dev_remove_pack),
X(dev_get),
X(dev_ioctl),
X(dev_queue_xmit),
X(dev_base),
#endif #endif
/******************************************************** /********************************************************
......
...@@ -322,7 +322,7 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) ...@@ -322,7 +322,7 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
if (ruid != (uid_t) -1 || if (ruid != (uid_t) -1 ||
(euid != (uid_t) -1 && euid != old_ruid)) (euid != (uid_t) -1 && euid != old_ruid))
current->suid = current->euid; current->suid = current->euid;
current->fsuid = euid; current->fsuid = current->euid;
return 0; return 0;
} }
......
Changes for 1.1.21 Changes for NET3.017
This is mostly small stuff as follows:
o accept()ed socket don't end up with an invalid sk->socket and give bogus
netstat output.
o FASYNC/SIGIO now works with sockets.
o Fixed the permissions on F_SETOWN for all. Its now as broken/working
as other systems. Really we need something like a 32bit generation
number on processes.
o ARP allows proxy for whole networks (a la cisco routers)
o TCP sendto() reports ENOTCONN in the right cases
o Removed some surplus uncommented code from tcp.c
o Fixed protocol violation during closedown in tcp.c
[Still not got the window < MSS bug fix included]
o Small bug fix in the apricot xen-ii driver code (Mark Evans)
o DE600 changes + DE620 driver (Bj0rn Eckwall)
o WWW error return bug fixed (Everyone!)
o SLIP default address is now better
o Small changes to PLIP (Niibe)
o Added PF_UNSPEC (Dominic Kubla)
o TCP fastpath for receive.
o Turbo charged tcp checksum routine (Arnt Gulbrandsen)
o PPP locking bug fixes (Florian La Roche)
To Do
o Include the HP onboard lance fixes.
o Fix Unix domain sockets.
o Fix the _SLOW_ TCP window calculation junk in tcp_data/tcp_ack.
o Make the dev_add_proto() list hashed by protocol type.
o Remove the call to dev->header_type - load it into the skbuff.
instead to avoid the extra calls and cache misses.
o Include new sk_buff skb_push() code and move toward using it.
o Fix the PI driver so pi0a can be down when pi0b is up without getting
crashes. Also fix the stuff to allow piconfig to set the parameters.
o Make AX.25 set the packet type - certainly before it hits IP.
o sk_buff building at the top level - pure kernel interfaces to the
protocol layers
o Clean up NFS, merge NFS/TCP code.
o SIGIO
o IP forwarding use of options properly (needs new sk_buff code)
o Reroute TCP retransmits if needed (needs new sk_buffs)
Changes for 1.1.20
o All read/write buffers are validated at the top level _only_
o All address structures are moved to and from user mode at the top
level. Thus you can now issue proto->bind(....) calls and related
functions such as connect from another kernel task. All thats left
to fix now is a kernel alloc_socket()/free_socket() and accompanying
proto->make_kernel(socket)
o Small fixes to address behaviour caused by the above
o Max NFS size of 16K bytes
o Added the apricot driver as a test (#'ed out in config.in)
o Fixed a missing function definition in net_init.c
o Added G4KLX ax25_router code
o Added Niibe's PLIP driver and altered it to support timer
configuration and IRQ/port setting. Added if_plip.h. Comments and
feedback appreciated on this (both to Niibe and me).
o Added AF_MAX/PF_MAX defines
o Added a note that the DE600 driver also works for a noname 'PE1200'.
o Network buffer statistics on shift-scroll_lock
o Fixed a serious race in the device driver code. This was causing odd
crashes with the Lance drivers, lockups with the ne2000 cards and
a few other 'bad' goings on. All drivers are effected. See
README.DEV if porting a driver to this revision.
If you see entries in your 'free while locked' count, those would
typically have crashed a pre 1.20 kernel.
o TCP keeps the timers above 0.2sec round-trip time because of the use of
delayed ACK's by BSD style kernels.
o Fixed a small BSD error in the return from datagram socket
recv/recvfrom() calls when data is truncated. BSD returns the true
length of the message, Linux returned the amount copied which broke
programs that did a MSG_PEEK with a small buffer and grew it if need
be (some of the AV/RTP stuff notably).
o Added TIOCINQ/OUTQ to AX.25 and IPX.
o Added driver ioctl() calls to IPX.
o Corrected the skb->len==0 in the tcp_data reset on shutdown to check
skb->copied_seq.
o IP options reflect onto SO_PRIORITY.
o When a driver is downed its ARP entries are flushed. Should solve
the occasional crash when taking out a modular driver.
o Added Donald's multicast reception while promiscuous fix for the
8390 drivers.
o Potential ARP TCP-retransmit clear race fixed. Incredibly
unlikely to occur but no doubt it will 8(.
Fixes added for 1.1.19
o Unix domain bind error code.
o skb->localroute starts cleared.
o Compiles with networking disabled
Fixes added for 1.1.18
o Dummy driver includes correctly.
o PPP fixes from A.L.
o ifslave fixes
o Small error causing nfsd to coredump fixed by Linus.
Fixes added for 1.1.17
o Charles Hedrick's fixes broken fragmentation totally. Mended.
o Contributed 'dummy' device added. Apparently some slip people want it.
o Tried to kill the memory problems with fragments by setting things
up more carefully and guarding them.
o Module fixes by Bj0rn.
o PLIP fix by Tanabe.
Fixes added for 1.1.16
o Charles Hedricks fixes to TCP.
o Small fixes all over the place.
Fixes added for 1.1.15
o Modular PLIP and 3c501 drivers. Now you -can- have multiple 3c501's
(sort of).
o Integrated new AX.25 - this will be ready for the big time in a few
releases.
Fixes added for 1.1.14
o Compiles properly on the whole 8)
o Yet more Unix /proc protection.
o Modular PLIP and 3c501 drivers. Now you -can- have multiple 3c501's
(sort of).
This fixes the following from the 1.1.12 release (see the relevant files
for the credits to authors).
o RARP compiles in properly
o Using new Tytso TTY drivers
o IP forwarding is configurable
o PC/TCP support
o AX.25 builds fine without SLIP driver (just PI)
o MTU recognized in routing table (but only by TCP currently)
o AX.25 PI driver merged into AX.25 code and kernel stubs
o UNIX /proc trap hopefully fixed
o DDI removed totally ready to use the PCMCIA people's stuff
o Unix domain lock/unlock now static (needlessly visible before)
o Split net/inet/sock.c into generic and IP components
o NFS client works correctly with 8K NFS
o Non IP builds work correctly
o Renamed inet_bh etc to net_bh to reflect true nature
o TCP handling of poor routes much improved
o TCP connect timing fixed
o Incredibly unlikely SLIP memory leak removed
o Loopback maintains IFF_LOOPBACK flag
o Johnathon Naylor(G4KLX) AX.25 changes
o Out of sync bug in lance driver fixed.
o First cut at ethernet loadable modules
o PCMCIA people have ifmap stuff. Will extend this to other drivers.
o New de600.c
o Clean up of IP layer - sorted a lot of redundant and duplicated code
out.
o Removed all the old non working debugging junk from the kernel.
o Removed all the devices the kernel used to use as a legacy from
FvK's days writing the linux networking.
o Greg Page's latest and greatest IPX fixes (including 802.2). Now
I've got the stuff to write a free Netware client too and some
volunteers to do it.
o Fixed the 1.1.12 ARP fragment bug.
...@@ -15,6 +15,12 @@ ...@@ -15,6 +15,12 @@
* Changes (see also sock.c) * Changes (see also sock.c)
* *
* A.N.Kuznetsov : Socket death error in accept(). * A.N.Kuznetsov : Socket death error in accept().
* John Richardson : Fix non blocking error in connect()
* so sockets that fail to connect
* don't return -EINPROGRESS.
* Alan Cox : Asynchronous I/O support
* Alan Cox : Keep correct socket pointer on sock structures
* when accept() ed
* *
* 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
...@@ -461,7 +467,10 @@ static void def_callback1(struct sock *sk) ...@@ -461,7 +467,10 @@ static void def_callback1(struct sock *sk)
static void def_callback2(struct sock *sk,int len) static void def_callback2(struct sock *sk,int len)
{ {
if(!sk->dead) if(!sk->dead)
{
wake_up_interruptible(sk->sleep); wake_up_interruptible(sk->sleep);
sock_wake_async(sk->socket);
}
} }
...@@ -875,6 +884,12 @@ static int inet_connect(struct socket *sock, struct sockaddr * uaddr, ...@@ -875,6 +884,12 @@ static int inet_connect(struct socket *sock, struct sockaddr * uaddr,
return(err); return(err);
sock->state = SS_CONNECTING; sock->state = SS_CONNECTING;
} }
if (sk->state > TCP_FIN_WAIT2 && sock->state==SS_CONNECTING)
{
sock->state=SS_UNCONNECTED;
return -ETIMEDOUT;
}
if (sk->state != TCP_ESTABLISHED &&(flags & O_NONBLOCK)) if (sk->state != TCP_ESTABLISHED &&(flags & O_NONBLOCK))
return(-EINPROGRESS); return(-EINPROGRESS);
...@@ -966,6 +981,7 @@ static int inet_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -966,6 +981,7 @@ static int inet_accept(struct socket *sock, struct socket *newsock, int flags)
} }
newsock->data = (void *)sk2; newsock->data = (void *)sk2;
sk2->sleep = newsock->wait; sk2->sleep = newsock->wait;
sk2->socket = newsock;
newsock->conn = NULL; newsock->conn = NULL;
if (flags & O_NONBLOCK) if (flags & O_NONBLOCK)
return(0); return(0);
...@@ -979,6 +995,7 @@ static int inet_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -979,6 +995,7 @@ static int inet_accept(struct socket *sock, struct socket *newsock, int flags)
sti(); sti();
sk1->pair = sk2; sk1->pair = sk2;
sk2->sleep = NULL; sk2->sleep = NULL;
sk2->socket=NULL;
newsock->data = NULL; newsock->data = NULL;
return(-ERESTARTSYS); return(-ERESTARTSYS);
} }
...@@ -1318,7 +1335,7 @@ void inet_proto_init(struct net_proto *pro) ...@@ -1318,7 +1335,7 @@ void inet_proto_init(struct net_proto *pro)
int i; int i;
printk("NET3 TCP/IP protocols stack v016\n"); printk("Swansea University Computer Society TCP/IP for NET3.017\n");
/* /*
* Tell SOCKET that we are alive... * Tell SOCKET that we are alive...
......
This diff is collapsed.
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
* Alan Cox : Transmit queue code does relevant stunts to * Alan Cox : Transmit queue code does relevant stunts to
* keep the queue safe. * keep the queue safe.
* Alan Cox : Fixed double lock. * Alan Cox : Fixed double lock.
* Alan Cox : Fixed promisc NULL pointer trap
* *
* Cleaned up and recommented by Alan Cox 2nd April 1994. I hope to have * Cleaned up and recommented by Alan Cox 2nd April 1994. I hope to have
* the rest as well commented in the end. * the rest as well commented in the end.
...@@ -439,9 +440,6 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) ...@@ -439,9 +440,6 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
/* /*
* Packet is now solely the responsibility of the driver * Packet is now solely the responsibility of the driver
*/ */
#ifdef CONFIG_SLAVE_BALANCING
dev->pkt_queue--;
#endif
return; return;
} }
...@@ -1080,19 +1078,24 @@ static int dev_ifsioc(void *arg, unsigned int getset) ...@@ -1080,19 +1078,24 @@ static int dev_ifsioc(void *arg, unsigned int getset)
dev->slave=NULL; dev->slave=NULL;
} }
#endif #endif
if( dev->set_multicast_list!=NULL)
{
/* /*
* Has promiscuous mode been turned off * Has promiscuous mode been turned off
*/ */
if ( (old_flags & IFF_PROMISC) && ((dev->flags & IFF_PROMISC) == 0))
dev->set_multicast_list(dev,0,NULL); if ( (old_flags & IFF_PROMISC) && ((dev->flags & IFF_PROMISC) == 0))
dev->set_multicast_list(dev,0,NULL);
/* /*
* Has it been turned on * Has it been turned on
*/ */
if ( (dev->flags & IFF_PROMISC) && ((old_flags & IFF_PROMISC) == 0)) if ( (dev->flags & IFF_PROMISC) && ((old_flags & IFF_PROMISC) == 0))
dev->set_multicast_list(dev,-1,NULL); dev->set_multicast_list(dev,-1,NULL);
}
/* /*
* Have we downed the interface * Have we downed the interface
...@@ -1364,11 +1367,6 @@ int dev_ioctl(unsigned int cmd, void *arg) ...@@ -1364,11 +1367,6 @@ int dev_ioctl(unsigned int cmd, void *arg)
{ {
switch(cmd) switch(cmd)
{ {
/*
* The old old setup ioctl. Even its name and this entry will soon be
* just so much ionization on a backup tape.
*/
case SIOCGIFCONF: case SIOCGIFCONF:
(void) dev_ifconf((char *) arg); (void) dev_ifconf((char *) arg);
return 0; return 0;
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
* Revision 0.26: Device drop kills IPX routes via it. (needed for modules) * Revision 0.26: Device drop kills IPX routes via it. (needed for modules)
* Revision 0.27: Autobind <Mark Evans> * Revision 0.27: Autobind <Mark Evans>
* Revision 0.28: Small fix for multiple local networks <Thomas Winder> * Revision 0.28: Small fix for multiple local networks <Thomas Winder>
* Revision 0.29: Assorted major errors removed <Mark Evans>
* Small correction to promisc mode error fix <Alan Cox>
* Asynchronous I/O support.
* *
* *
* *
...@@ -563,7 +566,10 @@ static void def_callback1(struct sock *sk) ...@@ -563,7 +566,10 @@ static void def_callback1(struct sock *sk)
static void def_callback2(struct sock *sk, int len) static void def_callback2(struct sock *sk, int len)
{ {
if(!sk->dead) if(!sk->dead)
{
wake_up_interruptible(sk->sleep); wake_up_interruptible(sk->sleep);
sock_wake_async(sk->socket);
}
} }
static int ipx_create(struct socket *sock, int protocol) static int ipx_create(struct socket *sock, int protocol)
...@@ -861,7 +867,7 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) ...@@ -861,7 +867,7 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
int free_it=0; int free_it=0;
/* Rule: Don't forward packets that have exceeded the hop limit. This is fixed at 16 in IPX */ /* Rule: Don't forward packets that have exceeded the hop limit. This is fixed at 16 in IPX */
if((ipx->ipx_tctrl==16) || (dev->flags & IFF_PROMISC)) if((ipx->ipx_tctrl==16) || (skb->pkt_type!=PACKET_HOST))
{ {
kfree_skb(skb,FREE_READ); kfree_skb(skb,FREE_READ);
return(0); return(0);
...@@ -1354,7 +1360,7 @@ void ipx_proto_init(struct net_proto *pro) ...@@ -1354,7 +1360,7 @@ void ipx_proto_init(struct net_proto *pro)
if ((p8022_datalink = register_8022_client(val, ipx_rcv)) == NULL) if ((p8022_datalink = register_8022_client(val, ipx_rcv)) == NULL)
printk("IPX: Unable to register with 802.2\n"); printk("IPX: Unable to register with 802.2\n");
printk("Swansea University Computer Society IPX 0.28 BETA for NET3.016\n"); printk("Swansea University Computer Society IPX 0.29 BETA for NET3.017\n");
} }
#endif #endif
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
* Authors: Alan Cox <iiitac@pyr.swan.ac.uk> * Authors: Alan Cox <iiitac@pyr.swan.ac.uk>
* Florian La Roche <rzsfl@rz.uni-sb.de> * Florian La Roche <rzsfl@rz.uni-sb.de>
* *
* Fixes:
* Alan Cox : Fixed the worst of the load balancer bugs.
*
* 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
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
...@@ -373,21 +376,10 @@ void kfree_skb(struct sk_buff *skb, int rw) ...@@ -373,21 +376,10 @@ void kfree_skb(struct sk_buff *skb, int rw)
skb->sk->wmem_alloc-=skb->mem_len; skb->sk->wmem_alloc-=skb->mem_len;
if(!skb->sk->dead) if(!skb->sk->dead)
skb->sk->write_space(skb->sk); skb->sk->write_space(skb->sk);
#ifdef CONFIG_SLAVE_BALANCING
if(skb->in_dev_queue && skb->dev!=NULL)
skb->dev->pkt_queue--;
#endif
kfree_skbmem(skb,skb->mem_len);
} }
} }
else else
{
#ifdef CONFIG_SLAVE_BALANCING
if(skb->in_dev_queue && skb->dev!=NULL)
skb->dev->pkt_queue--;
#endif
kfree_skbmem(skb, skb->mem_len); kfree_skbmem(skb, skb->mem_len);
}
} }
/* /*
......
...@@ -150,7 +150,7 @@ struct sock { ...@@ -150,7 +150,7 @@ struct sock {
char ax25_rrtimer; char ax25_rrtimer;
char ax25_timer; char ax25_timer;
unsigned char ax25_n2; unsigned char ax25_n2;
unsigned short ax25_t1,ax25_t3; unsigned short ax25_t1,ax25_t2,ax25_t3;
ax25_digi *ax25_digipeat; ax25_digi *ax25_digipeat;
#endif #endif
/* IP 'private area' or will be eventually */ /* IP 'private area' or will be eventually */
......
...@@ -83,6 +83,7 @@ ...@@ -83,6 +83,7 @@
* Matt Dillon : Yet more small nasties remove from the TCP code * Matt Dillon : Yet more small nasties remove from the TCP code
* (Be very nice to this man if tcp finally works 100%) 8) * (Be very nice to this man if tcp finally works 100%) 8)
* Alan Cox : BSD accept semantics. * Alan Cox : BSD accept semantics.
* Alan Cox : Reset on closedown bug.
* Peter De Schrijver : ENOTCONN check missing in tcp_sendto(). * Peter De Schrijver : ENOTCONN check missing in tcp_sendto().
* *
* *
...@@ -316,7 +317,7 @@ void tcp_err(int err, unsigned char *header, unsigned long daddr, ...@@ -316,7 +317,7 @@ void tcp_err(int err, unsigned char *header, unsigned long daddr,
th =(struct tcphdr *)header; th =(struct tcphdr *)header;
sk = get_sock(&tcp_prot, th->source/*dest*/, daddr, th->dest/*source*/, saddr); sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr);
if (sk == NULL) if (sk == NULL)
return; return;
...@@ -880,7 +881,7 @@ static int tcp_build_header(struct tcphdr *th, struct sock *sk, int push) ...@@ -880,7 +881,7 @@ static int 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 = tcp_select_window(sk)/*sk->prot->rspace(sk)*/; sk->window = tcp_select_window(sk);
th->window = htons(sk->window); th->window = htons(sk->window);
return(sizeof(*th)); return(sizeof(*th));
...@@ -1098,7 +1099,7 @@ static int tcp_write(struct sock *sk, unsigned char *from, ...@@ -1098,7 +1099,7 @@ static int tcp_write(struct sock *sk, unsigned char *from,
if (skb == NULL) if (skb == NULL)
{ {
if (nonblock /* || copied */) if (nonblock)
{ {
release_sock(sk); release_sock(sk);
if (copied) if (copied)
...@@ -1296,7 +1297,7 @@ static void tcp_read_wakeup(struct sock *sk) ...@@ -1296,7 +1297,7 @@ static void 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 = tcp_select_window(sk);/*sk->prot->rspace(sk);*/ sk->window = tcp_select_window(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;
...@@ -1715,7 +1716,7 @@ void tcp_shutdown(struct sock *sk, int how) ...@@ -1715,7 +1716,7 @@ void tcp_shutdown(struct sock *sk, int how)
buff->h.seq = sk->write_seq; buff->h.seq = sk->write_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->window=tcp_select_window(sk)/*sk->prot->rspace(sk)*/); t1->window = ntohs(sk->window=tcp_select_window(sk));
t1->fin = 1; t1->fin = 1;
t1->rst = 0; t1->rst = 0;
t1->doff = sizeof(*t1)/4; t1->doff = sizeof(*t1)/4;
...@@ -2166,7 +2167,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -2166,7 +2167,7 @@ static void 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->write_seq++); t1->seq = ntohl(newsk->write_seq++);
t1->ack = 1; t1->ack = 1;
newsk->window = tcp_select_window(newsk);/*newsk->prot->rspace(newsk);*/ newsk->window = tcp_select_window(newsk);
newsk->sent_seq = newsk->write_seq; newsk->sent_seq = newsk->write_seq;
t1->window = ntohs(newsk->window); t1->window = ntohs(newsk->window);
t1->res1 = 0; t1->res1 = 0;
...@@ -2186,7 +2187,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -2186,7 +2187,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
tcp_send_check(t1, daddr, saddr, sizeof(*t1)+4, newsk); tcp_send_check(t1, daddr, saddr, sizeof(*t1)+4, newsk);
newsk->prot->queue_xmit(newsk, dev, buff, 0); newsk->prot->queue_xmit(newsk, dev, buff, 0);
reset_timer(newsk, TIME_WRITE /* -1 ? FIXME ??? */, TCP_TIMEOUT_INIT); reset_timer(newsk, TIME_WRITE , TCP_TIMEOUT_INIT);
skb->sk = newsk; skb->sk = newsk;
/* /*
...@@ -2206,7 +2207,6 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -2206,7 +2207,6 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
static void tcp_close(struct sock *sk, int timeout) static void tcp_close(struct sock *sk, int timeout)
{ {
struct sk_buff *buff; struct sk_buff *buff;
int need_reset = 0;
struct tcphdr *t1, *th; struct tcphdr *t1, *th;
struct proto *prot; struct proto *prot;
struct device *dev=NULL; struct device *dev=NULL;
...@@ -2236,14 +2236,8 @@ static void tcp_close(struct sock *sk, int timeout) ...@@ -2236,14 +2236,8 @@ static void tcp_close(struct sock *sk, int timeout)
struct sk_buff *skb; struct sk_buff *skb;
if(sk->debug) if(sk->debug)
printk("Clean rcv queue\n"); printk("Clean rcv queue\n");
while((skb=skb_dequeue(&sk->receive_queue))!=NULL) while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
{ kfree_skb(skb, FREE_READ);
/* The +1 is not needed because the FIN takes up seq
is not read!!! */
if(skb->len > 0 && after(skb->h.th->seq + skb->len , sk->copied_seq))
need_reset = 0;
kfree_skb(skb, FREE_READ);
}
if(sk->debug) if(sk->debug)
printk("Cleaned.\n"); printk("Cleaned.\n");
} }
...@@ -2282,15 +2276,6 @@ static void tcp_close(struct sock *sk, int timeout) ...@@ -2282,15 +2276,6 @@ static void tcp_close(struct sock *sk, int timeout)
else else
reset_timer(sk, TIME_CLOSE, 4 * sk->rto); reset_timer(sk, TIME_CLOSE, 4 * sk->rto);
} }
#ifdef NOTDEF
/*
* Start a timer.
* original code was 4 * sk->rtt. In converting to the
* new rtt representation, we can't quite use that.
* it seems to make most sense to use the backed off value
*/
reset_timer(sk, TIME_CLOSE, 4 * sk->rto);
#endif
if (timeout) if (timeout)
tcp_time_wait(sk); tcp_time_wait(sk);
release_sock(sk); release_sock(sk);
...@@ -2380,9 +2365,9 @@ static void tcp_close(struct sock *sk, int timeout) ...@@ -2380,9 +2365,9 @@ static void tcp_close(struct sock *sk, int timeout)
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->window=tcp_select_window(sk)/*sk->prot->rspace(sk)*/); t1->window = ntohs(sk->window=tcp_select_window(sk));
t1->fin = 1; t1->fin = 1;
t1->rst = need_reset; t1->rst = 0;
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);
...@@ -2485,45 +2470,6 @@ tcp_write_xmit(struct sock *sk) ...@@ -2485,45 +2470,6 @@ tcp_write_xmit(struct sock *sk)
} }
/*
* This routine sorts the send list, and resets the
* sk->send_head and sk->send_tail pointers.
*/
static void sort_send(struct sock *sk)
{
struct sk_buff *list = NULL;
struct sk_buff *skb,*skb2,*skb3;
for (skb = sk->send_head; skb != NULL; skb = skb2)
{
skb2 = skb->link3;
if (list == NULL || before (skb2->h.seq, list->h.seq))
{
skb->link3 = list;
sk->send_tail = skb;
list = skb;
}
else
{
for (skb3 = list; ; skb3 = skb3->link3)
{
if (skb3->link3 == NULL ||
before(skb->h.seq, skb3->link3->h.seq))
{
skb->link3 = skb3->link3;
skb3->link3 = skb;
if (skb->link3 == NULL)
sk->send_tail = skb;
break;
}
}
}
}
sk->send_head = list;
}
/* /*
* This routine deals with incoming acks, but not outgoing ones. * This routine deals with incoming acks, but not outgoing ones.
*/ */
...@@ -2724,11 +2670,7 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int ...@@ -2724,11 +2670,7 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int
/* Check for a bug. */ /* Check for a bug. */
if (sk->send_head->link3 && if (sk->send_head->link3 &&
after(sk->send_head->h.seq, sk->send_head->link3->h.seq)) after(sk->send_head->h.seq, sk->send_head->link3->h.seq))
{
printk("INET: tcp.c: *** bug send_list out of order.\n"); printk("INET: tcp.c: *** bug send_list out of order.\n");
sort_send(sk);
}
if (before(sk->send_head->h.seq, ack+1)) if (before(sk->send_head->h.seq, ack+1))
{ {
struct sk_buff *oskb; struct sk_buff *oskb;
...@@ -2979,17 +2921,8 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int ...@@ -2979,17 +2921,8 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int
if (sk->rcv_ack_seq == sk->write_seq) if (sk->rcv_ack_seq == sk->write_seq)
{ {
flag |= 1; flag |= 1;
#ifdef THIS_BIT_IS_WRONG sk->shutdown |= SEND_SHUTDOWN;
if (sk->acked_seq != sk->fin_seq) tcp_set_state(sk,TCP_FIN_WAIT2);
{
tcp_time_wait(sk);
}
else
#endif
{
sk->shutdown |= SEND_SHUTDOWN;
tcp_set_state(sk,TCP_FIN_WAIT2);
}
} }
} }
...@@ -3094,7 +3027,7 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk, ...@@ -3094,7 +3027,7 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk,
{ {
new_seq= th->seq + skb->len + th->syn; /* Right edge of _data_ part of frame */ new_seq= th->seq + skb->len + th->syn; /* Right edge of _data_ part of frame */
if(after(new_seq,sk->/*copied*/acked_seq+1)) /* If the right edge of this frame is after the last copied byte if(after(new_seq,sk->acked_seq+1)) /* If the right edge of this frame is after the last copied byte
then it contains data we will never touch. We send an RST to then it contains data we will never touch. We send an RST to
ensure the far end knows it never got to the application */ ensure the far end knows it never got to the application */
{ {
...@@ -3110,12 +3043,6 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk, ...@@ -3110,12 +3043,6 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk,
sk->state_change(sk); sk->state_change(sk);
return(0); return(0);
} }
#if 0
/* Discard the frame here - we've already proved its a duplicate */
kfree_skb(skb, FREE_READ);
return(0);
#endif
} }
/* /*
* Now we have to walk the chain, and figure out where this one * Now we have to walk the chain, and figure out where this one
...@@ -3438,7 +3365,6 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th, ...@@ -3438,7 +3365,6 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th,
* sending the ack. * sending the ack.
*/ */
reset_timer(sk, TIME_CLOSE, TCP_TIMEOUT_LEN); reset_timer(sk, TIME_CLOSE, TCP_TIMEOUT_LEN);
/*sk->fin_seq = th->seq+1;*/
tcp_set_state(sk,TCP_CLOSE_WAIT); tcp_set_state(sk,TCP_CLOSE_WAIT);
if (th->rst) if (th->rst)
sk->shutdown = SHUTDOWN_MASK; sk->shutdown = SHUTDOWN_MASK;
...@@ -3468,7 +3394,6 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th, ...@@ -3468,7 +3394,6 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th,
*/ */
reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN); reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
/*sk->fin_seq = th->seq+1;*/
tcp_set_state(sk,TCP_CLOSING); tcp_set_state(sk,TCP_CLOSING);
break; break;
case TCP_FIN_WAIT2: case TCP_FIN_WAIT2:
...@@ -3476,7 +3401,6 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th, ...@@ -3476,7 +3401,6 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th,
* received a FIN -- send ACK and enter TIME_WAIT * received a FIN -- send ACK and enter TIME_WAIT
*/ */
reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN); reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
/*sk->fin_seq = th->seq+1;*/
sk->shutdown|=SHUTDOWN_MASK; sk->shutdown|=SHUTDOWN_MASK;
tcp_set_state(sk,TCP_TIME_WAIT); tcp_set_state(sk,TCP_TIME_WAIT);
break; break;
...@@ -3707,7 +3631,6 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -3707,7 +3631,6 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
*/ */
tcp_set_state(sk,TCP_SYN_SENT); tcp_set_state(sk,TCP_SYN_SENT);
/* sk->rtt = TCP_CONNECT_TIME;*/
sk->rto = TCP_TIMEOUT_INIT; sk->rto = TCP_TIMEOUT_INIT;
reset_timer(sk, TIME_WRITE, sk->rto); /* Timer for repeating the SYN until an answer */ reset_timer(sk, TIME_WRITE, sk->rto); /* Timer for repeating the SYN until an answer */
sk->retransmits = TCP_RETR2 - TCP_SYN_RETRIES; sk->retransmits = TCP_RETR2 - TCP_SYN_RETRIES;
...@@ -4376,7 +4299,7 @@ static void tcp_write_wakeup(struct sock *sk) ...@@ -4376,7 +4299,7 @@ static void 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(tcp_select_window(sk)/*sk->prot->rspace(sk)*/); t1->window = ntohs(tcp_select_window(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);
...@@ -4425,7 +4348,6 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int op ...@@ -4425,7 +4348,6 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int op
switch(optname) switch(optname)
{ {
case TCP_MAXSEG: case TCP_MAXSEG:
/* if(val<200||val>2048 || val>sk->mtu) */
/* /*
* values greater than interface MTU won't take effect. however at * values greater than interface MTU won't take effect. however at
* the point when this call is done we typically don't yet know * the point when this call is done we typically don't yet know
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
* of inet_bh() with this socket being handled it goes * of inet_bh() with this socket being handled it goes
* BOOM! Have to stop timer going off if net_bh is * BOOM! Have to stop timer going off if net_bh is
* active or the destroy causes crashes. * active or the destroy causes crashes.
* Alan Cox : Cleaned up unused code.
* *
* 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
...@@ -103,26 +104,9 @@ void net_timer (unsigned long data) ...@@ -103,26 +104,9 @@ void net_timer (unsigned long data)
sk->inuse = 1; sk->inuse = 1;
sti(); sti();
#ifdef NOTDEF
/*
* what the hell is this doing here? this belongs in tcp.c.
* I believe that this code is the cause of a lot of timer
* screwups, especially during close (like FIN_WAIT1 states
* with a KEEPOPEN timeout rather then a WRITE timeout).
*/
if (skb_peek(&sk->write_queue) &&
before(sk->window_seq, sk->write_queue.next->h.seq) &&
sk->send_head == NULL &&
sk->ack_backlog == 0 &&
sk->state != TCP_TIME_WAIT)
reset_timer(sk, TIME_PROBE0, sk->rto);
else if (sk->keepopen)
reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
#endif
/* Always see if we need to send an ack. */ /* Always see if we need to send an ack. */
if (sk->ack_backlog) if (sk->ack_backlog && !sk->zapped)
{ {
sk->prot->read_wakeup (sk); sk->prot->read_wakeup (sk);
if (! sk->dead) if (! sk->dead)
......
...@@ -17,7 +17,9 @@ ...@@ -17,7 +17,9 @@
* top level. * top level.
* Alan Cox : Move address structures to/from user * Alan Cox : Move address structures to/from user
* mode above the protocol layers. * mode above the protocol layers.
* Rob Janssen : Allow 0 length sends * Rob Janssen : Allow 0 length sends.
* Alan Cox : Asynchronous I/O support (cribbed from the
* tty drivers).
* *
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -62,6 +64,8 @@ static void sock_close(struct inode *inode, struct file *file); ...@@ -62,6 +64,8 @@ static void sock_close(struct inode *inode, struct file *file);
static int sock_select(struct inode *inode, struct file *file, int which, select_table *seltable); static int sock_select(struct inode *inode, struct file *file, int which, select_table *seltable);
static int sock_ioctl(struct inode *inode, struct file *file, static int sock_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
static int sock_fasync(struct inode *inode, struct file *filp, int on);
/* /*
...@@ -78,7 +82,9 @@ static struct file_operations socket_file_ops = { ...@@ -78,7 +82,9 @@ static struct file_operations socket_file_ops = {
sock_ioctl, sock_ioctl,
NULL, /* mmap */ NULL, /* mmap */
NULL, /* no special open code... */ NULL, /* no special open code... */
sock_close sock_close,
NULL, /* no fsync */
sock_fasync
}; };
/* /*
...@@ -256,6 +262,7 @@ static struct socket *sock_alloc(int wait) ...@@ -256,6 +262,7 @@ static struct socket *sock_alloc(int wait)
sock->data = NULL; sock->data = NULL;
sock->conn = NULL; sock->conn = NULL;
sock->iconn = NULL; sock->iconn = NULL;
sock->fasync_list = NULL;
/* /*
* This really shouldn't be necessary, but everything * This really shouldn't be necessary, but everything
* else depends on inodes, so we grab it. * else depends on inodes, so we grab it.
...@@ -467,7 +474,7 @@ static int sock_select(struct inode *inode, struct file *file, int sel_type, sel ...@@ -467,7 +474,7 @@ static int sock_select(struct inode *inode, struct file *file, int sel_type, sel
} }
void sock_close(struct inode *inode, struct file *file) void sock_close(struct inode *inode, struct file *filp)
{ {
struct socket *sock; struct socket *sock;
...@@ -483,10 +490,72 @@ void sock_close(struct inode *inode, struct file *file) ...@@ -483,10 +490,72 @@ void sock_close(struct inode *inode, struct file *file)
printk("NET: sock_close: can't find socket for inode!\n"); printk("NET: sock_close: can't find socket for inode!\n");
return; return;
} }
sock_fasync(inode, filp, 0);
sock_release(sock); sock_release(sock);
} }
/*
* Update the socket async list
*/
static int sock_fasync(struct inode *inode, struct file *filp, int on)
{
struct fasync_struct *fa, *fna=NULL, **prev;
struct socket *sock;
unsigned long flags;
if (on)
{
fna=(struct fasync_struct *)kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
if(fna==NULL)
return -ENOMEM;
}
sock = socki_lookup(inode);
prev=&(sock->fasync_list);
save_flags(flags);
cli();
for(fa=*prev; fa!=NULL; prev=&fa->fa_next,fa=*prev)
if(fa->fa_file==filp)
break;
if(on)
{
if(fa!=NULL)
{
kfree_s(fna,sizeof(struct fasync_struct));
restore_flags(flags);
return 0;
}
fna->fa_file=filp;
fna->magic=FASYNC_MAGIC;
fna->fa_next=sock->fasync_list;
sock->fasync_list=fna;
}
else
{
if(fa!=NULL)
{
*prev=fa->fa_next;
kfree_s(fa,sizeof(struct fasync_struct));
}
}
restore_flags(flags);
return 0;
}
int sock_wake_async(struct socket *sock)
{
if(sock->fasync_list==NULL)
return -1;
kill_fasync(sock->fasync_list, SIGIO);
return 0;
}
/* /*
* Wait for a connection. * Wait for a connection.
*/ */
...@@ -1265,6 +1334,32 @@ int sock_register(int family, struct proto_ops *ops) ...@@ -1265,6 +1334,32 @@ int sock_register(int family, struct proto_ops *ops)
return(-ENOMEM); return(-ENOMEM);
} }
/*
* This function is called by a protocol handler that wants to
* remove its address family, and have it unlinked from the
* SOCKET module.
*/
int sock_unregister(int family)
{
int i;
cli();
for(i = 0; i < NPROTO; i++)
{
if (pops[i] == NULL)
continue;
if(pops[i]->family == family)
{
pops[i]=NULL;
sti();
return(i);
}
}
sti();
return(-ENOENT);
}
void proto_init(void) void proto_init(void)
{ {
extern struct net_proto protocols[]; /* Network protocols */ extern struct net_proto protocols[]; /* Network protocols */
...@@ -1286,7 +1381,7 @@ void sock_init(void) ...@@ -1286,7 +1381,7 @@ void sock_init(void)
struct socket *sock; struct socket *sock;
int i; int i;
printk("Swansea University Computer Society NET3.016\n"); printk("Swansea University Computer Society NET3.017\n");
/* /*
* Release all sockets. * Release all sockets.
......
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