00001
00002
00003
00004
00005
00006
00007 #include "inet.h"
00008 #include "buf.h"
00009 #include "clock.h"
00010 #include "event.h"
00011 #include "type.h"
00012 #include "sr.h"
00013
00014 #include "io.h"
00015 #include "tcp_int.h"
00016 #include "tcp.h"
00017 #include "assert.h"
00018
00019 THIS_FILE
00020
00021 FORWARD void create_RST ARGS(( tcp_conn_t *tcp_conn,
00022 ip_hdr_t *ip_hdr, tcp_hdr_t *tcp_hdr, int data_len ));
00023 FORWARD void process_data ARGS(( tcp_conn_t *tcp_conn,
00024 tcp_hdr_t *tcp_hdr, acc_t *tcp_data, int data_len ));
00025 FORWARD void process_advanced_data ARGS(( tcp_conn_t *tcp_conn,
00026 tcp_hdr_t *tcp_hdr, acc_t *tcp_data, int data_len ));
00027
00028 PUBLIC void tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, tcp_data, data_len)
00029 tcp_conn_t *tcp_conn;
00030 ip_hdr_t *ip_hdr;
00031 tcp_hdr_t *tcp_hdr;
00032 acc_t *tcp_data;
00033 size_t data_len;
00034 {
00035 tcp_fd_t *connuser;
00036 int tcp_hdr_flags;
00037 int ip_hdr_len, tcp_hdr_len;
00038 u32_t seg_ack, seg_seq, rcv_hi, snd_una, snd_nxt;
00039 u16_t seg_wnd, mtu;
00040 size_t mss;
00041 int acceptable_ACK, segm_acceptable, send_rst, close_connection;
00042
00043 ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
00044 tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
00045
00046 tcp_hdr_flags= tcp_hdr->th_flags & TH_FLAGS_MASK;
00047 seg_ack= ntohl(tcp_hdr->th_ack_nr);
00048 seg_seq= ntohl(tcp_hdr->th_seq_nr);
00049 seg_wnd= ntohs(tcp_hdr->th_window);
00050
00051 #if 0
00052 { where(); tcp_print_conn(tcp_conn); printf("\n");
00053 tcp_print_pack(ip_hdr, tcp_hdr); printf("\n"); }
00054 #endif
00055
00056 switch (tcp_conn->tc_state)
00057 {
00058 case TCS_CLOSED:
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 if (!(tcp_hdr_flags & THF_RST))
00075 {
00076 create_RST(tcp_conn, ip_hdr, tcp_hdr, data_len);
00077 tcp_conn_write(tcp_conn, 1);
00078 }
00079 break;
00080 case TCS_LISTEN:
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 if (tcp_hdr_flags & THF_RST)
00105 break;
00106 if (tcp_hdr_flags & THF_ACK)
00107 {
00108 create_RST (tcp_conn, ip_hdr, tcp_hdr, data_len);
00109 tcp_conn_write(tcp_conn, 1);
00110 break;
00111 }
00112 if (tcp_hdr_flags & THF_SYN)
00113 {
00114 tcp_extract_ipopt(tcp_conn, ip_hdr);
00115 tcp_extract_tcpopt(tcp_conn, tcp_hdr, &mss);
00116 mtu= mss+IP_TCP_MIN_HDR_SIZE;
00117 if (mtu < IP_MIN_MTU)
00118 {
00119
00120 mtu= IP_DEF_MTU;
00121 }
00122 if (mtu < tcp_conn->tc_max_mtu)
00123 {
00124 tcp_conn->tc_max_mtu= mtu;
00125 tcp_conn->tc_mtu= mtu;
00126 DBLOCK(1, printf(
00127 "tcp[%d]: conn[%d]: mtu = %d\n",
00128 tcp_conn->tc_port-tcp_port_table,
00129 tcp_conn-tcp_conn_table,
00130 mtu););
00131 }
00132
00133 tcp_conn->tc_RCV_LO= seg_seq+1;
00134 tcp_conn->tc_RCV_NXT= seg_seq+1;
00135 tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO+
00136 tcp_conn->tc_rcv_wnd;
00137 tcp_conn->tc_RCV_UP= seg_seq;
00138 tcp_conn->tc_IRS= seg_seq;
00139 tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
00140 tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
00141 tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS+1;
00142 tcp_conn->tc_SND_UP= tcp_conn->tc_ISS-1;
00143 tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS-1;
00144 tcp_conn->tc_state= TCS_SYN_RECEIVED;
00145 tcp_conn->tc_stt= 0;
00146 assert (tcp_check_conn(tcp_conn));
00147 tcp_conn->tc_locaddr= ip_hdr->ih_dst;
00148 tcp_conn->tc_locport= tcp_hdr->th_dstport;
00149 tcp_conn->tc_remaddr= ip_hdr->ih_src;
00150 tcp_conn->tc_remport= tcp_hdr->th_srcport;
00151 tcp_conn_write(tcp_conn, 1);
00152
00153 DIFBLOCK(0x10, seg_seq == 0,
00154 printf("warning got 0 IRS from ");
00155 writeIpAddr(tcp_conn->tc_remaddr);
00156 printf("\n"));
00157
00158
00159 tcp_set_send_timer(tcp_conn);
00160
00161 break;
00162 }
00163
00164 break;
00165 case TCS_SYN_SENT:
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 if (tcp_hdr_flags & THF_ACK)
00214 {
00215 if (tcp_LEmod4G(seg_ack, tcp_conn->tc_ISS) ||
00216 tcp_Gmod4G(seg_ack, tcp_conn->tc_SND_NXT))
00217 if (tcp_hdr_flags & THF_RST)
00218 break;
00219 else
00220 {
00221
00222
00223
00224
00225 create_RST (tcp_conn, ip_hdr,
00226 tcp_hdr, data_len+1);
00227 tcp_conn_write(tcp_conn, 1);
00228 break;
00229 }
00230 acceptable_ACK= (tcp_LEmod4G(tcp_conn->tc_SND_UNA,
00231 seg_ack) && tcp_LEmod4G(seg_ack,
00232 tcp_conn->tc_SND_NXT));
00233 }
00234 else
00235 acceptable_ACK= FALSE;
00236 if (tcp_hdr_flags & THF_RST)
00237 {
00238 if (acceptable_ACK)
00239 {
00240 DBLOCK(1, printf(
00241 "calling tcp_close_connection\n"));
00242
00243 tcp_close_connection(tcp_conn,
00244 ECONNREFUSED);
00245 }
00246 break;
00247 }
00248 if (tcp_hdr_flags & THF_SYN)
00249 {
00250 tcp_extract_ipopt(tcp_conn, ip_hdr);
00251 tcp_extract_tcpopt(tcp_conn, tcp_hdr, &mss);
00252 mtu= mss+IP_TCP_MIN_HDR_SIZE;
00253 if (mtu < IP_MIN_MTU)
00254 {
00255
00256 mtu= IP_DEF_MTU;
00257 }
00258 if (mtu < tcp_conn->tc_max_mtu)
00259 {
00260 tcp_conn->tc_max_mtu= mtu;
00261 tcp_conn->tc_mtu= mtu;
00262 DBLOCK(1, printf(
00263 "tcp[%d]: conn[%d]: mtu = %d\n",
00264 tcp_conn->tc_port-tcp_port_table,
00265 tcp_conn-tcp_conn_table,
00266 mtu););
00267 }
00268 tcp_conn->tc_RCV_LO= seg_seq+1;
00269 tcp_conn->tc_RCV_NXT= seg_seq+1;
00270 tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO +
00271 tcp_conn->tc_rcv_wnd;
00272 tcp_conn->tc_RCV_UP= seg_seq;
00273 tcp_conn->tc_IRS= seg_seq;
00274 if (tcp_hdr_flags & THF_ACK)
00275 tcp_conn->tc_SND_UNA= seg_ack;
00276 if (tcp_Gmod4G(tcp_conn->tc_SND_UNA,
00277 tcp_conn->tc_ISS))
00278 {
00279 tcp_conn->tc_state= TCS_ESTABLISHED;
00280 tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
00281
00282 assert (tcp_check_conn(tcp_conn));
00283 assert(tcp_conn->tc_connInprogress);
00284
00285 tcp_restart_connect(tcp_conn);
00286
00287 tcp_conn->tc_flags |= TCF_SEND_ACK;
00288 tcp_conn_write(tcp_conn, 1);
00289 if (data_len != 0)
00290 {
00291 tcp_frag2conn(tcp_conn, ip_hdr,
00292 tcp_hdr, tcp_data, data_len);
00293
00294 return;
00295 }
00296 break;
00297 }
00298 tcp_conn->tc_state= TCS_SYN_RECEIVED;
00299
00300 assert (tcp_check_conn(tcp_conn));
00301
00302 tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
00303 tcp_conn_write(tcp_conn, 1);
00304 }
00305 break;
00306
00307 case TCS_SYN_RECEIVED:
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 rcv_hi= tcp_conn->tc_RCV_HI;
00326 if (tcp_hdr_flags & THF_URG)
00327 rcv_hi++;
00328 send_rst= tcp_Lmod4G(seg_seq, tcp_conn->tc_IRS) ||
00329 tcp_Gmod4G(seg_seq, tcp_conn->tc_RCV_NXT+0x10000);
00330 close_connection= 0;
00331
00332 if (!data_len)
00333 {
00334 if (rcv_hi == tcp_conn->tc_RCV_NXT)
00335 segm_acceptable= (seg_seq == rcv_hi);
00336 else
00337 {
00338 assert (tcp_Gmod4G(rcv_hi,
00339 tcp_conn->tc_RCV_NXT));
00340 segm_acceptable= (tcp_LEmod4G(tcp_conn->
00341 tc_RCV_NXT, seg_seq) &&
00342 tcp_Lmod4G(seg_seq, rcv_hi));
00343 }
00344 }
00345 else
00346 {
00347 if (tcp_Gmod4G(rcv_hi, tcp_conn->tc_RCV_NXT))
00348 {
00349 segm_acceptable= (tcp_LEmod4G(tcp_conn->
00350 tc_RCV_NXT, seg_seq) &&
00351 tcp_Lmod4G(seg_seq, rcv_hi)) ||
00352 (tcp_LEmod4G(tcp_conn->tc_RCV_NXT,
00353 seg_seq+data_len-1) &&
00354 tcp_Lmod4G(seg_seq+data_len-1,
00355 rcv_hi));
00356 }
00357 else
00358 {
00359 segm_acceptable= FALSE;
00360 }
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 if (!segm_acceptable)
00372 {
00373 if (tcp_hdr_flags & THF_RST)
00374 ;
00375 else if (send_rst)
00376 {
00377 create_RST(tcp_conn, ip_hdr, tcp_hdr,
00378 data_len);
00379 tcp_conn_write(tcp_conn, 1);
00380 }
00381 else
00382 {
00383 tcp_conn->tc_flags |= TCF_SEND_ACK;
00384 tcp_conn_write(tcp_conn, 1);
00385 }
00386 break;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 if (tcp_hdr_flags & THF_RST)
00400 close_connection= 1;
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 if ((tcp_hdr_flags & THF_SYN) && tcp_GEmod4G(seg_seq,
00413 tcp_conn->tc_RCV_NXT))
00414 {
00415 close_connection= 1;
00416 }
00417
00418 if (close_connection)
00419 {
00420 if (!tcp_conn->tc_orglisten)
00421 {
00422 tcp_close_connection(tcp_conn, ECONNREFUSED);
00423 break;
00424 }
00425
00426 connuser= tcp_conn->tc_fd;
00427 assert(connuser);
00428 if (connuser->tf_flags & TFF_LISTENQ)
00429 {
00430 tcp_close_connection (tcp_conn,
00431 ECONNREFUSED);
00432 }
00433 else
00434 {
00435 tcp_conn->tc_connInprogress= 0;
00436 tcp_conn->tc_fd= NULL;
00437
00438 tcp_close_connection (tcp_conn,
00439 ECONNREFUSED);
00440
00441
00442 tcp_conn->tc_ISS= 0;
00443
00444 (void)tcp_su4listen(connuser, tcp_conn,
00445 0 );
00446 }
00447 break;
00448 }
00449
00450
00451
00452
00453
00454 if (!(tcp_hdr_flags & THF_ACK))
00455 break;
00456
00457
00458
00459
00460
00461
00462
00463 if (tcp_Lmod4G(tcp_conn->tc_SND_UNA, seg_ack) &&
00464 tcp_LEmod4G(seg_ack, tcp_conn->tc_SND_NXT))
00465 {
00466 tcp_conn->tc_state= TCS_ESTABLISHED;
00467 tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
00468
00469 tcp_release_retrans(tcp_conn, seg_ack, seg_wnd);
00470
00471 assert (tcp_check_conn(tcp_conn));
00472 assert(tcp_conn->tc_connInprogress);
00473
00474 tcp_restart_connect(tcp_conn);
00475 tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, tcp_data,
00476 data_len);
00477
00478 return;
00479 }
00480 else
00481 {
00482 create_RST (tcp_conn, ip_hdr, tcp_hdr, data_len);
00483 tcp_conn_write(tcp_conn, 1);
00484 break;
00485 }
00486 break;
00487
00488 case TCS_ESTABLISHED:
00489 case TCS_CLOSING:
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 rcv_hi= tcp_conn->tc_RCV_HI;
00510 if (tcp_hdr_flags & THF_URG)
00511 rcv_hi++;
00512 if (!data_len)
00513 {
00514 if (rcv_hi == tcp_conn->tc_RCV_NXT)
00515 segm_acceptable= (seg_seq == rcv_hi);
00516 else
00517 {
00518 assert (tcp_Gmod4G(rcv_hi,
00519 tcp_conn->tc_RCV_NXT));
00520 segm_acceptable= (tcp_LEmod4G(tcp_conn->
00521 tc_RCV_NXT, seg_seq) &&
00522 tcp_Lmod4G(seg_seq, rcv_hi));
00523 }
00524 }
00525 else
00526 {
00527 if (tcp_Gmod4G(rcv_hi, tcp_conn->tc_RCV_NXT))
00528 {
00529 segm_acceptable= (tcp_LEmod4G(tcp_conn->
00530 tc_RCV_NXT, seg_seq) &&
00531 tcp_Lmod4G(seg_seq, rcv_hi)) ||
00532 (tcp_LEmod4G(tcp_conn->tc_RCV_NXT,
00533 seg_seq+data_len-1) &&
00534 tcp_Lmod4G(seg_seq+data_len-1,
00535 rcv_hi));
00536 }
00537 else
00538 {
00539 segm_acceptable= FALSE;
00540 }
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 if (!segm_acceptable)
00552 {
00553 if (!(tcp_hdr_flags & THF_RST))
00554 {
00555 DBLOCK(0x20,
00556 printf("segment is not acceptable\n");
00557 printf("\t");
00558 tcp_print_pack(ip_hdr, tcp_hdr);
00559 printf("\n\t");
00560 tcp_print_conn(tcp_conn);
00561 printf("\n"));
00562 tcp_conn->tc_flags |= TCF_SEND_ACK;
00563 tcp_conn_write(tcp_conn, 1);
00564
00565
00566
00567
00568 if (tcp_conn->tc_rcvd_data != NULL &&
00569 (tcp_hdr_flags & THF_PSH))
00570 {
00571 tcp_conn->tc_flags |= TCF_RCV_PUSH;
00572 if (tcp_conn->tc_fd &&
00573 (tcp_conn->tc_fd->tf_flags &
00574 TFF_READ_IP))
00575 {
00576 tcp_fd_read(tcp_conn, 1);
00577 }
00578 if (tcp_conn->tc_fd &&
00579 (tcp_conn->tc_fd->tf_flags &
00580 TFF_SEL_READ))
00581 {
00582 tcp_rsel_read(tcp_conn);
00583 }
00584 }
00585 }
00586 break;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 if (tcp_hdr_flags & THF_RST)
00600 {
00601 if ((tcp_conn->tc_flags &
00602 (TCF_FIN_SENT|TCF_FIN_RECV)) ==
00603 (TCF_FIN_SENT|TCF_FIN_RECV) &&
00604 tcp_conn->tc_send_data == NULL)
00605 {
00606
00607
00608
00609 tcp_close_connection (tcp_conn, 0);
00610 }
00611 else
00612 tcp_close_connection(tcp_conn, ECONNRESET);
00613 break;
00614 }
00615
00616
00617
00618
00619
00620
00621 if ((tcp_hdr_flags & THF_SYN) && tcp_GEmod4G(seg_seq,
00622 tcp_conn->tc_RCV_NXT))
00623 {
00624 tcp_close_connection(tcp_conn, ECONNRESET);
00625 break;
00626 }
00627
00628
00629
00630
00631
00632 if (!(tcp_hdr_flags & THF_ACK))
00633 break;
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 if (tcp_conn->tc_state != TCS_CLOSING)
00664 tcp_conn->tc_stt= 0;
00665
00666 snd_una= tcp_conn->tc_SND_UNA;
00667 snd_nxt= tcp_conn->tc_SND_NXT;
00668 if (seg_ack == snd_una)
00669 {
00670
00671 if (tcp_Gmod4G(snd_nxt, snd_una))
00672 {
00673
00674 if (++tcp_conn->tc_snd_dack ==
00675 TCP_DACK_RETRANS)
00676 {
00677 tcp_fast_retrans(tcp_conn);
00678 }
00679 }
00680
00681
00682
00683
00684
00685
00686
00687 if (tcp_conn->tc_snd_cwnd == snd_una &&
00688 seg_wnd != 0)
00689 {
00690 DBLOCK(2, printf("zero window opened\n"));
00691
00692
00693 mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
00694 if (seg_wnd > 2*mss)
00695 seg_wnd= 2*mss;
00696 tcp_conn->tc_snd_cwnd= snd_una+seg_wnd;
00697 tcp_conn_write(tcp_conn, 1);
00698 }
00699 if (seg_wnd == 0)
00700 {
00701 tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_TRM=
00702 snd_una;
00703 }
00704 }
00705 else if (tcp_Lmod4G(snd_una, seg_ack) &&
00706 tcp_LEmod4G(seg_ack, snd_nxt))
00707 {
00708 tcp_release_retrans(tcp_conn, seg_ack, seg_wnd);
00709 if (tcp_conn->tc_state == TCS_CLOSED)
00710 break;
00711 }
00712 else if (tcp_Gmod4G(seg_ack,
00713 snd_nxt))
00714 {
00715 tcp_conn->tc_flags |= TCF_SEND_ACK;
00716 tcp_conn_write(tcp_conn, 1);
00717 DBLOCK(1, printf(
00718 "got an ack of something I haven't send\n");
00719 printf( "seg_ack= %lu, SND_NXT= %lu\n",
00720 seg_ack, snd_nxt));
00721 break;
00722 }
00723
00724
00725
00726
00727 tcp_extract_ipopt(tcp_conn, ip_hdr);
00728 tcp_extract_tcpopt(tcp_conn, tcp_hdr, &mss);
00729
00730 if (data_len)
00731 {
00732 if (tcp_LEmod4G(seg_seq, tcp_conn->tc_RCV_NXT))
00733 {
00734 process_data (tcp_conn, tcp_hdr,
00735 tcp_data, data_len);
00736 }
00737 else
00738 {
00739 process_advanced_data (tcp_conn,
00740 tcp_hdr, tcp_data, data_len);
00741 }
00742 tcp_conn->tc_flags |= TCF_SEND_ACK;
00743 tcp_conn_write(tcp_conn, 1);
00744
00745
00746 break;
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 if ((tcp_hdr_flags & THF_FIN) && tcp_LEmod4G(seg_seq,
00765 tcp_conn->tc_RCV_NXT))
00766 {
00767 if (!(tcp_conn->tc_flags & TCF_FIN_RECV) &&
00768 tcp_Lmod4G(tcp_conn->tc_RCV_NXT,
00769 tcp_conn->tc_RCV_HI))
00770 {
00771 tcp_conn->tc_RCV_NXT++;
00772 tcp_conn->tc_flags |= TCF_FIN_RECV;
00773 }
00774 tcp_conn->tc_flags |= TCF_SEND_ACK;
00775 tcp_conn_write(tcp_conn, 1);
00776 if (tcp_conn->tc_fd &&
00777 (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
00778 {
00779 tcp_fd_read(tcp_conn, 1);
00780 }
00781 if (tcp_conn->tc_fd &&
00782 (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
00783 {
00784 tcp_rsel_read(tcp_conn);
00785 }
00786 }
00787 break;
00788 default:
00789 printf("tcp_frag2conn: unknown state ");
00790 tcp_print_state(tcp_conn);
00791 break;
00792 }
00793 if (tcp_data != NULL)
00794 bf_afree(tcp_data);
00795 }
00796
00797
00798 PRIVATE void
00799 process_data(tcp_conn, tcp_hdr, tcp_data, data_len)
00800 tcp_conn_t *tcp_conn;
00801 tcp_hdr_t *tcp_hdr;
00802 acc_t *tcp_data;
00803 int data_len;
00804 {
00805 u32_t lo_seq, hi_seq, urg_seq, seq_nr, adv_seq, nxt;
00806 u32_t urgptr;
00807 int tcp_hdr_flags;
00808 unsigned int offset;
00809 acc_t *tmp_data, *rcvd_data, *adv_data;
00810 int len_diff;
00811
00812 assert(tcp_conn->tc_busy);
00813
00814
00815 assert (!(tcp_hdr->th_flags & THF_SYN));
00816
00817 seq_nr= ntohl(tcp_hdr->th_seq_nr);
00818 urgptr= ntohs(tcp_hdr->th_urgptr);
00819
00820 tcp_data->acc_linkC++;
00821
00822 lo_seq= seq_nr;
00823 tcp_hdr_flags= tcp_hdr->th_flags & TH_FLAGS_MASK;
00824
00825 if (tcp_Lmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
00826 {
00827 DBLOCK(0x10,
00828 printf("segment is a retransmission\n"));
00829 offset= tcp_conn->tc_RCV_NXT-lo_seq;
00830 tcp_data= bf_delhead(tcp_data, offset);
00831 lo_seq += offset;
00832 data_len -= offset;
00833 if (tcp_hdr_flags & THF_URG)
00834 {
00835 printf("process_data: updating urgent pointer\n");
00836 if (urgptr >= offset)
00837 urgptr -= offset;
00838 else
00839 tcp_hdr_flags &= ~THF_URG;
00840 }
00841 }
00842 assert (lo_seq == tcp_conn->tc_RCV_NXT);
00843
00844 if (tcp_hdr_flags & THF_URG)
00845 {
00846 if (!(tcp_conn->tc_flags & TCF_BSD_URG))
00847 {
00848
00849
00850
00851 urgptr++;
00852 }
00853 if (urgptr == 0)
00854 tcp_hdr_flags &= ~THF_URG;
00855 }
00856
00857 if (tcp_hdr_flags & THF_URG)
00858 {
00859 if (urgptr > data_len)
00860 urgptr= data_len;
00861 urg_seq= lo_seq+urgptr;
00862
00863 if (tcp_GEmod4G(urg_seq, tcp_conn->tc_RCV_HI))
00864 urg_seq= tcp_conn->tc_RCV_HI;
00865 if (tcp_conn->tc_flags & TCF_BSD_URG)
00866 {
00867 if (tcp_Gmod4G(tcp_conn->tc_RCV_NXT,
00868 tcp_conn->tc_RCV_LO))
00869 {
00870 DBLOCK(1, printf(
00871 "ignoring urgent data\n"));
00872
00873 bf_afree(tcp_data);
00874
00875
00876
00877
00878 tcp_conn->tc_flags |= TCF_RCV_PUSH;
00879 if (tcp_conn->tc_fd &&
00880 (tcp_conn->tc_fd->tf_flags &
00881 TFF_READ_IP))
00882 {
00883 tcp_fd_read(tcp_conn, 1);
00884 }
00885 if (tcp_conn->tc_fd &&
00886 (tcp_conn->tc_fd->tf_flags &
00887 TFF_SEL_READ))
00888 {
00889 tcp_rsel_read(tcp_conn);
00890 }
00891 return;
00892 }
00893 }
00894 if (tcp_Gmod4G(urg_seq, tcp_conn->tc_RCV_UP))
00895 tcp_conn->tc_RCV_UP= urg_seq;
00896 #if 0
00897 if (urgptr < data_len)
00898 {
00899 data_len= urgptr;
00900 tmp_data= bf_cut(tcp_data, 0, data_len);
00901 bf_afree(tcp_data);
00902 tcp_data= tmp_data;
00903 tcp_hdr_flags &= ~THF_FIN;
00904 }
00905 #endif
00906 tcp_conn->tc_flags |= TCF_RCV_PUSH;
00907 }
00908 else
00909 {
00910
00911 }
00912
00913 if (tcp_hdr_flags & THF_PSH)
00914 {
00915 tcp_conn->tc_flags |= TCF_RCV_PUSH;
00916 }
00917
00918 hi_seq= lo_seq+data_len;
00919 if (tcp_Gmod4G(hi_seq, tcp_conn->tc_RCV_HI))
00920 {
00921 data_len= tcp_conn->tc_RCV_HI-lo_seq;
00922 tmp_data= bf_cut(tcp_data, 0, data_len);
00923 bf_afree(tcp_data);
00924 tcp_data= tmp_data;
00925 hi_seq= lo_seq+data_len;
00926 tcp_hdr_flags &= ~THF_FIN;
00927 }
00928 assert (tcp_LEmod4G (hi_seq, tcp_conn->tc_RCV_HI));
00929
00930 rcvd_data= tcp_conn->tc_rcvd_data;
00931 tcp_conn->tc_rcvd_data= 0;
00932 tmp_data= bf_append(rcvd_data, tcp_data);
00933 tcp_conn->tc_rcvd_data= tmp_data;
00934 tcp_conn->tc_RCV_NXT= hi_seq;
00935
00936 if ((tcp_hdr_flags & THF_FIN) &&
00937 tcp_Lmod4G(tcp_conn->tc_RCV_NXT, tcp_conn->tc_RCV_HI) &&
00938 !(tcp_conn->tc_flags & TCF_FIN_RECV))
00939 {
00940 tcp_conn->tc_RCV_NXT++;
00941 tcp_conn->tc_flags |= TCF_FIN_RECV;
00942 }
00943
00944 if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
00945 tcp_fd_read(tcp_conn, 1);
00946 if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
00947 tcp_rsel_read(tcp_conn);
00948
00949 DIFBLOCK(2, (tcp_conn->tc_RCV_NXT == tcp_conn->tc_RCV_HI),
00950 printf("conn[[%d] full receive buffer\n",
00951 tcp_conn-tcp_conn_table));
00952
00953 if (tcp_conn->tc_adv_data == NULL)
00954 return;
00955 if (tcp_hdr_flags & THF_FIN)
00956 {
00957 printf("conn[%d]: advanced data after FIN\n",
00958 tcp_conn-tcp_conn_table);
00959 tcp_data= tcp_conn->tc_adv_data;
00960 tcp_conn->tc_adv_data= NULL;
00961 bf_afree(tcp_data);
00962 return;
00963 }
00964
00965 lo_seq= tcp_conn->tc_adv_seq;
00966 if (tcp_Gmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
00967 return;
00968
00969 tcp_data= tcp_conn->tc_adv_data;
00970 tcp_conn->tc_adv_data= NULL;
00971
00972 data_len= bf_bufsize(tcp_data);
00973 if (tcp_Lmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
00974 {
00975 offset= tcp_conn->tc_RCV_NXT-lo_seq;
00976 if (offset >= data_len)
00977 {
00978 bf_afree(tcp_data);
00979 return;
00980 }
00981 tcp_data= bf_delhead(tcp_data, offset);
00982 lo_seq += offset;
00983 data_len -= offset;
00984 }
00985 assert (lo_seq == tcp_conn->tc_RCV_NXT);
00986
00987 hi_seq= lo_seq+data_len;
00988 assert (tcp_LEmod4G (hi_seq, tcp_conn->tc_RCV_HI));
00989
00990 rcvd_data= tcp_conn->tc_rcvd_data;
00991 tcp_conn->tc_rcvd_data= 0;
00992 tmp_data= bf_append(rcvd_data, tcp_data);
00993 tcp_conn->tc_rcvd_data= tmp_data;
00994 tcp_conn->tc_RCV_NXT= hi_seq;
00995
00996 assert (tcp_conn->tc_RCV_LO + bf_bufsize(tcp_conn->tc_rcvd_data) ==
00997 tcp_conn->tc_RCV_NXT ||
00998 (tcp_print_conn(tcp_conn), printf("\n"), 0));
00999
01000 if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
01001 tcp_fd_read(tcp_conn, 1);
01002 if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
01003 tcp_rsel_read(tcp_conn);
01004
01005 adv_data= tcp_conn->tc_adv_data;
01006 if (adv_data != NULL)
01007 {
01008
01009 adv_seq= tcp_conn->tc_adv_seq;
01010 nxt= tcp_conn->tc_RCV_NXT;
01011
01012 if (tcp_Gmod4G(adv_seq, nxt))
01013 return;
01014
01015 tcp_conn->tc_adv_data= NULL;
01016 data_len= bf_bufsize(adv_data);
01017
01018 if (tcp_Lmod4G(adv_seq, nxt))
01019 {
01020 if (tcp_LEmod4G(adv_seq+data_len, nxt))
01021 {
01022
01023 bf_afree(adv_data);
01024 return;
01025 }
01026
01027 len_diff= nxt-adv_seq;
01028 adv_data= bf_delhead(adv_data, len_diff);
01029 data_len -= len_diff;
01030 }
01031
01032 DBLOCK(1, printf("using advanced data\n"));
01033
01034
01035 if (tcp_conn->tc_rcvd_data == NULL)
01036 {
01037 tcp_conn->tc_rcvd_data= adv_data;
01038 }
01039 else
01040 {
01041 tcp_conn->tc_rcvd_data=
01042 bf_append(tcp_conn->tc_rcvd_data, adv_data);
01043 }
01044 tcp_conn->tc_SND_NXT += data_len;
01045 assert(tcp_check_conn(tcp_conn));
01046
01047 if (tcp_conn->tc_fd &&
01048 (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
01049 {
01050 tcp_fd_read(tcp_conn, 1);
01051 }
01052 if (tcp_conn->tc_fd &&
01053 (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
01054 {
01055 tcp_rsel_read(tcp_conn);
01056 }
01057 }
01058 }
01059
01060 PRIVATE void process_advanced_data(tcp_conn, tcp_hdr, tcp_data, data_len)
01061 tcp_conn_t *tcp_conn;
01062 tcp_hdr_t *tcp_hdr;
01063 acc_t *tcp_data;
01064 int data_len;
01065 {
01066 u32_t seq, adv_seq;
01067 acc_t *adv_data;
01068
01069 assert(tcp_conn->tc_busy);
01070
01071
01072
01073
01074
01075
01076 tcp_conn->tc_flags |= TCF_SEND_ACK;
01077 tcp_conn_write(tcp_conn, 1);
01078
01079 if (tcp_hdr->th_flags & THF_URG)
01080 return;
01081
01082 if (tcp_hdr->th_flags & THF_PSH)
01083 tcp_conn->tc_flags |= TCF_RCV_PUSH;
01084 seq= ntohl(tcp_hdr->th_seq_nr);
01085
01086
01087
01088
01089 if (tcp_Gmod4G(seq+data_len, tcp_conn->tc_RCV_HI))
01090 return;
01091
01092 adv_data= tcp_conn->tc_adv_data;
01093 adv_seq= tcp_conn->tc_adv_seq;
01094 tcp_conn->tc_adv_data= NULL;
01095
01096 tcp_data->acc_linkC++;
01097 if (adv_data == NULL)
01098 {
01099 adv_seq= seq;
01100 adv_data= tcp_data;
01101 }
01102 else if (seq + data_len == adv_seq)
01103 {
01104
01105 adv_data= bf_append(tcp_data, adv_data);
01106 adv_seq= seq;
01107 }
01108 else if (adv_seq + bf_bufsize(adv_data) == seq)
01109 {
01110
01111 adv_data= bf_append(adv_data, tcp_data);
01112 }
01113 else
01114 {
01115
01116 bf_afree(tcp_data);
01117 }
01118 tcp_conn->tc_adv_data= adv_data;
01119 tcp_conn->tc_adv_seq= adv_seq;
01120 }
01121
01122 PRIVATE void create_RST(tcp_conn, ip_hdr, tcp_hdr, data_len)
01123 tcp_conn_t *tcp_conn;
01124 ip_hdr_t *ip_hdr;
01125 tcp_hdr_t *tcp_hdr;
01126 int data_len;
01127 {
01128 acc_t *tmp_ipopt, *tmp_tcpopt, *tcp_pack;
01129 acc_t *RST_acc;
01130 ip_hdr_t *RST_ip_hdr;
01131 tcp_hdr_t *RST_tcp_hdr;
01132 size_t pack_size, ip_hdr_len, mss;
01133
01134 DBLOCK(0x10, printf("in create_RST, bad pack is:\n");
01135 tcp_print_pack(ip_hdr, tcp_hdr); tcp_print_state(tcp_conn);
01136 printf("\n"));
01137
01138 assert(tcp_conn->tc_busy);
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 if ((tcp_hdr->th_flags & (THF_FIN|THF_SYN)) == 0 &&
01150 data_len == 0)
01151 {
01152 #if DEBUG
01153 { printf("tcp_recv`create_RST: no data, no RST\n"); }
01154 #endif
01155 return;
01156 }
01157
01158 tmp_ipopt= tcp_conn->tc_remipopt;
01159 if (tmp_ipopt)
01160 tmp_ipopt->acc_linkC++;
01161 tmp_tcpopt= tcp_conn->tc_tcpopt;
01162 if (tmp_tcpopt)
01163 tmp_tcpopt->acc_linkC++;
01164
01165 tcp_extract_ipopt (tcp_conn, ip_hdr);
01166 tcp_extract_tcpopt (tcp_conn, tcp_hdr, &mss);
01167
01168 RST_acc= tcp_make_header (tcp_conn, &RST_ip_hdr, &RST_tcp_hdr,
01169 (acc_t *)0);
01170
01171 if (tcp_conn->tc_remipopt)
01172 bf_afree(tcp_conn->tc_remipopt);
01173 tcp_conn->tc_remipopt= tmp_ipopt;
01174 if (tcp_conn->tc_tcpopt)
01175 bf_afree(tcp_conn->tc_tcpopt);
01176 tcp_conn->tc_tcpopt= tmp_tcpopt;
01177
01178 RST_ip_hdr->ih_src= ip_hdr->ih_dst;
01179 RST_ip_hdr->ih_dst= ip_hdr->ih_src;
01180
01181 RST_tcp_hdr->th_srcport= tcp_hdr->th_dstport;
01182 RST_tcp_hdr->th_dstport= tcp_hdr->th_srcport;
01183 if (tcp_hdr->th_flags & THF_ACK)
01184 {
01185 RST_tcp_hdr->th_seq_nr= tcp_hdr->th_ack_nr;
01186 RST_tcp_hdr->th_flags= THF_RST;
01187 }
01188 else
01189 {
01190 RST_tcp_hdr->th_seq_nr= 0;
01191 RST_tcp_hdr->th_ack_nr=
01192 htonl(
01193 ntohl(tcp_hdr->th_seq_nr)+
01194 data_len +
01195 (tcp_hdr->th_flags & THF_SYN ? 1 : 0) +
01196 (tcp_hdr->th_flags & THF_FIN ? 1 : 0));
01197 RST_tcp_hdr->th_flags= THF_RST|THF_ACK;
01198 }
01199
01200 pack_size= bf_bufsize(RST_acc);
01201 RST_ip_hdr->ih_length= htons(pack_size);
01202 RST_tcp_hdr->th_window= htons(tcp_conn->tc_rcv_wnd);
01203 RST_tcp_hdr->th_chksum= 0;
01204
01205 RST_acc->acc_linkC++;
01206 ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
01207 tcp_pack= bf_delhead(RST_acc, ip_hdr_len);
01208 RST_tcp_hdr->th_chksum= ~tcp_pack_oneCsum (RST_ip_hdr, tcp_pack);
01209 bf_afree(tcp_pack);
01210
01211 DBLOCK(2, tcp_print_pack(ip_hdr, tcp_hdr); printf("\n");
01212 tcp_print_pack(RST_ip_hdr, RST_tcp_hdr); printf("\n"));
01213
01214 if (tcp_conn->tc_frag2send)
01215 bf_afree(tcp_conn->tc_frag2send);
01216 tcp_conn->tc_frag2send= RST_acc;
01217 tcp_conn_write(tcp_conn, 1);
01218 }
01219
01220 PUBLIC void
01221 tcp_fd_read(tcp_conn, enq)
01222 tcp_conn_t *tcp_conn;
01223 int enq;
01224 {
01225 tcp_fd_t *tcp_fd;
01226 size_t data_size, read_size;
01227 acc_t *data;
01228 int fin_recv, urg, push, result;
01229 i32_t old_window, new_window;
01230 u16_t mss;
01231
01232 assert(tcp_conn->tc_busy);
01233
01234 tcp_fd= tcp_conn->tc_fd;
01235
01236 assert (tcp_fd->tf_flags & TFF_READ_IP);
01237 if (tcp_conn->tc_state == TCS_CLOSED)
01238 {
01239 if (tcp_fd->tf_read_offset)
01240 tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
01241 else
01242 tcp_reply_read (tcp_fd, tcp_conn->tc_error);
01243 return;
01244 }
01245
01246 urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
01247 push= (tcp_conn->tc_flags & TCF_RCV_PUSH);
01248 fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);
01249
01250 data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
01251 if (fin_recv)
01252 data_size--;
01253 if (urg)
01254 {
01255 #if DEBUG
01256 printf("tcp_fd_read: RCV_UP = 0x%x, RCV_LO = 0x%x\n",
01257 tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
01258 #endif
01259 read_size= tcp_conn->tc_RCV_UP-tcp_conn->tc_RCV_LO;
01260 }
01261 else
01262 read_size= data_size;
01263
01264 if (read_size >= tcp_fd->tf_read_count)
01265 read_size= tcp_fd->tf_read_count;
01266 else if (!push && !fin_recv && !urg &&
01267 data_size < TCP_MIN_RCV_WND_SIZE)
01268 {
01269
01270 return;
01271 }
01272 else if (data_size == 0 && !fin_recv)
01273 {
01274
01275 return;
01276 }
01277
01278 if (read_size)
01279 {
01280 if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))
01281 {
01282 if (tcp_fd->tf_read_offset)
01283 {
01284 tcp_reply_read (tcp_fd,
01285 tcp_fd->tf_read_offset);
01286 }
01287 else
01288 {
01289 tcp_reply_read (tcp_fd, EURG);
01290 }
01291 return;
01292 }
01293 else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG))
01294 {
01295 if (tcp_fd->tf_read_offset)
01296 {
01297 tcp_reply_read (tcp_fd,
01298 tcp_fd->tf_read_offset);
01299 }
01300 else
01301 {
01302 tcp_reply_read(tcp_fd, ENOURG);
01303 }
01304 return;
01305 }
01306
01307 if (read_size == data_size)
01308 {
01309 data= tcp_conn->tc_rcvd_data;
01310 data->acc_linkC++;
01311 }
01312 else
01313 {
01314 data= bf_cut(tcp_conn->tc_rcvd_data, 0, read_size);
01315 }
01316 result= (*tcp_fd->tf_put_userdata) (tcp_fd->tf_srfd,
01317 tcp_fd->tf_read_offset, data, FALSE);
01318 if (result<0)
01319 {
01320 if (tcp_fd->tf_read_offset)
01321 tcp_reply_read(tcp_fd, tcp_fd->
01322 tf_read_offset);
01323 else
01324 tcp_reply_read(tcp_fd, result);
01325 return;
01326 }
01327 tcp_fd->tf_read_offset += read_size;
01328 tcp_fd->tf_read_count -= read_size;
01329
01330 if (data_size == read_size)
01331 {
01332 bf_afree(tcp_conn->tc_rcvd_data);
01333 tcp_conn->tc_rcvd_data= 0;
01334 }
01335 else
01336 {
01337 tcp_conn->tc_rcvd_data=
01338 bf_delhead(tcp_conn->tc_rcvd_data,
01339 read_size);
01340 }
01341 tcp_conn->tc_RCV_LO += read_size;
01342 data_size -= read_size;
01343 }
01344
01345
01346 if (tcp_conn->tc_RCV_LO - tcp_conn->tc_IRS > 0x40000000)
01347 {
01348 tcp_conn->tc_IRS += 0x20000000;
01349 DBLOCK(1, printf("tcp_fd_read: updating IRS to 0x%lx\n",
01350 (unsigned long)tcp_conn->tc_IRS););
01351 if (tcp_Lmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_IRS))
01352 {
01353 tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
01354 DBLOCK(1, printf(
01355 "tcp_fd_read: updating RCV_UP to 0x%lx\n",
01356 (unsigned long)tcp_conn->tc_RCV_UP););
01357 }
01358 DBLOCK(1, printf("tcp_fd_read: RCP_LO = 0x%lx\n",
01359 (unsigned long)tcp_conn->tc_RCV_LO););
01360 }
01361
01362 mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
01363 if (tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO <=
01364 tcp_conn->tc_rcv_wnd-mss)
01365 {
01366 old_window= tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_NXT;
01367 tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO +
01368 tcp_conn->tc_rcv_wnd;
01369 new_window= tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_NXT;
01370 assert(old_window >=0 && new_window >= old_window);
01371 if (old_window < mss && new_window >= mss)
01372 {
01373 tcp_conn->tc_flags |= TCF_SEND_ACK;
01374 DBLOCK(2, printf("opening window\n"));
01375 tcp_conn_write(tcp_conn, 1);
01376 }
01377 }
01378 if (tcp_conn->tc_rcvd_data == NULL &&
01379 tcp_conn->tc_adv_data == NULL)
01380 {
01381
01382 tcp_conn->tc_flags &= ~TCF_RCV_PUSH;
01383 }
01384 if (fin_recv || urg || tcp_fd->tf_read_offset ||
01385 !tcp_fd->tf_read_count)
01386 {
01387 tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
01388 return;
01389 }
01390 }
01391
01392 PUBLIC unsigned
01393 tcp_sel_read(tcp_conn)
01394 tcp_conn_t *tcp_conn;
01395 {
01396 tcp_fd_t *tcp_fd;
01397 size_t data_size;
01398 int fin_recv, urg, push;
01399
01400 tcp_fd= tcp_conn->tc_fd;
01401
01402 if (tcp_conn->tc_state == TCS_CLOSED)
01403 return 1;
01404
01405 fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);
01406 if (fin_recv)
01407 return 1;
01408
01409 data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
01410 if (data_size == 0)
01411 {
01412
01413 return 0;
01414 }
01415
01416 urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
01417 push= (tcp_conn->tc_flags & TCF_RCV_PUSH);
01418
01419 if (!push && !urg && data_size < TCP_MIN_RCV_WND_SIZE)
01420 {
01421
01422 return 0;
01423 }
01424
01425 return 1;
01426 }
01427
01428 PUBLIC void
01429 tcp_rsel_read(tcp_conn)
01430 tcp_conn_t *tcp_conn;
01431 {
01432 tcp_fd_t *tcp_fd;
01433
01434 if (tcp_sel_read(tcp_conn) == 0)
01435 return;
01436
01437 tcp_fd= tcp_conn->tc_fd;
01438 tcp_fd->tf_flags &= ~TFF_SEL_READ;
01439 if (tcp_fd->tf_select_res)
01440 tcp_fd->tf_select_res(tcp_fd->tf_srfd, SR_SELECT_READ);
01441 else
01442 printf("tcp_rsel_read: no select_res\n");
01443 }
01444
01445 PUBLIC void tcp_bytesavailable(tcp_fd, bytesp)
01446 tcp_fd_t *tcp_fd;
01447 int *bytesp;
01448 {
01449 tcp_conn_t *tcp_conn;
01450 size_t data_size, read_size;
01451 acc_t *data;
01452 int fin_recv, urg, push, result;
01453 i32_t old_window, new_window;
01454 u16_t mss;
01455
01456 *bytesp= 0;
01457
01458 if (!(tcp_fd->tf_flags & TFF_CONNECTED))
01459 return;
01460 tcp_conn= tcp_fd->tf_conn;
01461
01462 if (tcp_conn->tc_state == TCS_CLOSED)
01463 return;
01464
01465 urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
01466 push= (tcp_conn->tc_flags & TCF_RCV_PUSH);
01467 fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);
01468
01469 data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
01470 if (fin_recv)
01471 data_size--;
01472 if (urg)
01473 data_size= tcp_conn->tc_RCV_UP-tcp_conn->tc_RCV_LO;
01474
01475 if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))
01476 return;
01477 else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG))
01478 return;
01479
01480 *bytesp= data_size;
01481 }
01482
01483
01484
01485