Contiki-NG
Loading...
Searching...
No Matches
uip-nameserver.c
Go to the documentation of this file.
1/**
2 * \addtogroup uip
3 * @{
4 */
5
6/**
7 * \file
8 * uIP Name Server interface
9 * \author Víctor Ariño <victor.arino@tado.com>
10 */
11
12/*
13 * Copyright (c) 2014, tado° GmbH.
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the Institute nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * This file is part of the Contiki operating system.
41 *
42 */
43
44#include "contiki.h"
45#include "contiki-net.h"
46
47#include "lib/list.h"
48#include "lib/memb.h"
49#include <string.h>
50
51#include "sys/log.h"
52#define LOG_MODULE "IPv6"
53#define LOG_LEVEL LOG_LEVEL_NONE
54
55/** \brief Nameserver record */
56typedef struct uip_nameserver_record {
57 struct uip_nameserver_record *next;
58 uip_ipaddr_t ip;
59 uint32_t added;
60 uint32_t lifetime;
62
63#if UIP_NAMESERVER_POOL_SIZE > 1
64/** \brief Initialization flag */
65static uint8_t initialized = 0;
66#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
67
68/** \name List and memory block
69 * @{
70 */
71#if UIP_NAMESERVER_POOL_SIZE > 1
72LIST(dns);
73MEMB(dnsmemb, uip_nameserver_record, UIP_NAMESERVER_POOL_SIZE);
74#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
75static uip_ipaddr_t serveraddr;
76static uint32_t serverlifetime;
77#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
78/** @} */
79
80/** \brief Expiration time in seconds */
81#define DNS_EXPIRATION(r) \
82 (((UIP_NAMESERVER_INFINITE_LIFETIME - r->added) <= r->lifetime) ? \
83 UIP_NAMESERVER_INFINITE_LIFETIME : r->added + r->lifetime)
84/*----------------------------------------------------------------------------*/
85/**
86 * Initialize the module variables
87 */
88#if UIP_NAMESERVER_POOL_SIZE > 1
89static inline void
90init(void)
91{
92 list_init(dns);
93 memb_init(&dnsmemb);
94 initialized = 1;
95}
96#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
97/*----------------------------------------------------------------------------*/
98void
99uip_nameserver_update(const uip_ipaddr_t *nameserver, uint32_t lifetime)
100{
101 LOG_DBG("Nameserver update:");
102 LOG_DBG_6ADDR(nameserver);
103 LOG_DBG("\n");
104
105
106#if UIP_NAMESERVER_POOL_SIZE > 1
107 register uip_nameserver_record *e;
108
109 if(initialized == 0) {
110 init();
111 }
112
113 for(e = list_head(dns); e != NULL; e = list_item_next(e)) {
114 if(uip_ipaddr_cmp(&e->ip, nameserver)) {
115 break;
116 /* RFC6106: In case there's no more space, the new servers should replace
117 * the the eldest ones */
118 }
119 }
120
121 if(e == NULL) {
122 if((e = memb_alloc(&dnsmemb)) != NULL) {
123 list_add(dns, e);
124 } else {
125 uip_nameserver_record *p;
126 for(e = list_head(dns), p = list_head(dns); p != NULL;
127 p = list_item_next(p)) {
128 if(DNS_EXPIRATION(p) < DNS_EXPIRATION(e)) {
129 e = p;
130 }
131 }
132 }
133 }
134
135 /* RFC6106: In case the entry is existing the expiration time must be
136 * updated. Otherwise, new entries are added. */
137 if(e != NULL) {
138 if(lifetime == 0) {
139 memb_free(&dnsmemb, e);
140 list_remove(dns, e);
141 } else {
142 e->added = clock_seconds();
143 e->lifetime = lifetime;
144 uip_ipaddr_copy(&e->ip, nameserver);
145 }
146 }
147#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
148 uip_ipaddr_copy(&serveraddr, nameserver);
149 serverlifetime = lifetime;
150#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
151}
152/*----------------------------------------------------------------------------*/
153#if UIP_NAMESERVER_POOL_SIZE > 1
154/**
155 * Purge expired records
156 */
157static void
158purge(void)
159{
160 register uip_nameserver_record *e = NULL;
161 uint32_t time = clock_seconds();
162 for(e = list_head(dns); e != NULL; e = list_item_next(e)) {
163 if(DNS_EXPIRATION(e) < time) {
164 list_remove(dns, e);
165 memb_free(&dnsmemb, e);
166 e = list_head(dns);
167 }
168 }
169}
170#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
171/*----------------------------------------------------------------------------*/
172uip_ipaddr_t *
174{
175#if UIP_NAMESERVER_POOL_SIZE > 1
176 uint8_t i;
177 uip_nameserver_record *e = NULL;
178
179 if(initialized == 0) {
180 return NULL;
181 }
182 purge();
183 for(i = 1, e = list_head(dns); e != NULL && i <= num;
184 i++, e = list_item_next(e)) {
185 }
186
187 if(e != NULL) {
188 return &e->ip;
189 }
190 return NULL;
191#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
192 if(num > 0) {
193 return NULL;
194 }
195 return &serveraddr;
196#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
197}
198/*----------------------------------------------------------------------------*/
199uint32_t
201{
202#if UIP_NAMESERVER_POOL_SIZE > 1
203 register uip_nameserver_record *e = NULL;
205 uint32_t t;
206
207 if(initialized == 0 || list_length(dns) == 0) {
208 return 0;
209 }
210 purge();
211 for(e = list_head(dns); e != NULL; e = list_item_next(e)) {
212 t = DNS_EXPIRATION(e);
213 if(t < exp) {
214 exp = t;
215 }
216 }
217
218 return exp;
219#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
220 return serverlifetime;
221#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
222}
223/*----------------------------------------------------------------------------*/
224uint16_t
226{
227#if UIP_NAMESERVER_POOL_SIZE > 1
228 if(initialized == 0) {
229 return 0;
230 }
231 return list_length(dns);
232#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
233 if(uip_is_addr_unspecified(&serveraddr)) {
234 return 0;
235 } else {
236 return 1;
237 }
238#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
239}
240/*----------------------------------------------------------------------------*/
241/** @} */
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition clock.c:130
static void list_init(list_t list)
Initialize a list.
Definition list.h:152
#define LIST(name)
Declare a linked list.
Definition list.h:90
static void * list_item_next(const void *item)
Get the next item following this item.
Definition list.h:294
int list_length(const_list_t list)
Get the length of a list.
Definition list.c:160
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition list.c:71
void list_remove(list_t list, const void *item)
Remove a specific element from a list.
Definition list.c:134
static void * list_head(const_list_t list)
Get a pointer to the first element of a list.
Definition list.h:169
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition memb.c:78
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition memb.c:59
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Definition memb.c:52
#define MEMB(name, structure, num)
Declare a memory block.
Definition memb.h:91
uint32_t uip_nameserver_next_expiration(void)
Get next expiration time.
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Definition uip.h:1725
void uip_nameserver_update(const uip_ipaddr_t *nameserver, uint32_t lifetime)
Initialize the module variables.
struct uip_nameserver_record uip_nameserver_record
Nameserver record.
#define UIP_NAMESERVER_POOL_SIZE
Number of Nameservers to keep.
#define UIP_NAMESERVER_INFINITE_LIFETIME
Infinite Lifetime indicator.
#define DNS_EXPIRATION(r)
Expiration time in seconds.
uip_ipaddr_t * uip_nameserver_get(uint8_t num)
Get a Nameserver ip address given in RA.
uint16_t uip_nameserver_count(void)
Get the number of recorded name servers.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition uip.h:969
Linked list manipulation routines.
Header file for the logging system.
Memory block allocation routines.