iPXE
Data Structures | Defines | Functions | Variables
ndp.c File Reference

IPv6 neighbour discovery protocol. More...

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/in.h>
#include <ipxe/iobuf.h>
#include <ipxe/tcpip.h>
#include <ipxe/ipv6.h>
#include <ipxe/icmpv6.h>
#include <ipxe/neighbour.h>
#include <ipxe/dhcpv6.h>
#include <ipxe/ndp.h>

Go to the source code of this file.

Data Structures

struct  ndp_option_handler
 An NDP option handler. More...
struct  ndp_prefix_settings
 An NDP prefix settings block. More...
struct  ndp_settings
 An NDP settings block. More...
struct  ndp_prefix_operation
 An NDP per-prefix setting operation. More...
struct  ipv6conf
 An IPv6 configurator. More...

Defines

#define NDP_TAG(type, offset, len)   ( ( (len) << 16 ) | ( (offset) << 8 ) | (type) )
 Construct NDP tag.
#define NDP_TAG_TYPE(tag)   ( ( (tag) >> 0 ) & 0xff )
 Extract NDP tag type.
#define NDP_TAG_OFFSET(tag)   ( ( (tag) >> 8 ) & 0xff )
 Extract NDP tag offset.
#define NDP_TAG_LEN(tag)   ( ( (tag) >> 16 ) & 0xff )
 Extract NDP tag length.
#define NDP_TAG_INSTANCE(tag)   ( ( (tag) >> 24 ) & 0xff )
 Extract NDP tag instance.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static struct ipv6confipv6conf_demux (struct net_device *netdev)
 Identify IPv6 configurator by network device.
static int ipv6conf_rx_router_advertisement (struct net_device *netdev, struct in6_addr *router, struct ndp_router_advertisement_header *radv, size_t len)
 Handle router advertisement during IPv6 autoconfiguration.
static int ndp_tx_ll_addr (struct net_device *netdev, struct sockaddr_in6 *sin6_src, struct sockaddr_in6 *sin6_dest, const void *data, size_t len, unsigned int option_type)
 Transmit NDP packet with link-layer address option.
static int ndp_tx_request (struct net_device *netdev, struct net_protocol *net_protocol __unused, const void *net_dest, const void *net_source)
 Transmit NDP neighbour discovery request.
static int ndp_tx_router_solicitation (struct net_device *netdev)
 Transmit NDP router solicitation.
static int ndp_rx_neighbour_solicitation_ll_source (struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp, union ndp_option *option, size_t len)
 Process NDP neighbour solicitation source link-layer address option.
static int ndp_rx_neighbour_advertisement_ll_target (struct net_device *netdev, struct sockaddr_in6 *sin6_src __unused, union ndp_header *ndp, union ndp_option *option, size_t len)
 Process NDP neighbour advertisement target link-layer address option.
static int ndp_rx_router_advertisement_ll_source (struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp __unused, union ndp_option *option, size_t len)
 Process NDP router advertisement source link-layer address option.
static int ndp_rx_router_advertisement_prefix (struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp, union ndp_option *option, size_t len)
 Process NDP router advertisement prefix information option.
static int ndp_rx_option (struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp, union ndp_option *option, size_t len)
 Process received NDP option.
static int ndp_rx_options (struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp, size_t offset, size_t len)
 Process received NDP packet options.
static int ndp_rx_neighbour (struct io_buffer *iobuf, struct net_device *netdev, struct sockaddr_in6 *sin6_src, struct sockaddr_in6 *sin6_dest __unused)
 Process received NDP neighbour solicitation or advertisement.
static int ndp_rx_router_advertisement (struct io_buffer *iobuf, struct net_device *netdev, struct sockaddr_in6 *sin6_src, struct sockaddr_in6 *sin6_dest __unused)
 Process received NDP router advertisement.
static int ndp_applies (struct settings *settings __unused, const struct setting *setting)
 Check applicability of NDP setting.
static int ndp_fetch (struct settings *settings, struct setting *setting, void *data, size_t len)
 Fetch value of NDP setting.
static int ndp_prefix_applies (struct settings *settings __unused, const struct setting *setting)
 Check applicability of NDP per-prefix setting.
static int ndp_prefix_fetch_ip6 (struct settings *settings, void *data, size_t len)
 Fetch value of NDP IPv6 address setting.
static int ndp_prefix_fetch_len6 (struct settings *settings, void *data, size_t len)
 Fetch value of NDP prefix length setting.
static int ndp_prefix_fetch_gateway6 (struct settings *settings, void *data, size_t len)
 Fetch value of NDP router address setting.
static int ndp_prefix_fetch (struct settings *settings, struct setting *setting, void *data, size_t len)
 Fetch value of NDP pre-prefix setting.
static int ndp_register_settings (struct net_device *netdev, struct in6_addr *router, unsigned int lifetime, union ndp_option *options, size_t len)
 Register NDP settings.
struct setting ndp_dns6_setting __setting (SETTING_IP6_EXTRA, dns6)
 DNS server setting.
struct setting ndp_dnssl_setting __setting (SETTING_IP_EXTRA, dnssl)
 DNS search list setting.
static LIST_HEAD (ipv6confs)
 List of IPv6 configurators.
static void ipv6conf_free (struct refcnt *refcnt)
 Free IPv6 configurator.
static void ipv6conf_done (struct ipv6conf *ipv6conf, int rc)
 Finish IPv6 autoconfiguration.
static void ipv6conf_expired (struct retry_timer *timer, int fail)
 Handle IPv6 configurator timer expiry.
int start_ipv6conf (struct interface *job, struct net_device *netdev)
 Start IPv6 autoconfiguration.

Variables

struct neighbour_discovery ndp_discovery
 NDP neighbour discovery protocol.
static struct ndp_option_handler ndp_option_handlers []
 NDP option handlers.
struct icmpv6_handler
ndp_handlers[] 
__icmpv6_handler
 NDP ICMPv6 handlers.
static struct settings_scope ndp_settings_scope
 NDP settings scope.
static struct settings_operations ndp_settings_operations
 NDP settings operations.
static struct ndp_prefix_operation ndp_prefix_operations []
 NDP per-prefix settings operations.
static struct settings_operations ndp_prefix_settings_operations
 NDP per-prefix settings operations.
static struct interface_operation ipv6conf_job_op []
 IPv6 configurator job interface operations.
static struct interface_descriptor ipv6conf_job_desc
 IPv6 configurator job interface descriptor.
static struct interface_operation ipv6conf_dhcp_op []
 IPv6 configurator DHCPv6 interface operations.
static struct interface_descriptor ipv6conf_dhcp_desc
 IPv6 configurator DHCPv6 interface descriptor.
struct net_device_configurator
ipv6_configurator 
__net_device_configurator
 IPv6 network device configurator.

Detailed Description

IPv6 neighbour discovery protocol.

Definition in file ndp.c.


Define Documentation

#define NDP_TAG (   type,
  offset,
  len 
)    ( ( (len) << 16 ) | ( (offset) << 8 ) | (type) )

Construct NDP tag.

Parameters:
typeNDP option type
offsetStarting offset of data
lenLength of data (or 0 to use all remaining data)
Return values:
tagNDP tag

Definition at line 619 of file ndp.c.

#define NDP_TAG_TYPE (   tag)    ( ( (tag) >> 0 ) & 0xff )

Extract NDP tag type.

Parameters:
tagNDP tag
Return values:
typeNDP option type

Definition at line 628 of file ndp.c.

Referenced by ndp_fetch().

#define NDP_TAG_OFFSET (   tag)    ( ( (tag) >> 8 ) & 0xff )

Extract NDP tag offset.

Parameters:
tagNDP tag
Return values:
offsetStarting offset of data

Definition at line 636 of file ndp.c.

Referenced by ndp_fetch().

#define NDP_TAG_LEN (   tag)    ( ( (tag) >> 16 ) & 0xff )

Extract NDP tag length.

Parameters:
tagNDP tag
Return values:
lenLength of data (or 0 to use all remaining data)

Definition at line 644 of file ndp.c.

Referenced by ndp_fetch().

#define NDP_TAG_INSTANCE (   tag)    ( ( (tag) >> 24 ) & 0xff )

Extract NDP tag instance.

Parameters:
tagNDP tag
Return values:
instanceInstance

Definition at line 652 of file ndp.c.

Referenced by ndp_fetch().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static struct ipv6conf * ipv6conf_demux ( struct net_device netdev) [static, read]

Identify IPv6 configurator by network device.

Parameters:
netdevNetwork device
Return values:
ipv6IPv6 configurator, or NULL

Definition at line 1088 of file ndp.c.

References ipv6conf::list, list_for_each_entry, ipv6conf::netdev, and NULL.

Referenced by ipv6conf_rx_router_advertisement().

                                                                      {
        struct ipv6conf *ipv6conf;

        list_for_each_entry ( ipv6conf, &ipv6confs, list ) {
                if ( ipv6conf->netdev == netdev )
                        return ipv6conf;
        }
        return NULL;
}
static int ipv6conf_rx_router_advertisement ( struct net_device netdev,
struct in6_addr router,
struct ndp_router_advertisement_header radv,
size_t  len 
) [static]

Handle router advertisement during IPv6 autoconfiguration.

Parameters:
netdevNetwork device
routerRouter address
radvRouter advertisement
lenLength of router advertisement
Return values:
rcReturn status code

This function assumes that the router advertisement is well-formed, since it must have already passed through option processing.

Definition at line 1152 of file ndp.c.

References DBGC, ipv6conf::dhcp, ndp_router_advertisement_header::flags, ipv6conf_demux(), ipv6conf_done(), ndp_router_advertisement_header::lifetime, net_device::name, ndp_register_settings(), NDP_ROUTER_MANAGED, NDP_ROUTER_OTHER, ntohl, offsetof, ndp_router_advertisement_header::option, rc, start_dhcpv6(), stop_timer(), strerror(), and ipv6conf::timer.

Referenced by ndp_rx_router_advertisement().

                                                {
        struct ipv6conf *ipv6conf;
        size_t option_len;
        int stateful;
        int rc;

        /* Identify IPv6 configurator, if any */
        ipv6conf = ipv6conf_demux ( netdev );

        /* Do nothing unless IPv6 autoconfiguration is in progress */
        if ( ! ipv6conf )
                return 0;

        /* If this is not the first solicited router advertisement, ignore it */
        if ( ! timer_running ( &ipv6conf->timer ) )
                return 0;

        /* Stop router solicitation timer */
        stop_timer ( &ipv6conf->timer );

        /* Register NDP settings */
        option_len = ( len - offsetof ( typeof ( *radv ), option ) );
        if ( ( rc = ndp_register_settings ( netdev, router,
                                            ntohl ( radv->lifetime ),
                                            radv->option, option_len ) ) != 0 )
                return rc;

        /* Start DHCPv6 if required */
        if ( radv->flags & ( NDP_ROUTER_MANAGED | NDP_ROUTER_OTHER ) ) {
                stateful = ( radv->flags & NDP_ROUTER_MANAGED );
                if ( ( rc = start_dhcpv6 ( &ipv6conf->dhcp, netdev,
                                           stateful ) ) != 0 ) {
                        DBGC ( netdev, "NDP %s could not start state%s DHCPv6: "
                               "%s\n", netdev->name,
                               ( stateful ? "ful" : "less" ), strerror ( rc ) );
                        ipv6conf_done ( ipv6conf, rc );
                        return rc;
                }
                return 0;
        }

        /* Otherwise, terminate autoconfiguration */
        ipv6conf_done ( ipv6conf, 0 );

        return 0;
}
static int ndp_tx_ll_addr ( struct net_device netdev,
struct sockaddr_in6 sin6_src,
struct sockaddr_in6 sin6_dest,
const void *  data,
size_t  len,
unsigned int  option_type 
) [static]

Transmit NDP packet with link-layer address option.

Parameters:
netdevNetwork device
sin6_srcSource socket address
sin6_destDestination socket address
dataNDP header
lenSize of NDP header
option_typeNDP option type
Return values:
rcReturn status code

Definition at line 60 of file ndp.c.

References alloc_iob(), ndp_option_header::blocks, icmp_header::chksum, io_buffer::data, DBGC, ENOMEM, ndp_ll_addr_option::header, ndp_header::icmp, iob_put, iob_reserve, ndp_ll_addr_option::ll_addr, net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, MAX_LL_NET_HEADER_LEN, memcpy(), net_device::name, NDP_OPTION_BLKSZ, rc, strerror(), tcpip_chksum(), tcpip_tx(), and ndp_option_header::type.

Referenced by ndp_rx_neighbour_solicitation_ll_source(), ndp_tx_request(), and ndp_tx_router_solicitation().

                                                       {
        struct sockaddr_tcpip *st_src =
                ( ( struct sockaddr_tcpip * ) sin6_src );
        struct sockaddr_tcpip *st_dest =
                ( ( struct sockaddr_tcpip * ) sin6_dest );
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        struct io_buffer *iobuf;
        struct ndp_ll_addr_option *ll_addr_opt;
        union ndp_header *ndp;
        size_t option_len;
        int rc;

        /* Allocate and populate buffer */
        option_len = ( ( sizeof ( *ll_addr_opt ) +
                         ll_protocol->ll_addr_len + NDP_OPTION_BLKSZ - 1 ) &
                       ~( NDP_OPTION_BLKSZ - 1 ) );
        iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN + len + option_len );
        if ( ! iobuf )
                return -ENOMEM;
        iob_reserve ( iobuf, MAX_LL_NET_HEADER_LEN );
        memcpy ( iob_put ( iobuf, len ), data, len );
        ll_addr_opt = iob_put ( iobuf, option_len );
        ll_addr_opt->header.type = option_type;
        ll_addr_opt->header.blocks = ( option_len / NDP_OPTION_BLKSZ );
        memcpy ( ll_addr_opt->ll_addr, netdev->ll_addr,
                 ll_protocol->ll_addr_len );
        ndp = iobuf->data;
        ndp->icmp.chksum = tcpip_chksum ( ndp, ( len + option_len ) );

        /* Transmit packet */
        if ( ( rc = tcpip_tx ( iobuf, &icmpv6_protocol, st_src, st_dest,
                               netdev, &ndp->icmp.chksum ) ) != 0 ) {
                DBGC ( netdev, "NDP %s could not transmit packet: %s\n",
                       netdev->name, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int ndp_tx_request ( struct net_device netdev,
struct net_protocol *net_protocol  __unused,
const void *  net_dest,
const void *  net_source 
) [static]

Transmit NDP neighbour discovery request.

Parameters:
netdevNetwork device
net_protocolNetwork-layer protocol
net_destDestination network-layer address
net_sourceSource network-layer address
Return values:
rcReturn status code

Definition at line 113 of file ndp.c.

References AF_INET6, ndp_neighbour_header::icmp, ICMPV6_NEIGHBOUR_SOLICITATION, net_device::index, ipv6_solicited_node(), memcpy(), memset(), NDP_OPT_LL_SOURCE, ndp_tx_ll_addr(), rc, sockaddr_in6::sin6_addr, sockaddr_in6::sin6_family, sockaddr_in6::sin6_scope_id, ndp_neighbour_header::target, and icmp_header::type.

                                                                           {
        struct sockaddr_in6 sin6_src;
        struct sockaddr_in6 sin6_dest;
        struct ndp_neighbour_header neigh;
        int rc;

        /* Construct source address */
        memset ( &sin6_src, 0, sizeof ( sin6_src ) );
        sin6_src.sin6_family = AF_INET6;
        memcpy ( &sin6_src.sin6_addr, net_source,
                 sizeof ( sin6_src.sin6_addr ) );

        /* Construct multicast destination address */
        memset ( &sin6_dest, 0, sizeof ( sin6_dest ) );
        sin6_dest.sin6_family = AF_INET6;
        sin6_dest.sin6_scope_id = netdev->index;
        ipv6_solicited_node ( &sin6_dest.sin6_addr, net_dest );

        /* Construct neighbour header */
        memset ( &neigh, 0, sizeof ( neigh ) );
        neigh.icmp.type = ICMPV6_NEIGHBOUR_SOLICITATION;
        memcpy ( &neigh.target, net_dest, sizeof ( neigh.target ) );

        /* Transmit neighbour discovery packet */
        if ( ( rc = ndp_tx_ll_addr ( netdev, &sin6_src, &sin6_dest, &neigh,
                                     sizeof ( neigh ),
                                     NDP_OPT_LL_SOURCE ) ) != 0 )
                return rc;

        return 0;
}
static int ndp_tx_router_solicitation ( struct net_device netdev) [static]

Transmit NDP router solicitation.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 159 of file ndp.c.

References AF_INET6, ndp_router_solicitation_header::icmp, ICMPV6_ROUTER_SOLICITATION, net_device::index, ipv6_all_routers(), memset(), NDP_OPT_LL_SOURCE, ndp_tx_ll_addr(), NULL, rc, sockaddr_in6::sin6_addr, sockaddr_in6::sin6_family, sockaddr_in6::sin6_scope_id, and icmp_header::type.

Referenced by ipv6conf_expired().

                                                                    {
        struct ndp_router_solicitation_header rsol;
        struct sockaddr_in6 sin6_dest;
        int rc;

        /* Construct multicast destination address */
        memset ( &sin6_dest, 0, sizeof ( sin6_dest ) );
        sin6_dest.sin6_family = AF_INET6;
        sin6_dest.sin6_scope_id = netdev->index;
        ipv6_all_routers ( &sin6_dest.sin6_addr );

        /* Construct router solicitation */
        memset ( &rsol, 0, sizeof ( rsol ) );
        rsol.icmp.type = ICMPV6_ROUTER_SOLICITATION;

        /* Transmit packet */
        if ( ( rc = ndp_tx_ll_addr ( netdev, NULL, &sin6_dest, &rsol,
                                     sizeof ( rsol ), NDP_OPT_LL_SOURCE ) ) !=0)
                return rc;

        return 0;
}
static int ndp_rx_neighbour_solicitation_ll_source ( struct net_device netdev,
struct sockaddr_in6 sin6_src,
union ndp_header ndp,
union ndp_option option,
size_t  len 
) [static]

Process NDP neighbour solicitation source link-layer address option.

Parameters:
netdevNetwork device
sin6_srcSource socket address
ndpNDP packet
optionNDP option
lenNDP option length
Return values:
rcReturn status code

Definition at line 193 of file ndp.c.

References DBGC, EINVAL, ndp_neighbour_header::flags, ndp_neighbour_header::icmp, ICMPV6_NEIGHBOUR_ADVERTISEMENT, inet6_ntoa(), ipv6_has_addr(), ndp_ll_addr_option::ll_addr, ndp_option::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, memset(), net_device::name, NDP_NEIGHBOUR_OVERRIDE, NDP_NEIGHBOUR_SOLICITED, NDP_OPT_LL_TARGET, ndp_tx_ll_addr(), ndp_header::neigh, neighbour_define(), ll_protocol::ntoa, NULL, offsetof, rc, sockaddr_in6::sin6_addr, strerror(), ndp_neighbour_header::target, and icmp_header::type.

                                                       {
        struct ndp_neighbour_header *neigh = &ndp->neigh;
        struct ndp_ll_addr_option *ll_addr_opt = &option->ll_addr;
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        int rc;

        /* Silently ignore neighbour solicitations for addresses we do
         * not own.
         */
        if ( ! ipv6_has_addr ( netdev, &neigh->target ) )
                return 0;

        /* Sanity check */
        if ( offsetof ( typeof ( *ll_addr_opt ),
                        ll_addr[ll_protocol->ll_addr_len] ) > len ) {
                DBGC ( netdev, "NDP %s neighbour solicitation link-layer "
                       "address option too short at %zd bytes\n",
                       netdev->name, len );
                return -EINVAL;
        }

        /* Create or update neighbour cache entry */
        if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
                                       &sin6_src->sin6_addr,
                                       ll_addr_opt->ll_addr ) ) != 0 ) {
                DBGC ( netdev, "NDP %s could not define %s => %s: %s\n",
                       netdev->name, inet6_ntoa ( &sin6_src->sin6_addr ),
                       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
                       strerror ( rc ) );
                return rc;
        }

        /* Convert neighbour header to advertisement */
        memset ( neigh, 0, offsetof ( typeof ( *neigh ), target ) );
        neigh->icmp.type = ICMPV6_NEIGHBOUR_ADVERTISEMENT;
        neigh->flags = ( NDP_NEIGHBOUR_SOLICITED | NDP_NEIGHBOUR_OVERRIDE );

        /* Send neighbour advertisement */
        if ( ( rc = ndp_tx_ll_addr ( netdev, NULL, sin6_src, neigh,
                                     sizeof ( *neigh ),
                                     NDP_OPT_LL_TARGET ) ) != 0 )
                return rc;

        return 0;
}
static int ndp_rx_neighbour_advertisement_ll_target ( struct net_device netdev,
struct sockaddr_in6 *sin6_src  __unused,
union ndp_header ndp,
union ndp_option option,
size_t  len 
) [static]

Process NDP neighbour advertisement target link-layer address option.

Parameters:
netdevNetwork device
sin6_srcSource socket address
ndpNDP packet
optionNDP option
lenNDP option length
Return values:
rcReturn status code

Definition at line 254 of file ndp.c.

References DBGC, EINVAL, inet6_ntoa(), ndp_ll_addr_option::ll_addr, ndp_option::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, net_device::name, ndp_header::neigh, neighbour_update(), ll_protocol::ntoa, offsetof, rc, strerror(), and ndp_neighbour_header::target.

                                                        {
        struct ndp_neighbour_header *neigh = &ndp->neigh;
        struct ndp_ll_addr_option *ll_addr_opt = &option->ll_addr;
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        int rc;

        /* Sanity check */
        if ( offsetof ( typeof ( *ll_addr_opt ),
                        ll_addr[ll_protocol->ll_addr_len] ) > len ) {
                DBGC ( netdev, "NDP %s neighbour advertisement link-layer "
                       "address option too short at %zd bytes\n",
                       netdev->name, len );
                return -EINVAL;
        }

        /* Update neighbour cache entry, if any */
        if ( ( rc = neighbour_update ( netdev, &ipv6_protocol, &neigh->target,
                                       ll_addr_opt->ll_addr ) ) != 0 ) {
                DBGC ( netdev, "NDP %s could not update %s => %s: %s\n",
                       netdev->name, inet6_ntoa ( &neigh->target ),
                       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
                       strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int ndp_rx_router_advertisement_ll_source ( struct net_device netdev,
struct sockaddr_in6 sin6_src,
union ndp_header *ndp  __unused,
union ndp_option option,
size_t  len 
) [static]

Process NDP router advertisement source link-layer address option.

Parameters:
netdevNetwork device
sin6_srcSource socket address
ndpNDP packet
optionNDP option
lenNDP option length
Return values:
rcReturn status code

Definition at line 298 of file ndp.c.

References DBGC, EINVAL, inet6_ntoa(), ndp_ll_addr_option::ll_addr, ndp_option::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, net_device::name, neighbour_define(), ll_protocol::ntoa, offsetof, rc, sockaddr_in6::sin6_addr, and strerror().

                                                                               {
        struct ndp_ll_addr_option *ll_addr_opt = &option->ll_addr;
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        int rc;

        /* Sanity check */
        if ( offsetof ( typeof ( *ll_addr_opt ),
                        ll_addr[ll_protocol->ll_addr_len] ) > len ) {
                DBGC ( netdev, "NDP %s router advertisement link-layer address "
                       "option too short at %zd bytes\n", netdev->name, len );
                return -EINVAL;
        }

        /* Define neighbour cache entry */
        if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
                                       &sin6_src->sin6_addr,
                                       ll_addr_opt->ll_addr ) ) != 0 ) {
                DBGC ( netdev, "NDP %s could not define %s => %s: %s\n",
                       netdev->name, inet6_ntoa ( &sin6_src->sin6_addr ),
                       ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
                       strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int ndp_rx_router_advertisement_prefix ( struct net_device netdev,
struct sockaddr_in6 sin6_src,
union ndp_header ndp,
union ndp_option option,
size_t  len 
) [static]

Process NDP router advertisement prefix information option.

Parameters:
netdevNetwork device
sin6_srcSource socket address
ndpNDP packet
optionNDP option
lenNDP option length
Return values:
rcReturn status code

Definition at line 339 of file ndp.c.

References DBGC, EINVAL, ndp_prefix_information_option::flags, inet6_ntoa(), ndp_router_advertisement_header::lifetime, net_device::name, NDP_PREFIX_AUTONOMOUS, NDP_PREFIX_ON_LINK, ndp_prefix_information_option::prefix, ndp_option::prefix, ndp_prefix_information_option::prefix_len, ndp_header::radv, and sockaddr_in6::sin6_addr.

                                                                            {
        struct ndp_router_advertisement_header *radv = &ndp->radv;
        struct ndp_prefix_information_option *prefix_opt = &option->prefix;

        /* Sanity check */
        if ( sizeof ( *prefix_opt ) > len ) {
                DBGC ( netdev, "NDP %s router advertisement prefix option too "
                       "short at %zd bytes\n", netdev->name, len );
                return -EINVAL;
        }

        DBGC ( netdev, "NDP %s found %sdefault router %s ",
               netdev->name, ( radv->lifetime ? "" : "non-" ),
               inet6_ntoa ( &sin6_src->sin6_addr ) );
        DBGC ( netdev, "for %s-link %sautonomous prefix %s/%d\n",
               ( ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) ? "on" : "off" ),
               ( ( prefix_opt->flags & NDP_PREFIX_AUTONOMOUS ) ? "" : "non-" ),
               inet6_ntoa ( &prefix_opt->prefix ), prefix_opt->prefix_len );

        return 0;
}
static int ndp_rx_option ( struct net_device netdev,
struct sockaddr_in6 sin6_src,
union ndp_header ndp,
union ndp_option option,
size_t  len 
) [static]

Process received NDP option.

Parameters:
netdevNetwork device
sin6_srcSource socket address
ndpNDP packet
optionNDP option
lenOption length
Return values:
rcReturn status code

Definition at line 418 of file ndp.c.

References ndp_option::header, ndp_header::icmp, ndp_option_handler::icmp_type, ndp_option_handlers, ndp_option_handler::option_type, ndp_option_handler::rx, icmp_header::type, and ndp_option_header::type.

Referenced by ndp_rx_options().

                                                                  {
        struct ndp_option_handler *handler;
        unsigned int i;

        /* Locate a suitable option handler, if any */
        for ( i = 0 ; i < ( sizeof ( ndp_option_handlers ) /
                            sizeof ( ndp_option_handlers[0] ) ) ; i++ ) {
                handler = &ndp_option_handlers[i];
                if ( ( handler->icmp_type == ndp->icmp.type ) &&
                     ( handler->option_type == option->header.type ) ) {
                        return handler->rx ( netdev, sin6_src, ndp,
                                             option, len );
                }
        }

        /* Silently ignore unknown options as per RFC 4861 */
        return 0;
}
static int ndp_rx_options ( struct net_device netdev,
struct sockaddr_in6 sin6_src,
union ndp_header ndp,
size_t  offset,
size_t  len 
) [static]

Process received NDP packet options.

Parameters:
netdevNetwork device
sin6_srcSource socket address
ndpNDP header
offsetOffset to NDP options
lenLength of NDP packet
Return values:
rcReturn status code

Definition at line 449 of file ndp.c.

References ndp_option_header::blocks, DBGC, DBGC_HDA, EINVAL, ndp_option::header, net_device::name, NDP_OPTION_BLKSZ, ndp_rx_option(), offset, and rc.

Referenced by ndp_rx_neighbour(), and ndp_rx_router_advertisement().

                                                                               {
        union ndp_option *option;
        size_t remaining;
        size_t option_len;
        int rc;

        /* Sanity check */
        if ( len < offset ) {
                DBGC ( netdev, "NDP %s packet too short at %zd bytes (min %zd "
                       "bytes)\n", netdev->name, len, offset );
                return -EINVAL;
        }

        /* Search for option */
        option = ( ( ( void * ) ndp ) + offset );
        remaining = ( len - offset );
        while ( remaining ) {

                /* Sanity check */
                if ( ( remaining < sizeof ( option->header ) ) ||
                     ( option->header.blocks == 0 ) ||
                     ( remaining < ( option->header.blocks *
                                     NDP_OPTION_BLKSZ ) ) ) {
                        DBGC ( netdev, "NDP %s bad option length:\n",
                               netdev->name );
                        DBGC_HDA ( netdev, 0, option, remaining );
                        return -EINVAL;
                }
                option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );

                /* Handle option */
                if ( ( rc = ndp_rx_option ( netdev, sin6_src, ndp, option,
                                            option_len ) ) != 0 )
                        return rc;

                /* Move to next option */
                option = ( ( ( void * ) option ) + option_len );
                remaining -= option_len;
        }

        return 0;
}
static int ndp_rx_neighbour ( struct io_buffer iobuf,
struct net_device netdev,
struct sockaddr_in6 sin6_src,
struct sockaddr_in6 *sin6_dest  __unused 
) [static]

Process received NDP neighbour solicitation or advertisement.

Parameters:
iobufI/O buffer
netdevNetwork device
sin6_srcSource socket address
sin6_destDestination socket address
Return values:
rcReturn status code

Definition at line 503 of file ndp.c.

References io_buffer::data, free_iob(), iob_len(), len, ndp_rx_options(), ndp_header::neigh, offsetof, and rc.

                                                                        {
        union ndp_header *ndp = iobuf->data;
        struct ndp_neighbour_header *neigh = &ndp->neigh;
        size_t len = iob_len ( iobuf );
        int rc;

        /* Process options */
        if ( ( rc = ndp_rx_options ( netdev, sin6_src, ndp,
                                     offsetof ( typeof ( *neigh ), option ),
                                     len ) ) != 0 )
                goto err_options;

 err_options:
        free_iob ( iobuf );
        return rc;
}
static int ndp_rx_router_advertisement ( struct io_buffer iobuf,
struct net_device netdev,
struct sockaddr_in6 sin6_src,
struct sockaddr_in6 *sin6_dest  __unused 
) [static]

Process received NDP router advertisement.

Parameters:
iobufI/O buffer
netdevNetwork device
sin6_srcSource socket address
sin6_destDestination socket address
Return values:
rcReturn status code

Definition at line 533 of file ndp.c.

References io_buffer::data, free_iob(), iob_len(), ipv6conf_rx_router_advertisement(), len, ndp_rx_options(), offsetof, ndp_header::radv, rc, and sockaddr_in6::sin6_addr.

                                                                        {
        union ndp_header *ndp = iobuf->data;
        struct ndp_router_advertisement_header *radv = &ndp->radv;
        struct in6_addr *router = &sin6_src->sin6_addr;
        size_t len = iob_len ( iobuf );
        int rc;

        /* Process options */
        if ( ( rc = ndp_rx_options ( netdev, sin6_src, ndp,
                                     offsetof ( typeof ( *radv ), option ),
                                     len ) ) != 0 )
                goto err_options;

        /* Pass to IPv6 autoconfiguration */
        if ( ( rc = ipv6conf_rx_router_advertisement ( netdev, router,
                                                       radv, len ) ) != 0 )
                goto err_ipv6conf;

 err_ipv6conf:
 err_options:
        free_iob ( iobuf );
        return rc;
}
static int ndp_applies ( struct settings *settings  __unused,
const struct setting setting 
) [static]

Check applicability of NDP setting.

Parameters:
settingsSettings block
settingSetting to fetch
Return values:
appliesSetting applies within this settings block

Definition at line 661 of file ndp.c.

References ndp_settings_scope, and setting::scope.

                                                         {

        return ( setting->scope == &ndp_settings_scope );
}
static int ndp_fetch ( struct settings settings,
struct setting setting,
void *  data,
size_t  len 
) [static]

Fetch value of NDP setting.

Parameters:
settingsSettings block
settingSetting to fetch
dataBuffer to fill with setting data
lenLength of buffer
Return values:
lenLength of setting data, or negative error

Definition at line 676 of file ndp.c.

References ndp_option_header::blocks, container_of, DBGC, EINVAL, ENOENT, ndp_option::header, ndp_settings::len, memcpy(), net_device::name, NDP_OPTION_BLKSZ, NDP_TAG_INSTANCE, NDP_TAG_LEN, NDP_TAG_OFFSET, NDP_TAG_TYPE, netdev, offset, ndp_settings::options, settings::parent, setting::tag, ndp_option_header::type, and setting::type.

                                                {
        struct ndp_settings *ndpset =
                container_of ( settings, struct ndp_settings, settings );
        struct net_device *netdev =
                container_of ( settings->parent, struct net_device,
                               settings.settings );
        union ndp_option *option;
        unsigned int tag_type;
        unsigned int tag_offset;
        unsigned int tag_len;
        unsigned int tag_instance;
        size_t offset;
        size_t option_len;
        void *option_data;

        /* Parse setting tag */
        tag_type = NDP_TAG_TYPE ( setting->tag );
        tag_offset = NDP_TAG_OFFSET ( setting->tag );
        tag_len = NDP_TAG_LEN ( setting->tag );
        tag_instance = NDP_TAG_INSTANCE ( setting->tag );

        /* Scan through NDP options for requested type.  We can assume
         * that the options are well-formed, otherwise they would have
         * been rejected prior to being stored.
         */
        for ( offset = 0 ; offset < ndpset->len ; offset += option_len ) {

                /* Calculate option length */
                option = ( ( ( void * ) ndpset->options ) + offset );
                option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );

                /* Skip options that do not match this tag */
                if ( option->header.type != tag_type )
                        continue;

                /* Skip previous instances of this option */
                if ( tag_instance-- != 0 )
                        continue;

                /* Sanity check */
                if ( ( tag_offset + tag_len ) > option_len ) {
                        DBGC ( netdev, "NDP %s option %d too short\n",
                               netdev->name, tag_type );
                        return -EINVAL;
                }
                if ( ! tag_len )
                        tag_len = ( option_len - tag_offset );
                option_data = ( ( ( void * ) option ) + tag_offset );

                /* Copy data to output buffer */
                if ( len > tag_len )
                        len = tag_len;
                memcpy ( data, option_data, len );

                /* Default to hex if no type is specified */
                if ( ! setting->type )
                        setting->type = &setting_type_hex;

                return tag_len;
        }

        return -ENOENT;
}
static int ndp_prefix_applies ( struct settings *settings  __unused,
const struct setting setting 
) [static]

Check applicability of NDP per-prefix setting.

Parameters:
settingsSettings block
settingSetting to fetch
Return values:
appliesSetting applies within this settings block

Definition at line 755 of file ndp.c.

References ipv6_settings_scope, and setting::scope.

                                                                {

        return ( setting->scope == &ipv6_settings_scope );
}
static int ndp_prefix_fetch_ip6 ( struct settings settings,
void *  data,
size_t  len 
) [static]

Fetch value of NDP IPv6 address setting.

Parameters:
settingsSettings block
dataBuffer to fill with setting data
lenLength of buffer
Return values:
lenLength of setting data, or negative error

Definition at line 769 of file ndp.c.

References container_of, EINVAL, ENOENT, ndp_prefix_information_option::flags, ipv6_eui64(), memcpy(), NDP_PREFIX_AUTONOMOUS, netdev, settings::parent, prefix, ndp_prefix_information_option::prefix, ndp_prefix_settings::prefix, ndp_prefix_information_option::prefix_len, ndp_settings::settings, and ndp_prefix_information_option::valid.

                                               {
        struct ndp_prefix_settings *prefset =
                container_of ( settings, struct ndp_prefix_settings, settings );
        struct ndp_settings *ndpset =
                container_of ( settings->parent, struct ndp_settings, settings);
        struct net_device *netdev =
                container_of ( ndpset->settings.parent, struct net_device,
                               settings.settings );
        struct ndp_prefix_information_option *prefix = prefset->prefix;
        struct in6_addr ip6;
        int prefix_len;

        /* Skip dead prefixes */
        if ( ! prefix->valid )
                return -ENOENT;

        /* Construct IPv6 address via SLAAC, if applicable */
        memcpy ( &ip6, &prefix->prefix, sizeof ( ip6 ) );
        if ( prefix->flags & NDP_PREFIX_AUTONOMOUS ) {
                prefix_len = ipv6_eui64 ( &ip6, netdev );
                if ( prefix_len < 0 )
                        return prefix_len;
                if ( prefix_len != prefix->prefix_len )
                        return -EINVAL;
        }

        /* Fill in IPv6 address */
        if ( len > sizeof ( ip6 ) )
                len = sizeof ( ip6 );
        memcpy ( data, &ip6, len );

        return sizeof ( ip6 );
}
static int ndp_prefix_fetch_len6 ( struct settings settings,
void *  data,
size_t  len 
) [static]

