📄 icmp.c
字号:
/* Increment the number of ICMP messages sent. */
SNMP_icmpOutMsgs_Inc;
} /* ICMP_Reflect */
/****************************************************************************
*
* FUNCTION
*
* ICMP_Echo_Reply
*
* DESCRIPTION
*
* send out an icmp packet, probably in response to a ping operation
* interchanges the source and destination addresses of the packet,
* puts in my addresses for the source and sends it
*
* does not change any of the ICMP fields, just the IP and dlayers
* returns 0 on okay send, nonzero on error
*
* INPUTS
*
* buf_ptr
*
* OUTPUTS
*
* NU_SUCCESS Reply sent
* -1 Reply not sent.
*
******************************************************************************/
STATUS ICMP_Echo_Reply (NET_BUFFER *buf_ptr)
{
/* Set the deallocation list. */
buf_ptr->mem_dlist = &MEM_Buffer_Freelist;
/* Do not send an error in response to a broadcast packet. */
if (buf_ptr->mem_flags & (NET_BCAST | NET_MCAST))
{
MEM_One_Buffer_Chain_Free (buf_ptr, buf_ptr->mem_dlist);
return(-1);
}
ICMP_Reflect(buf_ptr);
return (NU_SUCCESS);
} /* end ICMP_Echo_Reply */
/***********************************************************************
*
* FUNCTION
*
* ICMP_Send_Echo_Request
*
* DESCRIPTION
*
* Send an ICMP echo request.
*
* INPUTS
*
* dest_ip
* timeout
*
* OUTPUTS
*
* NU_SUCCESS
* NU_NO_ACTION
* NU_MEM_ALLOC
* NU_NO_BUFFERS
*
*************************************************************************/
STATUS ICMP_Send_Echo_Request(UINT8 *dest_ip, UINT32 timeout)
{
ICMP_ECHO_LIST_ENTRY *echo_entry;
STATUS ret_status;
OPTION old_preempt;
NET_BUFFER *buf_ptr;
ICMP_LAYER *icmp_ptr;
UINT16 len;
UINT8 x, y;
NU_SUPERV_USER_VARIABLES
/* Grab the stack semaphore */
NU_Obtain_Semaphore (&TCP_Resource, NU_SUSPEND);
/* Switch to supervisor mode. */
NU_SUPERVISOR_MODE();
/* Allocate a buffer for the echo request (ping) */
buf_ptr = MEM_Buffer_Dequeue (&MEM_Buffer_Freelist);
/* Make sure we got one. */
if (buf_ptr != NU_NULL)
{
/* If the timeout is zero then used the default value. */
if (!timeout)
timeout = ICMP_DEFAULT_ECHO_TIMEOUT;
/* Bump the sequence number. */
ICMP_Echo_Req_Seq_Num++;
/* Set the data pointer to the correct location. */
buf_ptr->data_ptr = (buf_ptr->mem_parent_packet +
(NET_MAX_ICMP_HEADER_SIZE - sizeof (ICMP_LAYER)));
/* Get the length of the ICMP header. */
len = ICMP_ECHO_REQ_HEADER_SIZE;
/* Point to the ICMP layer */
icmp_ptr = (ICMP_LAYER *)buf_ptr->data_ptr;
/* Set the ICMP type to echo */
PUT8(icmp_ptr, ICMP_TYPE_OFFSET, ICMP_ECHO);
/* Set the code to zero, always zero for echo packets */
PUT8(icmp_ptr, ICMP_CODE_OFFSET, 0);
/* Set the ID and sequence number fields. */
PUT16(icmp_ptr, ICMP_ID_OFFSET, ICMP_ECHO_REQ_ID);
PUT16(icmp_ptr, ICMP_SEQ_OFFSET, ICMP_Echo_Req_Seq_Num);
/* Fill in the standard 32 bytes of data. */
for (x = 0, y = 'a'; x <= 31; x++)
{
/* Start back at A if we get to the end of the alphabet */
if (y > 'w')
y = 'a';
/* store the byte of data */
PUT8(icmp_ptr, ICMP_DATA_OFFSET + x, y++);
/* Bump the length */
len++;
}
/* Set the length for this buffer. */
buf_ptr->data_len = buf_ptr->mem_total_data_len = len;
/* Set the deallocation list */
buf_ptr->mem_dlist = &MEM_Buffer_Freelist;
/* Compute the checksum */
PUT16(icmp_ptr, ICMP_CKSUM_OFFSET, 0);
PUT16(icmp_ptr, ICMP_CKSUM_OFFSET, TLS_IP_Check_Buffer_Chain (buf_ptr) );
/* Send this packet. */
ret_status = IP_Send(buf_ptr, NU_NULL, IP_ADDR (dest_ip),
NU_NULL, NU_NULL, IP_TIME_TO_LIVE, IP_ICMP_PROT,
0, NU_NULL);
if (ret_status != NU_SUCCESS)
{
/* Release the stack semaphore */
NU_Release_Semaphore (&TCP_Resource);
/* The packet was not sent. Dealocate the buffer. If the packet was
transmitted it will be deallocated when the transmit complete
interrupt occurs. */
MEM_One_Buffer_Chain_Free (buf_ptr, buf_ptr->mem_dlist);
/* Increment the number of send errors. */
SNMP_icmpOutErrors_Inc;
/* Set the status to an error. */
ret_status = NU_NO_ACTION;
}
else
{
/* Increment the number of ICMP messages sent. */
SNMP_icmpOutMsgs_Inc;
/* Increment the number of ICMP echos (pings) sent. */
SNMP_icmpOutEchos_Inc;
/* Allocate memory for the ICMP echo entry */
ret_status = NU_Allocate_Memory (&System_Memory, (VOID **)&echo_entry,
sizeof (ICMP_ECHO_LIST_ENTRY), NU_NO_SUSPEND);
/* Make sure that we got some memory */
if (ret_status == NU_SUCCESS)
{
/* Fill in the echo entry structure. */
echo_entry->icmp_requesting_task = NU_Current_Task_Pointer();
echo_entry->icmp_echo_seq_num = ICMP_Echo_Req_Seq_Num;
/* Place it on the echo entry list. */
DLL_Enqueue (&ICMP_Echo_List, echo_entry);
/* Set an event to wake this task up if an echo reply
not not RX. */
UTL_Timerset (ICMP_ECHO_TIMEOUT, (UNSIGNED) echo_entry,
timeout, NU_NULL);
/* Change to no preemtion so that no other task can get in between the
time that we release the semaphore and self-suspend. */
old_preempt = NU_Change_Preemption (NU_NO_PREEMPT);
/* Release the stack semaphore */
NU_Release_Semaphore (&TCP_Resource);
/* Self-suspend waiting on the ping reply or a timeout. */
NU_Suspend_Task (echo_entry->icmp_requesting_task);
/* Restore the previous preemption state. */
NU_Change_Preemption (old_preempt);
/* Assign the status to that in the ICMP entry. It was
set by either the timeout or by the reception of
the reply. */
ret_status = echo_entry->icmp_echo_status;
/* Remove this entry from the echo entry list. */
DLL_Remove (&ICMP_Echo_List, echo_entry);
/* Deallocate the memory. */
NU_Deallocate_Memory (echo_entry);
}
else
{
/* Release the stack semaphore */
NU_Release_Semaphore (&TCP_Resource);
/* Increment the number of send errors due to the
lack of memory. */
SNMP_icmpOutErrors_Inc;
/* Set the status to an error. */
ret_status = NU_MEM_ALLOC;
}
}
}
else
{
/* Release the stack semaphore */
NU_Release_Semaphore (&TCP_Resource);
/* Increment the number of send errors due to the lack of buffers. */
SNMP_icmpOutErrors_Inc;
ret_status = NU_NO_BUFFERS;
}
/* Switch back to user mode. */
NU_USER_MODE();
return (ret_status);
} /* ICMP_Send_Echo_Reuest */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -