diff --git a/CHANGELOG b/CHANGELOG index 42e81894..653a8879 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,9 @@ HISTORY ++ New features: + 2016-12-14: Jan Breuer: + opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106) + 2016-12-14: David van Moolenbroek * opt.h, nd6.c: Added LWIP_HOOK_ND6_GET_GW() diff --git a/src/core/ipv6/nd6.c b/src/core/ipv6/nd6.c index 4dbaa7c5..689b56e7 100644 --- a/src/core/ipv6/nd6.c +++ b/src/core/ipv6/nd6.c @@ -60,6 +60,7 @@ #include "lwip/mld6.h" #include "lwip/ip.h" #include "lwip/stats.h" +#include "lwip/dns.h" #include @@ -394,6 +395,10 @@ nd6_input(struct pbuf *p, struct netif *inp) struct ra_header *ra_hdr; u8_t *buffer; /* Used to copy options. */ u16_t offset; +#ifdef LWIP_ND6_RDNSS_MAX_DNS_SERVERS + /* There can by multiple RDNSS options per RA */ + u8_t rdnss_server_idx = 0; +#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ /* Check that RA header fits in packet. */ if (p->len < sizeof(struct ra_header)) { @@ -538,6 +543,34 @@ nd6_input(struct pbuf *p, struct netif *inp) route_opt = (struct route_option *)buffer;*/ break; +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS + case ND6_OPTION_TYPE_RDNSS: + { + u8_t num, n; + struct rdnss_option * rdnss_opt; + rdnss_opt = (struct rdnss_option *)buffer; + num = (rdnss_opt->length - 1) / 2; + for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) { + /* Get a memory-aligned copy of the prefix. */ + ip6_addr_set(ip6_current_dest_addr(), &(rdnss_opt->rdnss_address[n])); + + if (htonl(rdnss_opt->lifetime) > 0) { + /* TODO implement Lifetime > 0 */ + dns_setserver(rdnss_server_idx++, ip_current_dest_addr()); + } else { + /* TODO implement DNS removal in dns.c */ + u8_t s; + for (s = 0; s < DNS_MAX_SERVERS; s++) { + const ip_addr_t *addr = dns_getserver(s); + if(ip_addr_cmp(addr, ip_current_dest_addr())) { + dns_setserver(s, NULL); + } + } + } + } + break; + } +#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ default: /* Unrecognized option, abort. */ ND6_STATS_INC(nd6.proterr); diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 2326b301..d350f3ce 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -2378,6 +2378,14 @@ #define LWIP_ND6_TCP_REACHABILITY_HINTS 1 #endif +/** + * LWIP_ND6_RDNSS_MAX_DNS_SERVERS > 0: Use IPv6 Router Advertisement Recursive + * DNS Server Option (as per RFC 6106) to copy a defined maximum number of DNS + * servers to the DNS module. + */ +#if !defined LWIP_ND6_RDNSS_MAX_DNS_SERVERS || defined __DOXYGEN__ +#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0 +#endif /** * @} */ diff --git a/src/include/lwip/prot/nd6.h b/src/include/lwip/prot/nd6.h index 7f46c535..2d4903d1 100644 --- a/src/include/lwip/prot/nd6.h +++ b/src/include/lwip/prot/nd6.h @@ -247,6 +247,29 @@ PACK_STRUCT_END # include "arch/epstruct.h" #endif +/** Recursive DNS Server Option. */ +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS +#define LWIP_RDNSS_OPTION_MAX_SERVERS LWIP_ND6_RDNSS_MAX_DNS_SERVERS +#else +#define LWIP_RDNSS_OPTION_MAX_SERVERS 1 +#endif +#define ND6_OPTION_TYPE_RDNSS (25) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct rdnss_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(u32_t lifetime); + PACK_STRUCT_FLD_S(ip6_addr_p_t rdnss_address[LWIP_RDNSS_OPTION_MAX_SERVERS]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + #ifdef __cplusplus } #endif