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/uip-nameserver.c b/core/net/ip/uip-nameserver.c new file mode 100644 index 000000000..f69de5594 --- /dev/null +++ b/core/net/ip/uip-nameserver.c @@ -0,0 +1,196 @@ +/** + * \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_namserver_record { + struct uip_namserver_record *next; + uip_ipaddr_t ip; + uint32_t added; + uint32_t lifetime; +} uip_namserver_record; + +/** \brief Initialization flag */ +static uint8_t initialized = 0; + +/** \name List and memory block + * @{ + */ +LIST(dns); +MEMB(dnsmemb, uip_namserver_record, UIP_NAMESERVER_POOL_SIZE); +/** @} */ + +/** \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 + */ +static void inline +init(void) +{ + list_init(dns); + memb_init(&dnsmemb); + initialized = 1; +} +/*----------------------------------------------------------------------------*/ +void +uip_nameserver_update(uip_ipaddr_t *nameserver, uint32_t lifetime) +{ + if(initialized == 0) { + init(); + } + + register uip_namserver_record *e; + 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_namserver_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); + } + } +} +/*----------------------------------------------------------------------------*/ +/** + * Purge expired records + */ +static void +purge(void) +{ + register uip_namserver_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); + } + } +} +/*----------------------------------------------------------------------------*/ +uip_ipaddr_t * +uip_nameserver_get(uint8_t num) +{ + uint8_t i; + uip_namserver_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; +} +/*----------------------------------------------------------------------------*/ +uint32_t +uip_nameserver_next_expiration(void) +{ + register uip_namserver_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; +} +/*----------------------------------------------------------------------------*/ +uint16_t +uip_nameserver_count(void) +{ + if(initialized == 0) { + return 0; + } + return list_length(dns); +} +/*----------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ip/uip-nameserver.h b/core/net/ip/uip-nameserver.h new file mode 100644 index 000000000..1b87ff39c --- /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 */ +#define UIP_NAMESERVER_POOL_SIZE 2 +/** \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. (\sa UIP_ND6_RDNSS_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_ */ +/** @} */