Fetch value of NDP prefix length setting.

Parameters:
settingsSettings block
dataBuffer to fill with setting data
lenLength of buffer
Return values:
lenLength of setting data, or negative error

Definition at line 812 of file ndp.c.

References container_of, data, ndp_prefix_information_option::flags, NDP_PREFIX_ON_LINK, prefix, ndp_prefix_settings::prefix, and ndp_prefix_information_option::prefix_len.

                                                {
        struct ndp_prefix_settings *prefset =
                container_of ( settings, struct ndp_prefix_settings, settings );
        struct ndp_prefix_information_option *prefix = prefset->prefix;
        uint8_t *len6;

        /* Fill in prefix length */
        if ( len >= sizeof ( *len6 ) ) {
                /* We treat an off-link prefix as having a prefix
                 * length covering the entire IPv6 address.
                 */
                len6 = data;
                *len6 = ( ( prefix->flags & NDP_PREFIX_ON_LINK ) ?
                          prefix->prefix_len : -1UL );
        }

        return sizeof ( *len6 );
}
static int ndp_prefix_fetch_gateway6 ( struct settings settings,
void *  data,
size_t  len 
) [static]

Fetch value of NDP router address setting.

Parameters:
settingsSettings block
dataBuffer to fill with setting data
lenLength of buffer
Return values:
lenLength of setting data, or negative error

Definition at line 840 of file ndp.c.

References container_of, ENOENT, ndp_settings::lifetime, memcpy(), settings::parent, and ndp_settings::router.

                                                                {
        struct ndp_settings *ndpset =
                container_of ( settings->parent, struct ndp_settings, settings);

        /* Treat non-routing router as non-existent */
        if ( ! ndpset->lifetime )
                return -ENOENT;

        /* Fill in router address */
        if ( len > sizeof ( ndpset->router ) )
                len = sizeof ( ndpset->router );
        memcpy ( data, &ndpset->router, len );

        return sizeof ( ndpset->router );
}
static int ndp_prefix_fetch ( struct settings settings,
struct setting setting,
void *  data,
size_t  len 
) [static]

Fetch value of NDP pre-prefix setting.

Parameters:
settingsSettings block
settingSetting to fetch
dataBuffer to fill with setting data
lenLength of buffer
Return values:
lenLength of setting data, or negative error

Definition at line 888 of file ndp.c.

References ENOENT, ndp_prefix_operation::fetch, ndp_prefix_operations, op, ndp_prefix_operation::setting, and setting_cmp().

                                                       {
        struct ndp_prefix_operation *op;
        unsigned int i;

        /* Handle per-prefix settings */
        for ( i = 0 ; i < ( sizeof ( ndp_prefix_operations ) /
                            sizeof ( ndp_prefix_operations[0] ) ) ; i++ ) {
                op = &ndp_prefix_operations[i];
                if ( setting_cmp ( setting, op->setting ) == 0 )
                        return op->fetch ( settings, data, len );
        }

        return -ENOENT;
}
static int ndp_register_settings ( struct net_device netdev,
struct in6_addr router,
unsigned int  lifetime,
union ndp_option options,
size_t  len 
) [static]

Register NDP settings.

Parameters:
netdevNetwork device
routerRouter address
lifetimeRouter lifetime
optionsNDP options
lenLength of options
Return values:
rcReturn status code

Definition at line 921 of file ndp.c.

References assert, ndp_option_header::blocks, ENOMEM, ndp_prefix_information_option::flags, ndp_option::header, IPV6_ORDER_PREFIX_ONLY, IPV6_ORDER_SLAAC, len, ndp_settings::len, lifetime, ndp_settings::lifetime, memcpy(), ndp_prefix_settings::name, NDP_OPT_PREFIX, NDP_OPTION_BLKSZ, NDP_PREFIX_AUTONOMOUS, NDP_SETTINGS_NAME, ndp_settings_scope, netdev_settings(), NULL, offset, ndp_settings::options, settings::order, settings::parent, ndp_option::prefix, ndp_prefix_settings::prefix, rc, ref_init, ref_put, ndp_settings::refcnt, register_settings(), ndp_settings::router, ndp_prefix_settings::settings, ndp_settings::settings, settings_init(), snprintf(), ndp_option_header::type, unregister_settings(), and zalloc().

Referenced by ipv6conf_rx_router_advertisement().

                                                                           {
        struct settings *parent = netdev_settings ( netdev );
        union ndp_option *option;
        struct ndp_settings *ndpset;
        struct ndp_prefix_settings *prefset;
        size_t offset;
        size_t option_len;
        unsigned int prefixes;
        unsigned int instance;
        int order;
        int rc;

        /* Count number of prefix options.  We can assume that the
         * options are well-formed, otherwise they would have been
         * rejected prior to being stored.
         */
        order = IPV6_ORDER_PREFIX_ONLY;
        for ( prefixes = 0, offset = 0 ; offset < len ; offset += option_len ) {

                /* Skip non-prefix options */
                option = ( ( ( void * ) options ) + offset );
                option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
                if ( option->header.type != NDP_OPT_PREFIX )
                        continue;

                /* Count number of prefixes */
                prefixes++;

                /* Increase overall order if we have SLAAC addresses */
                if ( option->prefix.flags & NDP_PREFIX_AUTONOMOUS )
                        order = IPV6_ORDER_SLAAC;
        }

        /* Allocate and initialise structure */
        ndpset = zalloc ( sizeof ( *ndpset ) + len +
                          ( prefixes * sizeof ( *prefset ) ) );
        if ( ! ndpset ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        ref_init ( &ndpset->refcnt, NULL );
        settings_init ( &ndpset->settings, &ndp_settings_operations,
                        &ndpset->refcnt, &ndp_settings_scope );
        ndpset->settings.order = order;
        memcpy ( &ndpset->router, router, sizeof ( ndpset->router ) );
        ndpset->lifetime = lifetime;
        ndpset->len = len;
        memcpy ( ndpset->options, options, len );
        prefset = ( ( ( void * ) ndpset->options ) + len );

        /* Register settings */
        if ( ( rc = register_settings ( &ndpset->settings, parent,
                                        NDP_SETTINGS_NAME ) ) != 0 )
                goto err_register;

        /* Construct and register per-prefix settings */
        for ( instance = 0, offset = 0 ; offset < len ; offset += option_len ) {

                /* Skip non-prefix options */
                option = ( ( ( void * ) ndpset->options ) + offset );
                option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
                if ( option->header.type != NDP_OPT_PREFIX )
                        continue;

                /* Initialise structure */
                settings_init ( &prefset->settings,
                                &ndp_prefix_settings_operations,
                                &ndpset->refcnt, &ndp_settings_scope );
                prefset->settings.order =
                        ( ( option->prefix.flags & NDP_PREFIX_AUTONOMOUS ) ?
                          IPV6_ORDER_SLAAC : IPV6_ORDER_PREFIX_ONLY );
                prefset->prefix = &option->prefix;
                snprintf ( prefset->name, sizeof ( prefset->name ), "%d",
                           instance++ );

                /* Register settings */
                if ( ( rc = register_settings ( &prefset->settings,
                                                &ndpset->settings,
                                                prefset->name ) ) != 0 )
                        goto err_register_prefix;

                /* Move to next per-prefix settings */
                prefset++;
        }
        assert ( instance == prefixes );

        ref_put ( &ndpset->refcnt );
        return 0;

 err_register_prefix:
        unregister_settings ( &ndpset->settings );
 err_register:
        ref_put ( &ndpset->refcnt );
 err_alloc:
        return rc;
}
struct setting ndp_dns6_setting __setting ( SETTING_IP6_EXTRA  ,
dns6   
) [read]

DNS server setting.

struct setting ndp_dnssl_setting __setting ( SETTING_IP_EXTRA  ,
dnssl   
) [read]

DNS search list setting.

static LIST_HEAD ( ipv6confs  ) [static]

List of IPv6 configurators.

static void ipv6conf_free ( struct refcnt refcnt) [static]

Free IPv6 configurator.

Parameters:
refcntReference count

Definition at line 1074 of file ndp.c.

References container_of, free, ipv6conf::netdev, and netdev_put().

Referenced by start_ipv6conf().

                                                    {
        struct ipv6conf *ipv6conf =
                container_of ( refcnt, struct ipv6conf, refcnt );

        netdev_put ( ipv6conf->netdev );
        free ( ipv6conf );
}
static void ipv6conf_done ( struct ipv6conf ipv6conf,
int  rc 
) [static]

Finish IPv6 autoconfiguration.

Parameters:
ipv6IPv6 configurator
rcReason for finishing

Definition at line 1104 of file ndp.c.

References ipv6conf::dhcp, intf_shutdown(), ipv6conf::job, ipv6conf::list, list_del, ref_put, ipv6conf::refcnt, stop_timer(), and ipv6conf::timer.

Referenced by ipv6conf_expired(), and ipv6conf_rx_router_advertisement().

                                                                {

        /* Shut down interfaces */
        intf_shutdown ( &ipv6conf->job, rc );
        intf_shutdown ( &ipv6conf->dhcp, rc );

        /* Stop timer */
        stop_timer ( &ipv6conf->timer );

        /* Remove from list and drop list's reference */
        list_del ( &ipv6conf->list );
        ref_put ( &ipv6conf->refcnt );
}
static void ipv6conf_expired ( struct retry_timer timer,
int  fail 
) [static]

Handle IPv6 configurator timer expiry.

Parameters:
timerRetry timer
failFailure indicator

Definition at line 1124 of file ndp.c.

References container_of, ETIMEDOUT, ipv6conf_done(), ndp_tx_router_solicitation(), ipv6conf::netdev, start_timer(), and ipv6conf::timer.

Referenced by start_ipv6conf().

                                                                     {
        struct ipv6conf *ipv6conf =
                container_of ( timer, struct ipv6conf, timer );

        /* If we have failed, terminate autoconfiguration */
        if ( fail ) {
                ipv6conf_done ( ipv6conf, -ETIMEDOUT );
                return;
        }

        /* Otherwise, transmit router solicitation and restart timer */
        start_timer ( &ipv6conf->timer );
        ndp_tx_router_solicitation ( ipv6conf->netdev );
}
int start_ipv6conf ( struct interface job,
struct net_device netdev 
)

Start IPv6 autoconfiguration.

Parameters:
jobJob control interface
netdevNetwork device
Return values:
rcReturn status code

Definition at line 1227 of file ndp.c.

References ipv6conf::dhcp, ENOMEM, intf_init(), intf_plug_plug(), ipv6conf_expired(), ipv6conf_free(), ipv6conf::job, ipv6conf::list, list_add, ipv6conf::netdev, netdev_get(), ref_init, ipv6conf::refcnt, start_timer_nodelay(), ipv6conf::timer, and zalloc().

                                                                        {
        struct ipv6conf *ipv6conf;

        /* Allocate and initialise structure */
        ipv6conf = zalloc ( sizeof ( *ipv6conf ) );
        if ( ! ipv6conf )
                return -ENOMEM;
        ref_init ( &ipv6conf->refcnt, ipv6conf_free );
        intf_init ( &ipv6conf->job, &ipv6conf_job_desc, &ipv6conf->refcnt );
        intf_init ( &ipv6conf->dhcp, &ipv6conf_dhcp_desc, &ipv6conf->refcnt );
        timer_init ( &ipv6conf->timer, ipv6conf_expired, &ipv6conf->refcnt );
        ipv6conf->netdev = netdev_get ( netdev );

        /* Start timer to initiate router solicitation */
        start_timer_nodelay ( &ipv6conf->timer );

        /* Attach parent interface, transfer reference to list, and return */
        intf_plug_plug ( &ipv6conf->job, job );
        list_add ( &ipv6conf->list, &ipv6confs );
        return 0;
}

Variable Documentation

Initial value:
 {
        .name = "NDP",
        .tx_request = ndp_tx_request,
}

NDP neighbour discovery protocol.

Definition at line 148 of file ndp.c.

Referenced by ndp_tx().

Initial value:

NDP option handlers.

Definition at line 385 of file ndp.c.

Referenced by ndp_rx_option().

struct icmpv6_handler ndp_handlers [] __icmpv6_handler
Initial value:

NDP ICMPv6 handlers.

Definition at line 561 of file ndp.c.

NDP settings scope.

Definition at line 609 of file ndp.c.

Referenced by ndp_applies(), and ndp_register_settings().

Initial value:
 {
        .applies = ndp_applies,
        .fetch = ndp_fetch,
}

NDP settings operations.

Definition at line 743 of file ndp.c.

Initial value:
 {
        { &ip6_setting, ndp_prefix_fetch_ip6 },
        { &len6_setting, ndp_prefix_fetch_len6 },
        { &gateway6_setting, ndp_prefix_fetch_gateway6 },
}

NDP per-prefix settings operations.

Definition at line 873 of file ndp.c.

Referenced by ndp_prefix_fetch().

Initial value:
 {
        .applies = ndp_prefix_applies,
        .fetch = ndp_prefix_fetch,
}

NDP per-prefix settings operations.

Definition at line 906 of file ndp.c.

Initial value:

IPv6 configurator job interface operations.

Definition at line 1203 of file ndp.c.

Initial value:

IPv6 configurator job interface descriptor.

Definition at line 1208 of file ndp.c.

Initial value:

IPv6 configurator DHCPv6 interface operations.

Definition at line 1212 of file ndp.c.

Initial value:

IPv6 configurator DHCPv6 interface descriptor.

Definition at line 1217 of file ndp.c.

Initial value:
 {
        .name = "ipv6",
        .start = start_ipv6conf,
}

IPv6 network device configurator.

Definition at line 1250 of file ndp.c.