Revision 5fafdf24 slirp/tcp_input.c
b/slirp/tcp_input.c | ||
---|---|---|
37 | 37 |
/* |
38 | 38 |
* Changes and additions relating to SLiRP |
39 | 39 |
* Copyright (c) 1995 Danny Gasparovski. |
40 |
*
|
|
41 |
* Please read the file COPYRIGHT for the
|
|
40 |
* |
|
41 |
* Please read the file COPYRIGHT for the |
|
42 | 42 |
* terms and conditions of the copyright. |
43 | 43 |
*/ |
44 | 44 |
|
... | ... | |
122 | 122 |
register struct tcpiphdr *q; |
123 | 123 |
struct socket *so = tp->t_socket; |
124 | 124 |
int flags; |
125 |
|
|
125 |
|
|
126 | 126 |
/* |
127 | 127 |
* Call with ti==0 after become established to |
128 | 128 |
* force pre-ESTABLISHED data up to user socket. |
... | ... | |
254 | 254 |
/* int ts_present = 0; */ |
255 | 255 |
|
256 | 256 |
DEBUG_CALL("tcp_input"); |
257 |
DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n",
|
|
257 |
DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", |
|
258 | 258 |
(long )m, iphlen, (long )inso )); |
259 |
|
|
259 |
|
|
260 | 260 |
/* |
261 | 261 |
* If called with m == 0, then we're continuing the connect |
262 | 262 |
*/ |
263 | 263 |
if (m == NULL) { |
264 | 264 |
so = inso; |
265 |
|
|
265 |
|
|
266 | 266 |
/* Re-set a few variables */ |
267 | 267 |
tp = sototcpcb(so); |
268 | 268 |
m = so->so_m; |
... | ... | |
270 | 270 |
ti = so->so_ti; |
271 | 271 |
tiwin = ti->ti_win; |
272 | 272 |
tiflags = ti->ti_flags; |
273 |
|
|
273 |
|
|
274 | 274 |
goto cont_conn; |
275 | 275 |
} |
276 |
|
|
277 |
|
|
276 |
|
|
277 |
|
|
278 | 278 |
tcpstat.tcps_rcvtotal++; |
279 | 279 |
/* |
280 | 280 |
* Get IP and TCP header together in first mbuf. |
... | ... | |
286 | 286 |
iphlen=sizeof(struct ip ); |
287 | 287 |
} |
288 | 288 |
/* XXX Check if too short */ |
289 |
|
|
289 |
|
|
290 | 290 |
|
291 | 291 |
/* |
292 | 292 |
* Save a copy of the IP header in case we want restore it |
293 | 293 |
* for sending an ICMP error message in response. |
294 | 294 |
*/ |
295 | 295 |
ip=mtod(m, struct ip *); |
296 |
save_ip = *ip;
|
|
296 |
save_ip = *ip; |
|
297 | 297 |
save_ip.ip_len+= iphlen; |
298 | 298 |
|
299 | 299 |
/* |
... | ... | |
305 | 305 |
ti->ti_len = htons((u_int16_t)tlen); |
306 | 306 |
len = sizeof(struct ip ) + tlen; |
307 | 307 |
/* keep checksum for ICMP reply |
308 |
* ti->ti_sum = cksum(m, len);
|
|
308 |
* ti->ti_sum = cksum(m, len); |
|
309 | 309 |
* if (ti->ti_sum) { */ |
310 | 310 |
if(cksum(m, len)) { |
311 | 311 |
tcpstat.tcps_rcvbadsum++; |
... | ... | |
327 | 327 |
optlen = off - sizeof (struct tcphdr); |
328 | 328 |
optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr); |
329 | 329 |
|
330 |
/*
|
|
330 |
/* |
|
331 | 331 |
* Do quick retrieval of timestamp options ("options |
332 | 332 |
* prediction?"). If timestamp is the only option and it's |
333 | 333 |
* formatted as recommended in RFC 1323 appendix A, we |
... | ... | |
347 | 347 |
*/ |
348 | 348 |
} |
349 | 349 |
tiflags = ti->ti_flags; |
350 |
|
|
350 |
|
|
351 | 351 |
/* |
352 | 352 |
* Convert TCP protocol specific fields to host format. |
353 | 353 |
*/ |
... | ... | |
361 | 361 |
*/ |
362 | 362 |
m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); |
363 | 363 |
m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); |
364 |
|
|
364 |
|
|
365 | 365 |
/* |
366 | 366 |
* Locate pcb for segment. |
367 | 367 |
*/ |
... | ... | |
385 | 385 |
* but should either do a listen or a connect soon. |
386 | 386 |
* |
387 | 387 |
* state == CLOSED means we've done socreate() but haven't |
388 |
* attached it to a protocol yet...
|
|
389 |
*
|
|
388 |
* attached it to a protocol yet... |
|
389 |
* |
|
390 | 390 |
* XXX If a TCB does not exist, and the TH_SYN flag is |
391 | 391 |
* the only flag set, then create a session, mark it |
392 | 392 |
* as if it was LISTENING, and continue... |
... | ... | |
394 | 394 |
if (so == 0) { |
395 | 395 |
if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN) |
396 | 396 |
goto dropwithreset; |
397 |
|
|
397 |
|
|
398 | 398 |
if ((so = socreate()) == NULL) |
399 | 399 |
goto dropwithreset; |
400 | 400 |
if (tcp_attach(so) < 0) { |
401 | 401 |
free(so); /* Not sofree (if it failed, it's not insqued) */ |
402 | 402 |
goto dropwithreset; |
403 | 403 |
} |
404 |
|
|
404 |
|
|
405 | 405 |
sbreserve(&so->so_snd, tcp_sndspace); |
406 | 406 |
sbreserve(&so->so_rcv, tcp_rcvspace); |
407 |
|
|
407 |
|
|
408 | 408 |
/* tcp_last_so = so; */ /* XXX ? */ |
409 | 409 |
/* tp = sototcpcb(so); */ |
410 |
|
|
410 |
|
|
411 | 411 |
so->so_laddr = ti->ti_src; |
412 | 412 |
so->so_lport = ti->ti_sport; |
413 | 413 |
so->so_faddr = ti->ti_dst; |
414 | 414 |
so->so_fport = ti->ti_dport; |
415 |
|
|
415 |
|
|
416 | 416 |
if ((so->so_iptos = tcp_tos(so)) == 0) |
417 | 417 |
so->so_iptos = ((struct ip *)ti)->ip_tos; |
418 |
|
|
418 |
|
|
419 | 419 |
tp = sototcpcb(so); |
420 | 420 |
tp->t_state = TCPS_LISTEN; |
421 | 421 |
} |
422 |
|
|
422 |
|
|
423 | 423 |
/* |
424 | 424 |
* If this is a still-connecting socket, this probably |
425 | 425 |
* a retransmit of the SYN. Whether it's a retransmit SYN |
... | ... | |
429 | 429 |
goto drop; |
430 | 430 |
|
431 | 431 |
tp = sototcpcb(so); |
432 |
|
|
432 |
|
|
433 | 433 |
/* XXX Should never fail */ |
434 | 434 |
if (tp == 0) |
435 | 435 |
goto dropwithreset; |
436 | 436 |
if (tp->t_state == TCPS_CLOSED) |
437 | 437 |
goto drop; |
438 |
|
|
438 |
|
|
439 | 439 |
/* Unscale the window into a 32-bit value. */ |
440 | 440 |
/* if ((tiflags & TH_SYN) == 0) |
441 | 441 |
* tiwin = ti->ti_win << tp->snd_scale; |
... | ... | |
458 | 458 |
* else do it below (after getting remote address). |
459 | 459 |
*/ |
460 | 460 |
if (optp && tp->t_state != TCPS_LISTEN) |
461 |
tcp_dooptions(tp, (u_char *)optp, optlen, ti);
|
|
461 |
tcp_dooptions(tp, (u_char *)optp, optlen, ti); |
|
462 | 462 |
/* , */ |
463 | 463 |
/* &ts_present, &ts_val, &ts_ecr); */ |
464 | 464 |
|
465 |
/*
|
|
465 |
/* |
|
466 | 466 |
* Header prediction: check for the two common cases |
467 | 467 |
* of a uni-directional data xfer. If the packet has |
468 | 468 |
* no control flags, is in-sequence, the window didn't |
... | ... | |
486 | 486 |
ti->ti_seq == tp->rcv_nxt && |
487 | 487 |
tiwin && tiwin == tp->snd_wnd && |
488 | 488 |
tp->snd_nxt == tp->snd_max) { |
489 |
/*
|
|
489 |
/* |
|
490 | 490 |
* If last ACK falls within this segment's sequence numbers, |
491 | 491 |
* record the timestamp. |
492 | 492 |
*/ |
... | ... | |
506 | 506 |
++tcpstat.tcps_predack; |
507 | 507 |
/* if (ts_present) |
508 | 508 |
* tcp_xmit_timer(tp, tcp_now-ts_ecr+1); |
509 |
* else
|
|
509 |
* else |
|
510 | 510 |
*/ if (tp->t_rtt && |
511 | 511 |
SEQ_GT(ti->ti_ack, tp->t_rtseq)) |
512 | 512 |
tcp_xmit_timer(tp, tp->t_rtt); |
... | ... | |
531 | 531 |
else if (tp->t_timer[TCPT_PERSIST] == 0) |
532 | 532 |
tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; |
533 | 533 |
|
534 |
/*
|
|
534 |
/* |
|
535 | 535 |
* There's room in so_snd, sowwakup will read() |
536 | 536 |
* from the socket if we can |
537 | 537 |
*/ |
538 | 538 |
/* if (so->so_snd.sb_flags & SB_NOTIFY) |
539 | 539 |
* sowwakeup(so); |
540 | 540 |
*/ |
541 |
/*
|
|
541 |
/* |
|
542 | 542 |
* This is called because sowwakeup might have |
543 | 543 |
* put data into so_snd. Since we don't so sowwakeup, |
544 | 544 |
* we don't need this.. XXX??? |
... | ... | |
567 | 567 |
if (tcp_emu(so,m)) sbappend(so, m); |
568 | 568 |
} else |
569 | 569 |
sbappend(so, m); |
570 |
|
|
571 |
/*
|
|
570 |
|
|
571 |
/* |
|
572 | 572 |
* XXX This is called when data arrives. Later, check |
573 | 573 |
* if we can actually write() to the socket |
574 | 574 |
* XXX Need to check? It's be NON_BLOCKING |
575 | 575 |
*/ |
576 | 576 |
/* sorwakeup(so); */ |
577 |
|
|
577 |
|
|
578 | 578 |
/* |
579 | 579 |
* If this is a short packet, then ACK now - with Nagel |
580 | 580 |
* congestion avoidance sender won't send more until |
581 | 581 |
* he gets an ACK. |
582 |
*
|
|
582 |
* |
|
583 | 583 |
* It is better to not delay acks at all to maximize |
584 | 584 |
* TCP throughput. See RFC 2581. |
585 |
*/
|
|
585 |
*/ |
|
586 | 586 |
tp->t_flags |= TF_ACKNOW; |
587 | 587 |
tcp_output(tp); |
588 | 588 |
return; |
... | ... | |
624 | 624 |
goto dropwithreset; |
625 | 625 |
if ((tiflags & TH_SYN) == 0) |
626 | 626 |
goto drop; |
627 |
|
|
627 |
|
|
628 | 628 |
/* |
629 | 629 |
* This has way too many gotos... |
630 | 630 |
* But a bit of spaghetti code never hurt anybody :) |
631 | 631 |
*/ |
632 |
|
|
632 |
|
|
633 | 633 |
/* |
634 | 634 |
* If this is destined for the control address, then flag to |
635 | 635 |
* tcp_ctl once connected, otherwise connect |
... | ... | |
641 | 641 |
if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) { |
642 | 642 |
/* Command or exec adress */ |
643 | 643 |
so->so_state |= SS_CTL; |
644 |
} else
|
|
644 |
} else |
|
645 | 645 |
#endif |
646 | 646 |
{ |
647 | 647 |
/* May be an add exec */ |
648 | 648 |
struct ex_list *ex_ptr; |
649 | 649 |
for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { |
650 |
if(ex_ptr->ex_fport == so->so_fport &&
|
|
650 |
if(ex_ptr->ex_fport == so->so_fport && |
|
651 | 651 |
lastbyte == ex_ptr->ex_addr) { |
652 | 652 |
so->so_state |= SS_CTL; |
653 | 653 |
break; |
... | ... | |
658 | 658 |
} |
659 | 659 |
/* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */ |
660 | 660 |
} |
661 |
|
|
661 |
|
|
662 | 662 |
if (so->so_emu & EMU_NOCONNECT) { |
663 | 663 |
so->so_emu &= ~EMU_NOCONNECT; |
664 | 664 |
goto cont_input; |
665 | 665 |
} |
666 |
|
|
666 |
|
|
667 | 667 |
if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { |
668 | 668 |
u_char code=ICMP_UNREACH_NET; |
669 | 669 |
DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n", |
... | ... | |
671 | 671 |
if(errno == ECONNREFUSED) { |
672 | 672 |
/* ACK the SYN, send RST to refuse the connection */ |
673 | 673 |
tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0, |
674 |
TH_RST|TH_ACK);
|
|
674 |
TH_RST|TH_ACK); |
|
675 | 675 |
} else { |
676 | 676 |
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; |
677 | 677 |
HTONL(ti->ti_seq); /* restore tcp header */ |
... | ... | |
699 | 699 |
} |
700 | 700 |
return; |
701 | 701 |
|
702 |
cont_conn:
|
|
703 |
/* m==NULL
|
|
702 |
cont_conn: |
|
703 |
/* m==NULL |
|
704 | 704 |
* Check if the connect succeeded |
705 | 705 |
*/ |
706 | 706 |
if (so->so_state & SS_NOFDREF) { |
707 | 707 |
tp = tcp_close(tp); |
708 | 708 |
goto dropwithreset; |
709 | 709 |
} |
710 |
cont_input:
|
|
710 |
cont_input: |
|
711 | 711 |
tcp_template(tp); |
712 |
|
|
712 |
|
|
713 | 713 |
if (optp) |
714 | 714 |
tcp_dooptions(tp, (u_char *)optp, optlen, ti); |
715 | 715 |
/* , */ |
716 | 716 |
/* &ts_present, &ts_val, &ts_ecr); */ |
717 |
|
|
717 |
|
|
718 | 718 |
if (iss) |
719 | 719 |
tp->iss = iss; |
720 |
else
|
|
720 |
else |
|
721 | 721 |
tp->iss = tcp_iss; |
722 | 722 |
tcp_iss += TCP_ISSINCR/2; |
723 | 723 |
tp->irs = ti->ti_seq; |
... | ... | |
729 | 729 |
tcpstat.tcps_accepts++; |
730 | 730 |
goto trimthenstep6; |
731 | 731 |
} /* case TCPS_LISTEN */ |
732 |
|
|
732 |
|
|
733 | 733 |
/* |
734 | 734 |
* If the state is SYN_SENT: |
735 | 735 |
* if seg contains an ACK, but not for our SYN, drop the input. |
... | ... | |
770 | 770 |
tcpstat.tcps_connects++; |
771 | 771 |
soisfconnected(so); |
772 | 772 |
tp->t_state = TCPS_ESTABLISHED; |
773 |
|
|
773 |
|
|
774 | 774 |
/* Do window scaling on this connection? */ |
775 | 775 |
/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == |
776 | 776 |
* (TF_RCVD_SCALE|TF_REQ_SCALE)) { |
... | ... | |
811 | 811 |
/* |
812 | 812 |
* States other than LISTEN or SYN_SENT. |
813 | 813 |
* First check timestamp, if present. |
814 |
* Then check that at least some bytes of segment are within
|
|
814 |
* Then check that at least some bytes of segment are within |
|
815 | 815 |
* receive window. If segment begins before rcv_nxt, |
816 | 816 |
* drop leading data (and SYN); if nothing left, just ack. |
817 |
*
|
|
817 |
* |
|
818 | 818 |
* RFC 1323 PAWS: If we have a timestamp reply on this segment |
819 | 819 |
* and it's less than ts_recent, drop it. |
820 | 820 |
*/ |
... | ... | |
849 | 849 |
if (tiflags & TH_SYN) { |
850 | 850 |
tiflags &= ~TH_SYN; |
851 | 851 |
ti->ti_seq++; |
852 |
if (ti->ti_urp > 1)
|
|
852 |
if (ti->ti_urp > 1) |
|
853 | 853 |
ti->ti_urp--; |
854 | 854 |
else |
855 | 855 |
tiflags &= ~TH_URG; |
... | ... | |
866 | 866 |
* of sequence; drop it. |
867 | 867 |
*/ |
868 | 868 |
tiflags &= ~TH_FIN; |
869 |
|
|
869 |
|
|
870 | 870 |
/* |
871 | 871 |
* Send an ACK to resynchronize and drop any data. |
872 | 872 |
* But keep on processing for RST or ACK. |
... | ... | |
1017 | 1017 |
goto dropwithreset; |
1018 | 1018 |
tcpstat.tcps_connects++; |
1019 | 1019 |
tp->t_state = TCPS_ESTABLISHED; |
1020 |
/*
|
|
1021 |
* The sent SYN is ack'ed with our sequence number +1
|
|
1022 |
* The first data byte already in the buffer will get
|
|
1020 |
/* |
|
1021 |
* The sent SYN is ack'ed with our sequence number +1 |
|
1022 |
* The first data byte already in the buffer will get |
|
1023 | 1023 |
* lost if no correction is made. This is only needed for |
1024 | 1024 |
* SS_CTL since the buffer is empty otherwise. |
1025 |
* tp->snd_una++; or:
|
|
1025 |
* tp->snd_una++; or: |
|
1026 | 1026 |
*/ |
1027 | 1027 |
tp->snd_una=ti->ti_ack; |
1028 | 1028 |
if (so->so_state & SS_CTL) { |
... | ... | |
1040 | 1040 |
} else { |
1041 | 1041 |
soisfconnected(so); |
1042 | 1042 |
} |
1043 |
|
|
1043 |
|
|
1044 | 1044 |
/* Do window scaling? */ |
1045 | 1045 |
/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == |
1046 | 1046 |
* (TF_RCVD_SCALE|TF_REQ_SCALE)) { |
... | ... | |
1094 | 1094 |
* the new ssthresh). |
1095 | 1095 |
* |
1096 | 1096 |
* Dup acks mean that packets have left the |
1097 |
* network (they're now cached at the receiver)
|
|
1097 |
* network (they're now cached at the receiver) |
|
1098 | 1098 |
* so bump cwnd by the amount in the receiver |
1099 | 1099 |
* to keep a constant cwnd packets in the |
1100 | 1100 |
* network. |
... | ... | |
1159 | 1159 |
/* if (ts_present) |
1160 | 1160 |
* tcp_xmit_timer(tp, tcp_now-ts_ecr+1); |
1161 | 1161 |
* else |
1162 |
*/
|
|
1162 |
*/ |
|
1163 | 1163 |
if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) |
1164 | 1164 |
tcp_xmit_timer(tp,tp->t_rtt); |
1165 | 1165 |
|
... | ... | |
1200 | 1200 |
} |
1201 | 1201 |
/* |
1202 | 1202 |
* XXX sowwakup is called when data is acked and there's room for |
1203 |
* for more data... it should read() the socket
|
|
1203 |
* for more data... it should read() the socket |
|
1204 | 1204 |
*/ |
1205 | 1205 |
/* if (so->so_snd.sb_flags & SB_NOTIFY) |
1206 | 1206 |
* sowwakeup(so); |
... | ... | |
1278 | 1278 |
* Don't look at window if no ACK: TAC's send garbage on first SYN. |
1279 | 1279 |
*/ |
1280 | 1280 |
if ((tiflags & TH_ACK) && |
1281 |
(SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
|
|
1281 |
(SEQ_LT(tp->snd_wl1, ti->ti_seq) || |
|
1282 | 1282 |
(tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) || |
1283 | 1283 |
(tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) { |
1284 | 1284 |
/* keep track of pure window updates */ |
... | ... | |
1313 | 1313 |
* If this segment advances the known urgent pointer, |
1314 | 1314 |
* then mark the data stream. This should not happen |
1315 | 1315 |
* in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since |
1316 |
* a FIN has been received from the remote side.
|
|
1316 |
* a FIN has been received from the remote side. |
|
1317 | 1317 |
* In these states we ignore the URG. |
1318 | 1318 |
* |
1319 | 1319 |
* According to RFC961 (Assigned Protocols), |
1320 | 1320 |
* the urgent pointer points to the last octet |
1321 | 1321 |
* of urgent data. We continue, however, |
1322 | 1322 |
* to consider it to indicate the first octet |
1323 |
* of data past the urgent section as the original
|
|
1323 |
* of data past the urgent section as the original |
|
1324 | 1324 |
* spec states (in one of two places). |
1325 | 1325 |
*/ |
1326 | 1326 |
if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) { |
... | ... | |
1328 | 1328 |
so->so_urgc = so->so_rcv.sb_cc + |
1329 | 1329 |
(tp->rcv_up - tp->rcv_nxt); /* -1; */ |
1330 | 1330 |
tp->rcv_up = ti->ti_seq + ti->ti_urp; |
1331 |
|
|
1331 |
|
|
1332 | 1332 |
} |
1333 | 1333 |
} else |
1334 | 1334 |
/* |
... | ... | |
1379 | 1379 |
*/ |
1380 | 1380 |
/* sofcantrcvmore(so); */ |
1381 | 1381 |
sofwdrain(so); |
1382 |
|
|
1382 |
|
|
1383 | 1383 |
tp->t_flags |= TF_ACKNOW; |
1384 | 1384 |
tp->rcv_nxt++; |
1385 | 1385 |
} |
... | ... | |
1393 | 1393 |
case TCPS_ESTABLISHED: |
1394 | 1394 |
if(so->so_emu == EMU_CTL) /* no shutdown on socket */ |
1395 | 1395 |
tp->t_state = TCPS_LAST_ACK; |
1396 |
else
|
|
1396 |
else |
|
1397 | 1397 |
tp->t_state = TCPS_CLOSE_WAIT; |
1398 | 1398 |
break; |
1399 | 1399 |
|
... | ... | |
1407 | 1407 |
|
1408 | 1408 |
/* |
1409 | 1409 |
* In FIN_WAIT_2 state enter the TIME_WAIT state, |
1410 |
* starting the time-wait timer, turning off the other
|
|
1410 |
* starting the time-wait timer, turning off the other |
|
1411 | 1411 |
* standard timers. |
1412 | 1412 |
*/ |
1413 | 1413 |
case TCPS_FIN_WAIT_2: |
... | ... | |
1430 | 1430 |
* If this is a small packet, then ACK now - with Nagel |
1431 | 1431 |
* congestion avoidance sender won't send more until |
1432 | 1432 |
* he gets an ACK. |
1433 |
*
|
|
1433 |
* |
|
1434 | 1434 |
* See above. |
1435 | 1435 |
*/ |
1436 | 1436 |
/* if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) { |
... | ... | |
1547 | 1547 |
* memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr)); |
1548 | 1548 |
* NTOHL(*ts_ecr); |
1549 | 1549 |
* |
1550 |
*/ /*
|
|
1550 |
*/ /* |
|
1551 | 1551 |
* * A timestamp received in a SYN makes |
1552 | 1552 |
* * it ok to send timestamp requests and replies. |
1553 | 1553 |
* */ |
... | ... | |
1578 | 1578 |
register struct mbuf *m; |
1579 | 1579 |
{ |
1580 | 1580 |
int cnt = ti->ti_urp - 1; |
1581 |
|
|
1581 |
|
|
1582 | 1582 |
while (cnt >= 0) { |
1583 | 1583 |
if (m->m_len > cnt) { |
1584 | 1584 |
char *cp = mtod(m, caddr_t) + cnt; |
... | ... | |
1615 | 1615 |
DEBUG_CALL("tcp_xmit_timer"); |
1616 | 1616 |
DEBUG_ARG("tp = %lx", (long)tp); |
1617 | 1617 |
DEBUG_ARG("rtt = %d", rtt); |
1618 |
|
|
1618 |
|
|
1619 | 1619 |
tcpstat.tcps_rttupdated++; |
1620 | 1620 |
if (tp->t_srtt != 0) { |
1621 | 1621 |
/* |
... | ... | |
1644 | 1644 |
if ((tp->t_rttvar += delta) <= 0) |
1645 | 1645 |
tp->t_rttvar = 1; |
1646 | 1646 |
} else { |
1647 |
/*
|
|
1647 |
/* |
|
1648 | 1648 |
* No rtt measurement yet - use the unsmoothed rtt. |
1649 | 1649 |
* Set the variance to half the rtt (so our first |
1650 | 1650 |
* retransmit happens at 3*rtt). |
... | ... | |
1668 | 1668 |
*/ |
1669 | 1669 |
TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), |
1670 | 1670 |
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ |
1671 |
|
|
1671 |
|
|
1672 | 1672 |
/* |
1673 | 1673 |
* We received an ack for a packet that wasn't retransmitted; |
1674 | 1674 |
* it is probably safe to discard any error indications we've |
... | ... | |
1702 | 1702 |
{ |
1703 | 1703 |
struct socket *so = tp->t_socket; |
1704 | 1704 |
int mss; |
1705 |
|
|
1705 |
|
|
1706 | 1706 |
DEBUG_CALL("tcp_mss"); |
1707 | 1707 |
DEBUG_ARG("tp = %lx", (long)tp); |
1708 | 1708 |
DEBUG_ARG("offer = %d", offer); |
1709 |
|
|
1709 |
|
|
1710 | 1710 |
mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr); |
1711 | 1711 |
if (offer) |
1712 | 1712 |
mss = min(mss, offer); |
1713 | 1713 |
mss = max(mss, 32); |
1714 | 1714 |
if (mss < tp->t_maxseg || offer != 0) |
1715 | 1715 |
tp->t_maxseg = mss; |
1716 |
|
|
1716 |
|
|
1717 | 1717 |
tp->snd_cwnd = mss; |
1718 |
|
|
1718 |
|
|
1719 | 1719 |
sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0)); |
1720 | 1720 |
sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0)); |
1721 |
|
|
1721 |
|
|
1722 | 1722 |
DEBUG_MISC((dfd, " returning mss = %d\n", mss)); |
1723 |
|
|
1723 |
|
|
1724 | 1724 |
return mss; |
1725 | 1725 |
} |
Also available in: Unified diff