This patch implements a modification of TCP on SunOS 4.1.3 to support cleaning up TIME_WAIT state at active close side. Copyright (c) 1997 University of Southern California. All rights reserved. Redistribution and use in source and binary forms are permitted provided that the above copyright notice and this paragraph are duplicated in all such forms and that any documentation, advertising materials, and other materials related to such distribution and use acknowledge that the software was developed by the University of Southern California, Information Sciences Institute. The name of the University may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -------------------------------------------------------------------------------- *** tcp.h.orig Wed Jun 16 12:13:51 1993 --- tcp.h Wed Apr 30 14:21:42 1997 *************** *** 60,63 **** --- 60,67 ---- #define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ #define TCP_MAXSEG 0x02 /* set maximum segment size */ + #ifdef PCBSWAP + #define TCP_PCBSWAP 0x04 /* swap pcbs on passive close */ + #endif + #endif /*!_netinet_tcp_h*/ *** tcp_subr.c.orig Wed Jun 16 12:13:52 1993 --- tcp_subr.c Wed Apr 30 14:37:44 1997 *************** *** 210,215 **** --- 210,233 ---- return (tcp_close(tp)); } + #ifdef PCBSWAP + /* + * Send an RST to the other side of the connection + * this is tcp_drop without the closing the socket, it's called from + * tcp_close() if PCBSWAP is in effect, the current connection is in + * LAST_ACK, has TF_PCBSWAP set and gets an ACK. See tcp_close() + */ + void tcp_swaprst(tp) + register struct tcpcb *tp; + { + struct socket *so = tp->t_inpcb->inp_socket; + + tp->t_state = TCPS_CLOSED; + (void) tcp_output(tp); + tcpstat.tcps_drops++; + } + #endif + /* * We need to clear the tcp_last_inp cache in tcp_input * when a connection finally goes away. *************** *** 231,236 **** --- 249,265 ---- struct socket *so = inp->inp_socket; register struct mbuf *m; + #ifdef PCBSWAP + if ( tp->t_state == TCPS_LAST_ACK && tp->t_flags & TF_PCBSWAP ) { + /* Send a RST packet to the other side and move this + connection to TIME_WAIT */ + tcp_swaprst(tp); + tp->t_state = TCPS_TIME_WAIT; + tcp_canceltimers(tp); + tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; + return ((struct tcpcb *)0); + } + #endif t = tp->seg_next; while (t != (struct tcpiphdr *)tp) { t = (struct tcpiphdr *)t->ti_next; *** tcp_usrreq.c.orig Wed Jun 16 12:13:52 1993 --- tcp_usrreq.c Thu May 1 21:17:20 1997 *************** *** 383,388 **** --- 383,399 ---- tp->t_flags &= ~TF_NODELAY; break; + #ifdef PCBSWAP + case TCP_PCBSWAP: + if (m == NULL || m->m_len < sizeof (int)) + error = EINVAL; + else if (*mtod(m, int *)) + tp->t_flags |= TF_PCBSWAP; + else + tp->t_flags &= ~TF_PCBSWAP; + break; + #endif + case TCP_MAXSEG: /* not yet */ default: error = EINVAL; *************** *** 400,405 **** --- 411,421 ---- case TCP_NODELAY: *mtod(m, int *) = tp->t_flags & TF_NODELAY; break; + #ifdef PCBSWAP + case TCP_PCBSWAP: + *mtod(m, int *) = tp->t_flags & TF_PCBSWAP; + break; + #endif case TCP_MAXSEG: *mtod(m, int *) = tp->t_maxseg; break; *** tcp_var.h.orig Wed Jun 16 12:13:52 1993 --- tcp_var.h Thu May 1 21:10:13 1997 *************** *** 32,37 **** --- 32,42 ---- #define TF_NODELAY 0x04 /* don't delay packets to coalesce */ #define TF_NOOPT 0x08 /* don't use tcp options */ #define TF_SENTFIN 0x10 /* have sent FIN */ + #ifdef PCBSWAP + /* High number so that fat pipe + stuff fits -- tvf */ + #define TF_PCBSWAP 0x20 /* Swap PCBs on passive close -- tvf */ + #endif struct tcpiphdr *t_template; /* skeletal packet for transmit */ struct inpcb *t_inpcb; /* back pointer to internet pcb */ /*