#include <stdint.h>
#include <string.h>
#include <byteswap.h>
#include <errno.h>
#include <gpxe/if_ether.h>
#include <gpxe/iobuf.h>
#include <gpxe/ndp.h>
#include <gpxe/icmp6.h>
#include <gpxe/ip6.h>
#include <gpxe/netdevice.h>
Go to the source code of this file.
Data Structures | |
| struct | ndp_entry |
Defines | |
| #define | NUM_NDP_ENTRIES 4 |
| Number of entries in the neighbour cache table. | |
| #define | ndp_table_end &ndp_table[NUM_NDP_ENTRIES] |
Functions | |
| static struct ndp_entry * | ndp_find_entry (struct in6_addr *in6) |
| Find entry in the neighbour cache. | |
| static void | add_ndp_entry (struct net_device *netdev, struct in6_addr *in6, void *ll_addr, int state) |
| Add NDP entry. | |
| int | ndp_resolve (struct net_device *netdev, struct in6_addr *dest, struct in6_addr *src, void *dest_ll_addr) |
| Resolve the link-layer address. | |
| int | ndp_process_advert (struct io_buffer *iobuf, struct sockaddr_tcpip *st_src __unused, struct sockaddr_tcpip *st_dest __unused) |
| Process neighbour advertisement. | |
Variables | |
| static struct ndp_entry | ndp_table [NUM_NDP_ENTRIES] |
| The neighbour cache table. | |
| static unsigned int | next_new_ndp_entry = 0 |
This file implements address resolution as specified by the neighbour discovery protocol in RFC2461. This protocol is part of the IPv6 protocol family.
Definition in file ndp.c.
| #define NUM_NDP_ENTRIES 4 |
Number of entries in the neighbour cache table.
Definition at line 34 of file ndp.c.
Referenced by add_ndp_entry().
| #define ndp_table_end &ndp_table[NUM_NDP_ENTRIES] |
Find entry in the neighbour cache.
| in6 | IP6 address |
Definition at line 48 of file ndp.c.
References ndp_entry::in6, IP6_EQUAL, NDP_STATE_INVALID, ndp_table, ndp_table_end, NULL, and ndp_entry::state.
Referenced by ndp_process_advert(), and ndp_resolve().
00048 { 00049 struct ndp_entry *ndp; 00050 00051 for ( ndp = ndp_table ; ndp < ndp_table_end ; ndp++ ) { 00052 if ( IP6_EQUAL ( ( *in6 ), ndp->in6 ) && 00053 ( ndp->state != NDP_STATE_INVALID ) ) { 00054 return ndp; 00055 } 00056 } 00057 return NULL; 00058 }
| static void add_ndp_entry | ( | struct net_device * | netdev, | |
| struct in6_addr * | in6, | |||
| void * | ll_addr, | |||
| int | state | |||
| ) | [static] |
Add NDP entry.
| netdev | Network device | |
| in6 | IP6 address | |
| ll_addr | Link-layer address | |
| state | State of the entry - one of the NDP_STATE_XXX values |
Definition at line 69 of file ndp.c.
References DBG, ndp_entry::in6, inet6_ntoa(), ndp_entry::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, ndp_entry::ll_protocol, memcpy, memset(), ll_protocol::name, ndp_table, next_new_ndp_entry, ll_protocol::ntoa, NUM_NDP_ENTRIES, and ndp_entry::state.
Referenced by ndp_resolve().
00070 { 00071 struct ndp_entry *ndp; 00072 ndp = &ndp_table[next_new_ndp_entry++ % NUM_NDP_ENTRIES]; 00073 00074 /* Fill up entry */ 00075 ndp->ll_protocol = netdev->ll_protocol; 00076 memcpy ( &ndp->in6, &( *in6 ), sizeof ( *in6 ) ); 00077 if ( ll_addr ) { 00078 memcpy ( ndp->ll_addr, ll_addr, netdev->ll_protocol->ll_addr_len ); 00079 } else { 00080 memset ( ndp->ll_addr, 0, netdev->ll_protocol->ll_addr_len ); 00081 } 00082 ndp->state = state; 00083 DBG ( "New neighbour cache entry: IP6 %s => %s %s\n", 00084 inet6_ntoa ( ndp->in6 ), netdev->ll_protocol->name, 00085 netdev->ll_protocol->ntoa ( ndp->ll_addr ) ); 00086 }
| int ndp_resolve | ( | struct net_device * | netdev, | |
| struct in6_addr * | dest, | |||
| struct in6_addr * | src, | |||
| void * | dest_ll_addr | |||
| ) |
Resolve the link-layer address.
| netdev | Network device | |
| dest | Destination address | |
| src | Source address |
| dest_ll_addr | Destination link-layer address or NULL | |
| rc | Status |
Definition at line 102 of file ndp.c.
References add_ndp_entry(), DBG, ENOENT, icmp6_send_solicit(), inet6_ntoa(), ndp_entry::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, memcpy, ll_protocol::name, ndp_find_entry(), NDP_STATE_INCOMPLETE, NDP_STATE_REACHABLE, ll_protocol::ntoa, NULL, and ndp_entry::state.
Referenced by ipv6_tx().
00103 { 00104 struct ll_protocol *ll_protocol = netdev->ll_protocol; 00105 struct ndp_entry *ndp; 00106 int rc; 00107 00108 ndp = ndp_find_entry ( dest ); 00109 /* Check if the entry is valid */ 00110 if ( ndp && ndp->state == NDP_STATE_REACHABLE ) { 00111 DBG ( "Neighbour cache hit: IP6 %s => %s %s\n", 00112 inet6_ntoa ( *dest ), ll_protocol->name, 00113 ll_protocol->ntoa ( ndp->ll_addr ) ); 00114 memcpy ( dest_ll_addr, ndp->ll_addr, ll_protocol->ll_addr_len ); 00115 return 0; 00116 } 00117 00118 /* Check if the entry was already created */ 00119 if ( ndp ) { 00120 DBG ( "Awaiting neighbour advertisement\n" ); 00121 /* For test */ 00122 // ndp->state = NDP_STATE_REACHABLE; 00123 // memcpy ( ndp->ll_addr, netdev->ll_addr, 6 ); 00124 // assert ( ndp->ll_protocol->ll_addr_len == 6 ); 00125 // icmp6_test_nadvert ( netdev, dest, ndp->ll_addr ); 00126 // assert ( ndp->state == NDP_STATE_REACHABLE ); 00127 /* Take it out till here */ 00128 return -ENOENT; 00129 } 00130 DBG ( "Neighbour cache miss: IP6 %s\n", inet6_ntoa ( *dest ) ); 00131 00132 /* Add entry in the neighbour cache */ 00133 add_ndp_entry ( netdev, dest, NULL, NDP_STATE_INCOMPLETE ); 00134 00135 /* Send neighbour solicitation */ 00136 if ( ( rc = icmp6_send_solicit ( netdev, src, dest ) ) != 0 ) { 00137 return rc; 00138 } 00139 return -ENOENT; 00140 }
| int ndp_process_advert | ( | struct io_buffer * | iobuf, | |
| struct sockaddr_tcpip *st_src | __unused, | |||
| struct sockaddr_tcpip *st_dest | __unused | |||
| ) |
Process neighbour advertisement.
| iobuf | I/O buffer | |
| st_src | Source address | |
| st_dest | Destination address |
Definition at line 149 of file ndp.c.
References assert, neighbour_advert::code, io_buffer::data, DBG, EINVAL, neighbour_advert::flags, ICMP6_FLAGS_SOLICITED, ndp_entry::in6, iob_len(), IP6_EQUAL, ndp_entry::ll_addr, ll_protocol::ll_addr_len, ndp_entry::ll_protocol, memcpy, ndp_find_entry(), NDP_STATE_REACHABLE, neighbour_advert::opt_len, neighbour_advert::opt_ll_addr, neighbour_advert::opt_type, ndp_entry::state, and neighbour_advert::target.
Referenced by icmp6_rx().
00150 { 00151 struct neighbour_advert *nadvert = iobuf->data; 00152 struct ndp_entry *ndp; 00153 00154 /* Sanity check */ 00155 if ( iob_len ( iobuf ) < sizeof ( *nadvert ) ) { 00156 DBG ( "Packet too short (%zd bytes)\n", iob_len ( iobuf ) ); 00157 return -EINVAL; 00158 } 00159 00160 assert ( nadvert->code == 0 ); 00161 assert ( nadvert->flags & ICMP6_FLAGS_SOLICITED ); 00162 assert ( nadvert->opt_type == 2 ); 00163 00164 /* Update the neighbour cache, if entry is present */ 00165 ndp = ndp_find_entry ( &nadvert->target ); 00166 if ( ndp ) { 00167 00168 assert ( nadvert->opt_len == 00169 ( ( 2 + ndp->ll_protocol->ll_addr_len ) / 8 ) ); 00170 00171 if ( IP6_EQUAL ( ndp->in6, nadvert->target ) ) { 00172 memcpy ( ndp->ll_addr, nadvert->opt_ll_addr, 00173 ndp->ll_protocol->ll_addr_len ); 00174 ndp->state = NDP_STATE_REACHABLE; 00175 return 0; 00176 } 00177 } 00178 DBG ( "Unsolicited advertisement (dropping packet)\n" ); 00179 return 0; 00180 }
The neighbour cache table.
Definition at line 37 of file ndp.c.
Referenced by add_ndp_entry(), and ndp_find_entry().
unsigned int next_new_ndp_entry = 0 [static] |
1.5.7.1