--- linux/net/ipv4/tcp_input.c.orig Wed Feb 9 04:35:27 2000 +++ linux/net/ipv4/tcp_input.c Thu Mar 2 12:55:28 2000 @@ -534,7 +534,12 @@ sk->err = ECONNRESET; } - tcp_done(sk); + if (sk->dead) { + tcp_done(sk); + } else { + tcp_done(sk); + sock_wake_async(sk->socket, 0, POLL_ERR); + } } /* This tags the retransmission queue when SACKs arrive. */ @@ -1659,8 +1664,7 @@ tp->num_sacks = 0; if (!sk->dead) { - sk->state_change(sk); - sock_wake_async(sk->socket, 1, POLL_HUP); + sk->data_ready(sk,0); } } --- linux/net/ipv4/tcp.c.orig Wed Feb 9 04:35:27 2000 +++ linux/net/ipv4/tcp.c Thu Mar 2 13:27:03 2000 @@ -1693,9 +1693,17 @@ void tcp_close(struct sock *sk, long timeout) { struct sk_buff *skb; + int old_shutdown; int data_was_unread = 0; lock_sock(sk); + old_shutdown = sk->shutdown; + if (((old_shutdown & SHUTDOWN_MASK) != SHUTDOWN_MASK) && + (sk->state != TCP_CLOSE)) { + read_lock(&sk->callback_lock); + sock_wake_async(sk->socket, 0, POLL_HUP); + read_unlock(&sk->callback_lock); + } sk->shutdown = SHUTDOWN_MASK; if(sk->state == TCP_LISTEN) { --- linux/net/socket.c.orig Sat Feb 12 19:52:04 2000 +++ linux/net/socket.c Thu Mar 2 13:45:22 2000 @@ -98,6 +98,7 @@ struct poll_table_struct *wait); static int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg); static int sock_fasync(int fd, struct file *filp, int on); static ssize_t sock_readv(struct file *file, const struct iovec *vector, unsigned long count, loff_t *ppos); @@ -375,11 +376,22 @@ void sock_release(struct socket *sock) { +struct sock *sk; +struct fasync_struct *fa; + if (sock->ops) sock->ops->release(sock); - if (sock->fasync_list) - printk(KERN_ERR "sock_release: fasync list not empty!\n"); + if ((sk = sock->sk) != NULL) { + lock_sock(sk); + write_lock_bh(&sk->callback_lock); + while ((fa = sock->fasync_list)) { + sock->fasync_list = fa->fa_next; + kfree_s(fa,sizeof(struct fasync_struct)); + } + write_unlock_bh(&sk->callback_lock); + release_sock(sk); + } sockets_in_use[smp_processor_id()].counter--; if (!sock->file) { @@ -598,7 +610,7 @@ return 0; } unlock_kernel(); - sock_fasync(-1, filp, 0); + //sock_fasync(-1, filp, 0); sock_release(socki_lookup(inode)); lock_kernel(); return 0; @@ -670,6 +682,7 @@ if (fa!=NULL) { write_lock_bh(&sk->callback_lock); + sock_wake_async(sock, 0, POLL_HUP); *prev=fa->fa_next; write_unlock_bh(&sk->callback_lock); kfree_s(fa,sizeof(struct fasync_struct)); @@ -919,6 +932,56 @@ return err; } +/* + * Setup the accepted socket + */ + +static void check_accept_flags(int fd, struct socket *sock, struct socket *newsock) +{ + struct sock *newsk = newsock->sk; + struct file *file1, *file2; + + file1 = sock->file; + file2 = newsock->file; + + if (newsk->accept_flags & SO_ACCEPT_F_ASYNC) { + + /* Inherit F_SETSIG, F_SETOWN and FASYNC and */ + /* send SIGIO if newsk is not in initial state */ + + file2->f_owner.signum = file1->f_owner.signum; + file2->f_owner.pid = file1->f_owner.pid; + file2->f_owner.uid = file1->f_owner.uid; + file2->f_owner.euid = file1->f_owner.euid; + sock_fcntl(file2, F_SETOWN, file2->f_owner.pid); + if (file1->f_flags & O_NONBLOCK) { + file2->f_flags |= O_NONBLOCK; + if (O_NONBLOCK != O_NDELAY) { + if (file1->f_flags & O_NDELAY) { + file2->f_flags |= O_NDELAY; + } + } + } + if (file1->f_flags & FASYNC) { + struct tcp_opt *tp = &(newsk->tp_pinfo.af_tcp); + + file2->f_flags |= FASYNC; + if (file2->f_op && file2->f_op->fasync) { + file2->f_op->fasync(fd, file2, 1); + } + if (newsk->err) { + read_lock(&newsk->callback_lock); + sock_wake_async(newsock, 0, POLL_ERR); + read_unlock(&newsk->callback_lock); + } else if (after(tp->rcv_nxt, tp->copied_seq)) { + /* Notify for data and/or FIN */ + read_lock(&newsk->callback_lock); + sock_wake_async(newsock, 1, POLL_IN); + read_unlock(&newsk->callback_lock); + } + } + } +} /* * For accept, we attempt to create a new socket, set up the link @@ -967,6 +1030,10 @@ if ((err = sock_map_fd(newsock)) < 0) goto out_release; + + /* We want to modify the accepted socket, so check accept_flags */ + if (newsock->sk->accept_flags) + check_accept_flags(err, sock, newsock); out_put: sockfd_put(sock); --- linux/net/core/sock.c.orig Sat Jan 22 21:54:57 2000 +++ linux/net/core/sock.c Wed Mar 1 14:14:59 2000 @@ -322,6 +322,12 @@ ret = sock_set_timeout(&sk->sndtimeo, optval, optlen); break; +#ifdef SO_ACCEPT_FLAGS + case SO_ACCEPT_FLAGS: + sk->accept_flags = val; + break; +#endif + #ifdef CONFIG_NETDEVICES case SO_BINDTODEVICE: { --- linux/include/asm-i386/socket.h.orig Mon Dec 22 03:41:24 1997 +++ linux/include/asm-i386/socket.h Wed Mar 1 12:37:44 2000 @@ -39,4 +39,9 @@ #define SO_ATTACH_FILTER 26 #define SO_DETACH_FILTER 27 +/* Flags for accept() */ +#define SO_ACCEPT_FLAGS 28 + /* Inherit FASYNC, O_NONBLOCK, ownership and rt signal */ +# define SO_ACCEPT_F_ASYNC 0x01 + #endif /* _ASM_SOCKET_H */ --- linux/include/net/sock.h.orig Wed Mar 1 11:17:55 2000 +++ linux/include/net/sock.h Wed Mar 1 14:07:36 2000 @@ -468,6 +468,7 @@ __u32 saddr; /* Sending source */ unsigned int allocation; /* Allocation mode */ int sndbuf; /* Size of send buffer in bytes */ + int accept_flags; /* Flags used from accept() */ struct sock *prev; /* Not all are volatile, but some are, so we might as well say they all are.