mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-24 22:13:52 +01:00
Merge pull request #8646 from miri64/gnrc/enh/dns-config
gnrc_ipv6_nib: Add capability to handle and send RDNSS option
This commit is contained in:
commit
dd165628ff
@ -305,6 +305,10 @@ ifneq (,$(filter gnrc_ipv6_nib_6ln,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sixlowpan_nd
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_ipv6_nib_dns,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ipv6_nib
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_ipv6_nib_router,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ipv6_nib
|
||||
endif
|
||||
@ -315,6 +319,9 @@ ifneq (,$(filter gnrc_ipv6_nib,$(USEMODULE)))
|
||||
USEMODULE += gnrc_netif
|
||||
USEMODULE += ipv6_addr
|
||||
USEMODULE += random
|
||||
ifneq (,$(filter sock_dns,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ipv6_nib_dns
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_udp,$(USEMODULE)))
|
||||
|
||||
@ -17,6 +17,7 @@ PSEUDOMODULES += gnrc_ipv6_router_default
|
||||
PSEUDOMODULES += gnrc_ipv6_nib_6lbr
|
||||
PSEUDOMODULES += gnrc_ipv6_nib_6ln
|
||||
PSEUDOMODULES += gnrc_ipv6_nib_6lr
|
||||
PSEUDOMODULES += gnrc_ipv6_nib_dns
|
||||
PSEUDOMODULES += gnrc_ipv6_nib_router
|
||||
PSEUDOMODULES += gnrc_netdev_default
|
||||
PSEUDOMODULES += gnrc_neterr
|
||||
|
||||
@ -222,6 +222,17 @@ extern "C" {
|
||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_SLAAC != 0
|
||||
*/
|
||||
#define GNRC_IPV6_NIB_VALID_ADDR (0x4fd2U)
|
||||
|
||||
/**
|
||||
* @brief Recursive DNS server timeout
|
||||
*
|
||||
* This message type is for the event of a recursive DNS server timeout.
|
||||
* The expected message context is the [UDP end point](@ref sock_udp_ep_t)
|
||||
* representing the DNS server.
|
||||
*
|
||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_DNS != 0
|
||||
*/
|
||||
#define GNRC_IPV6_NIB_RDNSS_TIMEOUT (0x4fd3U)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -68,6 +68,10 @@ extern "C" {
|
||||
#define GNRC_IPV6_NIB_CONF_ROUTER (1)
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_GNRC_IPV6_NIB_DNS
|
||||
#define GNRC_IPV6_NIB_CONF_DNS (1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Compile flags
|
||||
* @brief Compile flags to (de-)activate certain features for NIB
|
||||
@ -171,6 +175,15 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Support for DNS configuration options
|
||||
*
|
||||
* @see [RFC 8106](https://tools.ietf.org/html/rfc8106)
|
||||
*/
|
||||
#ifndef GNRC_IPV6_NIB_CONF_DNS
|
||||
#define GNRC_IPV6_NIB_CONF_DNS (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Multihop prefix and 6LoWPAN context distribution
|
||||
*
|
||||
|
||||
@ -250,6 +250,29 @@ gnrc_pktsnip_t *gnrc_ndp_opt_pi_build(const ipv6_addr_t *prefix,
|
||||
*/
|
||||
gnrc_pktsnip_t *gnrc_ndp_opt_mtu_build(uint32_t mtu, gnrc_pktsnip_t *next);
|
||||
|
||||
/**
|
||||
* @brief Builts the recursive DNS server option
|
||||
*
|
||||
* @see [RFC 8106, section 5.1](https://tools.ietf.org/html/rfc8106#section-5.1)
|
||||
* @pre `addrs != NULL`
|
||||
* @pre `addrs_num > 0`
|
||||
*
|
||||
* @note Should only be used with router advertisemnents. This is not checked
|
||||
* however, since nodes should silently ignore it in other NDP messages.
|
||||
*
|
||||
* @param[in] lifetime The lifetime of the recursive DNS servers
|
||||
* @param[in] addrs The addresses of the recursive DNS servers
|
||||
* @param[in] addrs_num The number of addresses in @p addrs
|
||||
* @param[in] next More options in the packet. NULL, if there are none.
|
||||
*
|
||||
* @return The packet snip list of options, on success
|
||||
* @return @p next, if RDNSS is not supported
|
||||
* @return NULL, if packet buffer is full
|
||||
*/
|
||||
gnrc_pktsnip_t *gnrc_ndp_opt_rdnss_build(uint32_t lifetime, ipv6_addr_t *addrs,
|
||||
unsigned addrs_num,
|
||||
gnrc_pktsnip_t *next);
|
||||
|
||||
/**
|
||||
* @brief Send pre-compiled neighbor solicitation depending on a given network
|
||||
* interface.
|
||||
|
||||
@ -88,6 +88,7 @@ extern "C" {
|
||||
#define NDP_OPT_PI (3) /**< prefix information option */
|
||||
#define NDP_OPT_RH (4) /**< redirected option */
|
||||
#define NDP_OPT_MTU (5) /**< MTU option */
|
||||
#define NDP_OPT_RDNSS (25) /**< recursive DNS server option */
|
||||
#define NDP_OPT_AR (33) /**< address registration option */
|
||||
#define NDP_OPT_6CTX (34) /**< 6LoWPAN context option */
|
||||
#define NDP_OPT_ABR (35) /**< authoritative border router option */
|
||||
@ -120,6 +121,12 @@ extern "C" {
|
||||
#define NDP_OPT_MTU_LEN (1U)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Minimum length of a recursive DNS server option (in units of 8 bytes)
|
||||
* @see [RFC 8106, section 5.1](https://tools.ietf.org/html/rfc8106#section-5.1)
|
||||
*/
|
||||
#define NDP_OPT_RDNSS_MIN_LEN (3U)
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @name Router constants
|
||||
@ -314,6 +321,19 @@ typedef struct __attribute__((packed)) {
|
||||
network_uint32_t mtu; /**< MTU */
|
||||
} ndp_opt_mtu_t;
|
||||
|
||||
/**
|
||||
* @brief Recursive DNS server option format
|
||||
* @extends ndp_opt_t
|
||||
*
|
||||
* @see [RFC 8106, section 5.1](https://tools.ietf.org/html/rfc8106#section-5.1)
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t type; /**< option type */
|
||||
uint8_t len; /**< length in units of 8 octets */
|
||||
network_uint16_t resv; /**< reserved field */
|
||||
network_uint32_t ltime; /**< lifetime in seconds */
|
||||
ipv6_addr_t addrs[]; /**< addresses of IPv6 recursive DNS servers */
|
||||
} ndp_opt_rdnss_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -28,6 +28,9 @@
|
||||
/* min domain name length is 1, so minimum record length is 7 */
|
||||
#define DNS_MIN_REPLY_LEN (unsigned)(sizeof(sock_dns_hdr_t ) + 7)
|
||||
|
||||
/* global DNS server UDP endpoint */
|
||||
sock_udp_ep_t sock_dns_server;
|
||||
|
||||
static ssize_t _enc_domain_name(uint8_t *out, const char *domain_name)
|
||||
{
|
||||
/*
|
||||
@ -132,6 +135,10 @@ int sock_dns_query(const char *domain_name, void *addr_out, int family)
|
||||
uint8_t buf[SOCK_DNS_QUERYBUF_LEN];
|
||||
uint8_t reply_buf[512];
|
||||
|
||||
if (sock_dns_server.port == 0) {
|
||||
return -ECONNREFUSED;
|
||||
}
|
||||
|
||||
if (strlen(domain_name) > SOCK_DNS_MAX_NAME_LEN) {
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
@ -17,6 +17,9 @@
|
||||
#include "net/gnrc/ndp.h"
|
||||
#include "net/gnrc/netif/internal.h"
|
||||
#include "net/gnrc/sixlowpan/nd.h"
|
||||
#if GNRC_IPV6_NIB_CONF_DNS
|
||||
#include "net/sock/dns.h"
|
||||
#endif
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||
#include "_nib-6ln.h"
|
||||
@ -131,6 +134,26 @@ static gnrc_pktsnip_t *_build_ext_opts(gnrc_netif_t *netif,
|
||||
_nib_offl_entry_t *pfx = NULL;
|
||||
unsigned id = netif->pid;
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_DNS && SOCK_HAS_IPV6
|
||||
uint32_t rdnss_ltime = _evtimer_lookup(&sock_dns_server,
|
||||
GNRC_IPV6_NIB_RDNSS_TIMEOUT);
|
||||
|
||||
if ((rdnss_ltime < UINT32_MAX) &&
|
||||
(!ipv6_addr_is_link_local((ipv6_addr_t *)sock_dns_server.addr.ipv6))) {
|
||||
gnrc_pktsnip_t *rdnsso = gnrc_ndp_opt_rdnss_build(
|
||||
rdnss_ltime * MS_PER_SEC,
|
||||
(ipv6_addr_t *)&sock_dns_server.addr,
|
||||
1U, ext_opts
|
||||
);
|
||||
if (rdnsso == NULL) {
|
||||
/* gnrc_ndp_opt_rdnss_build() only returns NULL when pktbuf is full
|
||||
* in this configuration */
|
||||
DEBUG("nib: No space left in packet buffer. Not adding RDNSSO\n");
|
||||
return NULL;
|
||||
}
|
||||
ext_opts = rdnsso;
|
||||
}
|
||||
#endif /* GNRC_IPV6_NIB_CONF_DNS */
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||
uint16_t ltime;
|
||||
gnrc_pktsnip_t *abro;
|
||||
|
||||
@ -26,6 +26,9 @@
|
||||
#include "net/gnrc/sixlowpan/nd.h"
|
||||
#include "net/ndp.h"
|
||||
#include "net/sixlowpan/nd.h"
|
||||
#if GNRC_IPV6_NIB_CONF_DNS
|
||||
#include "net/sock/dns.h"
|
||||
#endif
|
||||
|
||||
#include "_nib-internal.h"
|
||||
#include "_nib-arsm.h"
|
||||
@ -46,6 +49,10 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
static gnrc_pktqueue_t _queue_pool[GNRC_IPV6_NIB_NUMOF];
|
||||
#endif /* GNRC_IPV6_NIB_CONF_QUEUE_PKT */
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_DNS
|
||||
static evtimer_msg_event_t _rdnss_timeout;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @{
|
||||
@ -70,6 +77,9 @@ static void _handle_rtr_timeout(_nib_dr_entry_t *router);
|
||||
static void _handle_snd_na(gnrc_pktsnip_t *pkt);
|
||||
/* needs to be exported for 6LN's ARO handling */
|
||||
void _handle_search_rtr(gnrc_netif_t *netif);
|
||||
#if GNRC_IPV6_NIB_CONF_DNS
|
||||
static void _handle_rdnss_timeout(sock_udp_ep_t *dns_server);
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
void gnrc_ipv6_nib_init(void)
|
||||
@ -355,6 +365,10 @@ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type)
|
||||
case GNRC_IPV6_NIB_VALID_ADDR:
|
||||
_handle_valid_addr(ctx);
|
||||
break;
|
||||
#if GNRC_IPV6_NIB_CONF_DNS
|
||||
case GNRC_IPV6_NIB_RDNSS_TIMEOUT:
|
||||
_handle_rdnss_timeout(ctx);
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -388,6 +402,10 @@ void gnrc_ipv6_nib_change_rtr_adv_iface(gnrc_netif_t *netif, bool enable)
|
||||
*/
|
||||
static void _handle_mtuo(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6,
|
||||
const ndp_opt_mtu_t *mtuo);
|
||||
#if GNRC_IPV6_NIB_CONF_DNS
|
||||
static uint32_t _handle_rdnsso(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6,
|
||||
const ndp_opt_rdnss_t *rdnsso);
|
||||
#endif
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||
static uint32_t _handle_pio(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6,
|
||||
const ndp_opt_pi_t *pio,
|
||||
@ -696,6 +714,14 @@ static void _handle_rtr_adv(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6,
|
||||
#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */
|
||||
break;
|
||||
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
||||
#if GNRC_IPV6_NIB_CONF_DNS
|
||||
case NDP_OPT_RDNSS:
|
||||
next_timeout = _min(_handle_rdnsso(netif,
|
||||
(icmpv6_hdr_t *)rtr_adv,
|
||||
(ndp_opt_rdnss_t *)opt),
|
||||
next_timeout);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1225,6 +1251,13 @@ void _handle_search_rtr(gnrc_netif_t *netif)
|
||||
gnrc_netif_release(netif);
|
||||
}
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_DNS
|
||||
static void _handle_rdnss_timeout(sock_udp_ep_t *dns_server)
|
||||
{
|
||||
memset(dns_server, 0, sizeof(sock_udp_ep_t));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _handle_mtuo(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6,
|
||||
const ndp_opt_mtu_t *mtuo)
|
||||
{
|
||||
@ -1236,6 +1269,64 @@ static void _handle_mtuo(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6,
|
||||
}
|
||||
}
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_DNS
|
||||
static uint32_t _handle_rdnsso(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6,
|
||||
const ndp_opt_rdnss_t *rdnsso)
|
||||
{
|
||||
uint32_t ltime = UINT32_MAX;
|
||||
const ipv6_addr_t *addr;
|
||||
|
||||
if ((rdnsso->len < NDP_OPT_RDNSS_MIN_LEN) ||
|
||||
(icmpv6->type != ICMPV6_RTR_ADV)) {
|
||||
return ltime;
|
||||
}
|
||||
/* select first if unassigned, search possible address otherwise */
|
||||
addr = (sock_dns_server.port == 0) ? &rdnsso->addrs[0] : NULL;
|
||||
if (addr == NULL) {
|
||||
unsigned addrs_num = (rdnsso->len - 1) / 2;
|
||||
for (unsigned i = 0; i < addrs_num; i++) {
|
||||
if (memcmp(sock_dns_server.addr.ipv6,
|
||||
&rdnsso->addrs[i],
|
||||
sizeof(rdnsso->addrs[i])) == 0) {
|
||||
addr = &rdnsso->addrs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if SOCK_HAS_IPV6
|
||||
ltime = byteorder_ntohl(rdnsso->ltime);
|
||||
if (addr != NULL) {
|
||||
if (ltime > 0) {
|
||||
sock_dns_server.port = SOCK_DNS_PORT;
|
||||
sock_dns_server.family = AF_INET6;
|
||||
sock_dns_server.netif = netif->pid;
|
||||
memcpy(sock_dns_server.addr.ipv6, rdnsso->addrs,
|
||||
sizeof(sock_dns_server.addr.ipv6));
|
||||
|
||||
if (ltime < UINT32_MAX) {
|
||||
/* the valid lifetime is given in seconds, but our timers work
|
||||
* in milliseconds, so we have to scale down to the smallest
|
||||
* possible value (UINT32_MAX - 1). This is however alright
|
||||
* since we ask for a new router advertisement before this
|
||||
* timeout expires */
|
||||
ltime = (ltime > (UINT32_MAX / MS_PER_SEC)) ?
|
||||
(UINT32_MAX - 1) : ltime * MS_PER_SEC;
|
||||
_evtimer_add(&sock_dns_server, GNRC_IPV6_NIB_RDNSS_TIMEOUT,
|
||||
&_rdnss_timeout, ltime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
evtimer_del(&_nib_evtimer, &_rdnss_timeout.event);
|
||||
_handle_rdnss_timeout(&sock_dns_server);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)addr;
|
||||
#endif
|
||||
return ltime;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _remove_prefix(const ipv6_addr_t *pfx, unsigned pfx_len)
|
||||
{
|
||||
_nib_offl_entry_t *offl = NULL;
|
||||
|
||||
@ -222,6 +222,27 @@ gnrc_pktsnip_t *gnrc_ndp_opt_mtu_build(uint32_t mtu, gnrc_pktsnip_t *next)
|
||||
return pkt;
|
||||
}
|
||||
|
||||
gnrc_pktsnip_t *gnrc_ndp_opt_rdnss_build(uint32_t ltime, ipv6_addr_t *addrs,
|
||||
unsigned addrs_num,
|
||||
gnrc_pktsnip_t *next)
|
||||
{
|
||||
assert(addrs != NULL);
|
||||
assert(addrs_num > 0);
|
||||
size_t opt_size = sizeof(ndp_opt_t) + (sizeof(ipv6_addr_t) * addrs_num);
|
||||
gnrc_pktsnip_t *pkt = gnrc_ndp_opt_build(NDP_OPT_RDNSS, opt_size, next);
|
||||
|
||||
if (pkt != NULL) {
|
||||
ndp_opt_rdnss_t *rdnss_opt = pkt->data;
|
||||
rdnss_opt->resv.u16 = 0;
|
||||
rdnss_opt->ltime = byteorder_htonl(ltime);
|
||||
for (unsigned i = 0; i < addrs_num; i++) {
|
||||
memcpy(&rdnss_opt->addrs[i], &addrs[i],
|
||||
sizeof(rdnss_opt->addrs[i]));
|
||||
}
|
||||
}
|
||||
return pkt;
|
||||
}
|
||||
|
||||
static gnrc_pktsnip_t *_build_headers(gnrc_netif_t *netif,
|
||||
const ipv6_addr_t *src,
|
||||
const ipv6_addr_t *dst,
|
||||
|
||||
@ -9,6 +9,7 @@ BOARD_INSUFFICIENT_MEMORY := chronos telosb nucleo-f042k6 nucleo-f031k6 \
|
||||
USEMODULE += sock_dns
|
||||
USEMODULE += gnrc_sock_udp
|
||||
USEMODULE += gnrc_ipv6_default
|
||||
USEMODULE += gnrc_ipv6_nib_dns
|
||||
USEMODULE += gnrc_netdev_default
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
|
||||
|
||||
@ -31,13 +31,6 @@
|
||||
#define TEST_NAME "example.org"
|
||||
#endif
|
||||
|
||||
#ifndef DNS_SERVER
|
||||
#define DNS_SERVER "[2001:db8::1]:53"
|
||||
#endif
|
||||
|
||||
/* global DNS server UDP endpoint */
|
||||
sock_udp_ep_t sock_dns_server;
|
||||
|
||||
/* import "ifconfig" shell command, used for printing addresses */
|
||||
|
||||
extern int _gnrc_netif_config(int argc, char **argv);
|
||||
@ -46,8 +39,6 @@ int main(void)
|
||||
{
|
||||
uint8_t addr[16] = {0};
|
||||
|
||||
sock_udp_str2ep(&sock_dns_server, DNS_SERVER);
|
||||
|
||||
puts("waiting for router advertisement...");
|
||||
xtimer_usleep(1U*1000000);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user