diff --git a/apps/dhcp/dhcp.c b/apps/dhcp/dhcp.c index 9ac20b102..2c9d35003 100644 --- a/apps/dhcp/dhcp.c +++ b/apps/dhcp/dhcp.c @@ -88,7 +88,7 @@ makestrings(void) uip_getdraddr(&addr); makeaddr(&addr, gateway); - addrptr = resolv_getserver(); + addrptr = uip_nameserver_get(0); if(addrptr != NULL) { makeaddr(addrptr, dnsserver); } @@ -147,7 +147,7 @@ dhcpc_configured(const struct dhcpc_state *s) uip_sethostaddr(&s->ipaddr); uip_setnetmask(&s->netmask); uip_setdraddr(&s->default_router); - resolv_conf(&s->dnsaddr); + uip_nameserver_update(&s->dnsaddr, UIP_NAMESERVER_INFINITE_LIFETIME); set_statustext("Configured."); process_post(PROCESS_CURRENT(), SHOWCONFIG, NULL); } diff --git a/apps/netconf/netconf.c b/apps/netconf/netconf.c index 8249d35ec..b7a81fb99 100644 --- a/apps/netconf/netconf.c +++ b/apps/netconf/netconf.c @@ -113,7 +113,7 @@ makestrings(void) makeaddr(&addr, gateway); #if UIP_UDP - addrptr = resolv_getserver(); + addrptr = uip_nameserver_get(0); if(addrptr != NULL) { makeaddr(addrptr, dnsserver); } @@ -152,7 +152,7 @@ apply_tcpipconfig(void) #if UIP_UDP nullterminate(dnsserver); if(uiplib_ipaddrconv(dnsserver, &addr)) { - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); } #endif /* UIP_UDP */ } diff --git a/core/contiki-net.h b/core/contiki-net.h index d38d89344..087be23cb 100644 --- a/core/contiki-net.h +++ b/core/contiki-net.h @@ -44,6 +44,7 @@ #include "net/ip/uiplib.h" #include "net/ip/uip-udp-packet.h" #include "net/ip/simple-udp.h" +#include "net/ip/uip-nameserver.h" #if NETSTACK_CONF_WITH_IPV6 #include "net/ipv6/uip-icmp6.h" diff --git a/core/net/ip/resolv.c b/core/net/ip/resolv.c index 5df53ecac..4a9999cca 100644 --- a/core/net/ip/resolv.c +++ b/core/net/ip/resolv.c @@ -65,6 +65,7 @@ #include "net/ip/tcpip.h" #include "net/ip/resolv.h" #include "net/ip/uip-udp-packet.h" +#include "net/ip/uip-nameserver.h" #include "lib/random.h" #ifndef DEBUG @@ -227,17 +228,6 @@ struct dns_hdr { uint16_t numextrarr; }; -/** These default values for the DNS server are Google's public DNS: - * - */ -static uip_ipaddr_t resolv_default_dns_server = -#if NETSTACK_CONF_WITH_IPV6 - { { 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 } }; -#else /* NETSTACK_CONF_WITH_IPV6 */ - { { 8, 8, 8, 8 } }; -#endif /* NETSTACK_CONF_WITH_IPV6 */ - /** \internal The DNS answer message structure. */ struct dns_answer { /* DNS answer record starts with either a domain name or a pointer @@ -269,6 +259,7 @@ struct namemap { #endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */ uip_ipaddr_t ipaddr; uint8_t err; + uint8_t server; #if RESOLV_CONF_SUPPORTS_MDNS int is_mdns:1, is_probe:1; #endif @@ -637,6 +628,21 @@ mdns_prep_host_announce_packet(void) } #endif /* RESOLV_CONF_SUPPORTS_MDNS */ /*---------------------------------------------------------------------------*/ +static char +try_next_server(struct namemap *namemapptr) +{ +#if VERBOSE_DEBUG + printf("server %d\n", namemapptr->server); +#endif + namemapptr->server++; + if(uip_nameserver_get(namemapptr->server) != NULL) { + namemapptr->retries = 0; + return 1; + } + namemapptr->server = 0; + return 0; +} +/*---------------------------------------------------------------------------*/ /** \internal * Runs through the list of names to see if there are any that have * not yet been queried and, if so, sends out a query. @@ -666,16 +672,20 @@ check_entries(void) if(++namemapptr->retries == RESOLV_CONF_MAX_RETRIES) #endif /* RESOLV_CONF_SUPPORTS_MDNS */ { - /* STATE_ERROR basically means "not found". */ - namemapptr->state = STATE_ERROR; + /* Try the next server (if possible) before failing. Otherwise + simply mark the entry as failed. */ + if(try_next_server(namemapptr) == 0) { + /* STATE_ERROR basically means "not found". */ + namemapptr->state = STATE_ERROR; #if RESOLV_SUPPORTS_RECORD_EXPIRATION - /* Keep the "not found" error valid for 30 seconds */ - namemapptr->expiration = clock_seconds() + 30; + /* Keep the "not found" error valid for 30 seconds */ + namemapptr->expiration = clock_seconds() + 30; #endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */ - resolv_found(namemapptr->name, NULL); - continue; + resolv_found(namemapptr->name, NULL); + continue; + } } namemapptr->tmr = namemapptr->retries * namemapptr->retries * 3; @@ -747,7 +757,9 @@ check_entries(void) } else { uip_udp_packet_sendto(resolv_conn, uip_appdata, (query - (uint8_t *) uip_appdata), - &resolv_default_dns_server, UIP_HTONS(DNS_PORT)); + (const uip_ipaddr_t *) + uip_nameserver_get(namemapptr->server), + UIP_HTONS(DNS_PORT)); PRINTF("resolver: (i=%d) Sent DNS request for \"%s\".\n", i, namemapptr->name); @@ -755,7 +767,8 @@ check_entries(void) #else /* RESOLV_CONF_SUPPORTS_MDNS */ uip_udp_packet_sendto(resolv_conn, uip_appdata, (query - (uint8_t *) uip_appdata), - &resolv_default_dns_server, UIP_HTONS(DNS_PORT)); + uip_nameserver_get(namemapptr->server), + UIP_HTONS(DNS_PORT)); PRINTF("resolver: (i=%d) Sent DNS request for \"%s\".\n", i, namemapptr->name); #endif /* RESOLV_CONF_SUPPORTS_MDNS */ @@ -1041,11 +1054,28 @@ newdata(void) uip_ipaddr_copy(&namemapptr->ipaddr, (uip_ipaddr_t *) ans->ipaddr); resolv_found(namemapptr->name, &namemapptr->ipaddr); + break; skip_to_next_answer: queryptr = (unsigned char *)skip_name(queryptr) + 10 + uip_htons(ans->len); --nanswers; } + + /* Got to this point there's no answer, try next nameserver if available + since this one doesn't know the answer */ +#if RESOLV_CONF_SUPPORTS_MDNS + if(nanswers == 0 && UIP_UDP_BUF->srcport != UIP_HTONS(MDNS_PORT) + && hdr->id != 0) +#else + if(nanswers == 0) +#endif + { + if(try_next_server(namemapptr)) { + namemapptr->state = STATE_ASKING; + process_post(&resolv_process, PROCESS_EVENT_TIMER, NULL); + } + } + } /*---------------------------------------------------------------------------*/ #if RESOLV_CONF_SUPPORTS_MDNS @@ -1405,31 +1435,6 @@ resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr) return ret; } /*---------------------------------------------------------------------------*/ -/** - * Obtain the currently configured DNS server. - * - * \return A pointer to a 4-byte representation of the IP address of - * the currently configured DNS server or NULL if no DNS server has - * been configured. - */ -uip_ipaddr_t * -resolv_getserver(void) -{ - return &resolv_default_dns_server; -} -/*---------------------------------------------------------------------------*/ -/** - * Configure a DNS server. - * - * \param dnsserver A pointer to a 4-byte representation of the IP - * address of the DNS server to be configured. - */ -void -resolv_conf(const uip_ipaddr_t * dnsserver) -{ - uip_ipaddr_copy(&resolv_default_dns_server, dnsserver); -} -/*---------------------------------------------------------------------------*/ /** \internal * Callback function which is called when a hostname is found. * diff --git a/core/net/ip/resolv.h b/core/net/ip/resolv.h index cf1fef7e0..ed24d5bce 100644 --- a/core/net/ip/resolv.h +++ b/core/net/ip/resolv.h @@ -57,11 +57,6 @@ */ CCIF extern process_event_t resolv_event_found; -/* Functions. */ -CCIF void resolv_conf(const uip_ipaddr_t * dnsserver); - -CCIF uip_ipaddr_t *resolv_getserver(void); - enum { /** Hostname is fresh and usable. This response is cached and will eventually * expire to RESOLV_STATUS_EXPIRED.*/ @@ -95,6 +90,7 @@ enum { typedef uint8_t resolv_status_t; +/* Functions. */ CCIF resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr); CCIF void resolv_query(const char *name); diff --git a/core/net/ip/uip-nameserver.c b/core/net/ip/uip-nameserver.c new file mode 100644 index 000000000..6ced6b91e --- /dev/null +++ b/core/net/ip/uip-nameserver.c @@ -0,0 +1,234 @@ +/** + * \addtogroup uip6 + * @{ + */ + +/** + * \file + * uIP Name Server interface + * \author Víctor Ariño + */ + +/* + * Copyright (c) 2014, tado° GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-net.h" + +#include "lib/list.h" +#include "lib/memb.h" + +#include +/** \brief Nameserver record */ +typedef struct uip_nameserver_record { + struct uip_nameserver_record *next; + uip_ipaddr_t ip; + uint32_t added; + uint32_t lifetime; +} uip_nameserver_record; + +/** \brief Initialization flag */ +static uint8_t initialized = 0; + +/** \name List and memory block + * @{ + */ +#if UIP_NAMESERVER_POOL_SIZE > 1 +LIST(dns); +MEMB(dnsmemb, uip_nameserver_record, UIP_NAMESERVER_POOL_SIZE); +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ +static uip_ipaddr_t serveraddr; +static uint32_t serverlifetime; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +/** @} */ + +/** \brief Expiration time in seconds */ +#define DNS_EXPIRATION(r) \ + (((UIP_NAMESERVER_INFINITE_LIFETIME - r->added) <= r->lifetime) ? \ + UIP_NAMESERVER_INFINITE_LIFETIME : r->added + r->lifetime) +/*----------------------------------------------------------------------------*/ +/** + * Initialize the module variables + */ +#if UIP_NAMESERVER_POOL_SIZE > 1 +static CC_INLINE void +init(void) +{ + list_init(dns); + memb_init(&dnsmemb); + initialized = 1; +} +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +/*----------------------------------------------------------------------------*/ +void +uip_nameserver_update(uip_ipaddr_t *nameserver, uint32_t lifetime) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + register uip_nameserver_record *e; + + if(initialized == 0) { + init(); + } + + for(e = list_head(dns); e != NULL; e = list_item_next(e)) { + if(uip_ipaddr_cmp(&e->ip, nameserver)) { + break; + /* RFC6106: In case there's no more space, the new servers should replace + * the the eldest ones */ + } + } + + if(e == NULL) { + if((e = memb_alloc(&dnsmemb)) != NULL) { + list_add(dns, e); + } else { + uip_nameserver_record *p; + for(e = list_head(dns), p = list_head(dns); p != NULL; + p = list_item_next(p)) { + if(DNS_EXPIRATION(p) < DNS_EXPIRATION(e)) { + e = p; + } + } + } + } + + /* RFC6106: In case the entry is existing the expiration time must be + * updated. Otherwise, new entries are added. */ + if(e != NULL) { + if(lifetime == 0) { + memb_free(&dnsmemb, e); + list_remove(dns, e); + } else { + e->added = clock_seconds(); + e->lifetime = lifetime; + uip_ipaddr_copy(&e->ip, nameserver); + } + } +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ + uip_ipaddr_copy(&serveraddr, nameserver); + serverlifetime = lifetime; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +#if UIP_NAMESERVER_POOL_SIZE > 1 +/** + * Purge expired records + */ +static void +purge(void) +{ + register uip_nameserver_record *e = NULL; + uint32_t time = clock_seconds(); + for(e = list_head(dns); e != NULL; e = list_item_next(e)) { + if(DNS_EXPIRATION(e) < time) { + list_remove(dns, e); + memb_free(&dnsmemb, e); + e = list_head(dns); + } + } +} +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +/*----------------------------------------------------------------------------*/ +uip_ipaddr_t * +uip_nameserver_get(uint8_t num) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + uint8_t i; + uip_nameserver_record *e = NULL; + + if(initialized == 0) { + return NULL; + } + purge(); + for(i = 1, e = list_head(dns); e != NULL && i <= num; + i++, e = list_item_next(e)) { + } + + if(e != NULL) { + return &e->ip; + } + return NULL; +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ + if(num > 0) { + return NULL; + } + return &serveraddr; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +uint32_t +uip_nameserver_next_expiration(void) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + register uip_nameserver_record *e = NULL; + uint32_t exp = UIP_NAMESERVER_INFINITE_LIFETIME; + uint32_t t; + + if(initialized == 0 || list_length(dns) == 0) { + return 0; + } + purge(); + for(e = list_head(dns); e != NULL; e = list_item_next(e)) { + t = DNS_EXPIRATION(e); + if(t < exp) { + exp = t; + } + } + + return exp; +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ + return serverlifetime; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +uint16_t +uip_nameserver_count(void) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + if(initialized == 0) { + return 0; + } + return list_length(dns); +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ +#if NETSTACK_CONF_WITH_IPV6 + if(uip_is_addr_unspecified(&serveraddr)) { +#else /* NETSTACK_CONF_WITH_IPV6 */ + if(uip_ipaddr_cmp(&serveraddr, &uip_all_zeroes_addr)) { +#endif /* NETSTACK_CONF_WITH_IPV6 */ + return 0; + } else { + return 1; + } +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ip/uip-nameserver.h b/core/net/ip/uip-nameserver.h new file mode 100644 index 000000000..41dcf58c8 --- /dev/null +++ b/core/net/ip/uip-nameserver.h @@ -0,0 +1,101 @@ +/** + * \addtogroup uip6 + * @{ + */ + +/** + * \file + * uIP Name Server interface + * \author Víctor Ariño + */ + +/* + * Copyright (c) 2014, tado° GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#ifndef UIP_NAMESERVER_H_ +#define UIP_NAMESERVER_H_ + +/** + * \name General + * @{ + */ +/** \brief Number of Nameservers to keep */ +#ifndef UIP_CONF_NAMESERVER_POOL_SIZE +#define UIP_NAMESERVER_POOL_SIZE 1 +#else /* UIP_CONF_NAMESERVER_POOL_SIZE */ +#define UIP_NAMESERVER_POOL_SIZE UIP_CONF_NAMESERVER_POOL_SIZE +#endif /* UIP_CONF_NAMESERVER_POOL_SIZE */ +/** \brief Infinite Lifetime indicator */ +#define UIP_NAMESERVER_INFINITE_LIFETIME 0xFFFFFFFF +/** @} */ + +/** + * \name Nameserver maintenance + * @{ + */ +/** + * \brief Insert or update a nameserver into/from the pool + * + * The list is kept according to the RFC6106, which indicates that new entries + * will replace old ones (with lower lifetime) and existing entries will update + * their lifetimes. + * + * \param nameserver Pointer to the nameserver ip address + * \param lifetime Life time of the given address. Minimum is 0, which is + * considered to remove an entry. Maximum is 0xFFFFFFFF which + * is considered infinite. + */ +void uip_nameserver_update(uip_ipaddr_t *nameserver, uint32_t lifetime); + +/** + * \brief Get a Nameserver ip address given in RA + * + * \param num The number of the nameserver to obtain, starting at 0 and going + * up to the pool size. + */ +uip_ipaddr_t *uip_nameserver_get(uint8_t num); + +/** + * \brief Get next expiration time + * + * The least expiration time is returned + */ +uint32_t uip_nameserver_next_expiration(void); + +/** + * \brief Get the number of recorded name servers + */ +uint16_t uip_nameserver_count(void); +/** @} */ + +#endif /* UIP_NAMESERVER_H_ */ +/** @} */ diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index accaf8271..701f458fa 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -72,6 +72,7 @@ #include "net/ipv6/uip-icmp6.h" #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6.h" +#include "net/ip/uip-nameserver.h" #include "lib/random.h" /*------------------------------------------------------------------*/ @@ -112,6 +113,7 @@ void uip_log(char *msg); #define UIP_ND6_OPT_HDR_BUF ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) #define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) #define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) +#define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) /** @} */ static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/ @@ -715,6 +717,29 @@ uip_nd6_ra_output(uip_ipaddr_t * dest) uip_len += UIP_ND6_OPT_MTU_LEN; nd6_opt_offset += UIP_ND6_OPT_MTU_LEN; + +#if UIP_ND6_RA_RDNSS + if(uip_nameserver_count() > 0) { + uint8_t i = 0; + uip_ipaddr_t *ip = &UIP_ND6_OPT_RDNSS_BUF->ip; + uip_ipaddr_t *dns = NULL; + UIP_ND6_OPT_RDNSS_BUF->type = UIP_ND6_OPT_RDNSS; + UIP_ND6_OPT_RDNSS_BUF->reserved = 0; + UIP_ND6_OPT_RDNSS_BUF->lifetime = uip_nameserver_next_expiration(); + if(UIP_ND6_OPT_RDNSS_BUF->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) { + UIP_ND6_OPT_RDNSS_BUF->lifetime -= clock_seconds(); + } + while((dns = uip_nameserver_get(i)) != NULL) { + uip_ipaddr_copy(ip++, dns); + i++; + } + UIP_ND6_OPT_RDNSS_BUF->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1); + PRINTF("%d nameservers reported\n", i); + uip_len += UIP_ND6_OPT_RDNSS_BUF->len << 3; + nd6_opt_offset += UIP_ND6_OPT_RDNSS_BUF->len << 3; + } +#endif /* UIP_ND6_RA_RDNSS */ + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); @@ -938,6 +963,23 @@ ra_input(void) /* End of autonomous flag related processing */ } break; +#if UIP_ND6_RA_RDNSS + case UIP_ND6_OPT_RDNSS: + if(UIP_ND6_RA_BUF->flags_reserved & (UIP_ND6_O_FLAG << 6)) { + PRINTF("Processing RDNSS option\n"); + uint8_t naddr = (UIP_ND6_OPT_RDNSS_BUF->len - 1) / 2; + uip_ipaddr_t *ip = (uip_ipaddr_t *)(&UIP_ND6_OPT_RDNSS_BUF->ip); + PRINTF("got %d nameservers\n", naddr); + while(naddr-- > 0) { + PRINTF(" nameserver: "); + PRINT6ADDR(ip); + PRINTF(" lifetime: %lx\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); + uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); + ip++; + } + } + break; +#endif /* UIP_ND6_RA_RDNSS */ default: PRINTF("ND option not supported in RA"); break; diff --git a/core/net/ipv6/uip-nd6.h b/core/net/ipv6/uip-nd6.h index 6c88de614..8b5893328 100644 --- a/core/net/ipv6/uip-nd6.h +++ b/core/net/ipv6/uip-nd6.h @@ -87,7 +87,7 @@ #define UIP_ND6_MIN_RA_INTERVAL UIP_CONF_ND6_MIN_RA_INTERVAL #endif #define UIP_ND6_M_FLAG 0 -#define UIP_ND6_O_FLAG 0 +#define UIP_ND6_O_FLAG (UIP_ND6_RA_RDNSS || UIP_ND6_RA_DNSSL) #define UIP_ND6_ROUTER_LIFETIME 3 * UIP_ND6_MAX_RA_INTERVAL #define UIP_ND6_MAX_INITIAL_RA_INTERVAL 16 /*seconds*/ @@ -139,6 +139,23 @@ /** @} */ +/** \name RFC 6106 RA DNS Options Constants */ +/** @{ */ +#ifndef UIP_CONF_ND6_RA_RDNSS +#define UIP_ND6_RA_RDNSS 0 +#else +#define UIP_ND6_RA_RDNSS UIP_CONF_ND6_RA_RDNSS +#endif + +#ifndef UIP_CONF_ND6_RA_DNSSL +#define UIP_ND6_RA_DNSSL 0 +#else +#error Not implemented +#define UIP_ND6_RA_DNSSL UIP_CONF_ND6_RA_DNSSL +#endif +/** @} */ + + /** \name ND6 option types */ /** @{ */ #define UIP_ND6_OPT_SLLAO 1 @@ -146,6 +163,8 @@ #define UIP_ND6_OPT_PREFIX_INFO 3 #define UIP_ND6_OPT_REDIRECTED_HDR 4 #define UIP_ND6_OPT_MTU 5 +#define UIP_ND6_OPT_RDNSS 25 +#define UIP_ND6_OPT_DNSSL 31 /** @} */ /** \name ND6 option types */ @@ -168,6 +187,8 @@ #define UIP_ND6_OPT_HDR_LEN 2 #define UIP_ND6_OPT_PREFIX_INFO_LEN 32 #define UIP_ND6_OPT_MTU_LEN 8 +#define UIP_ND6_OPT_RDNSS_LEN 1 +#define UIP_ND6_OPT_DNSSL_LEN 1 /* Length of TLLAO and SLLAO options, it is L2 dependant */ @@ -290,6 +311,15 @@ typedef struct uip_nd6_opt_mtu { uint32_t mtu; } uip_nd6_opt_mtu; +/** \brief ND option RDNSS */ +typedef struct uip_nd6_opt_dns { + uint8_t type; + uint8_t len; + uint16_t reserved; + uint32_t lifetime; + uip_ipaddr_t ip; +} uip_nd6_opt_dns; + /** \struct Redirected header option */ typedef struct uip_nd6_opt_redirected_hdr { uint8_t type; diff --git a/cpu/6502/ipconfig/ipconfig.c b/cpu/6502/ipconfig/ipconfig.c index d21994032..5452b735a 100644 --- a/cpu/6502/ipconfig/ipconfig.c +++ b/cpu/6502/ipconfig/ipconfig.c @@ -117,7 +117,7 @@ makestrings(void) makeaddr(&addr, gateway); #if WITH_DNS - addrptr = resolv_getserver(); + addrptr = uip_nameserver_get(0); if(addrptr != NULL) { makeaddr(addrptr, dnsserver); } @@ -245,7 +245,7 @@ dhcpc_configured(const struct dhcpc_state *s) uip_setnetmask(&s->netmask); uip_setdraddr(&s->default_router); #if WITH_DNS - resolv_conf(&s->dnsaddr); + uip_nameserver_update(&s->dnsaddr, UIP_NAMESERVER_INFINITE_LIFETIME); #endif /* WITH_DNS */ set_statustext("Configured."); @@ -261,7 +261,7 @@ dhcpc_unconfigured(const struct dhcpc_state *s) uip_setnetmask(&nulladdr); uip_setdraddr(&nulladdr); #if WITH_DNS - resolv_conf(&nulladdr); + uip_nameserver_update(&nulladdr, UIP_NAMESERVER_INFINITE_LIFETIME); #endif /* WITH_DNS */ set_statustext("Unconfigured."); diff --git a/cpu/6502/lib/config.c b/cpu/6502/lib/config.c index 08677a682..545c47116 100644 --- a/cpu/6502/lib/config.c +++ b/cpu/6502/lib/config.c @@ -105,7 +105,7 @@ config_read(char *filename) uip_setnetmask(&config.netmask); uip_setdraddr(&config.draddr); #if WITH_DNS - resolv_conf(&config.resolvaddr); + uip_nameserver_update(&config.resolvaddr, UIP_NAMESERVER_INFINITE_LIFETIME); #endif /* WITH_DNS */ return &config.ethernetcfg; diff --git a/platform/apple2enh/contiki-main.c b/platform/apple2enh/contiki-main.c index 0d0751c1a..8a42a53da 100644 --- a/platform/apple2enh/contiki-main.c +++ b/platform/apple2enh/contiki-main.c @@ -104,7 +104,7 @@ main(void) uip_setdraddr(&addr); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); ethernet_config = &config; } diff --git a/platform/atarixl/contiki-main.c b/platform/atarixl/contiki-main.c index 61cd4c7bb..91cb35367 100644 --- a/platform/atarixl/contiki-main.c +++ b/platform/atarixl/contiki-main.c @@ -100,7 +100,7 @@ main(void) uip_setdraddr(&addr); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); ethernet_config = &config; } diff --git a/platform/c128/contiki-main.c b/platform/c128/contiki-main.c index c3d15f478..d28f24f75 100644 --- a/platform/c128/contiki-main.c +++ b/platform/c128/contiki-main.c @@ -100,7 +100,7 @@ main(void) uip_setdraddr(&addr); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); ethernet_config = &config; } diff --git a/platform/c64/contiki-main.c b/platform/c64/contiki-main.c index 57a333f0b..b5cc59a9c 100644 --- a/platform/c64/contiki-main.c +++ b/platform/c64/contiki-main.c @@ -98,7 +98,7 @@ main(void) uip_setdraddr(&addr); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); ethernet_config = &config; } diff --git a/platform/win32/contiki-main.c b/platform/win32/contiki-main.c index dcadd5385..5ced80992 100644 --- a/platform/win32/contiki-main.c +++ b/platform/win32/contiki-main.c @@ -140,7 +140,7 @@ main(int argc, char **argv) log_message("Def. Router: ", inet_ntoa(*(struct in_addr*)&addr)); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); log_message("DNS Server: ", inet_ntoa(*(struct in_addr*)&addr)); }