ndp.h 20 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
/*
 * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
 *
 * This file is subject to the terms and conditions of the GNU Lesser General
 * Public License v2.1. See the file LICENSE in the top level directory for
 * more details.
 */

/**
 * @defgroup    net_gnrc_ndp  IPv6 Neighbor discovery
 * @ingroup     net_gnrc_icmpv6
 * @brief       GNRC's IPv6 Neighbor Discovery implementation
 * @{
 *
 * @file
 * @brief       Definitions for GNRC's IPv6 Neighbor Discovery
 *
 * @author      Martine Lenders <mlenders@inf.fu-berlin.de>
 */

#ifndef GNRC_NDP_H_
#define GNRC_NDP_H_

#include <inttypes.h>
#include <stdlib.h>

#include "byteorder.h"
#include "net/ndp.h"
#include "net/gnrc/pkt.h"
#include "net/gnrc/icmpv6.h"
#include "net/ipv6/addr.h"
#include "net/gnrc/ipv6/nc.h"
#include "net/gnrc/ipv6/netif.h"

#include "net/gnrc/ndp/host.h"
#include "net/gnrc/ndp/internal.h"
#include "net/gnrc/ndp/router.h"
#include "net/gnrc/ndp/node.h"

#ifdef __cplusplus
extern "C" {
#endif

/** Message type for router timeouts */
#define GNRC_NDP_MSG_RTR_TIMEOUT                (0x0210)
/** Message type for address timeouts */
#define GNRC_NDP_MSG_ADDR_TIMEOUT               (0x0211)
/** Message type for multicast neighbor solicitation retransmissions */
#define GNRC_NDP_MSG_NBR_SOL_RETRANS            (0x0212)
/** Message type for periodic router advertisements */
#define GNRC_NDP_MSG_RTR_ADV_RETRANS            (0x0213)
/** Message type for delayed router advertisements */
#define GNRC_NDP_MSG_RTR_ADV_DELAY              (0x0214)
/** Message type for delayed router advertisements in a 6LoWPAN
 * 6LoWPAN needs a special handling, because router advertisements are only
 * sent after a short randomized delay, but not periodically. */
#define GNRC_NDP_MSG_RTR_ADV_SIXLOWPAN_DELAY    (0x0215)
/** Message type for periodic router solicitations */
#define GNRC_NDP_MSG_RTR_SOL_RETRANS            (0x0216)
/** Message type for neighbor cache state timeouts */
#define GNRC_NDP_MSG_NC_STATE_TIMEOUT           (0x0217)

/**
 * @name    Host constants
 * @{
 * @see     <a href="https://tools.ietf.org/html/rfc4861#section-10">
 *              RFC 4861, section 10
 *          </a>
 */
/**
 * @brief   Upper bound for randomised delay in seconds for initial
 *          router solicitation transmissions
 */
#define GNRC_NDP_MAX_RTR_SOL_DELAY      (1U)

/**
 * @brief   Interval in seconds between initial router solicitation
 *          transmissions
 */
#define GNRC_NDP_MAX_RTR_SOL_INT        (4U)

/**
 * @brief   Maximum number of  initial router solicitation transmissions
 */
#define GNRC_NDP_MAX_RTR_SOL_NUMOF      (3U)
/** @} */

/**
 * @name    Node constants
 * @{
 * @see     <a href="https://tools.ietf.org/html/rfc4861#section-10">
 *              RFC 4861, section 10
 *          </a>
 */
/**
 * @brief   Maximum number of unanswered multicast neighbor solicitations
 *          before address resolution is considered failed.
 */
#define GNRC_NDP_MAX_MC_NBR_SOL_NUMOF   (3U)

/**
 * @brief   Maximum number of unanswered unicast neighbor solicitations before
 *          an address is considered unreachable.
 */
#define GNRC_NDP_MAX_UC_NBR_SOL_NUMOF   (3U)

/**
 * @brief   Upper bound of randomized delay in seconds for a solicited
 *          neighbor advertisement transmission for an anycast target.
 */
#define GNRC_NDP_MAX_AC_TGT_DELAY       (1U)

/**
 * @brief   Maximum number of unsolicited neighbor advertisements before on
 *          link-layer address change.
 */
#define GNRC_NDP_MAX_NBR_ADV_NUMOF      (3U)

/**
 * @brief   Base value in mircoseconds for computing randomised
 *          reachable time.
 */
#define GNRC_NDP_REACH_TIME             (30U * SEC_IN_USEC)

/**
 * @brief   Time in mircoseconds between retransmissions of neighbor
 *          solicitations to a neighbor.
 */
#define GNRC_NDP_RETRANS_TIMER          (1U * SEC_IN_USEC)

/**
 * @brief   Delay in seconds for neighbor cache entry between entering
 *          DELAY state and entering PROBE state if no reachability
 *          confirmation has been received.
 */
#define GNRC_NDP_FIRST_PROBE_DELAY      (5U)

/**
 * @brief   Lower bound for randomised reachable time calculation.
 */
#define GNRC_NDP_MIN_RAND               (5U)

/**
 * @brief   Upper bound for randomised reachable time calculation.
 */
#define GNRC_NDP_MAX_RAND               (15U)
/** @} */

/**
 * @name    Router constants
 * @{
 * @see     <a href="https://tools.ietf.org/html/rfc4861#section-10">
 *              RFC 4861, section 10
 *          </a>
 */
/**
 * @brief   Initial router advertisement interval in seconds
 */
#define GNRC_NDP_MAX_INIT_RTR_ADV_INT   (16U)

/**
 * @brief   Maximum number of initial router advertisement transmissions
 */
#define GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF (3U)

/**
 * @brief   Maximum number of final router advertisement transmissions
 */
#define GNRC_NDP_MAX_FIN_RTR_ADV_NUMOF  (3U)

/**
 * @brief   Minimum delay in seconds between router advertisement
 *          transmissions
 */
#define GNRC_NDP_MIN_RTR_ADV_DELAY      (3U)

/**
 * @brief   Upper bound for randomised delay in microseconds between router
 *          solicitation reception and responding router advertisement
 *          transmission.
 */
#define GNRC_NDP_MAX_RTR_ADV_DELAY      (500U * MS_IN_USEC)
/** @} */

/**
 * @brief   Handles received neighbor solicitations.
 *
 * @param[in] iface         The receiving interface.
 * @param[in] pkt           The received packet.
 * @param[in] ipv6          The IPv6 header in @p pkt.
 * @param[in] nbr_sol       The neighbor solicitation in @p pkt.
 * @param[in] icmpv6_size   The overall size of the neighbor solicitation.
 */
void gnrc_ndp_nbr_sol_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                             ipv6_hdr_t *ipv6, ndp_nbr_sol_t *nbr_sol,
                             size_t icmpv6_size);

/**
 * @brief   Handles received neighbor advertisements.
 *
 * @param[in] iface         The receiving interface.
 * @param[in] pkt           The received packet.
 * @param[in] ipv6          The IPv6 header in @p pkt.
 * @param[in] nbr_adv       The neighbor advertisement in @p pkt.
 * @param[in] icmpv6_size   The overall size of the neighbor advertisement.
 */
void gnrc_ndp_nbr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                             ipv6_hdr_t *ipv6, ndp_nbr_adv_t *nbr_adv,
                             size_t icmpv6_size);

#if (defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER))
/**
 * @brief   Handles received router solicitations.
 *
 * @param[in] iface         The receiving interface.
 * @param[in] pkt           The received packet.
 * @param[in] ipv6          The IPv6 header in @p pkt.
 * @param[in] rtr_sol       The router solicitation in @p pkt.
 * @param[in] icmpv6_size   The overall size of the router solicitation.
 */
void gnrc_ndp_rtr_sol_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                             ipv6_hdr_t *ipv6, ndp_rtr_sol_t *rtr_sol,
                             size_t icmpv6_size);
#else
/**
 * @brief   A host *must* silently discard all received router solicitations.
 * @see     <a href="https://tools.ietf.org/html/rfc4861#section-6.2.6">
 *              RFC 4861, section 6.2.6
 *          </a>
 *
 * This macro is primarily an optimization to not go into the function defined
 * above.
 */
#define gnrc_ndp_rtr_sol_handle(iface, pkt, ipv6, rtr_sol, size)
#endif

/**
 * @brief   Handles received router advertisements
 *
 * @todo    As router check consistency as described in RFC 4861, section 6.2.3
 *
 * @param[in] iface         The receiving interface.
 * @param[in] pkt           The received packet.
 * @param[in] ipv6          The IPv6 header in @p pkt.
 * @param[in] rtr_adv       The router advertisement in @p pkt.
 * @param[in] icmpv6_size   The overall size of the router advertisement.
 */
void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                             ipv6_hdr_t *ipv6, ndp_rtr_adv_t *rtr_adv,
                             size_t icmpv6_size);

/**
 * @brief   Retransmits a multicast neighbor solicitation for an incomplete or
 *          probing neighbor cache entry @p nc_entry,
 *          if nc_entry::probes_remaining > 0.
 *
 * @details If nc_entry::probes_remaining > 0 it will be decremented. If it
 *          reaches 0 it the entry @p nc_entry will be removed from the
 *          neighbor cache.
 *
 * @param[in]   nc_entry    A neighbor cache entry. Will be ignored if its state
 *                          is not @ref GNRC_IPV6_NC_STATE_INCOMPLETE or
 *                          @ref GNRC_IPV6_NC_STATE_PROBE.
 */
void gnrc_ndp_retrans_nbr_sol(gnrc_ipv6_nc_t *nc_entry);

/**
 * @brief   Event handler for a neighbor cache state timeout.
 *
 * @param[in]   nc_entry    A neighbor cache entry.
 */
void gnrc_ndp_state_timeout(gnrc_ipv6_nc_t *nc_entry);

/**
 * @brief   NDP interface initialization.
 *
 * @param[in] iface     An IPv6 interface descriptor. Must not be NULL.
 */
void gnrc_ndp_netif_add(gnrc_ipv6_netif_t *iface);

/**
 * @brief   NDP interface removal.
 *
 * @param[in] iface     An IPv6 interface descriptor. Must not be NULL.
 */
void gnrc_ndp_netif_remove(gnrc_ipv6_netif_t *iface);

/**
 * @brief   Get link-layer address and interface for next hop to destination
 *          IPv6 address.
 *
 * @param[out] l2addr           The link-layer for the next hop to @p dst.
 * @param[out] l2addr_len       Length of @p l2addr.
 * @param[in] iface             The interface to search the next hop on.
 *                              May be @ref KERNEL_PID_UNDEF if not specified.
 * @param[in] dst               An IPv6 address to search the next hop for.
 * @param[in] pkt               Packet to send to @p dst. Leave NULL if you
 *                              just want to get the addresses.
 *
 * @return  The PID of the interface, on success.
 * @return  -EHOSTUNREACH, if @p dst is not reachable.
 * @return  -ENOBUFS, if @p l2addr_len was smaller than the resulting @p l2addr
 *          would be long.
 */
kernel_pid_t gnrc_ndp_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len,
                                      kernel_pid_t iface, ipv6_addr_t *dst,
                                      gnrc_pktsnip_t *pkt);

/**
 * @brief   Builds a neighbor solicitation message for sending.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4861#section-4.3">
 *          RFC 4861, section 4.3
 *      </a>
 *
 * @param[in] tgt       The target address.
 * @param[in] options   Options to append to the router solicitation.
 *
 * @return  The resulting ICMPv6 packet on success.
 * @return  NULL, on failure.
 */
gnrc_pktsnip_t *gnrc_ndp_nbr_sol_build(ipv6_addr_t *tgt, gnrc_pktsnip_t *options);

/**
 * @brief   Builds a neighbor advertisement message for sending.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4861#section-4.4">
 *          RFC 4861, section 4.4
 *      </a>
 *
 * @param[in] flags     Neighbor advertisement flags:
 *                      @ref NDP_NBR_ADV_FLAGS_R == 1 indicates, that the
 *                      sender is a router,
 *                      @ref NDP_NBR_ADV_FLAGS_S == 1 indicates that the
 *                      advertisement was sent in response to a neighbor
 *                      solicitation,
 *                      @ref NDP_NBR_ADV_FLAGS_O == 1 indicates that the
 *                      advertisement should override an existing cache entry
 *                      and update the cached link-layer address.
 * @param[in] tgt       For solicited advertisements, the Target Address field
 *                      in the neighbor solicitaton.
 *                      For and unsolicited advertisement, the address whose
 *                      link-layer address has changed.
 *                      MUST NOT be multicast.
 * @param[in] options   Options to append to the neighbor advertisement.
 *
 * @return  The resulting ICMPv6 packet on success.
 * @return  NULL, on failure.
 */
gnrc_pktsnip_t *gnrc_ndp_nbr_adv_build(uint8_t flags, ipv6_addr_t *tgt,
                                       gnrc_pktsnip_t *options);

/**
 * @brief   Builds a router solicitation message for sending.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4861#section-4.1">
 *          RFC 4861, section 4.1
 *      </a>
 *
 * @param[in] options   Options to append to the router solicitation.
 *
 * @return  The resulting ICMPv6 packet on success.
 * @return  NULL, on failure.
 */
gnrc_pktsnip_t *gnrc_ndp_rtr_sol_build(gnrc_pktsnip_t *options);

/**
 * @brief   Builds a router solicitation message for sending.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4861#section-4.1">
 *          RFC 4861, section 4.1
 *      </a>
 *
 * @param[in] options   Options to append to the router solicitation.
 *
 * @return  The resulting ICMPv6 packet on success.
 * @return  NULL, on failure.
 */
gnrc_pktsnip_t *gnrc_ndp_rtr_sol_build(gnrc_pktsnip_t *options);

#if (defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER))
/**
 * @brief   Builds a router advertisement message for sending.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4861#section-4.2">
 *          RFC 4861, section 4.2
 *      </a>
 *
 * @note    The source address for the packet MUST be the link-local address
 *          of the interface.
 *
 * @param[in] cur_hl        Default hop limit for outgoing IP packets, 0 if
 *                          unspecified by this router.
 * @param[in] flags         Flags as defined above.
 *                          @ref NDP_RTR_ADV_FLAGS_M == 1 indicates, that the
 *                          addresses are managed by DHCPv6,
 *                          @ref NDP_RTR_ADV_FLAGS_O == 1 indicates that other
 *                          configuration information is available via DHCPv6.
 * @param[in] ltime         Lifetime of the default router in seconds.
 * @param[in] reach_time    Time in milliseconds a node should assume a neighbor
 *                          reachable. 0 means unspecified by the router.
 * @param[in] retrans_timer Time in milliseconds between retransmitted
 *                          neighbor solicitations. 0 means unspecified by
 *                          the router.
 * @param[in] options       Options to append to the router advertisement.
 *
 * @return  The resulting ICMPv6 packet on success.
 * @return  NULL, on failure.
 */
gnrc_pktsnip_t *gnrc_ndp_rtr_adv_build(uint8_t cur_hl, uint8_t flags, uint16_t ltime,
                                       uint32_t reach_time, uint32_t retrans_timer,
                                       gnrc_pktsnip_t *options);
#else
/**
 * @brief   A host *must not* send router advertisements at any time (so why build them?)
 * @see     <a href="https://tools.ietf.org/html/rfc4861#section-6.3.4">
 *              RFC 4861, section 6.3.4
 *          </a>
 *
 * This macro is primarily an optimization to not go into the function defined
 * above.
 */
#define gnrc_ndp_rtr_adv_build(cur_hl, flags, ltime, reach_time, retrans_timer, options) (NULL)
#endif

/**
 * @brief   Builds a generic NDP option.
 *
 * @param[in] type  Type of the option.
 * @param[in] size  Size in byte of the option (will be rounded up to the next
 *                  multiple of 8).
 * @param[in] next  More options in the packet. NULL, if there are none.
 *
 * @return  The packet snip list of options, on success
 * @return  NULL, if packet buffer is full
 */
gnrc_pktsnip_t *gnrc_ndp_opt_build(uint8_t type, size_t size, gnrc_pktsnip_t *next);

/**
 * @brief   Builds the source link-layer address option.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4861#section-4.6.1">
 *          RFC 4861, section 4.6.1
 *      </a>
 *
 * @note    Must only be used with neighbor solicitations, router solicitations,
 *          and router advertisements. This is not checked however, since
 *          hosts should silently ignore it in other NDP messages.
 *
 * @param[in] l2addr        A link-layer address of variable length.
 * @param[in] l2addr_len    Length of @p l2addr.
 * @param[in] next          More options in the packet. NULL, if there are none.
 *
 * @return  The packet snip list of options, on success
 * @return  NULL, if packet buffer is full
 */
gnrc_pktsnip_t *gnrc_ndp_opt_sl2a_build(const uint8_t *l2addr, uint8_t l2addr_len,
                                        gnrc_pktsnip_t *next);

/**
 * @brief   Builds the target link-layer address option.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4861#section-4.6.1">
 *          RFC 4861, section 4.6.1
 *      </a>
 *
 * @note    Must only be used with neighbor advertisemnents and redirect packets.
 *          This is not checked however, since hosts should silently ignore it
 *          in other NDP messages.
 *
 * @param[in] l2addr        A link-layer address of variable length.
 * @param[in] l2addr_len    Length of @p l2addr.
 * @param[in] next          More options in the packet. NULL, if there are none.
 *
 * @return  The pkt snip list of options, on success
 * @return  NULL, if packet buffer is full
 */
gnrc_pktsnip_t *gnrc_ndp_opt_tl2a_build(const uint8_t *l2addr, uint8_t l2addr_len,
                                        gnrc_pktsnip_t *next);

#if (defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER))
/**
 * @brief   Builds the prefix information option.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4861#section-4.6.2">
 *          RFC 4861, section 4.6.2
 *      </a>
 *
 * @note    Must only be used with router advertisemnents. This is not checked
 *          however, since nodes should silently ignore it in other NDP messages.
 *
 * @param[in] prefix_len    The length of @p prefix in bits. Must be between
 *                          0 and 128.
 * @param[in] flags         Flags as defined above.
 *                          @ref NDP_OPT_PI_FLAGS_L == 1 indicates, that
 *                          @p prefix can be used for on-link determination,
 *                          @ref NDP_OPT_PI_FLAGS_A == 1 indicates, that
 *                          @p prefix can be used for stateless address
 *                          configuration.
 * @param[in] valid_ltime   Length of time in seconds that @p prefix is valid.
 *                          UINT32_MAX represents infinity.
 * @param[in] pref_ltime    Length of time in seconds that addresses using
 *                          @p prefix remain prefered. UINT32_MAX represents
 *                          infinity.
 * @param[in] prefix        An IPv6 address or a prefix of an IPv6 address.
 * @param[in] next          More options in the packet. NULL, if there are none.
 *
 * @return  The packet snip list of options, on success
 * @return  NULL, if packet buffer is full
 */
gnrc_pktsnip_t *gnrc_ndp_opt_pi_build(uint8_t prefix_len, uint8_t flags,
                                      uint32_t valid_ltime, uint32_t pref_ltime,
                                      ipv6_addr_t *prefix, gnrc_pktsnip_t *next);

/**
 * @brief   Builds the MTU option.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4861#section-4.6.4">
 *          RFC 4861, section 4.6.4
 *      </a>
 *
 * @note    Must only be used with router advertisemnents. This is not checked
 *          however, since nodes should silently ignore it in other NDP messages.
 *
 * @param[in] mtu           The recommended MTU for the link.
 * @param[in] next          More options in the packet. NULL, if there are none.
 *
 * @return  The packet snip list of options, on success
 * @return  NULL, if packet buffer is full
 */
gnrc_pktsnip_t *gnrc_ndp_opt_mtu_build(uint32_t mtu, gnrc_pktsnip_t *next);
#else
/**
 * @brief   A host *must not* send router advertisements at any time (so why build their options?)
 * @see     <a href="https://tools.ietf.org/html/rfc4861#section-6.3.4">
 *              RFC 4861, section 6.3.4
 *          </a>
 *
 * This macro is primarily an optimization to not go into the function defined
 * above.
 */
#define gnrc_ndp_opt_pi_build(prefix_len, flags, valid_ltime, pref_ltime, prefix, next) (NULL)

/**
 * @brief   A host *must not* send router advertisements at any time (so why build their options?)
 * @see     <a href="https://tools.ietf.org/html/rfc4861#section-6.3.4">
 *              RFC 4861, section 6.3.4
 *          </a>
 *
 * This macro is primarily an optimization to not go into the function defined
 * above.
 */
#define gnrc_ndp_opt_mtu_build(mtu, next)   (NULL)
#endif

#ifdef __cplusplus
}
#endif

#endif /* GNRC_NDP_H_ */
/**
 * @}
 */