📄 tcp_in.c
字号:
/***********************************************************************//* Local Function Definitions *//***********************************************************************//***********************************************************************//* sock_match: Match incoming segment to an open socket *//* *//***********************************************************************/static SOCKET sock_match(void){ SOCKET ls_sock = NULL; CircLink *link = TcpLruList.next_bck; /*-------------------------------------------------------------------*/ /* Search socket table for match. */ /*-------------------------------------------------------------------*/ for (; link != &TcpLruList; link = link->next_bck) { SOCKET sock = (SOCKET)link; /*-----------------------------------------------------------------*/ /* Check for local port match. */ /*-----------------------------------------------------------------*/ if (Net.Tcp->dst_port == sock->local.sin_port) { /*---------------------------------------------------------------*/ /* Check for IP address and remote port match. */ /*---------------------------------------------------------------*/ if ((Net.Tcp->src_port == sock->remote.sin_port) && (Net.Ip->src_ip == sock->remote.sin_addr.s_addr) && (Net.Ip->dst_ip == sock->local.sin_addr.s_addr)) { /*-------------------------------------------------------------*/ /* If not already there, move matching socket to head of list. */ /*-------------------------------------------------------------*/ if (link != TcpLruList.next_bck) { /*-----------------------------------------------------------*/ /* Remove from socket list. */ /*-----------------------------------------------------------*/ link->next_bck->next_fwd = link->next_fwd; link->next_fwd->next_bck = link->next_bck; /*-----------------------------------------------------------*/ /* Append to head of socket list. */ /*-----------------------------------------------------------*/ link->next_bck = TcpLruList.next_bck; link->next_fwd = &TcpLruList; TcpLruList.next_bck->next_fwd = link; TcpLruList.next_bck = link; } return sock; } /*---------------------------------------------------------------*/ /* Remember socket in listen state that matches port. */ /*---------------------------------------------------------------*/ if (sock->state == SS_LISTEN) ls_sock = sock; } } /*-------------------------------------------------------------------*/ /* If input contains SYN, use listen port match. */ /*-------------------------------------------------------------------*/ if ((Net.Tcp->flags & TCPF_SYN) && ls_sock) return ls_sock; /*-------------------------------------------------------------------*/ /* No match. */ /*-------------------------------------------------------------------*/ return NULL;}/***********************************************************************//* seq_ok: Determine if incoming segment is acceptable *//* *//* Note: Checks if sequence numbers of incoming segment fall within *//* acceptable range. If not, returns 0 with segment unaltered. *//* TcpJustAck() will acknowledge segments containing data, SYN, *//* or FIN. If some part of segment is acceptable, returns 1 *//* after trimming segment to just the acceptable range. *//* *//* SYN and initial data may be trimmed from segment beginning. *//* FIN and ending data may be trimmed from segment end. *//* *//* seq_ok() is generous in that it trims to the available buffer *//* space, not just the announced receive window, and it doesn't *//* trim an ending FIN unless it also has to trim ending data. *//* *//***********************************************************************/static int seq_ok(void){ uint rcv_win = Sock->rb_size - Sock->rb_count; /*-------------------------------------------------------------------*/ /* Allow all unsynchronized states (CLOSED, LISTEN, SYN-SENT). */ /*-------------------------------------------------------------------*/ if (Sock->state < SS_SYNRCVD) return TRUE; /*-------------------------------------------------------------------*/ /* Trim segment if some is below next expected sequence number. */ /*-------------------------------------------------------------------*/ if (SEQ_GT(Sock->rcv_nxt, Net.Tcp->seq_num)) { int todrop = Sock->rcv_nxt - Net.Tcp->seq_num; /*-----------------------------------------------------------------*/ /* Ensure trimmed part of received segment gets acknowledged. */ /*-----------------------------------------------------------------*/ Sock->flags |= SF_SENDFLG; /*-----------------------------------------------------------------*/ /* Trim SYN if present. Return if nothing else to drop. */ /*-----------------------------------------------------------------*/ if (Net.Tcp->flags & TCPF_SYN) { Net.Tcp->flags &= ~TCPF_SYN; --todrop; ++Net.Tcp->seq_num; } /*-----------------------------------------------------------------*/ /* If data is completely below the receive window, return TRUE */ /* with length set to zero in order to process acks and window. */ /*-----------------------------------------------------------------*/ if (todrop >= RxBuf->app_len) { RxBuf->length = RxBuf->app_len = RxBuf->app_len2 = 0; return TRUE; } /*-----------------------------------------------------------------*/ /* Adjust sequence number, data length and pointers. */ /*-----------------------------------------------------------------*/ TcpTrimBeg(RxBuf, todrop); } /*-------------------------------------------------------------------*/ /* Trim segment end if some data extends beyond receive buffer end. */ /*-------------------------------------------------------------------*/ if (SEQ_GT(Net.Tcp->seq_num + RxBuf->app_len, Sock->rcv_nxt + rcv_win)) { int new_len; /*-----------------------------------------------------------------*/ /* Return FALSE if segment is completely above receive window. */ /*-----------------------------------------------------------------*/ if (SEQ_GT(Net.Tcp->seq_num, Sock->rcv_nxt + rcv_win)) return FALSE; /*-----------------------------------------------------------------*/ /* Ensure trimmed part of received segment gets acknowledged. */ /*-----------------------------------------------------------------*/ Sock->flags |= SF_SENDFLG; /*-----------------------------------------------------------------*/ /* Trim to end of receive buffer. */ /*-----------------------------------------------------------------*/ new_len = rcv_win - (Net.Tcp->seq_num - Sock->rcv_nxt); RxBuf->length = new_len; RxBuf->app_len = new_len; /*-----------------------------------------------------------------*/ /* FIN takes no buffer space, but must be trimmed if end data is. */ /*-----------------------------------------------------------------*/ Net.Tcp->flags &= ~TCPF_FIN; } return TRUE;}/***********************************************************************//* do_opts: Handle TCP options for inbound segment *//* *//***********************************************************************/static void do_opts(void){ ui8 *optp = Net.Tcp->options; ui8 *tcp_data = optp + (TCP_HLEN(Net.Tcp) - TCPMHLEN); /*-------------------------------------------------------------------*/ /* Loop through option list, parsing each option present. */ /*-------------------------------------------------------------------*/ do { switch (*optp) { case TPO_NOOP: ++optp; break; case TPO_EOOL: break; case TPO_MSS: get_MSS((ui16 *)(optp + 2)); /*lint -fallthrough */ default: /*---------------------------------------------------------------*/ /* Advance option pointer by value in len field. */ /*---------------------------------------------------------------*/ optp += *(optp + 1); break; } } while ((*optp != TPO_EOOL) && (optp < tcp_data));}/***********************************************************************//* get_MSS: Set sender MSS from option in received segment *//* *//* Input: mssp = pointer to mss option *//* *//***********************************************************************/static void get_MSS(const ui16 *mssp){ ui16 mss; /*-------------------------------------------------------------------*/ /* If this is not a SYN segment, ignore the MSS option. */ /*-------------------------------------------------------------------*/ if ((Net.Tcp->flags & TCPF_SYN) == 0) return; /*-------------------------------------------------------------------*/ /* Extract the embedded MSS, converting it to host order. */ /*-------------------------------------------------------------------*/ mss = ntohs(*mssp); /*-------------------------------------------------------------------*/ /* Use the minimum of this and any previously sent MSS values. */ /*-------------------------------------------------------------------*/ if (Sock->snd_mss) Sock->snd_mss = min(mss, Sock->snd_mss); else Sock->snd_mss = mss;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -