Annotation of qemu/roms/ipxe/src/net/ndp.c, revision 1.1

1.1     ! root        1: #include <stdint.h>
        !             2: #include <string.h>
        !             3: #include <byteswap.h>
        !             4: #include <errno.h>
        !             5: #include <ipxe/if_ether.h>
        !             6: #include <ipxe/iobuf.h>
        !             7: #include <ipxe/ndp.h>
        !             8: #include <ipxe/icmp6.h>
        !             9: #include <ipxe/ip6.h>
        !            10: #include <ipxe/netdevice.h>
        !            11: 
        !            12: /** @file
        !            13:  *
        !            14:  * Neighbour Discovery Protocol
        !            15:  *
        !            16:  * This file implements address resolution as specified by the neighbour
        !            17:  * discovery protocol in RFC2461. This protocol is part of the IPv6 protocol
        !            18:  * family.
        !            19:  */
        !            20: 
        !            21: /* A neighbour entry */
        !            22: struct ndp_entry {
        !            23:        /** Target IP6 address */
        !            24:        struct in6_addr in6;
        !            25:        /** Link layer protocol */
        !            26:        struct ll_protocol *ll_protocol;
        !            27:        /** Link-layer address */
        !            28:        uint8_t ll_addr[MAX_LL_ADDR_LEN];
        !            29:        /** State of the neighbour entry */
        !            30:        int state;
        !            31: };
        !            32: 
        !            33: /** Number of entries in the neighbour cache table */
        !            34: #define NUM_NDP_ENTRIES 4
        !            35: 
        !            36: /** The neighbour cache table */
        !            37: static struct ndp_entry ndp_table[NUM_NDP_ENTRIES];
        !            38: #define ndp_table_end &ndp_table[NUM_NDP_ENTRIES]
        !            39: 
        !            40: static unsigned int next_new_ndp_entry = 0;
        !            41: 
        !            42: /**
        !            43:  * Find entry in the neighbour cache
        !            44:  *
        !            45:  * @v in6      IP6 address
        !            46:  */
        !            47: static struct ndp_entry *
        !            48: ndp_find_entry ( struct in6_addr *in6 ) {
        !            49:        struct ndp_entry *ndp;
        !            50: 
        !            51:        for ( ndp = ndp_table ; ndp < ndp_table_end ; ndp++ ) {
        !            52:                if ( IP6_EQUAL ( ( *in6 ), ndp->in6 ) && 
        !            53:                     ( ndp->state != NDP_STATE_INVALID ) ) {
        !            54:                        return ndp;
        !            55:                }
        !            56:        }
        !            57:        return NULL;
        !            58: }
        !            59: 
        !            60: /**
        !            61:  * Add NDP entry
        !            62:  * 
        !            63:  * @v netdev   Network device
        !            64:  * @v in6      IP6 address
        !            65:  * @v ll_addr  Link-layer address
        !            66:  * @v state    State of the entry - one of the NDP_STATE_XXX values
        !            67:  */
        !            68: static void 
        !            69: add_ndp_entry ( struct net_device *netdev, struct in6_addr *in6,
        !            70:                void *ll_addr, int state ) {
        !            71:        struct ndp_entry *ndp;
        !            72:        ndp = &ndp_table[next_new_ndp_entry++ % NUM_NDP_ENTRIES];
        !            73: 
        !            74:        /* Fill up entry */
        !            75:        ndp->ll_protocol = netdev->ll_protocol;
        !            76:        memcpy ( &ndp->in6, &( *in6 ), sizeof ( *in6 ) );
        !            77:        if ( ll_addr ) {
        !            78:                memcpy ( ndp->ll_addr, ll_addr, netdev->ll_protocol->ll_addr_len );
        !            79:        } else {
        !            80:                memset ( ndp->ll_addr, 0, netdev->ll_protocol->ll_addr_len );
        !            81:        }
        !            82:        ndp->state = state;
        !            83:        DBG ( "New neighbour cache entry: IP6 %s => %s %s\n",
        !            84:              inet6_ntoa ( ndp->in6 ), netdev->ll_protocol->name,
        !            85:              netdev->ll_protocol->ntoa ( ndp->ll_addr ) );
        !            86: }
        !            87: 
        !            88: /**
        !            89:  * Resolve the link-layer address
        !            90:  *
        !            91:  * @v netdev           Network device
        !            92:  * @v dest             Destination address
        !            93:  * @v src              Source address
        !            94:  * @ret dest_ll_addr   Destination link-layer address or NULL
        !            95:  * @ret rc             Status
        !            96:  *
        !            97:  * This function looks up the neighbour cache for an entry corresponding to the
        !            98:  * destination address. If it finds a valid entry, it fills up dest_ll_addr and
        !            99:  * returns 0. Otherwise it sends a neighbour solicitation to the solicited
        !           100:  * multicast address.
        !           101:  */
        !           102: int ndp_resolve ( struct net_device *netdev, struct in6_addr *dest,
        !           103:                  struct in6_addr *src, void *dest_ll_addr ) {
        !           104:        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        !           105:        struct ndp_entry *ndp;
        !           106:        int rc;
        !           107: 
        !           108:        ndp = ndp_find_entry ( dest );
        !           109:        /* Check if the entry is valid */
        !           110:        if ( ndp && ndp->state == NDP_STATE_REACHABLE ) {
        !           111:                DBG ( "Neighbour cache hit: IP6 %s => %s %s\n",
        !           112:                      inet6_ntoa ( *dest ), ll_protocol->name,
        !           113:                      ll_protocol->ntoa ( ndp->ll_addr ) );
        !           114:                memcpy ( dest_ll_addr, ndp->ll_addr, ll_protocol->ll_addr_len );
        !           115:                return 0;
        !           116:        }
        !           117: 
        !           118:        /* Check if the entry was already created */
        !           119:        if ( ndp ) {
        !           120:                DBG ( "Awaiting neighbour advertisement\n" );
        !           121:                /* For test */
        !           122: //             ndp->state = NDP_STATE_REACHABLE;
        !           123: //             memcpy ( ndp->ll_addr, netdev->ll_addr, 6 );
        !           124: //             assert ( ndp->ll_protocol->ll_addr_len == 6 );
        !           125: //             icmp6_test_nadvert ( netdev, dest, ndp->ll_addr );
        !           126: //             assert ( ndp->state == NDP_STATE_REACHABLE );
        !           127:                /* Take it out till here */
        !           128:                return -ENOENT;
        !           129:        }
        !           130:        DBG ( "Neighbour cache miss: IP6 %s\n", inet6_ntoa ( *dest ) );
        !           131: 
        !           132:        /* Add entry in the neighbour cache */
        !           133:        add_ndp_entry ( netdev, dest, NULL, NDP_STATE_INCOMPLETE );
        !           134: 
        !           135:        /* Send neighbour solicitation */
        !           136:        if ( ( rc = icmp6_send_solicit ( netdev, src, dest ) ) != 0 ) {
        !           137:                return rc;
        !           138:        }
        !           139:        return -ENOENT;
        !           140: }
        !           141: 
        !           142: /**
        !           143:  * Process neighbour advertisement
        !           144:  *
        !           145:  * @v iobuf    I/O buffer
        !           146:  * @v st_src   Source address
        !           147:  * @v st_dest  Destination address 
        !           148:  */
        !           149: int ndp_process_advert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src __unused,
        !           150:                           struct sockaddr_tcpip *st_dest __unused ) {
        !           151:        struct neighbour_advert *nadvert = iobuf->data;
        !           152:        struct ndp_entry *ndp;
        !           153: 
        !           154:        /* Sanity check */
        !           155:        if ( iob_len ( iobuf ) < sizeof ( *nadvert ) ) {
        !           156:                DBG ( "Packet too short (%zd bytes)\n", iob_len ( iobuf ) );
        !           157:                return -EINVAL;
        !           158:        }
        !           159: 
        !           160:        assert ( nadvert->code == 0 );
        !           161:        assert ( nadvert->flags & ICMP6_FLAGS_SOLICITED );
        !           162:        assert ( nadvert->opt_type == 2 );
        !           163: 
        !           164:        /* Update the neighbour cache, if entry is present */
        !           165:        ndp = ndp_find_entry ( &nadvert->target );
        !           166:        if ( ndp ) {
        !           167: 
        !           168:        assert ( nadvert->opt_len ==
        !           169:                        ( ( 2 + ndp->ll_protocol->ll_addr_len ) / 8 ) );
        !           170: 
        !           171:                if ( IP6_EQUAL ( ndp->in6, nadvert->target ) ) {
        !           172:                        memcpy ( ndp->ll_addr, nadvert->opt_ll_addr,
        !           173:                                 ndp->ll_protocol->ll_addr_len );
        !           174:                        ndp->state = NDP_STATE_REACHABLE;
        !           175:                        return 0;
        !           176:                }
        !           177:        }
        !           178:        DBG ( "Unsolicited advertisement (dropping packet)\n" );
        !           179:        return 0;
        !           180: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.