Annotation of qemu/roms/ipxe/src/net/ndp.c, revision 1.1.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.