📄 tcp.c
字号:
yet established a connection. */
if (flags & TRESET)
{
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
break;
}
/* Received a SYN, someone is starting a connection. */
if(flags & TSYN)
{
myport = GET16(p, TCP_DEST_OFFSET);
task_entry = listen_socket->s_accept_list;
/* verify that there is a task table port entry free */
if(NU_IGNORE_VALUE < (tasklist_num = TCP_Find_Empty_Port (task_entry)))
{
/* establish a TCP_Ports entry */
if((portlist_num = TCPSS_Net_Listen (myport, tcp_chk)) < 0)
{
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
return (1);
} /* end if establish a TCP_Ports entry */
/* send that port structure to tcpdo */
prt = TCP_Ports[portlist_num];
new_socket = SCK_Sockets[prt->p_socketd];
/* store the TCP_Ports entry number in the task table */
task_entry->socket_index[tasklist_num] = prt->p_socketd;
/* store the task ID in the port table */
new_socket->s_TXTask = task_entry->Task_ID;
} /* end if for no port num back from nuke */
else
{
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
return(1);
}
/* Preserve the Task_Entry information so we can cleanup in the case
where the connection is aborted before being accepted.
*/
new_socket->s_accept_list = task_entry;
new_socket->s_accept_index = tasklist_num;
/* remember anything important from the incoming TCP header */
prt->out.size = GET16(p, TCP_WINDOW_OFFSET);
prt->out.port = GET16(p, TCP_SRC_OFFSET);
prt->in.nxt = GET32(p, TCP_SEQ_OFFSET) + 1;
/* set the necessary fields in the outgoing TCP packet */
prt->out.tcp_flags = TSYN | TACK;
/* initialize all of the low-level transmission stuff
(IP and lower) */
prt->tcp_faddr = LONGSWAP(tcp_chk->source);
/* Send the SYN/ACK packet to the client. */
TCPSS_Send_SYN_FIN (prt, 4);
/* Indicate that a SYN has been received so get ready
to get an ACK. */
prt->state = SSYNR;
/* Increment the number of passive opens. */
SNMP_tcpPassiveOpens_Inc;
} /* end if */
else
{
/* Send a reset if this is not a SYN packet. */
TCP_Reset_FIN (p, tcp_chk, (INT16) buf_ptr->mem_total_data_len);
}
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free(&MEM_Buffer_List, &MEM_Buffer_Freelist);
break;
case SSYNR:
/* In the SYN Received State we expect that we got an ACK.
If we did, then we need to send an ACK and move on to
the connected state. */
if (flags & TRESET)
{
NERRS_Log_Error (NERR_RECOVERABLE, __FILE__, __LINE__);
/* Return to the closed state */
prt->state = SCLOSED;
/* Clean up this port. */
TCP_Cleanup(prt);
/* Increment the number of connection failures. */
SNMP_tcpAttemptFails_Inc;
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
return (1);
} /* end if */
/* The SYN flag should not be set. */
if(flags & TSYN)
{
/* It is possible that our ACK of the SYN was never recevied.
This check handles that case. If the SEQ number we expect is one
greater than the received SEQ number, then this is okay. */
if (prt->in.nxt != (GET32(p, TCP_SEQ_OFFSET) + 1))
{
/* Send a FIN and a RESET. */
prt->out.tcp_flags = TFIN | TRESET;
TCP_ACK_It(prt, 1);
/* Return to the closed state */
prt->state = SCLOSED;
/* Clean up the port. */
TCP_Cleanup(prt);
/* Increment the number of connection failures. */
SNMP_tcpAttemptFails_Inc;
}
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free(&MEM_Buffer_List, &MEM_Buffer_Freelist);
return(1);
}
/* We are expecting an ACK, if we did not get it then send
* the SYN/ACK back. */
if(!(flags & TACK))
{
prt->out.tcp_flags = TACK | TSYN;
TCP_ACK_It (prt, 1);
/* Preserve a pointer to the packet buffer just processed so we
* can deallocate it.
*/
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
break;
} /* end if */
/* Set up for the timeout timer. */
prt->out.lasttime = NU_Retrieve_Clock();
/* Starting ACK value */
prt->out.ack = GET32(p, TCP_ACK_OFFSET);
/* Accept his window size. */
prt->out.size = GET16(p, TCP_WINDOW_OFFSET);
prt->maxSendWin = prt->out.size;
/* Set up to send an ACK back. */
prt->out.tcp_flags = TACK;
/* Move on to established state. */
prt->state = SEST;
#if (INCLUDE_SNMP == NU_TRUE)
PUT32(tcp_laddr, 0, prt->tcp_laddr);
PUT32(tcp_faddr, 0, prt->tcp_faddr);
SNMP_tcpConnTableUpdate(SNMP_ADD, SEST, tcp_laddr, (UNSIGNED)(prt->in.port),
tcp_faddr, (UNSIGNED)(prt->out.port));
#endif
/* Mark the socket as connected. */
SCK_CONNECTED(prt->p_socketd);
/* Delete the timeout timer. */
UTL_Timerunset(TCPRETRANS, (UNSIGNED)prt->pindex, (INT32)prt->out.ack);
/* Remove the SYN packet from the window. */
TLS_Rmqueue(&prt->out, (INT32)prt->out.ack);
/* Get the task entry. The -1 indicates that we don't care about the
state as long as port number and port index match. */
task_entry = SCK_Sockets[prt->p_socketd]->s_accept_list;
tasklist_num = SCK_SearchTaskList(task_entry, -1, prt->p_socketd);
/* Indicate the connection is complete. This one can be accepted.*/
task_entry->stat_entry[tasklist_num] = SEST;
/* If there is a task waiting to accept a connection, resume him. */
if(task_entry->Task_ID)
{
/* Send an event to wake up the suspended server. */
TLS_Put_Event (CONOPEN, (UNSIGNED)prt->p_socketd);
}
/* Detemermine if the sender has specified a new maximum
message size. */
TCP_Check_MSS (prt, p, hlen);
/* fall through */
case SEST: /* normal data transmission */
/* If packet does not have a valid sequence number, then drop it. */
if ( !TCP_Valid_Seq((INT32)(GET32(p, TCP_SEQ_OFFSET)),(UINT16)(tlen - hlen),
(INT32)prt->in.nxt, (INT32)prt->in.size))
{
/* Send an ACK to let the foreign host know what we are expecting. */
TCP_ACK_It(prt, 1);
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free(&MEM_Buffer_List, &MEM_Buffer_Freelist);
return(1);
}
/* The SYN flag should no be set. */
if(flags & TSYN)
{
/* Send a FIN and a RESET. */
prt->out.tcp_flags = TFIN | TRESET;
TCP_ACK_It(prt, 1);
/* Return to the closed state */
prt->state = SCLOSED;
/* Clean up the port. */
TCP_Cleanup(prt);
/* Increment the number of resets from the established state. */
SNMP_tcpEstabResets_Inc;
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free(&MEM_Buffer_List, &MEM_Buffer_Freelist);
return(1);
}
/* See if the last packet acknowledged one that we sent. If
so, ackcheck will update the buffer and begin transmission
on the next part of the data if any is left in the buffer. If this
is and invalid ACK then we must drop this packet. */
if (TCP_ACK_Check(prt, p) == TCP_INVALID_ACK)
{
/* Drop this invalid packet by placing it back onto the
free list. */
MEM_Buffer_Chain_Free(&MEM_Buffer_List, &MEM_Buffer_Freelist);
}
else
{
/* Otherwise continue processing. */
/* Make sure that the connection is still in the ESTAB state after
the call to ackcheck. Ackcheck also checks for the RST bit so
there is the possibility that the connection was just reset. */
if (prt->state == SEST)
{
/* If there is data that is queued to be sent and all previously
sent data has been acknowledged, then send the queued data. */
if ( (prt->xmitFlag == NU_SET) &&
(prt->out.nextPacket != NU_NULL) &&
(prt->out.nxt == prt->out.ack) )
{
/* Clear the timer event that would have sent the data. */
UTL_Timerunset (CONTX, (UNSIGNED)prt->pindex, (INT32)1);
prt->out.tcp_flags |= TPUSH;
/* Save a pointer to the next packet to send. Then move
the next pointer forward. nextPacket should always
be NULL after these steps. */
nxtPkt = prt->out.nextPacket;
prt->out.nextPacket = prt->out.nextPacket->next;
/* Clear the event flag. */
prt->xmitFlag = NU_CLEAR;
/* Send the buffer. */
TCP_Xmit(prt, nxtPkt);
}
TCP_Estab1986 (prt, buf_ptr, tlen, hlen);
}
}
return (0);
case SSYNS: /* check to see if the ACK is for our SYN */
/* remember that tcpout is pre-set-up */
if (flags & TACK)
{ /* It is ACKING us */
/* Is the ACK for the SYN that was sent? If not we have a half open
connection (i.e., the foreign host believes there is already a
connection open on this port. So send a reset and drop the packet.
*/
if (GET32(p, TCP_ACK_OFFSET) != prt->out.nxt)
{
/* Send a reset. */
TCP_Reset_FIN (p, tcp_chk, (INT16) buf_ptr->mem_total_data_len);
NERRS_Log_Error (NERR_RECOVERABLE, __FILE__, __LINE__);
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
return (1);
} /* end if */
} /* end if */
if (flags & TRESET)
{
NERRS_Log_Error (NERR_RECOVERABLE, __FILE__, __LINE__);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -