コード例 #1
0
ファイル: ipcom_sysvar.c プロジェクト: rgmabs19357/Huawei-
/*
 *===========================================================================
 *                    ipcom_sysvar_pqueue_insert_cb
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 */
IP_STATIC void
ipcom_sysvar_pqueue_insert_cb(Ipcom_sysvar_entry *s, Ipcom_pqueue *pq)
{
    s->refcount++;
    ipcom_pqueue_insert(pq, s);
}
コード例 #2
0
/*
 *===========================================================================
 *                    ipnet_gre_input
 *===========================================================================
 * Description: Handler for received GRE packets.
 * Parameters:  pkt - Received GRE packet.
 * Returns:     0 = success, <0 = error code.
 *
 */
IP_GLOBAL int
ipnet_gre_input(Ipnet_netif *netif, Ipcom_pkt *pkt)
{
    Ipnet_pkt_gre *gre_hdr;
    int            gre_hdr_start = pkt->start;

    IP_BIT_CLR(pkt->flags, IPCOM_PKT_FLAG_IPV4 | IPCOM_PKT_FLAG_IPV6);
    gre_hdr = (Ipnet_pkt_gre *)&pkt->data[pkt->start];
    pkt->start += IPNET_GRE_HDR_SIZE;

    /* First 16-bits non-null, verify bits and version. */
    if (gre_hdr->flags_reserved0_ver)
    {
        /* RFC 2784: 2.3. Reserved0 (bits 1-12)
           A receiver MUST discard a packet where any of bits 1-5 are non-zero,
           unless that receiver implements RFC 1701. Bits 6-12 are reserved for
           future use. These bits MUST be sent as zero and MUST be ignored on
           receipt.

           RFC 2890: 2. Extensions to GRE Header
           Key present (bit 2)
           Sequence Number Present (bit 3)
        */
        if (IP_BIT_ISSET(gre_hdr->flags_reserved0_ver, IPNET_GRE_FLAG_MUSTBE0))
            goto cleanup;

        /* RFC 2784: 2.3.1. Version Number (bits 13-15)
           The Version Number field MUST contain the value zero.
        */
        if (IP_BIT_ISSET(gre_hdr->flags_reserved0_ver, IPNET_GRE_FLAG_VERSION))
            goto cleanup;

        /* RFC 2784: 2.5. Checksum (2 octets)
           The Checksum field contains the IP (one's complement) checksum sum of
           the all the 16 bit words in the GRE header and the payload packet.
           For purposes of computing the checksum, the value of the checksum
           field is zero. This field is present only if the Checksum Present bit
           is set to one.
        */
        if (IPNET_GRE_CHECKSUM_PRESENT(gre_hdr))
        {
            pkt->start += IPNET_GRE_OPT_CSUM_SIZE;

            /* IP checksum must be ok. */
            if (ipcom_in_checksum(&gre_hdr->flags_reserved0_ver, pkt->end - gre_hdr_start) != 0)
                goto cleanup;
        }

#ifdef IPNET_USE_RFC2890
        /* RFC 2890: 2.1. Key Field (4 octets)
           The Key field contains a four octet number which was inserted by the
           encapsulator. The actual method by which this Key is obtained is
           beyond the scope of the document. The Key field is intended to be
           used for identifying an individual traffic flow within a tunnel. For
           example, packets may need to be routed based on context information
           not present in the encapsulated data.  The Key field provides this
           context and defines a logical traffic flow between encapsulator and
           decapsulator.  Packets belonging to a traffic flow are encapsulated
           using the same Key value and the decapsulating tunnel endpoint
           identifies packets belonging to a traffic flow based on the Key Field
           value.
        */
        if (IPNET_GRE_KEY_PRESENT(gre_hdr))
        {
            Ip_u32 key;

            key = IP_GET_NTOHL(&pkt->data[pkt->start]);
            IPNET_GRE_PKT_SET_KEY(pkt, key);
            pkt->start += IPNET_GRE_OPT_KEY_SIZE;
        }

        /* RFC 2890: 2.2. Sequence Number (4 octets)
           The Sequence Number field is a four byte field and is inserted by the
           encapsulator when Sequence Number Present Bit is set. The Sequence
           Number MUST be used by the receiver to establish the order in which
           packets have been transmitted from the encapsulator to the receiver.
           The intended use of the Sequence Field is to provide unreliable but
           in-order delivery. If the Key present bit (bit 2) is set, the
           sequence number is specific to the traffic flow identified by the Key
           field. Note that packets without the sequence bit set can be
           interleaved with packets with the sequence bit set.
        */
        if (IPNET_GRE_SEQNUM_PRESENT(gre_hdr))
        {
            Ipnet_gre_t *gre = netif->ipcom.pdrv;
            Ip_u32       seqnum;

            seqnum = IP_GET_NTOHL(&pkt->data[pkt->start]);
            if (seqnum == gre->recv_seqnum)
                /* In order segment */
                ++gre->recv_seqnum;
            else if (IPCOM_IS_LT(seqnum, gre->recv_seqnum))
                /* Out of order */
                goto cleanup;
            else
            {
                Ip_u32 outoforder_timer;
                int max_perflow_buffer;

                max_perflow_buffer = ipcom_sysvar_get_as_int0("ipnet.gre.MAX_PERFLOW_BUFFER", 3);
                outoforder_timer = ipcom_sysvar_get_as_int0("ipnet.gre.OUTOFORDER_TIMER", 1000);

                if (max_perflow_buffer <= 0)
                    /* No buffering allowed */
                    goto cleanup;

                while (ipcom_pqueue_size(gre->reassembly_queue) >= max_perflow_buffer)
                {
                    ipnet_timeout_cancel(gre->reassembly_tmo);
                    /* Call the timeout handler to force the oldest packet(s)
                       to be inputted to the stack and the receive sequence
                       number to advanced */
                    ipnet_gre_seq_tmo(netif);
                }

                if (gre_hdr->protocol_type == ip_htons(0x0800))
                    IP_BIT_SET(pkt->flags, IPCOM_PKT_FLAG_IPV4);
                else if (gre_hdr->protocol_type == ip_htons(0x86DD))
                    IP_BIT_SET(pkt->flags, IPCOM_PKT_FLAG_IPV6);

                IPNET_PKT_SET_TIMEOUT_ABS(pkt, ipnet->msec_now + outoforder_timer);
                if (gre->reassembly_tmo == IP_NULL)
                    if (ipnet_timeout_schedule(outoforder_timer,
                                               (Ipnet_timeout_handler) ipnet_gre_seq_tmo,
                                               netif,
                                               &gre->reassembly_tmo) < 0)
                        goto cleanup;
                if (ipcom_pqueue_insert(gre->reassembly_queue, pkt) != IPCOM_SUCCESS)
                {
                    ipnet_timeout_cancel(gre->reassembly_tmo);
                    goto cleanup;
                }
                return 0;
            }
            pkt->start += IPNET_GRE_OPT_SEQNUM_SIZE;
        }
#endif /* IPNET_USE_RFC2890 */
    }

    /**/
    if (netif->ipcom.link_tap)
        /* start is PAYLOAD == the inner IP header; ipstart points to the PREVIOUS
         * IP header */
        netif->ipcom.link_tap(&netif->ipcom, pkt, IP_PACKET_HOST, gre_hdr->protocol_type, pkt->start, pkt->start);

#ifdef IPCOM_USE_INET
    /* IPv4 in GRE. */
    if (gre_hdr->protocol_type == ip_htons(0x0800))
        return ipnet_ip4_input(netif, pkt);
#endif

#ifdef IPCOM_USE_INET6
    /* IPv6 in GRE. */
    if (gre_hdr->protocol_type == ip_htons(0x86DD))
        return ipnet_ip6_input(netif, pkt);
#endif

    /* Unsupported Protocol Type, drop. */

 cleanup:
    ipcom_pkt_free(pkt);
    return -IP_ERRNO_EINVAL;
}