Commit | Line | Data |
---|---|---|
4ad99bae | 1 | /* tcp_usrreq.c 1.31 81/11/20 */ |
72f24d7d | 2 | |
4eb5d593 | 3 | #include "../h/param.h" |
72f24d7d | 4 | #include "../h/systm.h" |
dad64fdf BJ |
5 | #include "../h/mbuf.h" |
6 | #include "../h/socket.h" | |
eee3ab16 BJ |
7 | #include "../h/socketvar.h" |
8 | #include "../h/protosw.h" | |
9 | #include "../net/inet.h" | |
53a5409e | 10 | #include "../net/inet_pcb.h" |
eee3ab16 | 11 | #include "../net/inet_systm.h" |
4ad99bae | 12 | #include "../net/if.h" |
eee3ab16 BJ |
13 | #include "../net/imp.h" |
14 | #include "../net/ip.h" | |
eb44bfb2 | 15 | #include "../net/ip_var.h" |
eee3ab16 | 16 | #include "../net/tcp.h" |
72f24d7d | 17 | #define TCPFSTAB |
186b5a8a BJ |
18 | #ifdef TCPDEBUG |
19 | #define TCPSTATES | |
20 | #endif | |
eee3ab16 BJ |
21 | #include "../net/tcp_fsm.h" |
22 | #include "../net/tcp_var.h" | |
23 | #include "/usr/include/errno.h" | |
24 | ||
eee3ab16 BJ |
25 | /* |
26 | * Tcp initialization | |
27 | */ | |
28 | tcp_init() | |
29 | { | |
30 | ||
31 | tcp_iss = 1; /* wrong */ | |
53a5409e | 32 | tcb.inp_next = tcb.inp_prev = &tcb; |
eee3ab16 | 33 | } |
4eb5d593 | 34 | |
e1506033 BJ |
35 | /* |
36 | * Tcp finite state machine entries for timer and user generated | |
37 | * requests. These routines raise the ipl to that of the network | |
38 | * to prevent reentry. In particluar, this requires that the software | |
39 | * clock interrupt have lower priority than the network so that | |
40 | * we can enter the network from timeout routines without improperly | |
41 | * nesting the interrupt stack. | |
42 | */ | |
43 | ||
44 | /* | |
eee3ab16 | 45 | * Tcp protocol timeout routine called every 500 ms. |
e1506033 BJ |
46 | * Updates the timers in all active tcb's and |
47 | * causes finite state machine actions if timers expire. | |
48 | */ | |
eee3ab16 | 49 | tcp_slowtimo() |
4eb5d593 | 50 | { |
53a5409e BJ |
51 | register struct inpcb *ip; |
52 | register struct tcpcb *tp; | |
72f24d7d | 53 | int s = splnet(); |
eee3ab16 | 54 | register short *tmp; |
9c5022e3 | 55 | register int i; |
72f24d7d BJ |
56 | COUNT(TCP_TIMEO); |
57 | ||
58 | /* | |
59 | * Search through tcb's and update active timers. | |
60 | */ | |
53a5409e BJ |
61 | for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) { |
62 | tp = intotcpcb(ip); | |
9c5022e3 | 63 | tmp = &tp->t_init; |
2e80fb4c | 64 | for (i = 0; i < TNTIMERS; i++) { |
9c5022e3 | 65 | if (*tmp && --*tmp == 0) |
cdad2eb1 BJ |
66 | (void) tcp_usrreq(tp->t_inpcb->inp_socket, |
67 | PRU_SLOWTIMO, (struct mbuf *)0, | |
68 | (caddr_t)i); | |
2e80fb4c BJ |
69 | tmp++; |
70 | } | |
72f24d7d BJ |
71 | tp->t_xmt++; |
72 | } | |
eee3ab16 | 73 | tcp_iss += ISSINCR/2; /* increment iss */ |
72f24d7d | 74 | splx(s); |
4eb5d593 BJ |
75 | } |
76 | ||
e1506033 BJ |
77 | /* |
78 | * Cancel all timers for tcp tp. | |
79 | */ | |
80 | tcp_tcancel(tp) | |
53a5409e | 81 | struct tcpcb *tp; |
e1506033 | 82 | { |
eee3ab16 | 83 | register short *tmp = &tp->t_init; |
e1506033 BJ |
84 | register int i; |
85 | ||
86 | for (i = 0; i < TNTIMERS; i++) | |
87 | *tmp++ = 0; | |
88 | } | |
89 | ||
4ad99bae | 90 | struct tcpcb *tcp_newtcpcb(); |
9c5022e3 BJ |
91 | /* |
92 | * Process a TCP user request for tcp tb. If this is a send request | |
93 | * then m is the mbuf chain of send data. If this is a timer expiration | |
94 | * (called from the software clock routine), then timertype tells which timer. | |
95 | */ | |
eee3ab16 BJ |
96 | tcp_usrreq(so, req, m, addr) |
97 | struct socket *so; | |
98 | int req; | |
9c5022e3 | 99 | struct mbuf *m; |
eee3ab16 | 100 | caddr_t addr; |
4eb5d593 | 101 | { |
53a5409e | 102 | register struct inpcb *inp = sotoinpcb(so); |
cdad2eb1 | 103 | register struct tcpcb *tp; |
72f24d7d BJ |
104 | int s = splnet(); |
105 | register int nstate; | |
186b5a8a BJ |
106 | #ifdef TCPDEBUG |
107 | struct tcp_debug tdb; | |
108 | #endif | |
eee3ab16 | 109 | int error = 0; |
72f24d7d BJ |
110 | COUNT(TCP_USRREQ); |
111 | ||
53a5409e BJ |
112 | /* |
113 | * Make sure attached. If not, | |
114 | * only PRU_ATTACH is valid. | |
115 | */ | |
cdad2eb1 BJ |
116 | #ifdef TCPDEBUG |
117 | tdb.td_tod = 0; | |
118 | #endif | |
119 | if (inp == 0) { | |
53a5409e BJ |
120 | if (req != PRU_ATTACH) { |
121 | splx(s); | |
122 | return (EINVAL); | |
123 | } | |
cdad2eb1 BJ |
124 | } else { |
125 | tp = intotcpcb(inp); | |
126 | nstate = tp->t_state; | |
9c5022e3 | 127 | #ifdef KPROF |
cdad2eb1 | 128 | tcp_acounts[nstate][req]++; |
9c5022e3 | 129 | #endif |
186b5a8a | 130 | #ifdef TCPDEBUG |
cdad2eb1 BJ |
131 | if (((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug)) { |
132 | tdb_setup(tp, (struct tcpiphdr *)0, req, &tdb); | |
133 | tdb.td_tim = timertype; | |
134 | } | |
186b5a8a | 135 | #endif |
cdad2eb1 BJ |
136 | tp->tc_flags &= ~TC_NET_KEEP; |
137 | } | |
138 | ||
eee3ab16 | 139 | switch (req) { |
4eb5d593 | 140 | |
eee3ab16 | 141 | case PRU_ATTACH: |
4ad99bae | 142 | if (inp) { |
eee3ab16 | 143 | error = EISCONN; |
cdad2eb1 | 144 | break; |
53a5409e | 145 | } |
4ad99bae BJ |
146 | tp = tcp_newtcpcb(); |
147 | if (tp == 0) { | |
148 | error = ENOBUFS; | |
149 | break; | |
150 | } | |
151 | error = in_pcballoc(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr); | |
152 | if (error) { | |
153 | m_free(dtom(tp)); | |
154 | break; | |
155 | } | |
156 | inp = (struct inpcb *)so->so_pcb; | |
157 | tp->t_inpcb = inp; | |
158 | inp->inp_ppcb = (caddr_t)tp; | |
159 | if (so->so_options & SO_ACCEPTCONN) | |
53a5409e | 160 | nstate = LISTEN; |
4ad99bae | 161 | else |
53a5409e | 162 | nstate = CLOSED; |
72f24d7d | 163 | break; |
4eb5d593 | 164 | |
eee3ab16 | 165 | case PRU_DETACH: |
cdad2eb1 | 166 | tcp_detach(tp); |
eee3ab16 BJ |
167 | break; |
168 | ||
eee3ab16 | 169 | case PRU_CONNECT: |
53a5409e | 170 | if (tp->t_state != 0 && tp->t_state != CLOSED) |
9c5022e3 | 171 | goto bad; |
4ad99bae BJ |
172 | error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); |
173 | if (error) | |
53a5409e | 174 | break; |
cdad2eb1 | 175 | (void) tcp_sndctl(tp); |
72f24d7d | 176 | nstate = SYN_SENT; |
53a5409e | 177 | soisconnecting(so); |
72f24d7d | 178 | break; |
4eb5d593 | 179 | |
2b4b57cd | 180 | case PRU_ACCEPT: |
4ad99bae BJ |
181 | soisconnected(so); |
182 | break; | |
2b4b57cd | 183 | |
eee3ab16 | 184 | case PRU_DISCONNECT: |
53a5409e BJ |
185 | if ((tp->tc_flags & TC_FIN_RCVD) == 0) |
186 | goto abort; | |
187 | if (nstate < ESTAB) | |
cdad2eb1 | 188 | tcp_disconnect(tp); |
53a5409e BJ |
189 | else { |
190 | tp->tc_flags |= TC_SND_FIN; | |
cdad2eb1 | 191 | (void) tcp_sndctl(tp); |
53a5409e BJ |
192 | tp->tc_flags |= TC_USR_CLOSED; |
193 | soisdisconnecting(so); | |
194 | } | |
eee3ab16 BJ |
195 | break; |
196 | ||
eee3ab16 | 197 | case PRU_SHUTDOWN: |
9c5022e3 | 198 | switch (nstate) { |
4eb5d593 | 199 | |
9c5022e3 | 200 | case LISTEN: |
e1506033 | 201 | case SYN_SENT: |
72f24d7d | 202 | nstate = CLOSED; |
9c5022e3 | 203 | break; |
4eb5d593 | 204 | |
e1506033 | 205 | case SYN_RCVD: |
9c5022e3 BJ |
206 | case L_SYN_RCVD: |
207 | case ESTAB: | |
e1506033 | 208 | case CLOSE_WAIT: |
9c5022e3 | 209 | tp->tc_flags |= TC_SND_FIN; |
cdad2eb1 | 210 | (void) tcp_sndctl(tp); |
9c5022e3 BJ |
211 | tp->tc_flags |= TC_USR_CLOSED; |
212 | nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK; | |
213 | break; | |
214 | ||
9c5022e3 BJ |
215 | case FIN_W1: |
216 | case FIN_W2: | |
217 | case TIME_WAIT: | |
218 | case CLOSING: | |
219 | case LAST_ACK: | |
220 | case RCV_WAIT: | |
9c5022e3 BJ |
221 | break; |
222 | ||
223 | default: | |
224 | goto bad; | |
225 | } | |
72f24d7d BJ |
226 | break; |
227 | ||
eee3ab16 | 228 | case PRU_RCVD: |
9c5022e3 BJ |
229 | if (nstate < ESTAB || nstate == CLOSED) |
230 | goto bad; | |
e1506033 | 231 | tcp_sndwin(tp); |
2a4921ab BJ |
232 | if ((tp->tc_flags&TC_FIN_RCVD) && |
233 | (tp->tc_flags&TC_USR_CLOSED) == 0 && | |
234 | rcv_empty(tp)) | |
53a5409e | 235 | error = ESHUTDOWN; |
eee3ab16 | 236 | if (nstate == RCV_WAIT && rcv_empty(tp)) |
9c5022e3 | 237 | nstate = CLOSED; |
72f24d7d BJ |
238 | break; |
239 | ||
eee3ab16 | 240 | case PRU_SEND: |
9c5022e3 BJ |
241 | switch (nstate) { |
242 | ||
243 | case ESTAB: | |
244 | case CLOSE_WAIT: | |
53a5409e | 245 | tcp_usrsend(tp, m); |
9c5022e3 BJ |
246 | break; |
247 | ||
248 | default: | |
249 | if (nstate < ESTAB) | |
250 | goto bad; | |
eee3ab16 | 251 | m_freem(m); |
53a5409e | 252 | error = ENOTCONN; |
9c5022e3 BJ |
253 | break; |
254 | } | |
72f24d7d BJ |
255 | break; |
256 | ||
53a5409e | 257 | abort: |
eee3ab16 | 258 | case PRU_ABORT: |
53a5409e | 259 | tcp_abort(tp); |
72f24d7d BJ |
260 | nstate = CLOSED; |
261 | break; | |
262 | ||
eee3ab16 | 263 | case PRU_CONTROL: |
53a5409e | 264 | error = EOPNOTSUPP; |
eee3ab16 BJ |
265 | break; |
266 | ||
eee3ab16 BJ |
267 | case PRU_SLOWTIMO: |
268 | switch (nstate) { | |
269 | ||
270 | case 0: | |
271 | case CLOSED: | |
272 | case LISTEN: | |
273 | goto bad; | |
274 | ||
275 | default: | |
276 | nstate = tcp_timers(tp, (int)addr); | |
277 | } | |
278 | break; | |
279 | ||
9c5022e3 BJ |
280 | default: |
281 | panic("tcp_usrreq"); | |
282 | bad: | |
283 | printf("tcp: bad state: tcb=%x state=%d input=%d\n", | |
eee3ab16 | 284 | tp, tp->t_state, req); |
9c5022e3 | 285 | nstate = EFAILEC; |
72f24d7d BJ |
286 | break; |
287 | } | |
72f24d7d | 288 | #ifdef TCPDEBUG |
8f5a3361 BJ |
289 | if (tdb.td_tod) |
290 | tdb_stuff(&tdb, nstate); | |
72f24d7d | 291 | #endif |
72f24d7d BJ |
292 | switch (nstate) { |
293 | ||
186b5a8a | 294 | case CLOSED: |
72f24d7d BJ |
295 | case SAME: |
296 | break; | |
4eb5d593 | 297 | |
72f24d7d | 298 | case EFAILEC: |
9c5022e3 BJ |
299 | if (m) |
300 | m_freem(dtom(m)); | |
72f24d7d | 301 | break; |
4eb5d593 | 302 | |
72f24d7d BJ |
303 | default: |
304 | tp->t_state = nstate; | |
305 | break; | |
306 | } | |
307 | splx(s); | |
53a5409e | 308 | return (error); |
4eb5d593 BJ |
309 | } |
310 | ||
4ad99bae BJ |
311 | struct tcpcb * |
312 | tcp_newtcpcb() | |
72f24d7d | 313 | { |
4ad99bae BJ |
314 | struct mbuf *m = m_getclr(0); |
315 | register struct tcpcb *tp; | |
316 | COUNT(TCP_NEWTCPCB); | |
317 | ||
318 | if (m == 0) | |
319 | return (0); | |
320 | tp = mtod(m, struct tcpcb *); | |
72f24d7d | 321 | |
a1904ebf | 322 | /* |
53a5409e | 323 | * Make empty reassembly queue. |
a1904ebf | 324 | */ |
53a5409e | 325 | tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; |
4eb5d593 | 326 | |
a1904ebf | 327 | /* |
53a5409e | 328 | * Initialize sequence numbers and round trip retransmit timer. |
a1904ebf | 329 | */ |
72f24d7d | 330 | tp->t_xmtime = T_REXMT; |
a1904ebf BJ |
331 | tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una = |
332 | tp->iss = tcp_iss; | |
72f24d7d | 333 | tp->snd_off = tp->iss + 1; |
dad64fdf | 334 | tcp_iss += (ISSINCR >> 1) + 1; |
4ad99bae | 335 | return (tp); |
4eb5d593 BJ |
336 | } |
337 | ||
cdad2eb1 BJ |
338 | tcp_detach(tp) |
339 | struct tcpcb *tp; | |
72f24d7d | 340 | { |
eee3ab16 | 341 | COUNT(TCP_DETACH); |
72f24d7d | 342 | |
cdad2eb1 BJ |
343 | in_pcbfree(tp->t_inpcb); |
344 | (void) m_free(dtom(tp)); | |
53a5409e | 345 | } |
eee3ab16 | 346 | |
53a5409e BJ |
347 | tcp_disconnect(tp) |
348 | register struct tcpcb *tp; | |
349 | { | |
350 | register struct tcpiphdr *t; | |
a1904ebf | 351 | |
4ad99bae | 352 | COUNT(TCP_DISCONNECT); |
53a5409e BJ |
353 | tcp_tcancel(tp); |
354 | t = tp->seg_next; | |
eb44bfb2 | 355 | for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next) |
53a5409e BJ |
356 | m_freem(dtom(t)); |
357 | tcp_drainunack(tp); | |
e1506033 | 358 | if (tp->t_template) { |
cdad2eb1 | 359 | (void) m_free(dtom(tp->t_template)); |
e1506033 | 360 | tp->t_template = 0; |
dad64fdf | 361 | } |
53a5409e BJ |
362 | in_pcbfree(tp->t_inpcb); |
363 | } | |
364 | ||
cdad2eb1 BJ |
365 | tcp_abort(tp) |
366 | register struct tcpcb *tp; | |
53a5409e | 367 | { |
53a5409e | 368 | |
4ad99bae | 369 | COUNT(TCP_ABORT); |
53a5409e BJ |
370 | switch (tp->t_state) { |
371 | ||
372 | case SYN_RCVD: | |
373 | case ESTAB: | |
374 | case FIN_W1: | |
375 | case FIN_W2: | |
376 | case CLOSE_WAIT: | |
377 | tp->tc_flags |= TC_SND_RST; | |
378 | tcp_sndnull(tp); | |
379 | } | |
cdad2eb1 | 380 | soisdisconnected(tp->t_inpcb->inp_socket); |
4eb5d593 BJ |
381 | } |
382 | ||
a1904ebf | 383 | /* |
e1506033 | 384 | * Send data queue headed by m0 into the protocol. |
a1904ebf | 385 | */ |
ea727f86 | 386 | tcp_usrsend(tp, m0) |
53a5409e | 387 | register struct tcpcb *tp; |
186b5a8a BJ |
388 | struct mbuf *m0; |
389 | { | |
53a5409e | 390 | register struct socket *so = tp->t_inpcb->inp_socket; |
a1904ebf | 391 | COUNT(TCP_USRSEND); |
4eb5d593 | 392 | |
53a5409e | 393 | sbappend(&so->so_snd, m0); |
eee3ab16 | 394 | if (tp->t_options & TO_EOL) |
53a5409e | 395 | tp->snd_end = tp->snd_off + so->so_snd.sb_cc; |
eee3ab16 | 396 | if (tp->t_options & TO_URG) { |
53a5409e | 397 | tp->snd_urp = tp->snd_off + so->so_snd.sb_cc + 1; |
a3d78bbd | 398 | tp->tc_flags |= TC_SND_URG; |
72f24d7d | 399 | } |
cdad2eb1 | 400 | (void) tcp_send(tp); |
4eb5d593 BJ |
401 | } |
402 | ||
a1904ebf BJ |
403 | /* |
404 | * TCP timer went off processing. | |
405 | */ | |
186b5a8a | 406 | tcp_timers(tp, timertype) |
53a5409e | 407 | register struct tcpcb *tp; |
186b5a8a | 408 | int timertype; |
4eb5d593 | 409 | { |
4eb5d593 | 410 | |
72f24d7d | 411 | COUNT(TCP_TIMERS); |
186b5a8a | 412 | switch (timertype) { |
4eb5d593 | 413 | |
72f24d7d BJ |
414 | case TFINACK: /* fin-ack timer */ |
415 | switch (tp->t_state) { | |
416 | ||
417 | case TIME_WAIT: | |
418 | /* | |
419 | * We can be sure our ACK of foreign FIN was rcvd, | |
420 | * and can close if no data left for user. | |
421 | */ | |
422 | if (rcv_empty(tp)) { | |
53a5409e | 423 | tcp_disconnect(tp); |
72f24d7d BJ |
424 | return (CLOSED); |
425 | } | |
426 | return (RCV_WAIT); /* 17 */ | |
427 | ||
9c5022e3 | 428 | case CLOSING: |
a3d78bbd | 429 | tp->tc_flags |= TC_WAITED_2_ML; |
72f24d7d BJ |
430 | return (SAME); |
431 | ||
432 | default: | |
433 | return (SAME); | |
434 | } | |
4eb5d593 | 435 | |
72f24d7d BJ |
436 | case TREXMT: /* retransmission timer */ |
437 | if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ | |
438 | /* | |
eee3ab16 | 439 | * Set so for a retransmission, increase rexmt time |
72f24d7d BJ |
440 | * in case of multiple retransmissions. |
441 | */ | |
442 | tp->snd_nxt = tp->snd_una; | |
a3d78bbd | 443 | tp->tc_flags |= TC_REXMT; |
72f24d7d BJ |
444 | tp->t_xmtime = tp->t_xmtime << 1; |
445 | if (tp->t_xmtime > T_REMAX) | |
446 | tp->t_xmtime = T_REMAX; | |
cdad2eb1 | 447 | (void) tcp_send(tp); |
72f24d7d BJ |
448 | } |
449 | return (SAME); | |
450 | ||
451 | case TREXMTTL: /* retransmit too long */ | |
452 | if (tp->t_rtl_val > tp->snd_una) /* 36 */ | |
cdad2eb1 | 453 | tcp_error(tp, EIO); /* URXTIMO !?! */ |
72f24d7d BJ |
454 | /* |
455 | * If user has already closed, abort the connection. | |
456 | */ | |
a3d78bbd | 457 | if (tp->tc_flags & TC_USR_CLOSED) { |
53a5409e | 458 | tcp_abort(tp); |
72f24d7d BJ |
459 | return (CLOSED); |
460 | } | |
461 | return (SAME); | |
462 | ||
463 | case TPERSIST: /* persist timer */ | |
464 | /* | |
465 | * Force a byte send through closed window. | |
466 | */ | |
a3d78bbd | 467 | tp->tc_flags |= TC_FORCE_ONE; |
cdad2eb1 | 468 | (void) tcp_send(tp); |
72f24d7d BJ |
469 | return (SAME); |
470 | } | |
471 | panic("tcp_timers"); | |
cdad2eb1 | 472 | /*NOTREACHED*/ |
4eb5d593 BJ |
473 | } |
474 | ||
cdad2eb1 | 475 | /*ARGSUSED*/ |
53a5409e BJ |
476 | tcp_sense(m) |
477 | struct mbuf *m; | |
478 | { | |
479 | ||
4ad99bae | 480 | COUNT(TCP_SENSE); |
53a5409e BJ |
481 | return (EOPNOTSUPP); |
482 | } | |
483 | ||
cdad2eb1 BJ |
484 | tcp_error(tp, errno) |
485 | struct tcpcb *tp; | |
eee3ab16 | 486 | int errno; |
4eb5d593 | 487 | { |
cdad2eb1 | 488 | struct socket *so = tp->t_inpcb->inp_socket; |
4eb5d593 | 489 | |
4ad99bae | 490 | COUNT(TCP_ERROR); |
eee3ab16 | 491 | so->so_error = errno; |
53a5409e BJ |
492 | sorwakeup(so); |
493 | sowwakeup(so); | |
4eb5d593 | 494 | } |
186b5a8a BJ |
495 | |
496 | #ifdef TCPDEBUG | |
a1904ebf BJ |
497 | /* |
498 | * TCP debugging utility subroutines. | |
499 | * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID. | |
500 | */ | |
e006f425 | 501 | tdb_setup(tp, n, input, tdp) |
53a5409e BJ |
502 | struct tcpcb *tp; |
503 | register struct tcpiphdr *n; | |
e006f425 BJ |
504 | int input; |
505 | register struct tcp_debug *tdp; | |
506 | { | |
507 | ||
a1904ebf | 508 | COUNT(TDB_SETUP); |
e006f425 BJ |
509 | tdp->td_tod = time; |
510 | tdp->td_tcb = tp; | |
511 | tdp->td_old = tp->t_state; | |
512 | tdp->td_inp = input; | |
513 | tdp->td_tim = 0; | |
514 | tdp->td_new = -1; | |
515 | if (n) { | |
eb44bfb2 BJ |
516 | tdp->td_sno = n->ti_seq; |
517 | tdp->td_ano = n->ti_ackno; | |
e006f425 | 518 | tdp->td_wno = n->t_win; |
eb44bfb2 BJ |
519 | tdp->td_lno = n->ti_len; |
520 | tdp->td_flg = n->ti_flags; | |
e006f425 BJ |
521 | } else |
522 | tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno = | |
523 | tdp->td_flg = 0; | |
524 | } | |
525 | ||
526 | tdb_stuff(tdp, nstate) | |
527 | struct tcp_debug *tdp; | |
528 | int nstate; | |
529 | { | |
a1904ebf | 530 | COUNT(TDB_STUFF); |
e006f425 BJ |
531 | |
532 | tdp->td_new = nstate; | |
533 | tcp_debug[tdbx++ % TDBSIZE] = *tdp; | |
534 | if (tcpconsdebug & 2) | |
535 | tcp_prt(tdp); | |
536 | } | |
a1904ebf | 537 | |
a1904ebf BJ |
538 | tcp_prt(tdp) |
539 | register struct tcp_debug *tdp; | |
540 | { | |
541 | COUNT(TCP_PRT); | |
542 | ||
ddfd844e BJ |
543 | printf("%x ", ((int)tdp->td_tcb)&0xffffff); |
544 | if (tdp->td_inp == INSEND) { | |
545 | printf("SEND #%x", tdp->td_sno); | |
546 | tdp->td_lno = ntohs(tdp->td_lno); | |
547 | tdp->td_wno = ntohs(tdp->td_wno); | |
548 | } else { | |
549 | if (tdp->td_inp == INRECV) | |
550 | printf("RCV #%x ", tdp->td_sno); | |
551 | printf("%s.%s", | |
552 | tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]); | |
553 | if (tdp->td_inp == ISTIMER) | |
554 | printf("(%s)", tcptimers[tdp->td_tim]); | |
555 | printf(" -> %s", | |
556 | tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]); | |
557 | if (tdp->td_new == -1) | |
558 | printf(" (FAILED)"); | |
a1904ebf | 559 | } |
ddfd844e BJ |
560 | /* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */ |
561 | if (tdp->td_lno) | |
562 | printf(" len=%d", tdp->td_lno); | |
563 | if (tdp->td_wno) | |
564 | printf(" win=%d", tdp->td_wno); | |
565 | if (tdp->td_flg & TH_FIN) printf(" FIN"); | |
566 | if (tdp->td_flg & TH_SYN) printf(" SYN"); | |
567 | if (tdp->td_flg & TH_RST) printf(" RST"); | |
568 | if (tdp->td_flg & TH_EOL) printf(" EOL"); | |
569 | if (tdp->td_flg & TH_ACK) printf(" ACK %x", tdp->td_ano); | |
570 | if (tdp->td_flg & TH_URG) printf(" URG"); | |
a1904ebf BJ |
571 | printf("\n"); |
572 | } | |
e006f425 | 573 | #endif |