📄 ip.c
字号:
case IP_IGMP_PROT :
/* Increment the number of IP packets successfully delivered. */
SNMP_ipInDelivers_Inc;
return (IGMP_Interpret(buf_ptr, (INT)hlen));
#endif
#if (INCLUDE_IP_RAW == NU_TRUE)
case IP_RAW_PROT :
case IP_HELLO_PROT :
case IP_OSPF_PROT :
/** Any additional Raw IP protocols that are supported in the
future must have a case here ***/
return (IPRaw_Interpret((NET_BUFFER *)buf_ptr, device));
#endif
default:
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 a invalid
protocol field. */
SNMP_ipInUnknownProtos_Inc;
return (1);
} /* end switch */
} /* IP_Interpret */
/***********************************************************************
*
* FUNCTION
*
* IP_Send
*
* DESCRIPTION
*
* Send an IP packet.
*
* INPUTS
*
* buf_ptr
* ro
* dest_ip
* src_ip
* flags
* ttl
* protocol
* tos
* mopt
*
* OUTPUTS
*
* NU_HOST_UNREACHABLE
* NU_ACCESS
* NU_MSGSIZE
*
*************************************************************************/
STATUS IP_Send(NET_BUFFER *buf_ptr, RTAB_ROUTE *ro, UINT32 dest_ip,
UINT32 src_ip, INT32 flags, INT ttl, INT protocol, INT tos,
IP_MULTI_OPTIONS *mopt)
{
IPLAYER *ip_dgram;
INT hlen = sizeof (IPLAYER);
DV_DEVICE_ENTRY *int_face;
RTAB_ROUTE iproute;
SCK_SOCKADDR_IP *dest;
STATUS status;
#if (INCLUDE_IP_MULTICASTING == NU_FALSE)
UNUSED_PARAMETER(mopt);
#endif
/* Here use a macro to resolve get a pointer to the IP header. */
ip_dgram = IP_BUFF_TO_IP(buf_ptr);
/* If this is a forwarded packet or if it is a raw IP packet, then don't
mess with the IP header. */
if (flags & (IP_FORWARDING | IP_RAWOUTPUT))
{
#if INCLUDE_IP_RAW
if (flags & IP_RAWOUTPUT)
{
/* The RAWOUTPUT flag means that the application created
the header. Therefore buffer size will include the size of the
header. The code further down in this function assumes that
the header is not included in the buffer size, thus we
subtract the header size from the buffer size here as it will
be added back further below. */
/* Get a pointer to the user created IP header. */
ip_dgram = (IPLAYER *)buf_ptr->data_ptr;
/* Obtain the length of the user created IP header. */
hlen = (GET8(ip_dgram, IP_VERSIONANDHDRLEN_OFFSET) & 0xf) << 2;
/* Subtract it from the length of the buffer. */
buf_ptr->mem_total_data_len -= hlen;
buf_ptr->data_len -= hlen;
/* One other thing that must be checked since the user created
the IP header is the ID field of the header. If the application
set this field to zero it means that we must generate the
ID here. */
if ( (GET16(ip_dgram, IP_IDENT_OFFSET)) == 0)
/* Set the IP packet ID. */
PUT16(ip_dgram, IP_IDENT_OFFSET, (UINT16)IP_Ident++);
/* Increment the number of IP packets transmitted. NOTE: this does
not include packets that are being forwarded. */
SNMP_ipOutRequests_Inc;
}
else
#endif
{
hlen = (INT16)((GET8(ip_dgram, IP_VERSIONANDHDRLEN_OFFSET) & 0xf) << 2);
buf_ptr->mem_total_data_len = GET16(ip_dgram, IP_TLEN_OFFSET) - hlen;
}
}
else
{
/* Set the IP header length and the IP version. */
PUT8(ip_dgram, IP_VERSIONANDHDRLEN_OFFSET,
(UINT8)((hlen >> 2) | (IP_VERSION << 4)) );
/* Zero out the fragment field */
PUT16(ip_dgram, IP_FRAGS_OFFSET, 0);
/* Set the IP packet ID. */
PUT16(ip_dgram, IP_IDENT_OFFSET, (UINT16)IP_Ident++);
/* Set the type of service. */
PUT8(ip_dgram, IP_SERVICE_OFFSET, (UINT8)tos);
/* Set the total length (data and IP header) of this packet. */
PUT16(ip_dgram, IP_TLEN_OFFSET, (INT16)(buf_ptr->mem_total_data_len + hlen));
/* Set the time to live */
PUT8(ip_dgram, IP_TTL_OFFSET, (UINT8)ttl);
/* Set the protocol. */
PUT8(ip_dgram, IP_PROTOCOL_OFFSET, (UINT8)protocol);
/* Set the destination IP address. */
PUT32(ip_dgram, IP_DEST_OFFSET, dest_ip);
/* Increment the number of IP packets transmitted. NOTE: this does
not include packets that are being forwarded. */
SNMP_ipOutRequests_Inc;
}
/* Update the length and data ptr for the head buffer. */
buf_ptr->data_len += hlen;
buf_ptr->mem_total_data_len += hlen;
buf_ptr->data_ptr = (UINT8 *)ip_dgram;
/* If a route was not provided then point to the temporary
route structure. */
if (ro == NU_NULL)
{
ro = &iproute;
UTL_Zero((CHAR *)ro, sizeof(*ro));
}
/* Point to the destination. */
dest = &ro->rt_ip_dest;
/* Check to see if there is a cached route. If so verify that it is too the
same destination and that it is still up. If it not free it and try
again.
*/
if (ro->rt_route && ( (((ro->rt_route->rt_flags & RT_UP) == 0) ||
(dest->sck_addr != dest_ip)) ||
((!(ro->rt_route->rt_device->dev_flags & DV_RUNNING)) &&
(!(ro->rt_route->rt_device->dev_flags & DV_UP)))))
{
RTAB_Free(ro->rt_route);
ro->rt_route = NU_NULL;
}
if (ro->rt_route == NU_NULL)
{
dest->sck_family = SK_FAM_IP;
dest->sck_len = sizeof (*dest);
dest->sck_addr = dest_ip;
}
/* NOTE: Bypassing routing is not necessary yet, but may be supported in
future releases. */
#ifdef NOT_SUPPORTED
/* Check to see if the caller specified that routing should be bypassed. */
if (flags & IP_ROUTETOIF)
{
}
else
#endif /* NOT_SUPPORTED */
{
if (ro->rt_route == NU_NULL)
IP_Find_Route(ro);
if (ro->rt_route == NU_NULL)
{
/* Return host unreachable error. The only resource allocated in
this function is a route, but we failed to find the route so it
is safe to return here.
*/
/* Increment the number of packets that could not be delivered
because a route could not be found. */
SNMP_ipOutNoRoutes_Inc;
return (NU_HOST_UNREACHABLE);
}
int_face = ro->rt_route->rt_device;
ro->rt_route->rt_use++;
/* If the next hop is a gateway then set the destination ip address to
the gateway. */
if (ro->rt_route->rt_flags & RT_GATEWAY)
dest = &ro->rt_route->rt_gateway;
}
/* Is this packet destined for a multicast address */
if (IP_MULTICAST_ADDR(GET32(ip_dgram, IP_DEST_OFFSET)))
{
#if INCLUDE_IP_MULTICASTING
/* Mark this buffer as containing a multicast packet. */
buf_ptr->mem_flags |= NET_MCAST;
/* IP destination address is multicast. Make sure "dest" still points
to the address in "ro". It may have been changed to point to a
gateway address above
*/
dest = &ro->rt_ip_dest;
/* Did the caller provide any multicast options. */
if (mopt != NU_NULL)
{
/* Use the options provided by the caller. */
PUT8(ip_dgram, IP_TTL_OFFSET, (UINT8)mopt->ipo_ttl);
if (mopt->ipo_device != NU_NULL)
int_face = mopt->ipo_device;
}
else
PUT8(ip_dgram, IP_TTL_OFFSET, (UINT8)IP_DEFAULT_MULTICAST_TTL);
/* Confirm that the outgoing interface supports multicast. */
if ((int_face->dev_flags & DV_MULTICAST) == 0)
{
SNMP_ipOutNoRoutes_Inc;
return (NU_HOST_UNREACHABLE);
}
/* If a source address has not been specified then use the source
address of the outgoing interface. */
if (src_ip == IP_ADDR_ANY)
{
PUT32(ip_dgram, IP_SRC_OFFSET, int_face->dev_addr.dev_ip_addr);
}
else
{
/* Note: this was added because when calculating the UDP */
/* checksum this is needed */
PUT32(ip_dgram, IP_SRC_OFFSET, src_ip);
}
/* NOTE: When multicastLoop Back and/or multicast routing are supported
this is where it should be done. */
#else /* !INCLUDE_IP_MULTICASTING */
/* If multicasting support was not desired then return an error. */
SNMP_ipOutNoRoutes_Inc;
return (NU_HOST_UNREACHABLE);
#endif /* INCLUDE_IP_MULTICASTING */
}
else
{
/* Has a source address been specified? If not use the address of the
outgoing interface. In the current release the source address will
probably always be known at this point. */
if (src_ip != IP_ADDR_ANY)
PUT32(ip_dgram, IP_SRC_OFFSET, src_ip);
else
PUT32(ip_dgram, IP_SRC_OFFSET, int_face->dev_addr.dev_ip_addr);
/* Check for broadcast destination address. If this is a broadcast make
sure the interface supports broadcasting and that the caller enabled
broadcasting.
*/
if (IP_Broadcast_Addr(dest_ip, int_face))
{
/* Does the interface support broadcasting. */
if ( (int_face->dev_flags & DV_BROADCAST) == 0)
return (NU_ACCESS);
/* Did the caller enable broadcasting. */
if ( (flags & IP_ALLOWBROADCAST) == 0)
return (NU_ACCESS);
/* Inform the MAC layer to send this as a link-level broadcast. */
buf_ptr->mem_flags |= NET_BCAST;
}
else
/* Make sure the broadcast flag is clear. */
buf_ptr->mem_flags &= ~NET_BCAST;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -