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

📄 ip.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
    }

    /* 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 + -