69 #include "lib/random.h"
72 #define DEBUG CONTIKI_TARGET_COOJA
82 #define NULL (void *)0
85 #if !defined(__SDCC) && defined(SDCC_REVISION)
90 #define DEBUG_PRINTF(...) printf(__VA_ARGS__)
92 #define DEBUG_PRINTF(...) do { } while(0)
95 #if DEBUG || VERBOSE_DEBUG
96 #define PRINTF(...) printf(__VA_ARGS__)
98 #define PRINTF(...) do { } while(0)
103 strncasecmp(
const char *s1,
const char *s2,
size_t n)
106 return strncmp(s1, s2, n);
109 strcasecmp(
const char *s1,
const char *s2)
112 return strcmp(s1, s2);
115 int strcasecmp(
const char *s1,
const char *s2);
116 int strncasecmp(
const char *s1,
const char *s2,
size_t n);
119 #define UIP_UDP_BUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
125 #ifndef RESOLV_CONF_SUPPORTS_MDNS
126 #define RESOLV_CONF_SUPPORTS_MDNS 1
129 #ifndef RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS
130 #define RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS 0
134 #ifndef RESOLV_CONF_MAX_RETRIES
135 #define RESOLV_CONF_MAX_RETRIES 4
138 #ifndef RESOLV_CONF_MAX_MDNS_RETRIES
139 #define RESOLV_CONF_MAX_MDNS_RETRIES 3
142 #ifndef RESOLV_CONF_MAX_DOMAIN_NAME_SIZE
143 #define RESOLV_CONF_MAX_DOMAIN_NAME_SIZE 32
146 #ifdef RESOLV_CONF_AUTO_REMOVE_TRAILING_DOTS
147 #define RESOLV_AUTO_REMOVE_TRAILING_DOTS RESOLV_CONF_AUTO_REMOVE_TRAILING_DOTS
149 #define RESOLV_AUTO_REMOVE_TRAILING_DOTS RESOLV_CONF_SUPPORTS_MDNS
152 #ifdef RESOLV_CONF_VERIFY_ANSWER_NAMES
153 #define RESOLV_VERIFY_ANSWER_NAMES RESOLV_CONF_VERIFY_ANSWER_NAMES
155 #define RESOLV_VERIFY_ANSWER_NAMES RESOLV_CONF_SUPPORTS_MDNS
158 #ifdef RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION
159 #define RESOLV_SUPPORTS_RECORD_EXPIRATION RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION
161 #define RESOLV_SUPPORTS_RECORD_EXPIRATION 1
164 #if RESOLV_CONF_SUPPORTS_MDNS && !RESOLV_VERIFY_ANSWER_NAMES
165 #error RESOLV_CONF_SUPPORTS_MDNS cannot be set without RESOLV_CONF_VERIFY_ANSWER_NAMES
168 #if !defined(CONTIKI_TARGET_NAME) && defined(BOARD)
169 #define stringy2(x) #x
170 #define stringy(x) stringy2(x)
171 #define CONTIKI_TARGET_NAME stringy(BOARD)
174 #ifndef CONTIKI_CONF_DEFAULT_HOSTNAME
175 #ifdef CONTIKI_TARGET_NAME
176 #define CONTIKI_CONF_DEFAULT_HOSTNAME "contiki-"CONTIKI_TARGET_NAME
178 #define CONTIKI_CONF_DEFAULT_HOSTNAME "contiki"
183 #define DNS_TYPE_CNAME 5
184 #define DNS_TYPE_PTR 12
185 #define DNS_TYPE_MX 15
186 #define DNS_TYPE_TXT 16
187 #define DNS_TYPE_AAAA 28
188 #define DNS_TYPE_SRV 33
189 #define DNS_TYPE_ANY 255
190 #define DNS_TYPE_NSEC 47
192 #if NETSTACK_CONF_WITH_IPV6
193 #define NATIVE_DNS_TYPE DNS_TYPE_AAAA
195 #define NATIVE_DNS_TYPE DNS_TYPE_A
198 #define DNS_CLASS_IN 1
199 #define DNS_CLASS_ANY 255
206 #define MDNS_PORT 5353
209 #ifndef MDNS_RESPONDER_PORT
210 #define MDNS_RESPONDER_PORT 5354
216 uint8_t flags1, flags2;
217 #define DNS_FLAG1_RESPONSE 0x80
218 #define DNS_FLAG1_OPCODE_STATUS 0x10
219 #define DNS_FLAG1_OPCODE_INVERSE 0x08
220 #define DNS_FLAG1_OPCODE_STANDARD 0x00
221 #define DNS_FLAG1_AUTHORATIVE 0x04
222 #define DNS_FLAG1_TRUNC 0x02
223 #define DNS_FLAG1_RD 0x01
224 #define DNS_FLAG2_RA 0x80
225 #define DNS_FLAG2_ERR_MASK 0x0f
226 #define DNS_FLAG2_ERR_NONE 0x00
227 #define DNS_FLAG2_ERR_NAME 0x03
228 uint16_t numquestions;
242 #if NETSTACK_CONF_WITH_IPV6
250 #define STATE_UNUSED 0
251 #define STATE_ERROR 1
253 #define STATE_ASKING 3
260 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
261 unsigned long expiration;
266 #if RESOLV_CONF_SUPPORTS_MDNS
267 int is_mdns:1, is_probe:1;
269 char name[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
272 #ifndef UIP_CONF_RESOLV_ENTRIES
273 #define RESOLV_ENTRIES 4
275 #define RESOLV_ENTRIES UIP_CONF_RESOLV_ENTRIES
278 static struct namemap names[RESOLV_ENTRIES];
280 static uint8_t seqno;
284 static struct etimer retry;
288 PROCESS(resolv_process,
"DNS resolver");
290 static void resolv_found(
char *name, uip_ipaddr_t *
ipaddr);
293 struct dns_question {
298 #if RESOLV_CONF_SUPPORTS_MDNS
299 static char resolv_hostname[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
302 MDNS_STATE_WAIT_BEFORE_PROBE,
307 static uint8_t mdns_state;
309 static const uip_ipaddr_t resolv_mdns_addr =
310 #if NETSTACK_CONF_WITH_IPV6
311 { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb } };
315 { { 224, 0, 0, 251 } };
317 static int mdns_needs_host_announce;
319 PROCESS(mdns_probe_process,
"mDNS probe");
323 #if RESOLV_VERIFY_ANSWER_NAMES || VERBOSE_DEBUG
332 decode_name(
const unsigned char *query,
char *dest,
333 const unsigned char *packet)
335 int len = RESOLV_CONF_MAX_DOMAIN_NAME_SIZE;
337 unsigned char n = *query++;
343 const uint16_t offset = query[0] + ((n & ~0xC0) << 8);
346 query = packet + offset;
381 dns_name_isequal(
const unsigned char *queryptr,
const char *name,
382 const unsigned char *packet)
384 unsigned char n = *queryptr++;
391 queryptr = packet + queryptr[0] + ((n & ~0xC0) << 8);
400 if(tolower((
unsigned int)*name++) != tolower((
unsigned int)*queryptr++)) {
407 if((n != 0) && (*name++ !=
'.')) {
421 static unsigned char *
422 skip_name(
unsigned char *query)
426 DEBUG_PRINTF(
"resolver: skip name: ");
431 DEBUG_PRINTF(
"<skip-to-%d>", query[0] + ((n & ~0xC0) << 8));
439 DEBUG_PRINTF(
"%c", *query);
444 }
while(*query != 0);
451 static unsigned char *
452 encode_name(
unsigned char *query,
const char *nameptr)
462 nptr = (
char *)query;
464 for(n = 0; *nameptr !=
'.' && *nameptr != 0; ++nameptr) {
470 }
while(*nameptr != 0);
478 #if RESOLV_CONF_SUPPORTS_MDNS
482 mdns_announce_requested(
void)
484 mdns_needs_host_announce = 1;
490 start_name_collision_check(clock_time_t after)
498 static unsigned char *
499 mdns_write_announce_records(
unsigned char *queryptr, uint8_t *
count)
501 #if NETSTACK_CONF_WITH_IPV6
504 for(i = 0; i < UIP_DS6_ADDR_NB; ++i) {
506 #
if !RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS
511 queryptr = encode_name(queryptr, resolv_hostname);
515 *queryptr++ =
sizeof(
struct dns_hdr);
518 *queryptr++ = (uint8_t) ((NATIVE_DNS_TYPE) >> 8);
519 *queryptr++ = (uint8_t) ((NATIVE_DNS_TYPE));
521 *queryptr++ = (uint8_t) ((DNS_CLASS_IN | 0x8000) >> 8);
522 *queryptr++ = (uint8_t) ((DNS_CLASS_IN | 0x8000));
530 *queryptr++ =
sizeof(uip_ipaddr_t);
533 queryptr +=
sizeof(uip_ipaddr_t);
538 struct dns_answer *ans;
540 queryptr = encode_name(queryptr, resolv_hostname);
541 ans = (
struct dns_answer *)queryptr;
543 ans->class =
UIP_HTONS(DNS_CLASS_IN | 0x8000);
546 ans->len =
UIP_HTONS(
sizeof(uip_ipaddr_t));
548 queryptr = (
unsigned char *)ans +
sizeof(*ans);
558 mdns_prep_host_announce_packet(
void)
560 static const struct {
575 sizeof(
struct dns_hdr),
579 #if NETSTACK_CONF_WITH_IPV6
593 unsigned char *queryptr;
595 uint8_t total_answers = 0;
599 struct dns_hdr *hdr = (
struct dns_hdr *)
uip_appdata;
602 memset((
void *)hdr, 0,
sizeof(*hdr));
604 hdr->flags1 |= DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE;
606 queryptr = (
unsigned char *)
uip_appdata +
sizeof(*hdr);
608 queryptr = mdns_write_announce_records(queryptr, &total_answers);
614 queryptr = encode_name(queryptr, resolv_hostname);
618 *queryptr++ =
sizeof(*hdr);
621 memcpy((
void *)queryptr, (
void *)&nsec_record,
sizeof(nsec_record));
623 queryptr +=
sizeof(nsec_record);
627 ((uint8_t*)&hdr->numanswers)[1] = total_answers;
628 ((uint8_t*)&hdr->numextrarr)[1] = 1;
635 try_next_server(
struct namemap *namemapptr)
638 printf(
"server %d\n", namemapptr->server);
640 namemapptr->server++;
642 namemapptr->retries = 0;
645 namemapptr->server = 0;
660 register struct dns_hdr *hdr;
662 register struct namemap *namemapptr;
664 for(i = 0; i < RESOLV_ENTRIES; ++i) {
665 namemapptr = &names[i];
666 if(namemapptr->state == STATE_NEW || namemapptr->state == STATE_ASKING) {
668 if(namemapptr->state == STATE_ASKING) {
669 if(--namemapptr->tmr == 0) {
670 #if RESOLV_CONF_SUPPORTS_MDNS
671 if(++namemapptr->retries ==
672 (namemapptr->is_mdns ? RESOLV_CONF_MAX_MDNS_RETRIES :
675 if(++namemapptr->retries == RESOLV_CONF_MAX_RETRIES)
680 if(try_next_server(namemapptr) == 0) {
682 namemapptr->state = STATE_ERROR;
684 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
689 resolv_found(namemapptr->name,
NULL);
693 namemapptr->tmr = namemapptr->retries * namemapptr->retries * 3;
695 #if RESOLV_CONF_SUPPORTS_MDNS
696 if(namemapptr->is_probe) {
708 namemapptr->state = STATE_ASKING;
710 namemapptr->retries = 0;
713 memset(hdr, 0,
sizeof(
struct dns_hdr));
715 namemapptr->id = hdr->id;
716 #if RESOLV_CONF_SUPPORTS_MDNS
717 if(!namemapptr->is_mdns || namemapptr->is_probe) {
718 hdr->flags1 = DNS_FLAG1_RD;
720 if(namemapptr->is_mdns) {
724 hdr->flags1 = DNS_FLAG1_RD;
727 query = (
unsigned char *)
uip_appdata +
sizeof(*hdr);
728 query = encode_name(query, namemapptr->name);
729 #if RESOLV_CONF_SUPPORTS_MDNS
730 if(namemapptr->is_probe) {
731 *query++ = (uint8_t) ((DNS_TYPE_ANY) >> 8);
732 *query++ = (uint8_t) ((DNS_TYPE_ANY));
736 *query++ = (uint8_t) ((NATIVE_DNS_TYPE) >> 8);
737 *query++ = (uint8_t) ((NATIVE_DNS_TYPE));
739 *query++ = (uint8_t) ((DNS_CLASS_IN) >> 8);
740 *query++ = (uint8_t) ((DNS_CLASS_IN));
741 #if RESOLV_CONF_SUPPORTS_MDNS
742 if(namemapptr->is_mdns) {
743 if(namemapptr->is_probe) {
751 query = mdns_write_announce_records(query, &count);
756 &resolv_mdns_addr,
UIP_HTONS(MDNS_PORT));
758 PRINTF(
"resolver: (i=%d) Sent MDNS %s for \"%s\".\n", i,
759 namemapptr->is_probe?
"probe":
"request",namemapptr->name);
763 (
const uip_ipaddr_t *)
767 PRINTF(
"resolver: (i=%d) Sent DNS request for \"%s\".\n", i,
775 PRINTF(
"resolver: (i=%d) Sent DNS request for \"%s\".\n", i,
789 uint8_t nquestions, nanswers;
793 register struct namemap *namemapptr =
NULL;
795 struct dns_answer *ans;
797 register struct dns_hdr const *hdr = (
struct dns_hdr *)
uip_appdata;
799 unsigned char *queryptr = (
unsigned char *)hdr +
sizeof(*hdr);
801 const uint8_t is_request = ((hdr->flags1 & ~1) == 0) && (hdr->flags2 == 0);
806 nquestions = (uint8_t) uip_ntohs(hdr->numquestions);
807 nanswers = (uint8_t) uip_ntohs(hdr->numanswers);
809 queryptr = (
unsigned char *)hdr +
sizeof(*hdr);
813 (
"resolver: flags1=0x%02X flags2=0x%02X nquestions=%d, nanswers=%d, nauthrr=%d, nextrarr=%d\n",
814 hdr->flags1, hdr->flags2, (uint8_t) nquestions, (uint8_t) nanswers,
815 (uint8_t) uip_ntohs(hdr->numauthrr),
816 (uint8_t) uip_ntohs(hdr->numextrarr));
818 if(is_request && (nquestions == 0)) {
820 DEBUG_PRINTF(
"resolver: Skipping request with no questions.\n");
826 for(; nquestions > 0;
827 queryptr = skip_name(queryptr) +
sizeof(
struct dns_question),
830 #if RESOLV_CONF_SUPPORTS_MDNS
840 struct dns_question *question = (
struct dns_question *)skip_name(queryptr);
842 #if !ARCH_DOESNT_NEED_ALIGNED_STRUCTS
843 static struct dns_question aligned;
844 memcpy(&aligned, question,
sizeof(aligned));
848 DEBUG_PRINTF(
"resolver: Question %d: type=%d class=%d\n", ++i,
851 if(((uip_ntohs(question->class) & 0x7FFF) != DNS_CLASS_IN) ||
852 ((question->type !=
UIP_HTONS(DNS_TYPE_ANY)) &&
853 (question->type !=
UIP_HTONS(NATIVE_DNS_TYPE)))) {
858 if(!dns_name_isequal(queryptr, resolv_hostname,
uip_appdata)) {
862 PRINTF(
"resolver: THIS IS A REQUEST FOR US!!!\n");
864 if(mdns_state == MDNS_STATE_READY) {
868 if(UIP_UDP_BUF->srcport ==
UIP_HTONS(MDNS_PORT)) {
869 mdns_announce_requested();
872 mdns_prep_host_announce_packet(),
873 &UIP_UDP_BUF->srcipaddr,
874 UIP_UDP_BUF->srcport);
879 PRINTF(
"resolver: But we are still probing. Waiting...\n");
884 nauthrr = (uint8_t)uip_ntohs(hdr->numauthrr);
906 #if RESOLV_CONF_SUPPORTS_MDNS
907 if(UIP_UDP_BUF->srcport ==
UIP_HTONS(MDNS_PORT) &&
918 for(i = 0; i < RESOLV_ENTRIES; ++i) {
919 namemapptr = &names[i];
920 if(namemapptr->state == STATE_ASKING &&
921 namemapptr->id == hdr->id) {
926 if(i >= RESOLV_ENTRIES || i < 0 || namemapptr->state != STATE_ASKING) {
927 PRINTF(
"resolver: DNS response has bad ID (%04X) \n", uip_ntohs(hdr->id));
931 PRINTF(
"resolver: Incoming response for \"%s\".\n", namemapptr->name);
934 namemapptr->state = STATE_ERROR;
936 namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
938 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
944 if(namemapptr->err != 0) {
945 namemapptr->state = STATE_ERROR;
946 resolv_found(namemapptr->name,
NULL);
954 while(nanswers > 0) {
955 ans = (
struct dns_answer *)skip_name(queryptr);
957 #if !ARCH_DOESNT_NEED_ALIGNED_STRUCTS
959 static struct dns_answer aligned;
960 memcpy(&aligned, ans,
sizeof(aligned));
968 DEBUG_PRINTF(
"resolver: Answer %d: \"%s\", type %d, class %d, ttl %d, length %d\n",
969 ++i, debug_name, uip_ntohs(ans->type),
970 uip_ntohs(ans->class) & 0x7FFF,
971 (
int)((uint32_t) uip_ntohs(ans->ttl[0]) << 16) | (uint32_t)
972 uip_ntohs(ans->ttl[1]), uip_ntohs(ans->len));
978 if(((uip_ntohs(ans->class) & 0x7FFF) != DNS_CLASS_IN) ||
979 (ans->len !=
UIP_HTONS(
sizeof(uip_ipaddr_t)))) {
980 goto skip_to_next_answer;
983 if(ans->type !=
UIP_HTONS(NATIVE_DNS_TYPE)) {
984 goto skip_to_next_answer;
987 #if RESOLV_CONF_SUPPORTS_MDNS
988 if(UIP_UDP_BUF->srcport ==
UIP_HTONS(MDNS_PORT) &&
990 int8_t available_i = RESOLV_ENTRIES;
992 DEBUG_PRINTF(
"resolver: MDNS query.\n");
997 for(i = 0; i < RESOLV_ENTRIES; ++i) {
998 namemapptr = &names[i];
999 if(dns_name_isequal(queryptr, namemapptr->name,
uip_appdata)) {
1002 if((namemapptr->state == STATE_UNUSED)
1003 #
if RESOLV_SUPPORTS_RECORD_EXPIRATION
1004 || (namemapptr->state == STATE_DONE &&
clock_seconds() > namemapptr->expiration)
1010 if(i == RESOLV_ENTRIES) {
1011 DEBUG_PRINTF(
"resolver: Unsolicited MDNS response.\n");
1013 namemapptr = &names[i];
1014 if(!decode_name(queryptr, namemapptr->name,
uip_appdata)) {
1015 DEBUG_PRINTF(
"resolver: MDNS name too big to cache.\n");
1017 goto skip_to_next_answer;
1020 if(i == RESOLV_ENTRIES) {
1022 (
"resolver: Not enough room to keep track of unsolicited MDNS answer.\n");
1024 if(dns_name_isequal(queryptr, resolv_hostname,
uip_appdata)) {
1026 resolv_found(resolv_hostname, (uip_ipaddr_t *) ans->ipaddr);
1029 goto skip_to_next_answer;
1031 namemapptr = &names[i];
1049 DEBUG_PRINTF(
"resolver: Answer for \"%s\" is usable.\n", namemapptr->name);
1051 namemapptr->state = STATE_DONE;
1052 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
1053 namemapptr->expiration = ans->ttl[1] + (ans->ttl[0] << 8);
1059 resolv_found(namemapptr->name, &namemapptr->ipaddr);
1062 skip_to_next_answer:
1063 queryptr = (
unsigned char *)skip_name(queryptr) + 10 +
uip_htons(ans->len);
1069 #if RESOLV_CONF_SUPPORTS_MDNS
1070 if(nanswers == 0 && UIP_UDP_BUF->srcport !=
UIP_HTONS(MDNS_PORT)
1076 if(try_next_server(namemapptr)) {
1077 namemapptr->state = STATE_ASKING;
1084 #if RESOLV_CONF_SUPPORTS_MDNS
1092 strncpy(resolv_hostname, hostname, RESOLV_CONF_MAX_DOMAIN_NAME_SIZE);
1095 if(strlen(resolv_hostname) < 7 ||
1096 strcasecmp(resolv_hostname + strlen(resolv_hostname) - 6,
".local") != 0) {
1097 strncat(resolv_hostname,
".local", RESOLV_CONF_MAX_DOMAIN_NAME_SIZE);
1100 PRINTF(
"resolver: hostname changed to \"%s\"\n", resolv_hostname);
1102 start_name_collision_check(0);
1112 return resolv_hostname;
1120 static struct etimer delay;
1123 mdns_state = MDNS_STATE_WAIT_BEFORE_PROBE;
1125 PRINTF(
"mdns-probe: Process (re)started.\n");
1129 PRINTF(
"mdns-probe: Probing will begin in %ld clocks.\n",
1130 (
long)*(clock_time_t *) data);
1141 mdns_state = MDNS_STATE_PROBING;
1146 }
while(strcasecmp(resolv_hostname, data) != 0);
1148 mdns_state = MDNS_STATE_READY;
1149 mdns_announce_requested();
1151 PRINTF(
"mdns-probe: Finished probing.\n");
1164 memset(names, 0,
sizeof(names));
1168 PRINTF(
"resolver: Process started.\n");
1172 #if RESOLV_CONF_SUPPORTS_MDNS
1173 PRINTF(
"resolver: Supports MDNS.\n");
1176 #if NETSTACK_CONF_WITH_IPV6
1177 uip_ds6_maddr_add(&resolv_mdns_addr);
1188 if(ev == PROCESS_EVENT_TIMER) {
1196 #if RESOLV_CONF_SUPPORTS_MDNS
1197 if(mdns_needs_host_announce) {
1200 PRINTF(
"resolver: Announcing that we are \"%s\".\n",
1205 len = mdns_prep_host_announce_packet();
1208 len, &resolv_mdns_addr,
UIP_HTONS(MDNS_PORT));
1210 mdns_needs_host_announce = 0;
1225 #if RESOLV_CONF_SUPPORTS_MDNS
1226 if(mdns_needs_host_announce) {
1238 static uint8_t initialized = 0;
1245 #if RESOLV_AUTO_REMOVE_TRAILING_DOTS
1247 remove_trailing_dots(
const char *name) {
1248 static char dns_name_without_dots[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
1249 size_t len = strlen(name);
1251 if(name[len - 1] ==
'.') {
1252 strncpy(dns_name_without_dots, name,
sizeof(dns_name_without_dots));
1253 while(len && (dns_name_without_dots[len - 1] ==
'.')) {
1254 dns_name_without_dots[--len] = 0;
1256 name = dns_name_without_dots;
1261 #define remove_trailing_dots(x) (x)
1274 uint8_t lseq, lseqi;
1276 register struct namemap *nameptr = 0;
1283 name = remove_trailing_dots(name);
1285 for(i = 0; i < RESOLV_ENTRIES; ++i) {
1286 nameptr = &names[i];
1287 if(0 == strcasecmp(nameptr->name, name)) {
1290 if((nameptr->state == STATE_UNUSED)
1291 #
if RESOLV_SUPPORTS_RECORD_EXPIRATION
1292 || (nameptr->state == STATE_DONE &&
clock_seconds() > nameptr->expiration)
1297 }
else if(seqno - nameptr->seqno > lseq) {
1298 lseq = seqno - nameptr->seqno;
1303 if(i == RESOLV_ENTRIES) {
1305 nameptr = &names[i];
1308 PRINTF(
"resolver: Starting query for \"%s\".\n", name);
1310 memset(nameptr, 0,
sizeof(*nameptr));
1312 strncpy(nameptr->name, name,
sizeof(nameptr->name));
1313 nameptr->state = STATE_NEW;
1314 nameptr->seqno = seqno;
1317 #if RESOLV_CONF_SUPPORTS_MDNS
1319 size_t name_len = strlen(name);
1321 const char local_suffix[] =
"local";
1323 if((name_len > (
sizeof(local_suffix) - 1)) &&
1324 (0 == strcasecmp(name + name_len - (
sizeof(local_suffix) - 1), local_suffix))) {
1325 PRINTF(
"resolver: Using MDNS to look up \"%s\".\n", name);
1326 nameptr->is_mdns = 1;
1328 nameptr->is_mdns = 0;
1331 nameptr->is_probe = (mdns_state == MDNS_STATE_PROBING) &&
1332 (0 == strcmp(nameptr->name, resolv_hostname));
1355 struct namemap *nameptr;
1358 name = remove_trailing_dots(name);
1360 #if UIP_CONF_LOOPBACK_INTERFACE
1361 if(strcmp(name,
"localhost")) {
1362 static uip_ipaddr_t loopback =
1363 #if NETSTACK_CONF_WITH_IPV6
1364 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } };
1367 { { 127, 0, 0, 1 } };
1370 *ipaddr = &loopback;
1377 for(i = 0; i < RESOLV_ENTRIES; ++i) {
1378 nameptr = &names[i];
1380 if(strcasecmp(name, nameptr->name) == 0) {
1381 switch (nameptr->state) {
1384 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
1397 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
1406 *ipaddr = &nameptr->ipaddr;
1418 PRINTF(
"resolver: Found \"%s\" in cache.\n", name);
1422 (
"resolver: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x \n",
1423 ((uint8_t *) addr)[0], ((uint8_t *) addr)[1], ((uint8_t *) addr)[2],
1424 ((uint8_t *) addr)[3], ((uint8_t *) addr)[4], ((uint8_t *) addr)[5],
1425 ((uint8_t *) addr)[6], ((uint8_t *) addr)[7], ((uint8_t *) addr)[8],
1426 ((uint8_t *) addr)[9], ((uint8_t *) addr)[10],
1427 ((uint8_t *) addr)[11], ((uint8_t *) addr)[12],
1428 ((uint8_t *) addr)[13], ((uint8_t *) addr)[14],
1429 ((uint8_t *) addr)[15]);
1433 DEBUG_PRINTF(
"resolver: \"%s\" is NOT cached.\n", name);
1446 resolv_found(
char *name, uip_ipaddr_t *
ipaddr)
1448 #if RESOLV_CONF_SUPPORTS_MDNS
1449 if(strncasecmp(resolv_hostname, name, strlen(resolv_hostname)) == 0 &&
1451 #
if NETSTACK_CONF_WITH_IPV6
1452 && !uip_ds6_is_my_addr(ipaddr)
1454 && uip_ipaddr_cmp(&uip_hostaddr, ipaddr) != 0
1459 if(mdns_state == MDNS_STATE_PROBING) {
1463 PRINTF(
"resolver: Name collision detected for \"%s\".\n", name);
1466 resolv_hostname[strlen(resolv_hostname) - 6] = 0;
1469 for(i = 0; i < 3; ++i) {
1472 char append_str[4] =
"-XX";
1474 append_str[2] = (((val & 0xF) > 9) ?
'a' :
'0') + (val & 0xF);
1476 append_str[1] = (((val & 0xF) > 9) ?
'a' :
'0') + (val & 0xF);
1477 strncat(resolv_hostname, append_str,
1478 sizeof(resolv_hostname) - strlen(resolv_hostname) - 1);
1482 strncat(resolv_hostname,
".local", RESOLV_CONF_MAX_DOMAIN_NAME_SIZE);
1485 }
else if(mdns_state == MDNS_STATE_READY) {
1490 PRINTF(
"resolver: Possible name collision, probing...\n");
1491 start_name_collision_check(0);
1499 PRINTF(
"resolver: Found address for \"%s\".\n", name);
1501 (
"resolver: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x \n",
1502 ((uint8_t *) ipaddr)[0], ((uint8_t *) ipaddr)[1],
1503 ((uint8_t *) ipaddr)[2], ((uint8_t *) ipaddr)[3],
1504 ((uint8_t *) ipaddr)[4], ((uint8_t *) ipaddr)[5],
1505 ((uint8_t *) ipaddr)[6], ((uint8_t *) ipaddr)[7],
1506 ((uint8_t *) ipaddr)[8], ((uint8_t *) ipaddr)[9],
1507 ((uint8_t *) ipaddr)[10], ((uint8_t *) ipaddr)[11],
1508 ((uint8_t *) ipaddr)[12], ((uint8_t *) ipaddr)[13],
1509 ((uint8_t *) ipaddr)[14], ((uint8_t *) ipaddr)[15]);
1511 PRINTF(
"resolver: Unable to retrieve address for \"%s\".\n", name);
Hostname was found, but it's status has expired.
uip_ipaddr_t * uip_nameserver_get(uint8_t num)
Get a Nameserver ip address given in RA.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Header file for module for sending UDP packets through uIP.
static void newdata(void)
static uip_ds6_addr_t * addr
Pointer to a router list entry.
process_event_t tcpip_event
The uIP event.
Header file for IPv6-related data structures.
The server has returned a not-found response for this domain name.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
#define PROCESS_END()
Define the end of a process.
Representation of a uIP UDP connection.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
uip_appdata
Pointer to the application data in the packet buffer.
void process_exit(struct process *p)
Cause a process to exit.
#define UIP_LLADDR_LEN
Link layer address length.
uIP DNS resolver code header file.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
process_event_t resolv_event_found
Event that is broadcasted when a DNS name has been resolved.
Hostname was not found in the cache.
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
process_event_t process_alloc_event(void)
Allocate a global event number.
Header for the Contiki/uIP interface.
struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
#define NULL
The null pointer.
void resolv_set_hostname(const char *hostname)
Changes the local hostname advertised by MDNS.
resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t **ipaddr)
Look up a hostname in the array of known hostnames.
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
#define RESOLV_CONF_MAX_RETRIES
The maximum number of retries when asking for a name.
Hostname is fresh and usable.
#define CLOCK_SECOND
A second, measured in system clock time.
#define uip_gethostaddr(addr)
Get the IP address of this host.
static volatile clock_time_t count
These routines define the AVR-specific calls declared in /core/sys/clock.h CLOCK_SECOND is the number...
void process_start(struct process *p, process_data_t data)
Start a process.
void resolv_query(const char *name)
Queues a name so that a question for the name will be sent out.
This hostname is in the process of being resolved.
uIP Name Server interface
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
void tcpip_poll_udp(struct uip_udp_conn *conn)
Cause a specified UDP connection to be polled.
CCIF unsigned long clock_seconds(void)
Get the current value of the platform seconds.
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC3513 i.e.
#define uip_udp_bind(conn, port)
Bind a UDP connection to a local port.
uip_ds6_netif_t uip_ds6_if
The single interface.
#define uip_poll()
Is the connection being polled by uIP?
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
#define uip_newdata()
Is new incoming data available?
const char * resolv_get_hostname(void)
Returns the local hostname being advertised via MDNS.
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
#define PROCESS_BEGIN()
Define the beginning of a process.