xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 4886)
1*4886Swnj /* tcp_usrreq.c 1.27 81/11/14 */
24567Swnj 
34497Swnj #include "../h/param.h"
44567Swnj #include "../h/systm.h"
54664Swnj #include "../h/mbuf.h"
64664Swnj #include "../h/socket.h"
74809Swnj #include "../h/socketvar.h"
84809Swnj #include "../h/protosw.h"
94809Swnj #include "../net/inet.h"
10*4886Swnj #include "../net/inet_host.h"
11*4886Swnj #include "../net/inet_pcb.h"
124809Swnj #include "../net/inet_systm.h"
134809Swnj #include "../net/imp.h"
144809Swnj #include "../net/ip.h"
154809Swnj #include "../net/tcp.h"
164567Swnj #define TCPFSTAB
174584Swnj #ifdef TCPDEBUG
184584Swnj #define TCPSTATES
194584Swnj #endif
204809Swnj #include "../net/tcp_fsm.h"
214809Swnj #include "../net/tcp_var.h"
224809Swnj #include "/usr/include/errno.h"
234497Swnj 
244734Swnj /*
254809Swnj  * Tcp initialization
264809Swnj  */
274809Swnj tcp_init()
284809Swnj {
294809Swnj 
304809Swnj 	tcp_iss = 1;		/* wrong */
31*4886Swnj 	tcb.inp_next = tcb.inp_prev = &tcb;
324809Swnj }
334809Swnj 
344809Swnj /*
354734Swnj  * Tcp finite state machine entries for timer and user generated
364734Swnj  * requests.  These routines raise the ipl to that of the network
374734Swnj  * to prevent reentry.  In particluar, this requires that the software
384734Swnj  * clock interrupt have lower priority than the network so that
394734Swnj  * we can enter the network from timeout routines without improperly
404734Swnj  * nesting the interrupt stack.
414734Swnj  */
424734Swnj 
434734Swnj /*
444809Swnj  * Tcp protocol timeout routine called every 500 ms.
454734Swnj  * Updates the timers in all active tcb's and
464734Swnj  * causes finite state machine actions if timers expire.
474734Swnj  */
484809Swnj tcp_slowtimo()
494497Swnj {
50*4886Swnj 	register struct inpcb *ip;
51*4886Swnj 	register struct tcpcb *tp;
524567Swnj 	int s = splnet();
534809Swnj 	register short *tmp;
544731Swnj 	register int i;
554567Swnj COUNT(TCP_TIMEO);
564497Swnj 
574567Swnj 	/*
584567Swnj 	 * Search through tcb's and update active timers.
594567Swnj 	 */
60*4886Swnj 	for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) {
61*4886Swnj 		tp = intotcpcb(ip);
624731Swnj 		tmp = &tp->t_init;
634735Swnj 		for (i = 0; i < TNTIMERS; i++) {
644731Swnj 			if (*tmp && --*tmp == 0)
65*4886Swnj 				tcp_usrreq(tp->t_inpcb->inp_socket,
66*4886Swnj 				    PRU_SLOWTIMO, 0, i);
674735Swnj 			tmp++;
684735Swnj 		}
694567Swnj 		tp->t_xmt++;
704567Swnj 	}
714809Swnj 	tcp_iss += ISSINCR/2;		/* increment iss */
724567Swnj 	splx(s);
734497Swnj }
744497Swnj 
754731Swnj /*
764734Swnj  * Cancel all timers for tcp tp.
774734Swnj  */
784734Swnj tcp_tcancel(tp)
79*4886Swnj 	struct tcpcb *tp;
804734Swnj {
814809Swnj 	register short *tmp = &tp->t_init;
824734Swnj 	register int i;
834734Swnj 
844734Swnj 	for (i = 0; i < TNTIMERS; i++)
854734Swnj 		*tmp++ = 0;
864734Swnj }
874734Swnj 
884734Swnj /*
894731Swnj  * Process a TCP user request for tcp tb.  If this is a send request
904731Swnj  * then m is the mbuf chain of send data.  If this is a timer expiration
914731Swnj  * (called from the software clock routine), then timertype tells which timer.
924731Swnj  */
934809Swnj tcp_usrreq(so, req, m, addr)
944809Swnj 	struct socket *so;
954809Swnj 	int req;
964731Swnj 	struct mbuf *m;
974809Swnj 	caddr_t addr;
984497Swnj {
99*4886Swnj 	register struct inpcb *inp = sotoinpcb(so);
100*4886Swnj 	register struct tcpcb *tp = intotcpcb(inp);
1014567Swnj 	int s = splnet();
1024567Swnj 	register int nstate;
1034584Swnj #ifdef TCPDEBUG
1044584Swnj 	struct tcp_debug tdb;
1054584Swnj #endif
1064809Swnj 	int error = 0;
1074567Swnj COUNT(TCP_USRREQ);
1084497Swnj 
109*4886Swnj 	/*
110*4886Swnj 	 * Make sure attached.  If not,
111*4886Swnj 	 * only PRU_ATTACH is valid.
112*4886Swnj 	 */
1134809Swnj 	if (tp) {
1144809Swnj 		nstate = tp->t_state;
1154809Swnj 		tp->tc_flags &= ~TC_NET_KEEP;
116*4886Swnj 	} else
117*4886Swnj 		if (req != PRU_ATTACH) {
118*4886Swnj 			splx(s);
119*4886Swnj 			return (EINVAL);
120*4886Swnj 		}
121*4886Swnj 
122*4886Swnj 	/*
123*4886Swnj 	 * Do tracing and accounting.
124*4886Swnj 	 */
1254731Swnj #ifdef KPROF
1264809Swnj 	acounts[nstate][req]++;
1274731Swnj #endif
1284584Swnj #ifdef TCPDEBUG
1294809Swnj 	if (tp && ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug)) {
130*4886Swnj 		tdb_setup(tp, (struct tcpiphdr *)0, req, &tdb);
1314584Swnj 		tdb.td_tim = timertype;
1324584Swnj 	} else
1334584Swnj 		tdb.td_tod = 0;
1344584Swnj #endif
1354809Swnj 	switch (req) {
1364497Swnj 
1374809Swnj 	case PRU_ATTACH:
1384809Swnj 		if (tp)
1394809Swnj 			error = EISCONN;
140*4886Swnj 		else {
141*4886Swnj 			tcp_attach(so);
142*4886Swnj 			tp = sototcpcb(so);
143*4886Swnj 		}
144*4886Swnj 		if (so->so_options & SO_ACCEPTCONN) {
145*4886Swnj 			inp->inp_lhost = h_make(&n_lhost);
146*4886Swnj 			in_pcbgenport(&tcb, inp);
147*4886Swnj 			nstate = LISTEN;
148*4886Swnj 		} else
149*4886Swnj 			nstate = CLOSED;
1504567Swnj 		break;
1514497Swnj 
1524809Swnj 	case PRU_DETACH:
153*4886Swnj 		tcp_detach(so);
1544809Swnj 		break;
1554809Swnj 
1564809Swnj 	case PRU_CONNECT:
157*4886Swnj 		if (tp->t_state != 0 && tp->t_state != CLOSED)
1584731Swnj 			goto bad;
159*4886Swnj 		inp->inp_fhost = in_hmake((struct in_addr *)addr, &error);
160*4886Swnj 		if (inp->inp_fhost == 0)
161*4886Swnj 			break;
1624676Swnj 		tcp_sndctl(tp);
1634567Swnj 		nstate = SYN_SENT;
164*4886Swnj 		soisconnecting(so);
1654567Swnj 		break;
1664497Swnj 
1674809Swnj 	case PRU_DISCONNECT:
168*4886Swnj 		if ((tp->tc_flags & TC_FIN_RCVD) == 0)
169*4886Swnj 			goto abort;
170*4886Swnj 		if (nstate < ESTAB)
171*4886Swnj 			tcp_disconnect(so);
172*4886Swnj 		else {
173*4886Swnj 			tp->tc_flags |= TC_SND_FIN;
174*4886Swnj 			tcp_sendctl(tp);
175*4886Swnj 			tp->tc_flags |= TC_USR_CLOSED;
176*4886Swnj 			soisdisconnecting(so);
177*4886Swnj 		}
1784809Swnj 		break;
1794809Swnj 
1804809Swnj 	case PRU_SHUTDOWN:
1814731Swnj 		switch (nstate) {
1824497Swnj 
1834731Swnj 		case LISTEN:
1844734Swnj 		case SYN_SENT:
1854731Swnj 			nstate = CLOSED;
1864731Swnj 			break;
1874731Swnj 
1884734Swnj 		case SYN_RCVD:
1894731Swnj 		case L_SYN_RCVD:
1904731Swnj 		case ESTAB:
1914734Swnj 		case CLOSE_WAIT:
1924731Swnj 			tp->tc_flags |= TC_SND_FIN;
1934731Swnj 			tcp_sndctl(tp);
1944731Swnj 			tp->tc_flags |= TC_USR_CLOSED;
1954731Swnj 			nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK;
1964731Swnj 			break;
1974731Swnj 
1984731Swnj 		case FIN_W1:
1994731Swnj 		case FIN_W2:
2004731Swnj 		case TIME_WAIT:
2014731Swnj 		case CLOSING:
2024731Swnj 		case LAST_ACK:
2034731Swnj 		case RCV_WAIT:
2044731Swnj 			break;
2054731Swnj 
2064731Swnj 		default:
2074731Swnj 			goto bad;
2084731Swnj 		}
2094567Swnj 		break;
2104497Swnj 
2114809Swnj 	case PRU_RCVD:
2124731Swnj 		if (nstate < ESTAB || nstate == CLOSED)
2134731Swnj 			goto bad;
2144734Swnj 		tcp_sndwin(tp);
2154691Swnj 		if ((tp->tc_flags&TC_FIN_RCVD) &&
2164691Swnj 		    (tp->tc_flags&TC_USR_CLOSED) == 0 &&
2174691Swnj 		    rcv_empty(tp))
218*4886Swnj 			error = ESHUTDOWN;
2194809Swnj 		if (nstate == RCV_WAIT && rcv_empty(tp))
2204567Swnj 			nstate = CLOSED;
2214567Swnj 		break;
2224497Swnj 
2234809Swnj 	case PRU_SEND:
2244731Swnj 		switch (nstate) {
2254567Swnj 
2264731Swnj 		case ESTAB:
2274731Swnj 		case CLOSE_WAIT:
228*4886Swnj 			tcp_usrsend(tp, m);
2294731Swnj 			break;
2304731Swnj 
2314731Swnj 		default:
2324731Swnj 			if (nstate < ESTAB)
2334731Swnj 				goto bad;
2344809Swnj 			m_freem(m);
235*4886Swnj 			error = ENOTCONN;
2364731Swnj 			break;
2374731Swnj 		}
2384567Swnj 		break;
2394567Swnj 
240*4886Swnj abort:
2414809Swnj 	case PRU_ABORT:
242*4886Swnj 		tcp_abort(tp);
2434567Swnj 		nstate = CLOSED;
2444567Swnj 		break;
2454567Swnj 
2464809Swnj 	case PRU_CONTROL:
247*4886Swnj 		error = EOPNOTSUPP;
2484809Swnj 		break;
2494809Swnj 
2504809Swnj 	case PRU_SLOWTIMO:
2514809Swnj 		switch (nstate) {
2524809Swnj 
2534809Swnj 		case 0:
2544809Swnj 		case CLOSED:
2554809Swnj 		case LISTEN:
2564809Swnj 			goto bad;
2574809Swnj 
2584809Swnj 		default:
2594809Swnj 			nstate = tcp_timers(tp, (int)addr);
2604809Swnj 		}
2614809Swnj 		break;
2624809Swnj 
2634731Swnj 	default:
2644731Swnj 		panic("tcp_usrreq");
2654731Swnj 	bad:
2664731Swnj 		printf("tcp: bad state: tcb=%x state=%d input=%d\n",
2674809Swnj 		    tp, tp->t_state, req);
2684731Swnj 		nstate = EFAILEC;
2694567Swnj 		break;
2704567Swnj 	}
2714567Swnj #ifdef TCPDEBUG
2724605Swnj 	if (tdb.td_tod)
2734605Swnj 		tdb_stuff(&tdb, nstate);
2744567Swnj #endif
2754567Swnj 	switch (nstate) {
2764567Swnj 
2774584Swnj 	case CLOSED:
2784567Swnj 	case SAME:
2794567Swnj 		break;
2804567Swnj 
2814567Swnj 	case EFAILEC:
2824731Swnj 		if (m)
2834731Swnj 			m_freem(dtom(m));
2844567Swnj 		break;
2854567Swnj 
2864567Swnj 	default:
2874567Swnj 		tp->t_state = nstate;
2884567Swnj 		break;
2894567Swnj 	}
2904567Swnj 	splx(s);
291*4886Swnj 	return (error);
2924497Swnj }
2934497Swnj 
2944809Swnj tcp_attach(so)
2954809Swnj 	register struct socket *so;
2964809Swnj {
297*4886Swnj 	register struct tcpcb *tp;
2984809Swnj COUNT(TCP_ATTACH);
2994497Swnj 
3004682Swnj 	/*
301*4886Swnj 	 * Make empty reassembly queue.
3024682Swnj 	 */
303*4886Swnj 	tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
3044497Swnj 
3054682Swnj 	/*
306*4886Swnj 	 * Initialize sequence numbers and round trip retransmit timer.
3074682Swnj 	 */
3084567Swnj 	tp->t_xmtime = T_REXMT;
3094682Swnj 	tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una =
3104682Swnj 	    tp->iss = tcp_iss;
3114567Swnj 	tp->snd_off = tp->iss + 1;
3124664Swnj 	tcp_iss += (ISSINCR >> 1) + 1;
3134497Swnj }
3144497Swnj 
315*4886Swnj tcp_detach(so)
316*4886Swnj 	register struct socket *so;
3174497Swnj {
318*4886Swnj 	register struct tcpcb *tp = (struct tcpcb *)so->so_pcb;
319*4886Swnj 	register struct tcpiphdr *t;
3204567Swnj 	register struct mbuf *m;
3214809Swnj COUNT(TCP_DETACH);
3224497Swnj 
323*4886Swnj 	wmemfree((caddr_t)tp, 1024);
324*4886Swnj 	m_release(so->so_rcv.sb_hiwat + so->so_snd.sb_hiwat + 2 * MSIZE);
325*4886Swnj }
326*4886Swnj 
327*4886Swnj tcp_disconnect(tp)
328*4886Swnj 	register struct tcpcb *tp;
329*4886Swnj {
330*4886Swnj 	register struct tcpiphdr *t;
331*4886Swnj 	register struct mbuf *m;
332*4886Swnj 	register struct socket *so;
333*4886Swnj 
3344734Swnj 	tcp_tcancel(tp);
335*4886Swnj 	t = tp->seg_next;
336*4886Swnj 	for (; t != (struct tcpiphdr *)tp; t = t->t_next)
3374567Swnj 		m_freem(dtom(t));
338*4886Swnj 	tcp_drainunack(tp);
3394734Swnj 	if (tp->t_template) {
3404734Swnj 		m_free(dtom(tp->t_template));
3414734Swnj 		tp->t_template = 0;
3424664Swnj 	}
343*4886Swnj 	in_pcbfree(tp->t_inpcb);
3444497Swnj }
3454497Swnj 
346*4886Swnj tcp_abort(so)
347*4886Swnj 	register struct socket *so;
348*4886Swnj {
349*4886Swnj 	register struct tcpcb *tp = sototcpcb(so);
350*4886Swnj 
351*4886Swnj 	switch (tp->t_state) {
352*4886Swnj 
353*4886Swnj 	case SYN_RCVD:
354*4886Swnj 	case ESTAB:
355*4886Swnj 	case FIN_W1:
356*4886Swnj 	case FIN_W2:
357*4886Swnj 	case CLOSE_WAIT:
358*4886Swnj 		tp->tc_flags |= TC_SND_RST;
359*4886Swnj 		tcp_sndnull(tp);
360*4886Swnj 	}
361*4886Swnj 	if (so)
362*4886Swnj 		soisdisconnected(so);
363*4886Swnj }
364*4886Swnj 
3654682Swnj /*
3664734Swnj  * Send data queue headed by m0 into the protocol.
3674682Swnj  */
3684678Swnj tcp_usrsend(tp, m0)
369*4886Swnj 	register struct tcpcb *tp;
3704584Swnj 	struct mbuf *m0;
3714497Swnj {
3724497Swnj 	register struct mbuf *m, *n;
373*4886Swnj 	register struct socket *so = tp->t_inpcb->inp_socket;
3744497Swnj 	register off;
3754574Swnj 	seq_t last;
3764682Swnj COUNT(TCP_USRSEND);
3774497Swnj 
378*4886Swnj 	sbappend(&so->so_snd, m0);
3794809Swnj 	if (tp->t_options & TO_EOL)
380*4886Swnj 		tp->snd_end = tp->snd_off + so->so_snd.sb_cc;
3814809Swnj 	if (tp->t_options & TO_URG) {
382*4886Swnj 		tp->snd_urp = tp->snd_off + so->so_snd.sb_cc + 1;
3834576Swnj 		tp->tc_flags |= TC_SND_URG;
3844567Swnj 	}
3854678Swnj 	tcp_send(tp);
3864497Swnj }
3874497Swnj 
3884682Swnj /*
3894682Swnj  * TCP timer went off processing.
3904682Swnj  */
3914584Swnj tcp_timers(tp, timertype)
392*4886Swnj 	register struct tcpcb *tp;
3934584Swnj 	int timertype;
3944497Swnj {
3954497Swnj 
3964567Swnj COUNT(TCP_TIMERS);
3974584Swnj 	switch (timertype) {
3984497Swnj 
3994567Swnj 	case TFINACK:		/* fin-ack timer */
4004567Swnj 		switch (tp->t_state) {
4014497Swnj 
4024567Swnj 		case TIME_WAIT:
4034567Swnj 			/*
4044567Swnj 			 * We can be sure our ACK of foreign FIN was rcvd,
4054567Swnj 			 * and can close if no data left for user.
4064567Swnj 			 */
4074567Swnj 			if (rcv_empty(tp)) {
408*4886Swnj 				tcp_disconnect(tp);
4094567Swnj 				return (CLOSED);
4104567Swnj 			}
4114567Swnj 			return (RCV_WAIT);			/* 17 */
4124497Swnj 
4134731Swnj 		case CLOSING:
4144576Swnj 			tp->tc_flags |= TC_WAITED_2_ML;
4154567Swnj 			return (SAME);
4164497Swnj 
4174567Swnj 		default:
4184567Swnj 			return (SAME);
4194567Swnj 		}
4204497Swnj 
4214567Swnj 	case TREXMT:		/* retransmission timer */
4224567Swnj 		if (tp->t_rexmt_val > tp->snd_una) {	 	/* 34 */
4234567Swnj 			/*
4244809Swnj 			 * Set so for a retransmission, increase rexmt time
4254567Swnj 			 * in case of multiple retransmissions.
4264567Swnj 			 */
4274567Swnj 			tp->snd_nxt = tp->snd_una;
4284576Swnj 			tp->tc_flags |= TC_REXMT;
4294567Swnj 			tp->t_xmtime = tp->t_xmtime << 1;
4304567Swnj 			if (tp->t_xmtime > T_REMAX)
4314567Swnj 				tp->t_xmtime = T_REMAX;
4324678Swnj 			tcp_send(tp);
4334567Swnj 		}
4344567Swnj 		return (SAME);
4354497Swnj 
4364567Swnj 	case TREXMTTL:		/* retransmit too long */
4374567Swnj 		if (tp->t_rtl_val > tp->snd_una)		/* 36 */
438*4886Swnj 			tcp_error(EIO);		/* URXTIMO !?! */
4394567Swnj 		/*
4404567Swnj 		 * If user has already closed, abort the connection.
4414567Swnj 		 */
4424576Swnj 		if (tp->tc_flags & TC_USR_CLOSED) {
443*4886Swnj 			tcp_abort(tp);
4444567Swnj 			return (CLOSED);
4454567Swnj 		}
4464567Swnj 		return (SAME);
4474497Swnj 
4484567Swnj 	case TPERSIST:		/* persist timer */
4494567Swnj 		/*
4504567Swnj 		 * Force a byte send through closed window.
4514567Swnj 		 */
4524576Swnj 		tp->tc_flags |= TC_FORCE_ONE;
4534678Swnj 		tcp_send(tp);
4544567Swnj 		return (SAME);
4554567Swnj 	}
4564567Swnj 	panic("tcp_timers");
4574497Swnj }
4584497Swnj 
459*4886Swnj tcp_sense(m)
460*4886Swnj 	struct mbuf *m;
461*4886Swnj {
462*4886Swnj 
463*4886Swnj 	return (EOPNOTSUPP);
464*4886Swnj }
465*4886Swnj 
4664809Swnj tcp_error(so, errno)
4674809Swnj 	struct socket *so;
4684809Swnj 	int errno;
4694497Swnj {
4704567Swnj COUNT(TO_USER);
4714497Swnj 
4724809Swnj 	so->so_error = errno;
473*4886Swnj 	sorwakeup(so);
474*4886Swnj 	sowwakeup(so);
4754497Swnj }
4764584Swnj 
4774584Swnj #ifdef TCPDEBUG
4784682Swnj /*
4794682Swnj  * TCP debugging utility subroutines.
4804682Swnj  * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID.
4814682Swnj  */
4824670Swnj tdb_setup(tp, n, input, tdp)
483*4886Swnj 	struct tcpcb *tp;
484*4886Swnj 	register struct tcpiphdr *n;
4854670Swnj 	int input;
4864670Swnj 	register struct tcp_debug *tdp;
4874670Swnj {
4884670Swnj 
4894682Swnj COUNT(TDB_SETUP);
4904670Swnj 	tdp->td_tod = time;
4914670Swnj 	tdp->td_tcb = tp;
4924670Swnj 	tdp->td_old = tp->t_state;
4934670Swnj 	tdp->td_inp = input;
4944670Swnj 	tdp->td_tim = 0;
4954670Swnj 	tdp->td_new = -1;
4964670Swnj 	if (n) {
4974670Swnj 		tdp->td_sno = n->t_seq;
4984670Swnj 		tdp->td_ano = n->t_ackno;
4994670Swnj 		tdp->td_wno = n->t_win;
5004670Swnj 		tdp->td_lno = n->t_len;
5014670Swnj 		tdp->td_flg = n->th_flags;
5024670Swnj 	} else
5034670Swnj 		tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno =
5044670Swnj 		    tdp->td_flg = 0;
5054670Swnj }
5064670Swnj 
5074670Swnj tdb_stuff(tdp, nstate)
5084670Swnj 	struct tcp_debug *tdp;
5094670Swnj 	int nstate;
5104670Swnj {
5114682Swnj COUNT(TDB_STUFF);
5124670Swnj 
5134670Swnj 	tdp->td_new = nstate;
5144670Swnj 	tcp_debug[tdbx++ % TDBSIZE] = *tdp;
5154670Swnj 	if (tcpconsdebug & 2)
5164670Swnj 		tcp_prt(tdp);
5174670Swnj }
5184682Swnj 
5194682Swnj tcp_prt(tdp)
5204682Swnj 	register struct tcp_debug *tdp;
5214682Swnj {
5224682Swnj COUNT(TCP_PRT);
5234682Swnj 
5244698Swnj 	printf("%x ", ((int)tdp->td_tcb)&0xffffff);
5254698Swnj 	if (tdp->td_inp == INSEND) {
5264698Swnj 		printf("SEND #%x", tdp->td_sno);
5274698Swnj 		tdp->td_lno = ntohs(tdp->td_lno);
5284698Swnj 		tdp->td_wno = ntohs(tdp->td_wno);
5294698Swnj 	} else {
5304698Swnj 		if (tdp->td_inp == INRECV)
5314698Swnj 			printf("RCV #%x ", tdp->td_sno);
5324698Swnj 		printf("%s.%s",
5334698Swnj 		    tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]);
5344698Swnj 		if (tdp->td_inp == ISTIMER)
5354698Swnj 			printf("(%s)", tcptimers[tdp->td_tim]);
5364698Swnj 		printf(" -> %s",
5374698Swnj 		    tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]);
5384698Swnj 		if (tdp->td_new == -1)
5394698Swnj 			printf(" (FAILED)");
5404698Swnj 	}
5414682Swnj 	/* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */
5424698Swnj 	if (tdp->td_lno)
5434698Swnj 		printf(" len=%d", tdp->td_lno);
5444698Swnj 	if (tdp->td_wno)
5454698Swnj 		printf(" win=%d", tdp->td_wno);
5464698Swnj 	if (tdp->td_flg & TH_FIN) printf(" FIN");
5474698Swnj 	if (tdp->td_flg & TH_SYN) printf(" SYN");
5484698Swnj 	if (tdp->td_flg & TH_RST) printf(" RST");
5494698Swnj 	if (tdp->td_flg & TH_EOL) printf(" EOL");
5504698Swnj 	if (tdp->td_flg & TH_ACK)  printf(" ACK %x", tdp->td_ano);
5514698Swnj 	if (tdp->td_flg & TH_URG) printf(" URG");
5524682Swnj 	printf("\n");
5534682Swnj }
5544670Swnj #endif
555