📄 icmp.c
字号:
/* If this is the port we want, assign an error code */
if((prt != NU_NULL) && (prt->in.port == src_port) &&
(prt->out.port == dest_port) &&
(prt->tcp_faddr == dst) &&
(prt->tcp_laddr == src))
{
if (prt->icmp_error == 0)
{
/* Set the icmp_error field in the port to 1 to indicate
* "No Route to Host" */
if ( (icp->icmp_code == 0) || (icp->icmp_code == 1) ||
((icp->icmp_code >= 5) && (icp->icmp_code <= 12)) )
prt->icmp_error = 1;
/* Set the icmp_error field in the port to 2 to indicate
* "Connection Refused" */
else if ( (icp->icmp_code == 2) || (icp->icmp_code == 3) )
prt->icmp_error = 2;
/* Set the icmp_error field in the port to 3 to indicate
* "Message Too Long" */
else if (icp->icmp_code == 4)
prt->icmp_error = 3;
}
break;
}
} /* end for, i < TCP_MAX_PORTS */
#endif /* INCLUDE_TCP == NU_TRUE */
/* Return the buffer back to the free buffer pool. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
break;
default:
/* Drop the packet by placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
/* Increment the number of ICMP messages received with errors. */
SNMP_icmpInErrors_Inc;
break;
} /* end switch */
return (0);
} /* end icmpinterpret() */
/***********************************************************************
*
* FUNCTION
*
* ICMP_Send_Error
*
* DESCRIPTION
*
* Send an ICMP packet.
*
* INPUTS
*
* buf_ptr
* type
* code
* dest
* device
*
* OUTPUTS
*
* None.
*
*************************************************************************/
VOID ICMP_Send_Error(NET_BUFFER *buf_ptr, INT type, INT code, UINT32 dest,
DV_DEVICE_ENTRY *device)
{
NET_BUFFER *send_buf;
IPLAYER *ip_pkt;
ICMP_LAYER *icmp_shdr;
UINT8 temp_buf[sizeof(IPLAYER) + 8];
ip_pkt = (IPLAYER *)buf_ptr->data_ptr;
/* Do not generate an ICMP error message in response to an ICMP packet,
except for the case where we are responding to an echo request. */
if((GET8(ip_pkt, IP_PROTOCOL_OFFSET) == IP_ICMP_PROT) &&
((type != (ICMP_ECHOREPLY))))
{
if ( type != ICMP_REDIRECT)
return;
}
/* Do not send an error in response to a broadcast packet. */
if(buf_ptr->mem_flags & (NET_BCAST | NET_MCAST))
return;
/* Perform aditional verification on the packet. We want to reject the ICMP
error for the same reasons that we refuse to forward a packet. */
if ( IP_Canforward(GET32(ip_pkt, IP_DEST_OFFSET)) != NU_SUCCESS)
return;
/* Allocate a buffer to build the ICMP packet in. */
if ((send_buf = (NET_BUFFER *)MEM_Buffer_Dequeue(&MEM_Buffer_Freelist))== NU_NULL)
{
NERRS_Log_Error (NERR_SEVERE, __FILE__, __LINE__);
SNMP_icmpOutErrors_Inc;
return;
}
send_buf->mem_dlist = &MEM_Buffer_Freelist;
/* Begin filling in ICMP header. */
/* Fill in the type. */
icmp_shdr = (ICMP_LAYER *)(send_buf->mem_parent_packet +
(NET_MAX_ICMP_HEADER_SIZE - sizeof (ICMP_LAYER)));
PUT8(icmp_shdr, ICMP_TYPE_OFFSET, (UINT8)type);
if (type == ICMP_REDIRECT)
{
PUT32(icmp_shdr, ICMP_GWADDR_OFFSET, dest);
SNMP_icmpOutRedirects_Inc;
}
else
{
PUT32(icmp_shdr, ICMP_VOID_OFFSET, 0);
if (type == ICMP_PARAPROB)
{
PUT8(icmp_shdr, ICMP_PPTR_OFFSET, (UINT8)code);
code = 0;
SNMP_icmpOutParmProbs_Inc;
}
else if ( (type == ICMP_UNREACH) &&
(code == ICMP_UNREACH_NEEDFRAG && device) )
{
PUT16(icmp_shdr, ICMP_NEXTMTU_OFFSET, (INT16)device->dev_mtu);
SNMP_icmpOutDestUnreachs_Inc;
}
}
PUT8(icmp_shdr, ICMP_CODE_OFFSET, (UINT8)code);
/* Copy the old IP packet into the data portion of the ICMP packet. */
/* It would be simpler and more efficient to copy yhe data straight from the
original IP packet to the ICMP packet. However, that will not work on
DSPs. Hence the two copies below. */
GET_STRING(ip_pkt, 0, temp_buf, sizeof(IPLAYER) + 8);
PUT_STRING(icmp_shdr, ICMP_IP_OFFSET, temp_buf, sizeof(IPLAYER) + 8);
/* Point to where the new IP header should begin. */
send_buf->data_ptr = (UINT8 *)icmp_shdr - sizeof(IPLAYER);
/* Copy the IP header. */
memcpy(send_buf->data_ptr, ip_pkt, sizeof(IPLAYER));
send_buf->data_ptr = (UINT8 *)icmp_shdr;
send_buf->mem_buf_device = device;
/* The size of the data so far is the sizof(ICMP_LAYER) + 8. At first
it might seem that 20 bytes for the IP header that is part of the
ICMP data needs to added as well. However, that 20 bytes is included
in ICMP_LAYER. */
send_buf->mem_total_data_len = sizeof(ICMP_LAYER) + 8;
send_buf->data_len = sizeof(ICMP_LAYER) + 8;
ICMP_Reflect(send_buf);
} /* ICMP_Send_Error */
/***********************************************************************
*
* FUNCTION
*
* ICMP_Reflect
*
* DESCRIPTION
*
* Send an ICMP echo response.
*
* INPUTS
*
* buf_ptr
*
* OUTPUTS
*
* None.
*
*************************************************************************/
VOID ICMP_Reflect(NET_BUFFER *buf_ptr)
{
IPLAYER *ip_pkt;
UINT32 t, icmpsrc;
DV_DEVICE_ENTRY *temp_dev;
ICMP_LAYER *icmp_l;
STATUS stat;
/* Point to the ICMP packet. */
ip_pkt = (IPLAYER *)(buf_ptr->data_ptr - sizeof (IPLAYER));
/* Keep a copy of the original destination. */
t = GET32(ip_pkt, IP_DEST_OFFSET);
/* Make the source the new destination. */
PUT32(ip_pkt, IP_DEST_OFFSET, GET32(ip_pkt, IP_SRC_OFFSET) );
/* Set the new source address. If an exact math can not be found then use
the source address for the receiving interface. */
for(temp_dev = DEV_Table.dv_head;
temp_dev;
temp_dev = temp_dev->dev_next)
{
/* Is there an exact match on the IP address. */
if ( temp_dev->dev_addr.dev_ip_addr == t)
break;
}
/* If a match was found use the IP address for that device, else use the IP
address for the receiving device. */
if (temp_dev)
icmpsrc = temp_dev->dev_addr.dev_ip_addr;
else
icmpsrc = buf_ptr->mem_buf_device->dev_addr.dev_ip_addr;
/* Compute the ICMP checksum. */
icmp_l = (ICMP_LAYER *)(buf_ptr->data_ptr);
PUT16(icmp_l, ICMP_CKSUM_OFFSET, 0);
PUT16(icmp_l, ICMP_CKSUM_OFFSET, TLS_IP_Check_Buffer_Chain (buf_ptr));
/* Send this packet. */
stat = IP_Send(buf_ptr, NU_NULL, GET32(ip_pkt, IP_DEST_OFFSET),
icmpsrc, NU_NULL, IP_TIME_TO_LIVE, IP_ICMP_PROT, 0, NU_NULL);
if (stat != NU_SUCCESS)
{
/* 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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -