⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nat_rx.c

📁 VXWORKS NAT 部分源代码3 有兴趣朋友可以参考下
💻 C
📖 第 1 页 / 共 2 页
字号:
	
	switch (nat_packet_type)
	{
		case NAT_TCP:
			return_code = handle_tcp_translation_global_rx ((TCP_PACKET*)p_packet);
			break;
		case NAT_ICMP_DATAGRAM:
			
			return_code = handle_icmp_translation_global_rx_datagram ((ICMP_PACKET*)p_packet);
			
			break;
		case NAT_ICMP_TRANSACTION:
			return_code = handle_icmp_translation_global_rx_transaction ((ICMP_PACKET*)p_packet);
			break;
		case NAT_RIP:
		case NAT_UDP:
			return_code = handle_udp_translation_global_rx ((UDP_PACKET*)p_packet);
			break;
		case NAT_UNKNOWN_PROTOCOL:
			if (nat.filter_unknown_protocols == TRUE)
			{
				return_code = FAIL;
			}
			else
			{
				return_code = TRUE;
			}
			break;
		default:
			return_code = FAIL;
	}
	
	return (return_code);
}

/********************************************************************************************
	This function handles translation of outbound packets (i.e. received from local port).
********************************************************************************************/
static enum TEST nat_handle_translation_for_local_rx (M_BLK* pMblk,
	enum NAT_PACKET_TYPES nat_packet_type)
{
	enum TEST return_code;

	/* none of the following functions currently use the port_number passed */
		
	switch (nat_packet_type)
	{
		case NAT_TCP:
			return_code = handle_tcp_translation_local_rx (
				(TCP_PACKET *) pMblk->mBlkHdr.mData);
			break;
		case NAT_ICMP_DATAGRAM:
			return_code = handle_icmp_translation_local_rx_datagram (
				(ICMP_PACKET *) pMblk->mBlkHdr.mData);
			break;
		case NAT_ICMP_TRANSACTION:
			return_code = handle_icmp_translation_local_rx_transaction (
				(ICMP_PACKET *) pMblk->mBlkHdr.mData);
			break;
		case NAT_RIP:
		case NAT_UDP:
			return_code = handle_udp_translation_local_rx (
				(UDP_PACKET *) pMblk->mBlkHdr.mData);
			break;
		case NAT_UNKNOWN_PROTOCOL:
			if (nat.filter_unknown_protocols == TRUE)
			{
				return_code = FAIL;
			}
			else
			{
				return_code = TRUE;
			}
			break;
		default:
			return_code = FAIL;
	}

	return (return_code);
}

/*************************************************************************************
Description:
	Look for a registered agent (e.g. ALG) from the given NAT instance.
*************************************************************************************/
NAT_AGENT_INFO *nat_find_agent(
	NAT_CLASS	*nat_p,
	u_short		protocol,
	u_long		remote_port,
	u_long		local_port
	)
{
	NAT_AGENT_INFO	*agent_info;
	
        semTake(agentListLock, WAIT_FOREVER);

        agent_info = (NAT_AGENT_INFO *) lstFirst(&nat.agent_list);

	while (agent_info != NULL)
	    {
	    if (agent_info->session_tag.protocol == protocol && 
		(agent_info->session_tag.transport == remote_port || 
		 agent_info->session_tag.transport == local_port))
		{
		nat_printf (NAT_PRINTF_TRACE, 
			    "Registered agent found for port %d\n", 
			    agent_info->session_tag.transport);
		break;
		}
	    agent_info = (NAT_AGENT_INFO *) lstNext((NODE*)agent_info);
	    }
	semGive(agentListLock);
        return (agent_info);
}

/******************************************************************************
*
* natIcmpErrorHookAdd - Install the NAT ICMP error handling routine
*
*/

void natIcmpErrorHookAdd (void)
    {
    if (_icmpErrorHook != NULL)
        {
        stdIcmpErrorHook = _icmpErrorHook;
        _icmpErrorHook = (VOIDFUNCPTR)natIcmpErrorHook;
        }
    else
        nat_printf (NAT_PRINTF_ERROR,
                    "natIcmpErrorHookAdd Error: _icmpErrorHook is NULL\n");
    }

/******************************************************************************
*
* natIcmpErrorHookRemove - Remove the NAT ICMP error handling routine
*
*/

void natIcmpErrorHookRemove (void)
    {
    if (stdIcmpErrorHook != NULL)
        _icmpErrorHook = stdIcmpErrorHook;
    }

/*****************************************************************************
*
* natIcmpErrorHook - Process the ICMP error message generated by the stack
*
* This routine handles the ICMP error message generated by the NAT device's
* own IP stack on the NAT translated packets. Consider this scenario:
* a TCP/UDP packet enters the NAT device via global port, is translated by NAT,
* and is handed to the IP stack.  But the IP stack can't deliver the packet to 
* the local port because of an error condition (e.g., MTU size is too small
* and the don't fragment bit is set).  The IP stack then constructs an
* ICMP error message (e.g., destination unreachable) with the embedded 
* fragment of the offending packet. However, this fragment must be retranslated 
* back to its global address before sending it out to the driver. Otherwise it
* will have incorrect local address. The same scenario can happen for a TCP/UDP 
* packet coming from a NAT device's local port. In this case, if we don't
* retranslate the packet, it will possibly have the NAT device's own global 
* interface address as the destination address, thus will be wrongly sent to
* the loopback interface.
*
* To solve the problem, this routine will first convert the NAT translated 
* packet back to the original and then hand to the standard ICMP error handling
* routine. This requires the standard ICMP error handle hook to be
* installed with this new routine and the original one is called within
* this routine.
*
*/

void natIcmpErrorHook 
    (
    M_BLK_ID  pMblk, /* orginal IP packet */  
    int type,        /* ICMP type */
    int code,        /* ICMP code */
    ULONG dest,
    struct ifnet *destifp
    )
    {
    struct ifnet * pIf;

    /* convert back the NAT translated packet to the original  */

    pIf = pMblk->m_pkthdr.rcvif;

    natTranslatedIpPacketConvert(pMblk,pIf,type);

    /* call the standard ICMP error handling routine */

    (*stdIcmpErrorHook)(pMblk,type,code,dest,destifp);
    }

/******************************************************************************
*
* natTranslatedIpPacketConvert - convert back the NAT translated packet
*
* This routine converts the NAT translated packet back to the original as if it
* was not translated. When the packet pointed to by parameter pMblk arrives at
* this function. It has already been translated by NAT filter. That means the
* packet's destination,source addresses as well as the port numbers if it
* is a TCP/UDP packet is no longer same as the ones when it came in the network
* port. These elements need to be translated back. Instead of inventing a set
* of reverse translation routines for the TCP,UDP or other packet headers, we
* find it easy to constructs an ICMP packet with necessary fields and copy the
* packet header as the payload of the ICMP packet, and then utilize existing
* NAT ICMP translation routines to perfrom the conversion.
*
* The converted packet header will be copied back to the original packet. The  
* caller of this routine takes it and then call the standard ICMP error 
* handling routine. And a real ICMP packet will be constructed there.  
*
* This routine must also take consideration of the ICMP error messages generated
* on the packets which are not touched by the NAT translation filter, are now
* also intercepted by this new NAT ICMP error handling routine. They must not
* be erroneously translated. 
*
*/

LOCAL void natTranslatedIpPacketConvert
    (
    M_BLK_ID  pMblk,    /* original IP packet */
    struct ifnet * pIf, /* network interface the packet coming from */
    int type
    )
    {
    M_BLK_ID pTmpMblk;
    ICMP_PACKET * pIcmpPkt;
    IP_PACKET * pIpPacket;
    ULONG address;
    int inx;
    enum NAT_PORT_TYPE icmpPortType;
    enum TEST retCode;
    char ifName[IF_DEV_NAME_LEN];

    /* filter out non NAT related packets */

    if (nat.enabled == FALSE || pIf == NULL)
        return;   /* no translation */

    inx = 0;
    while ((pIf->if_name[inx]) && (inx < (IF_DEV_NAME_LEN - 2)) )
        ifName[inx] = pIf->if_name[inx++];
        
    ifName[inx++] = '0' + pIf->if_unit;
    ifName[inx++] = 0;

    /* find this packet is coming from global or local interface or neither */

    for (inx = 0; inx < sizeof(nat.port)/sizeof(nat.port[0]); inx++)
        {
        if ((nat.port[inx].ifunit == pIf) ||
	    ((nat.port[inx].ifunit == NULL) &&  /* dynamically attached IF */
	     (strcmp(nat.port[inx].ifname,ifName)==0)) )
            {
            /* Found the port */
            break;
            }
        }

    if (inx == sizeof(nat.port)/sizeof(nat.port[0]))

        /* no port found, the packet does not come from a NAT port  */
        return;  /* no translation */

    /* allocate a mblk to hold the temp ICMP packet */

    pTmpMblk = netTupleGet(_pNetDpool, 128,M_DONTWAIT,MT_DATA,TRUE);

    if (pTmpMblk == NULL)
        {
        nat_printf (NAT_PRINTF_ERROR,
                    "natIcmpErrorHook: Can't get a mblk\n");
        return;
        }

    /* construct an incomplete ICMP header, good enough for the NAT ICMP
     * translation
     */

    pIcmpPkt = (ICMP_PACKET *)(pTmpMblk->mBlkHdr.mData);
    bcopy((char *)pMblk->mBlkHdr.mData,(char *)&pIcmpPkt->ip_header,
	  sizeof(IP_HEADER));
    pIcmpPkt->ip_header.protocol = IPPROTO_ICMP;

    /* construct the ICMP error packet's destination and source addresses */

    address = pIcmpPkt->ip_header.source_address;
    pIcmpPkt->ip_header.source_address =pIcmpPkt->ip_header.destination_address;
    pIcmpPkt->ip_header.destination_address = address;

    pIcmpPkt->ip_header.total_length = htons(80);  /* fake one */ 
    pIcmpPkt->header.checksum = 0x1122;  /* fake one */
    pIcmpPkt->header.type     = type;

    /* The ICMP error packet generated by this NAT deivce's IP stack on the
     * packet coming from the NAT global port just looks as if a ICMP error
     * packet coming from the NAT local interface and vice versa, as far as
     * the NAT translation filter concerns.
     */

    /* so reverse the port type */

    if (nat.port[inx].type == NAT_GLOBAL_PORT)
	icmpPortType = NAT_LOCAL_PORT;
    else
	icmpPortType = NAT_GLOBAL_PORT;

    /* Further checking whether this packet needs to be translated back */

    if (nat_filter_rx(ntohl(pIcmpPkt->ip_header.destination_address),
		      inx, icmpPortType) != NAT_TRANSLATE)
        {
        netMblkClFree(pTmpMblk);
        return;   /* no translation */
        }

    /* copy the original IP and TCP headers  */

    bcopy((char *)pMblk->mBlkHdr.mData,
	  (char *)&pIcmpPkt->header.option.unreachable_message.ip_data,
	  sizeof(IP_HEADER) + sizeof(TCP_HEADER));

    /* perform the translation */

    if (icmpPortType == NAT_GLOBAL_PORT)
        {
        retCode = nat_handle_translation_for_global_rx(
                        (IP_PACKET *)(pTmpMblk->mBlkHdr.mData),
                        NAT_ICMP_DATAGRAM);
        }
    else
        {
        retCode = nat_handle_translation_for_local_rx(pTmpMblk,
			   NAT_ICMP_DATAGRAM);
        }

    if (retCode == FAIL)
	{
	/* again this packet is not translated by NAT, simply return */

        netMblkClFree(pTmpMblk);
        return;
        }

    /* now translation is done, copy it back to the original mblk */

    bcopy((char *)&pIcmpPkt->header.option.unreachable_message.ip_data,
              (char *)pMblk->mBlkHdr.mData,
	      sizeof(IP_HEADER) + sizeof(TCP_HEADER));

    /* the IP header checksum is most likely not correct due to the fact the 
     * ipintr zeroed it in the default configuration. Recalculate it.
     */
    pIpPacket = (IP_PACKET*) pMblk->mBlkHdr.mData;

    /* The total length is already in host byte order, convert it back */

    pIpPacket->header.total_length = htons(pIpPacket->header.total_length);

    /* the offset is already in host byte order, convert it back */

    pIpPacket->header.fragment = htons(pIpPacket->header.fragment);

    /* do the checksum calculation */
 
    pIpPacket->header.header_checksum = 0;
    pIpPacket->header.header_checksum = in_cksum(pMblk,
                   pIpPacket->header.version_header_length.header_length << 2);

    /* the icmp_error will add IP header length to the total length field
     * and assume the id field is in host byte order. So we need to set proper
     * values for these two fields here before feeding to the icmp_error.
     */

    pIpPacket->header.total_length = ntohs(pIpPacket->header.total_length);
    pIpPacket->header.total_length -= 
           (pIpPacket->header.version_header_length.header_length << 2);

    pIpPacket->header.identifier = ntohs(pIpPacket->header.identifier);
    pIpPacket->header.fragment = ntohs(pIpPacket->header.fragment);

    /* free the allocated temporary mblk */

    netMblkClFree(pTmpMblk);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -