📄 tcp_recv.c
字号:
hdr_acc= bf_memreq(tcp_hdr_len); /* make fresh header */ if (tcp_conn->tc_state == TCS_CLOSED) {#if DEBUG { where(); printf("connection closed while inuse\n"); }#endif bf_afree(hdr_acc); return; } assert (hdr_acc->acc_length == tcp_hdr_len); tmp_hdr= (tcp_hdr_t *)ptr2acc_data(hdr_acc);#if DEBUG & 256 { where(); printf("doing memcpy\n"); }#endif memcpy ((char *)tmp_hdr, (char *)tcp_hdr, tcp_hdr_len); tcp_hdr= tmp_hdr; data_acc= bf_cut (tcp_data, tcp_hdr_len, data_len); seg_seq= ntohl(tcp_hdr->th_seq_nr); tcp_hdr->th_seq_nr= seg_seq; /* seq_nr in host format */ if (tcp_hdr->th_flags & THF_URG) { seg_up= ntohs(tcp_hdr->th_urgptr); tcp_hdr->th_urgptr= seg_up; /* urgptr in host format */ tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO+ tcp_conn->tc_rcv_wnd+tcp_conn->tc_urg_wnd; } assert (!(tcp_hdr->th_flags & THF_SYN)); assert (tcp_Gmod4G(seg_seq, tcp_conn->tc_RCV_NXT)); tcp_hdr->th_flags &= ~THF_FIN; /* it is too difficult to preserve a FIN */ seg_hi= seg_seq + data_len; if (tcp_Gmod4G(seg_hi, tcp_conn->tc_RCV_HI)) { seg_hi= tcp_conn->tc_RCV_HI; data_len= seg_hi-seg_seq; if (!data_len) { bf_afree(hdr_acc); bf_afree(data_acc); return; }#if DEBUG { where(); printf("Cutting packet\n"); }#endif tmp_acc= bf_cut(data_acc, 0, data_len); bf_afree(data_acc); data_acc= tmp_acc; } hdr_acc->acc_next= data_acc; hdr_acc->acc_ext_link= 0; head_acc= tcp_conn->tc_rcv_queue; tcp_conn->tc_rcv_queue= 0; tail_acc_ptr= 0; next_acc= head_acc; while (next_acc) { assert (next_acc->acc_length >= TCP_MIN_HDR_SIZE); tmp_hdr= (tcp_hdr_t *)ptr2acc_data(next_acc); if (tcp_Lmod4G(seg_seq, tmp_hdr->th_seq_nr)) {#if DEBUG & 256 { where(); printf("calling merge_packs\n"); } #endif next_acc= merge_packs(hdr_acc, next_acc); hdr_acc= 0; if (tail_acc_ptr) {assert (*tail_acc_ptr); (*tail_acc_ptr)->acc_ext_link= 0;#if DEBUG & 256 { where(); printf("calling merge_packs\n"); } #endif *tail_acc_ptr= merge_packs( *tail_acc_ptr, next_acc); } else head_acc= next_acc; break; } if (!tail_acc_ptr) tail_acc_ptr= &head_acc; else tail_acc_ptr= &(*tail_acc_ptr)->acc_ext_link; next_acc= next_acc->acc_ext_link; } if (hdr_acc) { next_acc= hdr_acc; hdr_acc= 0; if (tail_acc_ptr) { if (*tail_acc_ptr) { (*tail_acc_ptr)->acc_ext_link= 0;#if DEBUG & 256 { where(); printf("calling merge_packs\n"); } #endif *tail_acc_ptr= merge_packs( *tail_acc_ptr, next_acc); } else *tail_acc_ptr= next_acc; } else head_acc= next_acc; } if (tcp_conn->tc_state == TCS_CLOSED) { while (head_acc) { next_acc= head_acc->acc_ext_link; bf_afree(head_acc); head_acc= next_acc; } return; } tcp_conn->tc_rcv_queue= head_acc;} PRIVATE acc_t *merge_packs(first, next)acc_t *first;acc_t *next;{ tcp_hdr_t *first_hdr, *next_hdr; int first_hdr_len, next_hdr_len, first_data_len, next_data_len; acc_t *next_acc, *tmp_acc; assert (first->acc_length >= TCP_MIN_HDR_SIZE); assert (next->acc_length >= TCP_MIN_HDR_SIZE); first_hdr= (tcp_hdr_t *)ptr2acc_data(first); next_hdr= (tcp_hdr_t *)ptr2acc_data(next); first_hdr_len= (first_hdr->th_data_off & TH_DO_MASK) >>2; next_hdr_len= (next_hdr->th_data_off & TH_DO_MASK) >> 2; first_data_len= first_hdr->th_chksum-first_hdr_len; next_data_len= next_hdr->th_chksum-next_hdr_len;assert (tcp_LEmod4G(first_hdr->th_seq_nr, next_hdr->th_seq_nr));assert (first_hdr_len + first_data_len == bf_bufsize(first));#if DEBUG if (next_hdr_len + next_data_len != bf_bufsize(next)) { ip_panic(( "fatal error: %d + %d != %d\n", next_hdr_len, next_data_len, bf_bufsize(next) )); }#endifassert (next_hdr_len + next_data_len == bf_bufsize(next)); if (tcp_Lmod4G(first_hdr->th_seq_nr+first_data_len, next_hdr->th_seq_nr)) { first->acc_ext_link= next; return first; } if (first_hdr->th_seq_nr == next_hdr->th_seq_nr) if (first_data_len <= next_data_len) { bf_afree(first); return next; } else { first->acc_ext_link= next->acc_ext_link; bf_afree(next); return first; } if (tcp_GEmod4G(first_hdr->th_seq_nr+first_data_len, next_hdr->th_seq_nr+next_data_len)) { first->acc_ext_link= next->acc_ext_link; bf_afree(next); return first; } first_data_len= next_hdr->th_seq_nr-first_hdr->th_seq_nr; first_hdr->th_chksum= first_data_len+first_hdr_len+ next_data_len; tmp_acc= bf_cut(first, 0, first_hdr_len + first_data_len); bf_afree(first); first= tmp_acc; if (next_hdr->th_flags & THF_PSH) first_hdr->th_flags |= THF_PSH; if (next_hdr->th_flags & THF_URG) { if (!(first_hdr->th_flags & THF_URG)) { first_hdr->th_flags |= THF_URG; first_hdr->th_urgptr= next_hdr->th_seq_nr+ next_hdr->th_urgptr- first_hdr->th_seq_nr; } else if (next_hdr->th_seq_nr+next_hdr->th_urgptr- first_hdr->th_seq_nr > first_hdr->th_urgptr) first_hdr->th_urgptr= next_hdr->th_seq_nr+ next_hdr->th_urgptr- first_hdr->th_seq_nr; } next_acc= next->acc_ext_link; tmp_acc= bf_cut(next, next_hdr_len ,next_data_len); bf_afree(next); next= tmp_acc; tmp_acc= bf_append (first, next); tmp_acc->acc_ext_link= next_acc; return tmp_acc;}PRIVATE void create_RST(tcp_conn, ip_hdr, tcp_hdr)tcp_conn_t *tcp_conn;ip_hdr_t *ip_hdr;tcp_hdr_t *tcp_hdr;{ acc_t *tmp_ipopt, *tmp_tcpopt; ip_hdropt_t ip_hdropt; tcp_hdropt_t tcp_hdropt; acc_t *RST_acc; ip_hdr_t *RST_ip_hdr; tcp_hdr_t *RST_tcp_hdr; char *ptr2RSThdr; size_t pack_size; tmp_ipopt= tcp_conn->tc_remipopt; if (tmp_ipopt) tmp_ipopt->acc_linkC++; tmp_tcpopt= tcp_conn->tc_remtcpopt; if (tmp_tcpopt) tmp_tcpopt->acc_linkC++; tcp_extract_ipopt (tcp_conn, ip_hdr); tcp_extract_tcpopt (tcp_conn, tcp_hdr); RST_acc= tcp_make_header (tcp_conn, &RST_ip_hdr, &RST_tcp_hdr, (acc_t *)0); if (!RST_acc) {#if DEBUG { where(); printf("connection closed while inuse\n"); }#endif return; } if (tcp_conn->tc_remipopt) bf_afree(tcp_conn->tc_remipopt); tcp_conn->tc_remipopt= tmp_ipopt; if (tcp_conn->tc_remtcpopt) bf_afree(tcp_conn->tc_remtcpopt); tcp_conn->tc_remtcpopt= tmp_tcpopt; RST_ip_hdr->ih_src= ip_hdr->ih_dst; RST_ip_hdr->ih_dst= ip_hdr->ih_src; RST_tcp_hdr->th_srcport= tcp_hdr->th_dstport; RST_tcp_hdr->th_dstport= tcp_hdr->th_srcport; if (tcp_hdr->th_flags & THF_ACK) { RST_tcp_hdr->th_seq_nr= tcp_hdr->th_ack_nr; RST_tcp_hdr->th_flags= THF_RST; } else { RST_tcp_hdr->th_seq_nr= 0; RST_tcp_hdr->th_ack_nr= htonl(ntohl(tcp_hdr->th_seq_nr)+ tcp_hdr->th_chksum-((tcp_hdr->th_data_off & TH_DO_MASK) >> 2)+ (tcp_hdr->th_flags & THF_SYN ? 1 : 0) + (tcp_hdr->th_flags & THF_FIN ? 1 : 0)); RST_tcp_hdr->th_flags= THF_RST|THF_ACK; } pack_size= bf_bufsize(RST_acc); RST_ip_hdr->ih_length= htons(pack_size); RST_tcp_hdr->th_window= htons(tcp_conn->tc_rcv_wnd); RST_tcp_hdr->th_chksum= 0; RST_tcp_hdr->th_chksum= ~tcp_pack_oneCsum (RST_acc, pack_size); if (tcp_conn->tc_frag2send) bf_afree(tcp_conn->tc_frag2send); tcp_conn->tc_frag2send= RST_acc;}PUBLIC void tcp_restart_fd_read (tcp_conn)tcp_conn_t *tcp_conn;{ tcp_fd_t *new_fd, *hi_fd, *urgent_fd, *normal_fd, *tcp_fd;#if DEBUG & 256 { where(); printf("tcp_restart_fd_read called\n"); }#endif do { tcp_fd= tcp_conn->tc_readuser; if (tcp_fd) fd_read (tcp_fd); else tcp_fd= &tcp_fd_table[TCP_FD_NR-1]; if (!tcp_conn->tc_readuser) { urgent_fd= 0; normal_fd= 0; for (new_fd= tcp_fd+1, hi_fd= &tcp_fd_table[TCP_FD_NR]; new_fd<hi_fd; new_fd++) switch_read_fd(tcp_conn, new_fd, &urgent_fd, &normal_fd); for (new_fd= tcp_fd_table, hi_fd= tcp_fd+1; new_fd < hi_fd; new_fd++) switch_read_fd(tcp_conn, new_fd, &urgent_fd, &normal_fd); if (urgent_fd) tcp_fd= urgent_fd; else tcp_fd= normal_fd; tcp_conn->tc_readuser= tcp_fd; } else return; } while (tcp_conn->tc_readuser);}PRIVATE void switch_read_fd (tcp_conn, new_fd, ref_urg_fd, ref_norm_fd)tcp_conn_t *tcp_conn;tcp_fd_t *new_fd, **ref_urg_fd, **ref_norm_fd;{ if (!(new_fd->tf_flags & TFF_INUSE)) return; if (new_fd->tf_conn != tcp_conn) return; if (!(new_fd->tf_flags & TFF_READ_IP)) return; if (new_fd->tf_flags & TFF_RECV_URG) { if (!*ref_urg_fd) *ref_urg_fd= new_fd; } else { if (!*ref_norm_fd) *ref_norm_fd= new_fd; }}PRIVATE void fd_read(tcp_fd)tcp_fd_t *tcp_fd;{ tcp_conn_t *tcp_conn; size_t data_size, read_size; acc_t * data; int urg, result; int more2write; more2write= FALSE; tcp_conn= tcp_fd->tf_conn; assert (tcp_fd->tf_flags & TFF_READ_IP); if (tcp_conn->tc_state == TCS_CLOSED) { tcp_conn->tc_readuser= 0;#if DEBUG { where(); printf("calling tcp_reply_read\n"); }#endif if (tcp_fd->tf_read_offset) tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset); else tcp_reply_read (tcp_fd, tcp_conn->tc_error); return; }#if URG_PROPERLY_IMPLEMENTED urg= (tcp_GEmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO) && tcp_Lmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_NXT));#else#define urg 0#endif if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG)) { tcp_conn->tc_readuser= 0;#if DEBUG { where(); printf("calling tcp_reply_read\n"); }#endif if (tcp_fd->tf_read_offset) tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset); else tcp_reply_read (tcp_fd, EURG); return; } else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG)) { tcp_conn->tc_readuser= 0;#if DEBUG { where(); printf("calling tcp_reply_read\n"); }#endif if (tcp_fd->tf_read_offset) tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset); else tcp_reply_read(tcp_fd, ENOURG); return; } data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO; if (tcp_conn->tc_flags & TCF_FIN_RECV) data_size--; if (urg) read_size= tcp_conn->tc_RCV_UP+1-tcp_conn->tc_RCV_LO; else read_size= data_size; if (read_size>tcp_fd->tf_read_count) read_size= tcp_fd->tf_read_count; if (read_size) { if (read_size == data_size) data= bf_dupacc(tcp_conn->tc_rcvd_data); else data= bf_cut(tcp_conn->tc_rcvd_data, 0, read_size); result= (*tcp_fd->tf_put_userdata) (tcp_fd->tf_srfd, tcp_fd->tf_read_offset, data, FALSE); if (tcp_conn->tc_state == TCS_CLOSED) {#if DEBUG { where(); printf("connection closed while inuse\n"); }#endif return; } if (result<0) { tcp_conn->tc_readuser= 0;#if DEBUG { where(); printf("calling tcp_reply_read\n"); }#endif if (tcp_fd->tf_read_offset) tcp_reply_read(tcp_fd, tcp_fd-> tf_read_offset); else tcp_reply_read(tcp_fd, result); return; } tcp_fd->tf_read_offset += read_size; tcp_fd->tf_read_count -= read_size; if (data_size == read_size) { bf_afree(tcp_conn->tc_rcvd_data); tcp_conn->tc_rcvd_data= 0; } else { data= tcp_conn->tc_rcvd_data; tcp_conn->tc_rcvd_data= bf_cut(data, read_size, data_size-read_size); bf_afree(data); } tcp_conn->tc_RCV_LO += read_size; data_size -= read_size; } if (tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO < (tcp_conn-> tc_rcv_wnd >> 2)) { tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO + tcp_conn->tc_rcv_wnd; tcp_conn->tc_flags |= TCF_SEND_ACK;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif more2write= TRUE; } if (!data_size && (tcp_conn->tc_flags & TCF_RCV_PUSH)) { tcp_conn->tc_flags &= ~TCF_RCV_PUSH;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif if (tcp_fd->tf_read_offset) { tcp_conn->tc_readuser= 0;#if DEBUG & 256 { where(); printf("calling tcp_reply_read\n"); }#endif tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset); if (more2write) tcp_restart_write(tcp_conn); return; } } if ((tcp_conn->tc_flags & TCF_FIN_RECV) || !tcp_fd->tf_read_count) { tcp_conn->tc_readuser= 0;#if DEBUG & 256 { where(); printf("calling tcp_reply_read\n"); }#endif tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset); if (more2write) tcp_restart_write(tcp_conn); return; } if (more2write) tcp_restart_write(tcp_conn);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -