📄 ip.c
字号:
}
/* silently toss this legal-but-useless packet */
if (iplen <= hlen)
{
/* 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 IP packets received with header errors. */
SNMP_ipInHdrErrors_Inc;
return (1);
}
/*
* See if there are any IP options to be handled.
* We don't understand IP options, post a warning to the user and drop
* the packet.
*/
/* check for options in packet */
if (hlen > sizeof (IPLAYER))
{
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);
/* Increment the number of IP packets received with header errors. */
SNMP_ipInHdrErrors_Inc;
return (1);
} /* end if */
/* The following loop checks to see if the packet is for us. A match occurs
if the destination IP matches one of our IP addresses or if it is a
broadcast address on a device that supports broadcasting.
*/
for(temp_dev = DEV_Table.dv_head;
temp_dev != NU_NULL;
temp_dev = temp_dev->dev_next)
{
/* Is there an exact match on the IP address. */
if (temp_dev->dev_addr.dev_ip_addr == GET32(pkt, IP_DEST_OFFSET))
break;
/* If the current device is the same one the packet was received on and
the device supports broadcast packets check for a match on supported
broadcast addresses.
*/
if ( (temp_dev == device) && (temp_dev->dev_flags & DV_BROADCAST) )
{
/* If the destination is either of the broadcast addresses,
then keep it.
*/
if ( (GET32(pkt, IP_DEST_OFFSET) == 0) ||
(GET32(pkt, IP_DEST_OFFSET) == IP_ADDR_BROADCAST) )
{
break;
}
/* Is this a broadcast for our network. */
if (temp_dev->dev_addr.dev_net == GET32(pkt, IP_DEST_OFFSET))
break;
if (temp_dev->dev_addr.dev_net_brdcast == GET32(pkt, IP_DEST_OFFSET))
break;
}
}
/* If this is a NAT Router, call the NAT routine */
#if (INCLUDE_NAT == NU_TRUE)
if (IP_NAT_Initialize)
{
if ((status = NAT_Translate(device, &pkt, &buf_ptr)) == NU_SUCCESS)
return (status);
else if (status != NAT_NO_NAT)
{
/* Drop it. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
return (1);
}
}
#endif
#if ((INCLUDE_DHCP == NU_TRUE) || (INCLUDE_BOOTP == NU_TRUE))
/* Before this packet is rejected check to see if the device has an
IP_address. If not then pass it to UDP. It could be a DHCP response
packet.
*/
if ( !(device->dev_flags & DV_UP) )
{
if (GET8(pkt, IP_PROTOCOL_OFFSET) == IP_UDP_PROT)
{
temp_dev = device;
}
}
#endif /* ((INCLUDE_DHCP == NU_TRUE) || (INCLUDE_BOOTP == NU_TRUE)) */
/* If the destination IP address did not match any of ours, then check to
see if it is destined for a multicast address. */
if (!temp_dev)
{
if (IP_MULTICAST_ADDR(GET32(pkt, IP_DEST_OFFSET)))
{
#if INCLUDE_IP_MULTICASTING
/* NOTE: If/when multicast routing support is added it will need to
be handled here. */
/* Do we belong to the multicast group on the receive device. */
ipm = IP_Lookup_Multi( GET32(pkt, IP_DEST_OFFSET), &device->dev_addr);
if (ipm != NU_NULL)
/* We belong to the multicast group. Set temp_dev so the checks
below will be passed. */
temp_dev = device;
#else
/* Multicasting support was not desired so drop the packet by
placing it back on the buffer_freelist. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
SNMP_ipInAddrErrors_Inc;
return (1);
#endif /* INCLUDE_IP_MULTICASTING */
}
}
if (!temp_dev)
{
#if INCLUDE_IP_FORWARDING
/* This packet is not for us. Attempt to forward the packet if
possible. */
/* Remove the buffer that we have been processing from the buffer_list.
The IP forwarding function will handle the deallocation. */
buf_ptr = (NET_BUFFER *)MEM_Buffer_Dequeue(&MEM_Buffer_List);
/* Initialize the deallocation list pointer. */
buf_ptr->mem_dlist = &MEM_Buffer_Freelist;
if (IP_Forwarding)
IP_Forward(buf_ptr);
else
{
/* Increment the number of IP packets received with the wrong IP addr.*/
SNMP_ipInAddrErrors_Inc;
/* Drop it. */
MEM_One_Buffer_Chain_Free(buf_ptr, buf_ptr->mem_dlist);
}
#else
/* Increment the number of IP packets received with the wrong IP addr.*/
SNMP_ipInAddrErrors_Inc;
/* Drop it. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
#endif
return (1);
}
#if INCLUDE_IP_REASSEMBLY
/* If offset or IP_MF are set then this is a fragment and we must
reassemble. */
if (GET16(pkt, IP_FRAGS_OFFSET) & ~IP_DF)
{
/* Increment the number of IP fragments that have been received. */
SNMP_ipReasmReqds_Inc;
/* Search the list of fragmented packets to see if at least one fragment
from the same packet was previously received. */
for (fp = IP_Frag_Queue.ipq_head; fp != NU_NULL; fp = fp->ipq_next)
{
/* Fragments are uniquely identified by IP id, source address,
destination address, and protocol. */
if ( (GET16(pkt, IP_IDENT_OFFSET) == fp->ipq_id) &&
(GET32(pkt, IP_SRC_OFFSET) == fp->ipq_source) &&
(GET32(pkt, IP_DEST_OFFSET) == fp->ipq_dest) &&
(GET8(pkt, IP_PROTOCOL_OFFSET) == fp->ipq_protocol) )
{
break;
}
}
ip = pkt;
/* Adjust the IP length to not refelect the header. */
PUT16(ip, IP_TLEN_OFFSET, (UINT16)(GET16(ip, IP_TLEN_OFFSET) - hlen));
/* Set ipf_mff if more fragments are expected. */
PUT8(ip, IPF_MFF_OFFSET, (UINT8)(GET8(ip, IPF_MFF_OFFSET) & ~1));
if (GET16(ip, IP_FRAGS_OFFSET) & IP_MF)
PUT8(ip, IPF_MFF_OFFSET, (UINT8)(GET8(ip, IPF_MFF_OFFSET) | 1));
/* Convert the offset of this fragment to bytes and shift off the 3 flag bits. */
PUT16(ip, IP_FRAGS_OFFSET, (INT16)(GET16(ip, IP_FRAGS_OFFSET) << 3) );
/* If this datagram is marked as having more fragments or this is not the
first fragment, attempt reassembly. */
if (GET8(ip, IPF_MFF_OFFSET) & 1 || GET16(ip, IP_FRAGS_OFFSET) )
{
a_buf = IP_Reassembly((IP_FRAG *)ip, fp, buf_ptr);
if (a_buf == NU_NULL)
{
/* A complete packet could not yet be assembled, return. */
return (1);
}
/* If we make it here then a framented packet has been put back together. We need
to set all pointers and other local variables to match what they would normally
be if this packet was simply a RX packet and not a reasembled one. */
/* Point the buffer pointer to the buffer of the reasembled packet. */
buf_ptr = a_buf;
/* Set the IP packet pointer to the IP header. */
pkt = (IPLAYER *) buf_ptr->data_ptr;
/* Get the header length. */
hlen = (UINT16)((GET8(pkt, IP_VERSIONANDHDRLEN_OFFSET) & 0x0f) << 2);
/* Strip off the IP header. */
buf_ptr->mem_total_data_len -= hlen;
buf_ptr->data_len -= hlen;
buf_ptr->data_ptr += hlen;
/* Increment the number of IP fragmented packets that have
successfully been reasmebled. */
SNMP_ipReasmOKs_Inc;
}
else if (fp)
{
IP_Free_Queue_Element(fp);
/* Drop this packet. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
SNMP_ipInHdrErrors_Inc;
return (1);
}
}
#else
/* If the processing of fragments is not desired, then drop this packet. */
/* If offset and IP_MF are set then this is a fragment. */
if (GET16(pkt, IP_FRAGS_OFFSET) & ~IP_DF)
{
/* Increment the number of IP fragments that have been received,
even though we don't process them. */
SNMP_ipReasmReqds_Inc;
/* Drop the current buffer. */
MEM_Buffer_Chain_Free (&MEM_Buffer_List, &MEM_Buffer_Freelist);
SNMP_ipInDiscards_Inc;
return(1);
}
#endif
else /* This is not a fragment. */
{
/* Strip off the IP header. */
buf_ptr->mem_total_data_len -= hlen;
buf_ptr->data_len -= hlen;
buf_ptr->data_ptr += hlen;
}
/* Create the pseudo tcp header for upper layer protocols to
compute their checksum */
/* The GET32 macro automatically puts the addresses in the native
architectures byte order. In this case we wish to keep the addresses in
big endian or network byte order. So swap the values returned by GET32. */
tcp_chk.source = LONGSWAP(GET32(pkt, IP_SRC_OFFSET));
tcp_chk.dest = LONGSWAP(GET32(pkt, IP_DEST_OFFSET));
tcp_chk.z = 0;
tcp_chk.proto = GET8(pkt, IP_PROTOCOL_OFFSET);
tcp_chk.tcplen = (UINT16)INTSWAP((UINT16)buf_ptr->mem_total_data_len);
/* which protocol to handle this packet? */
switch (GET8(pkt, IP_PROTOCOL_OFFSET))
{
#if (INCLUDE_UDP == NU_TRUE)
case IP_UDP_PROT:
/* Increment the number of IP packets successfully delivered. */
SNMP_ipInDelivers_Inc;
return (UDP_Interpret(buf_ptr, &tcp_chk));
#endif
#if (INCLUDE_TCP == NU_TRUE)
case IP_TCP_PROT:
/* Increment the number of IP packets successfully delivered. */
SNMP_ipInDelivers_Inc;
/* pass tcplen on to TCP */
return (TCP_Interpret(buf_ptr, &tcp_chk));
#endif
case IP_ICMP_PROT:
/* Increment the number of IP packets successfully delivered. */
SNMP_ipInDelivers_Inc;
return (ICMP_Interpret(buf_ptr, GET32(pkt, IP_SRC_OFFSET)));
#if (INCLUDE_IP_MULTICASTING == NU_TRUE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -