78#ifndef RESOLV_CONF_SUPPORTS_MDNS
79#define RESOLV_SUPPORTS_MDNS 0
81#define RESOLV_SUPPORTS_MDNS RESOLV_CONF_SUPPORTS_MDNS
86#if RESOLV_SUPPORTS_MDNS
91#define LOG_MODULE "Resolv"
92#define LOG_LEVEL LOG_LEVEL_NONE
94int strcasecmp(
const char *s1,
const char *s2);
95int strncasecmp(
const char *s1,
const char *s2,
size_t n);
97#ifndef RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS
98#define RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS 0
102#ifndef RESOLV_CONF_MAX_RETRIES
103#define RESOLV_CONF_MAX_RETRIES 4
106#ifndef RESOLV_CONF_MAX_MDNS_RETRIES
107#define RESOLV_CONF_MAX_MDNS_RETRIES 3
110#ifndef RESOLV_CONF_MAX_DOMAIN_NAME_SIZE
111#define RESOLV_CONF_MAX_DOMAIN_NAME_SIZE 32
114#ifdef RESOLV_CONF_AUTO_REMOVE_TRAILING_DOTS
115#define RESOLV_AUTO_REMOVE_TRAILING_DOTS RESOLV_CONF_AUTO_REMOVE_TRAILING_DOTS
117#define RESOLV_AUTO_REMOVE_TRAILING_DOTS RESOLV_SUPPORTS_MDNS
120#ifdef RESOLV_CONF_VERIFY_ANSWER_NAMES
121#define RESOLV_VERIFY_ANSWER_NAMES RESOLV_CONF_VERIFY_ANSWER_NAMES
123#define RESOLV_VERIFY_ANSWER_NAMES RESOLV_SUPPORTS_MDNS
126#ifdef RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION
127#define RESOLV_SUPPORTS_RECORD_EXPIRATION RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION
129#define RESOLV_SUPPORTS_RECORD_EXPIRATION 1
132#if RESOLV_SUPPORTS_MDNS && !RESOLV_VERIFY_ANSWER_NAMES
133#error RESOLV_SUPPORTS_MDNS cannot be set without RESOLV_CONF_VERIFY_ANSWER_NAMES
136#if !defined(CONTIKI_TARGET_NAME) && defined(BOARD)
137#define stringy2(x) #x
138#define stringy(x) stringy2(x)
139#define CONTIKI_TARGET_NAME stringy(BOARD)
142#ifndef CONTIKI_CONF_DEFAULT_HOSTNAME
143#ifdef CONTIKI_TARGET_NAME
144#define CONTIKI_CONF_DEFAULT_HOSTNAME "contiki-"CONTIKI_TARGET_NAME
146#define CONTIKI_CONF_DEFAULT_HOSTNAME "contiki"
151#define DNS_TYPE_CNAME 5
152#define DNS_TYPE_PTR 12
153#define DNS_TYPE_MX 15
154#define DNS_TYPE_TXT 16
155#define DNS_TYPE_AAAA 28
156#define DNS_TYPE_SRV 33
157#define DNS_TYPE_ANY 255
158#define DNS_TYPE_NSEC 47
160#define NATIVE_DNS_TYPE DNS_TYPE_AAAA
162#define DNS_CLASS_IN 1
163#define DNS_CLASS_ANY 255
170#define MDNS_PORT 5353
173#ifndef MDNS_RESPONDER_PORT
174#define MDNS_RESPONDER_PORT 5354
180 uint8_t flags1, flags2;
181#define DNS_FLAG1_RESPONSE 0x80
182#define DNS_FLAG1_OPCODE_STATUS 0x10
183#define DNS_FLAG1_OPCODE_INVERSE 0x08
184#define DNS_FLAG1_OPCODE_STANDARD 0x00
185#define DNS_FLAG1_AUTHORATIVE 0x04
186#define DNS_FLAG1_TRUNC 0x02
187#define DNS_FLAG1_RD 0x01
188#define DNS_FLAG2_RA 0x80
189#define DNS_FLAG2_ERR_MASK 0x0f
190#define DNS_FLAG2_ERR_NONE 0x00
191#define DNS_FLAG2_ERR_NAME 0x03
192 uint16_t numquestions;
210#define STATE_UNUSED 0
213#define STATE_ASKING 3
220#if RESOLV_SUPPORTS_RECORD_EXPIRATION
221 unsigned long expiration;
226#if RESOLV_SUPPORTS_MDNS
230 char name[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
233#ifndef UIP_CONF_RESOLV_ENTRIES
234#define RESOLV_ENTRIES 4
236#define RESOLV_ENTRIES UIP_CONF_RESOLV_ENTRIES
239static struct namemap names[RESOLV_ENTRIES];
242static struct etimer retry;
245PROCESS(resolv_process,
"DNS resolver");
247static void resolv_found(
char *name, uip_ipaddr_t *
ipaddr);
255#if RESOLV_SUPPORTS_MDNS
256static char resolv_hostname[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
259 MDNS_STATE_WAIT_BEFORE_PROBE,
264static uint8_t mdns_state;
266static const uip_ipaddr_t resolv_mdns_addr =
267{ { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb } };
271static int mdns_needs_host_announce;
273PROCESS(mdns_probe_process,
"mDNS probe");
285decode_name(
const unsigned char *query,
char *dest,
286 const unsigned char *packet,
size_t packet_len)
288 const unsigned char *end = packet + packet_len;
289 int dest_len = RESOLV_CONF_MAX_DOMAIN_NAME_SIZE;
290 unsigned char label_len;
292 LOG_DBG(
"decoding name: \"");
297 label_len = *query++;
299 while(dest_len && label_len) {
300 if(label_len & 0xc0) {
304 const uint16_t offset = query[0] + ((label_len & ~0xC0) << 8);
305 if(offset >= packet_len) {
306 LOG_ERR(
"Offset %"PRIu16
" exceeds packet length %zu\n",
310 LOG_DBG_(
"<skip-to-%d>", offset);
311 query = packet + offset;
312 label_len = *query++;
319 if(query - packet + label_len > packet_len) {
320 LOG_ERR(
"Cannot read outside the packet data\n");
324 for(; label_len; --label_len) {
325 LOG_DBG_(
"%c", *query);
329 if(--dest_len == 0) {
337 LOG_ERR(
"Cannot read outside the packet data\n");
340 label_len = *query++;
351 return dest_len != 0;
356#if RESOLV_SUPPORTS_MDNS
358dns_name_isequal(
const unsigned char *queryptr,
const char *name,
359 const unsigned char *packet,
size_t packet_len)
361 const unsigned char *end = packet + packet_len;
362 unsigned char label_len;
364 if(*name == 0 || queryptr >= end) {
368 label_len = *queryptr++;
370 while(label_len > 0) {
371 if(label_len & 0xc0) {
372 if(queryptr >= end) {
375 const uint16_t offset = queryptr[0] + ((label_len & ~0xC0) << 8);
376 if(offset >= packet_len) {
379 queryptr = packet + offset;
380 label_len = *queryptr++;
383 for(; label_len; --label_len) {
384 if(!*name || queryptr >= end) {
388 if(tolower(*name++) != tolower(*queryptr++)) {
393 if(queryptr >= end) {
396 label_len = *queryptr++;
398 if(label_len != 0 && *name++ !=
'.') {
413static unsigned char *
414skip_name(
unsigned char *query,
const unsigned char *packet,
size_t packet_len)
416 const unsigned char *end = packet + packet_len;
418 LOG_DBG(
"skip name: ");
421 unsigned char n = *query;
425 if(query + 2 > end) {
428 LOG_DBG_(
"<skip-to-%d>\n", query[0] + ((n & ~0xC0) << 8));
440 if(query + n > end) {
445 LOG_DBG_(
"%c", *query);
452 LOG_ERR(
"skip_name: name runs past end of packet\n");
458static unsigned char *
459encode_name(
unsigned char *query,
const char *nameptr)
465 char *nptr = (
char *)query;
469 for(n = 0; *nameptr !=
'.' && *nameptr != 0; ++nameptr) {
475 }
while(*nameptr != 0);
483#if RESOLV_SUPPORTS_MDNS
487mdns_announce_requested(
void)
489 mdns_needs_host_announce = 1;
495start_name_collision_check(clock_time_t after)
503static unsigned char *
504mdns_write_announce_records(
unsigned char *queryptr, uint8_t *
count)
508 for(i = 0; i < UIP_DS6_ADDR_NB; ++i) {
510#
if !RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS
515 queryptr = encode_name(queryptr, resolv_hostname);
519 *queryptr++ =
sizeof(
struct dns_hdr);
522 *queryptr++ = (uint8_t)(NATIVE_DNS_TYPE >> 8);
523 *queryptr++ = (uint8_t)NATIVE_DNS_TYPE;
525 *queryptr++ = (uint8_t)((DNS_CLASS_IN | 0x8000) >> 8);
526 *queryptr++ = (uint8_t)(DNS_CLASS_IN | 0x8000);
534 *queryptr++ =
sizeof(uip_ipaddr_t);
538 queryptr +=
sizeof(uip_ipaddr_t);
549mdns_prep_host_announce_packet(
void)
551 static const struct {
565 sizeof(
struct dns_hdr),
578 struct dns_hdr *hdr = (
struct dns_hdr *)
uip_appdata;
579 unsigned char *queryptr = (
unsigned char *)
uip_appdata +
sizeof(*hdr);
580 uint8_t total_answers = 0;
583 memset((
void *)hdr, 0,
sizeof(*hdr));
584 hdr->flags1 |= DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE;
586 queryptr = mdns_write_announce_records(queryptr, &total_answers);
592 queryptr = encode_name(queryptr, resolv_hostname);
596 *queryptr++ =
sizeof(*hdr);
599 memcpy((
void *)queryptr, (
void *)&nsec_record,
sizeof(nsec_record));
601 queryptr +=
sizeof(nsec_record);
605 ((uint8_t *)&hdr->numanswers)[1] = total_answers;
606 ((uint8_t *)&hdr->numextrarr)[1] = 1;
613try_next_server(
struct namemap *namemapptr)
615 namemapptr->server++;
617 LOG_DBG(
"Using server ");
619 LOG_DBG_(
", num %u\n", namemapptr->server);
620 namemapptr->retries = 0;
623 LOG_DBG(
"No nameserver, num %u\n", namemapptr->server);
624 namemapptr->server = 0;
637 for(i = 0; i < RESOLV_ENTRIES; ++i) {
638 struct namemap *namemapptr = &names[i];
639 if(namemapptr->state == STATE_NEW || namemapptr->state == STATE_ASKING) {
641 if(namemapptr->state == STATE_ASKING) {
642 if(namemapptr->tmr == 0 || --namemapptr->tmr == 0) {
643#if RESOLV_SUPPORTS_MDNS
644 if(++namemapptr->retries ==
645 (namemapptr->is_mdns ? RESOLV_CONF_MAX_MDNS_RETRIES :
653 if(try_next_server(namemapptr) == 0) {
655 namemapptr->state = STATE_ERROR;
657#if RESOLV_SUPPORTS_RECORD_EXPIRATION
662 resolv_found(namemapptr->name, NULL);
666 namemapptr->tmr = namemapptr->retries * namemapptr->retries * 3;
668#if RESOLV_SUPPORTS_MDNS
669 if(namemapptr->is_probe) {
679 namemapptr->state = STATE_ASKING;
681 namemapptr->retries = 0;
684 struct dns_hdr *hdr = (
struct dns_hdr *)
uip_appdata;
685 memset(hdr, 0,
sizeof(
struct dns_hdr));
686 hdr->id = random_rand();
687 namemapptr->id = hdr->id;
689#if RESOLV_SUPPORTS_MDNS
690 if(!namemapptr->is_mdns || namemapptr->is_probe) {
691 hdr->flags1 = DNS_FLAG1_RD;
693 if(namemapptr->is_mdns) {
697 hdr->flags1 = DNS_FLAG1_RD;
701 uint8_t *query = (
unsigned char *)
uip_appdata +
sizeof(*hdr);
702 query = encode_name(query, namemapptr->name);
704#if RESOLV_SUPPORTS_MDNS
705 if(namemapptr->is_probe) {
706 *query++ = (uint8_t)((DNS_TYPE_ANY) >> 8);
707 *query++ = (uint8_t)((DNS_TYPE_ANY));
711 *query++ = (uint8_t)(NATIVE_DNS_TYPE >> 8);
712 *query++ = (uint8_t)NATIVE_DNS_TYPE;
714 *query++ = (uint8_t)(DNS_CLASS_IN >> 8);
715 *query++ = (uint8_t)DNS_CLASS_IN;
716#if RESOLV_SUPPORTS_MDNS
717 if(namemapptr->is_mdns) {
718 if(namemapptr->is_probe) {
726 query = mdns_write_announce_records(query, &
count);
731 &resolv_mdns_addr,
UIP_HTONS(MDNS_PORT));
733 LOG_DBG(
"(i=%d) Sent MDNS %s for \"%s\"\n", i,
734 namemapptr->is_probe ?
"probe" :
"request", namemapptr->name);
738 (
const uip_ipaddr_t *)
742 LOG_DBG(
"(i=%d) Sent DNS request for \"%s\"\n", i,
750 LOG_DBG(
"(i=%d) Sent DNS request for \"%s\"\n", i,
765 struct dns_hdr const *hdr = (
struct dns_hdr *)
uip_appdata;
772 LOG_DBG(
"Packet too short to contain a DNS header\n");
776 const uint8_t is_request = (hdr->flags1 & ~1) == 0 && hdr->flags2 == 0;
781 uint16_t nquestions = uip_ntohs(hdr->numquestions);
782 uint16_t nanswers = uip_ntohs(hdr->numanswers);
784 unsigned char *queryptr = (
unsigned char *)hdr +
sizeof(*hdr);
787 LOG_DBG(
"flags1=0x%02X flags2=0x%02X nquestions=%d, nanswers=%d, " \
788 "nauthrr=%d, nextrarr=%d\n",
789 hdr->flags1, hdr->flags2, nquestions, nanswers,
790 uip_ntohs(hdr->numauthrr),
791 uip_ntohs(hdr->numextrarr));
793 if(is_request && nquestions == 0) {
795 LOG_DBG(
"Skipping request with no questions\n");
801 while(nquestions > 0) {
807 unsigned char *qname = queryptr;
809 if(qrecord == NULL) {
814 queryptr = qrecord +
sizeof(
struct dns_question);
817#if RESOLV_SUPPORTS_MDNS
827 struct dns_question *question = (
struct dns_question *)qrecord;
833 if(qrecord +
sizeof(
struct dns_question) >
838#if !ARCH_DOESNT_NEED_ALIGNED_STRUCTS
839 static struct dns_question aligned;
840 memcpy(&aligned, question,
sizeof(aligned));
844 LOG_DBG(
"Question %d: type=%d class=%d\n", ++i,
847 if((uip_ntohs(question->class) & 0x7FFF) != DNS_CLASS_IN ||
848 (question->type !=
UIP_HTONS(DNS_TYPE_ANY) &&
849 question->type !=
UIP_HTONS(NATIVE_DNS_TYPE))) {
858 LOG_DBG(
"Received MDNS request for us\n");
860 if(mdns_state == MDNS_STATE_READY) {
864 if(UIP_UDP_BUF->srcport ==
UIP_HTONS(MDNS_PORT)) {
865 mdns_announce_requested();
868 mdns_prep_host_announce_packet(),
870 UIP_UDP_BUF->srcport);
876 LOG_DBG(
"But we are still probing. Waiting...\n");
882 nauthrr = uip_ntohs(hdr->numauthrr);
898 struct namemap *namemapptr = NULL;
900#if RESOLV_SUPPORTS_MDNS
901 if(UIP_UDP_BUF->srcport ==
UIP_HTONS(MDNS_PORT) && hdr->id == 0) {
911 for(i = 0; i < RESOLV_ENTRIES; ++i) {
912 namemapptr = &names[i];
913 if(namemapptr->state == STATE_ASKING &&
914 namemapptr->id == hdr->id) {
919 if(i >= RESOLV_ENTRIES || i < 0 || namemapptr->state != STATE_ASKING) {
920 LOG_DBG(
"DNS response has bad ID (%04X)\n", uip_ntohs(hdr->id));
924 LOG_DBG(
"Incoming response for \"%s\"\n", namemapptr->name);
927 namemapptr->state = STATE_ERROR;
928 namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
930#if RESOLV_SUPPORTS_RECORD_EXPIRATION
936 if(namemapptr->err != 0) {
937 namemapptr->state = STATE_ERROR;
938 resolv_found(namemapptr->name, NULL);
946 while(nanswers > 0) {
951 const unsigned char *packet_end =
954 if(arecord == NULL) {
958 struct dns_answer *ans = (
struct dns_answer *)arecord;
964 if(arecord + 10 > packet_end) {
968#if !ARCH_DOESNT_NEED_ALIGNED_STRUCTS
975 static struct dns_answer aligned;
976 size_t avail = (size_t)(packet_end - arecord);
977 memcpy(&aligned, ans, avail <
sizeof(aligned) ? avail :
sizeof(aligned));
982 if(LOG_DBG_ENABLED) {
983 char debug_name[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
985 LOG_DBG(
"Answer %d: \"%s\", type %d, class %d, ttl %"PRIu32
", length %d\n",
986 ++i, debug_name, uip_ntohs(ans->type),
987 uip_ntohs(ans->class) & 0x7FFF,
988 (uint32_t)((uint32_t)uip_ntohs(ans->ttl[0]) << 16) |
989 (uint32_t)uip_ntohs(ans->ttl[1]), uip_ntohs(ans->len));
995 if((uip_ntohs(ans->class) & 0x7FFF) != DNS_CLASS_IN ||
996 ans->len !=
UIP_HTONS(
sizeof(uip_ipaddr_t))) {
997 goto skip_to_next_answer;
1000 if(ans->type !=
UIP_HTONS(NATIVE_DNS_TYPE)) {
1001 goto skip_to_next_answer;
1008 if(arecord + 10 + uip_ntohs(ans->len) > packet_end) {
1009 LOG_ERR(
"Answer rdata runs past end of packet\n");
1013#if RESOLV_SUPPORTS_MDNS
1014 if(UIP_UDP_BUF->srcport ==
UIP_HTONS(MDNS_PORT) && hdr->id == 0) {
1015 int8_t available_i = RESOLV_ENTRIES;
1017 LOG_DBG(
"MDNS query\n");
1022 for(i = 0; i < RESOLV_ENTRIES; ++i) {
1023 namemapptr = &names[i];
1024 if(dns_name_isequal(queryptr, namemapptr->name,
uip_appdata,
1028 if((namemapptr->state == STATE_UNUSED)
1029#
if RESOLV_SUPPORTS_RECORD_EXPIRATION
1030 || (namemapptr->state == STATE_DONE &&
1037 if(i == RESOLV_ENTRIES) {
1043 if(available_i == RESOLV_ENTRIES) {
1044 LOG_DBG(
"Not enough room to keep track of unsolicited MDNS answer\n");
1046 if(dns_name_isequal(queryptr, resolv_hostname,
uip_appdata,
1049 resolv_found(resolv_hostname, (uip_ipaddr_t *)ans->ipaddr);
1052 goto skip_to_next_answer;
1055 LOG_DBG(
"Unsolicited MDNS response\n");
1057 namemapptr = &names[i];
1058 if(!decode_name(queryptr, namemapptr->name,
1060 LOG_DBG(
"MDNS name too big to cache\n");
1062 goto skip_to_next_answer;
1065 namemapptr = &names[i];
1082 LOG_DBG(
"Answer for \"%s\" is usable\n", namemapptr->name);
1084 namemapptr->state = STATE_DONE;
1085#if RESOLV_SUPPORTS_RECORD_EXPIRATION
1086 namemapptr->expiration = (uint32_t)uip_ntohs(ans->ttl[0]) << 16 |
1087 (uint32_t)uip_ntohs(ans->ttl[1]);
1088 LOG_DBG(
"Expires in %lu seconds\n", namemapptr->expiration);
1095 resolv_found(namemapptr->name, &namemapptr->ipaddr);
1104 queryptr = arecord + 10 + uip_ntohs(ans->len);
1110#if RESOLV_SUPPORTS_MDNS
1111 if(nanswers == 0 && UIP_UDP_BUF->srcport !=
UIP_HTONS(MDNS_PORT)
1117 if(try_next_server(namemapptr)) {
1118 namemapptr->state = STATE_ASKING;
1119 process_post(&resolv_process, PROCESS_EVENT_TIMER, NULL);
1124#if RESOLV_SUPPORTS_MDNS
1130resolv_set_hostname(
const char *hostname)
1132 strncpy(resolv_hostname, hostname, RESOLV_CONF_MAX_DOMAIN_NAME_SIZE);
1135 resolv_hostname[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE] =
'\0';
1138 if(strlen(resolv_hostname) < 7 ||
1139 strcasecmp(resolv_hostname + strlen(resolv_hostname) - 6,
".local") != 0) {
1140 strncat(resolv_hostname,
".local",
1141 RESOLV_CONF_MAX_DOMAIN_NAME_SIZE - strlen(resolv_hostname));
1144 LOG_DBG(
"hostname changed to \"%s\"\n", resolv_hostname);
1146 start_name_collision_check(0);
1154resolv_get_hostname(
void)
1156 return resolv_hostname;
1164 static struct etimer delay;
1167 mdns_state = MDNS_STATE_WAIT_BEFORE_PROBE;
1169 LOG_DBG(
"mdns-probe: Process (re)started\n");
1173 LOG_DBG(
"mdns-probe: Probing will begin in %ld clocks\n",
1174 (
long)*(clock_time_t *)data);
1185 mdns_state = MDNS_STATE_PROBING;
1190 }
while(strcasecmp(resolv_hostname, data) != 0);
1192 mdns_state = MDNS_STATE_READY;
1193 mdns_announce_requested();
1195 LOG_DBG(
"mdns-probe: Finished probing\n");
1208 memset(names, 0,
sizeof(names));
1212 LOG_DBG(
"Process started\n");
1214 resolv_conn =
udp_new(NULL, 0, NULL);
1215 if(resolv_conn == NULL) {
1216 LOG_ERR(
"No UDP connection available, exiting the process!\n");
1220#if RESOLV_SUPPORTS_MDNS
1221 LOG_DBG(
"Supports MDNS\n");
1224 uip_ds6_maddr_add(&resolv_mdns_addr);
1226 resolv_set_hostname(CONTIKI_CONF_DEFAULT_HOSTNAME);
1232 if(ev == PROCESS_EVENT_TIMER) {
1239#if RESOLV_SUPPORTS_MDNS
1240 if(mdns_needs_host_announce) {
1243 LOG_DBG(
"Announcing that we are \"%s\"\n",
1247 len = mdns_prep_host_announce_packet();
1249 len, &resolv_mdns_addr,
UIP_HTONS(MDNS_PORT));
1250 mdns_needs_host_announce = 0;
1265#if RESOLV_SUPPORTS_MDNS
1266 if(mdns_needs_host_announce) {
1278 static uint8_t initialized = 0;
1285#if RESOLV_AUTO_REMOVE_TRAILING_DOTS
1287remove_trailing_dots(
const char *name)
1289 static char dns_name_without_dots[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
1290 size_t len = strlen(name);
1292 if(len && name[len - 1] ==
'.') {
1293 strncpy(dns_name_without_dots, name, RESOLV_CONF_MAX_DOMAIN_NAME_SIZE);
1294 while(len && (dns_name_without_dots[len - 1] ==
'.')) {
1295 dns_name_without_dots[--len] = 0;
1297 name = dns_name_without_dots;
1302#define remove_trailing_dots(x) (x)
1313 uint8_t lseqi = 0, lseq = 0, i = 0;
1314 struct namemap *nameptr = 0;
1319 name = remove_trailing_dots(name);
1321 for(i = 0; i < RESOLV_ENTRIES; ++i) {
1322 nameptr = &names[i];
1323 if(0 == strcasecmp(nameptr->name, name)) {
1326 if((nameptr->state == STATE_UNUSED)
1327#
if RESOLV_SUPPORTS_RECORD_EXPIRATION
1328 || (nameptr->state == STATE_DONE &&
clock_seconds() > nameptr->expiration)
1333 }
else if(seqno - nameptr->seqno > lseq) {
1334 lseq = seqno - nameptr->seqno;
1339 if(i == RESOLV_ENTRIES) {
1341 nameptr = &names[i];
1344 LOG_DBG(
"Starting query for \"%s\"\n", name);
1346 memset(nameptr, 0,
sizeof(*nameptr));
1348 strncpy(nameptr->name, name,
sizeof(nameptr->name) - 1);
1349 nameptr->state = STATE_NEW;
1350 nameptr->seqno = seqno;
1353#if RESOLV_SUPPORTS_MDNS
1355 size_t name_len = strlen(name);
1356 const char local_suffix[] =
"local";
1358 if(name_len > (
sizeof(local_suffix) - 1) &&
1359 strcasecmp(name + name_len - (
sizeof(local_suffix) - 1),
1360 local_suffix) == 0) {
1361 LOG_DBG(
"Using MDNS to look up \"%s\"\n", name);
1362 nameptr->is_mdns =
true;
1364 nameptr->is_mdns =
false;
1367 nameptr->is_probe = mdns_state == MDNS_STATE_PROBING &&
1368 strcmp(nameptr->name, resolv_hostname) == 0;
1390 name = remove_trailing_dots(name);
1392#if UIP_CONF_LOOPBACK_INTERFACE
1393 if(strcmp(name,
"localhost") == 0) {
1394 static uip_ipaddr_t loopback =
1395 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } };
1406 for(i = 0; i < RESOLV_ENTRIES; ++i) {
1407 struct namemap *nameptr = &names[i];
1409 if(strcasecmp(name, nameptr->name) == 0) {
1410 switch(nameptr->state) {
1413#if RESOLV_SUPPORTS_RECORD_EXPIRATION
1426#if RESOLV_SUPPORTS_RECORD_EXPIRATION
1435 *
ipaddr = &nameptr->ipaddr;
1443 if(LOG_DBG_ENABLED) {
1447 LOG_DBG(
"Found \"%s\" in cache => ", name);
1449 LOG_DBG_6ADDR(
addr);
1454 LOG_DBG(
"\"%s\" is NOT cached\n", name);
1467resolv_found(
char *name, uip_ipaddr_t *
ipaddr)
1469#if RESOLV_SUPPORTS_MDNS
1470 if(strncasecmp(resolv_hostname, name, strlen(resolv_hostname)) == 0 &&
1474 if(mdns_state == MDNS_STATE_PROBING) {
1478 LOG_DBG(
"Name collision detected for \"%s\"\n", name);
1481 resolv_hostname[strlen(resolv_hostname) - 6] = 0;
1484 for(i = 0; i < 3; ++i) {
1487 char append_str[4] =
"-XX";
1489 append_str[2] = (((val & 0xF) > 9) ?
'a' :
'0') + (val & 0xF);
1491 append_str[1] = (((val & 0xF) > 9) ?
'a' :
'0') + (val & 0xF);
1493 strncat(resolv_hostname, append_str,
1494 sizeof(resolv_hostname) - strlen(resolv_hostname) - 1);
1498 strncat(resolv_hostname,
".local",
1499 RESOLV_CONF_MAX_DOMAIN_NAME_SIZE - strlen(resolv_hostname));
1502 }
else if(mdns_state == MDNS_STATE_READY) {
1507 LOG_DBG(
"Possible name collision, probing...\n");
1508 start_name_collision_check(0);
1513 LOG_DBG(
"Found address for \"%s\" => ", name);
1517 LOG_DBG(
"Unable to retrieve address for \"%s\"\n", name);
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
static volatile uint64_t count
Num.
#define CLOCK_SECOND
A second, measured in system clock time.
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_EXIT()
Exit the currently running process.
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
void process_exit(struct process *p)
Cause a process to exit.
process_event_t process_alloc_event(void)
Allocate a global event number.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
#define PROCESS_END()
Define the end of a process.
void process_start(struct process *p, process_data_t data)
Start a process.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
process_event_t tcpip_event
The uIP event.
struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
void tcpip_poll_udp(struct uip_udp_conn *conn)
Cause a specified UDP connection to be polled.
uip_lladdr_t uip_lladdr
Host L2 address.
void * uip_appdata
Pointer to the application data in the packet buffer.
#define UIP_LLADDR_LEN
802.15.4 address
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
uip_ipaddr_t * uip_nameserver_get(uint8_t num)
Get a Nameserver ip address given in RA.
uip_ds6_netif_t uip_ds6_if
The single interface.
#define UIP_IP_BUF
Direct access to IPv6 header.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer.
#define uip_newdata()
Is new incoming data available?
#define uip_poll()
Is the connection being polled by uIP?
#define uip_udp_bind(conn, port)
Bind a UDP connection to a local port.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
void resolv_query(const char *name)
Queues a name so that a question for the name will be sent out.
#define RESOLV_CONF_MAX_RETRIES
The maximum number of retries when asking for a name.
resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t **ipaddr)
Look up a hostname in the array of known hostnames.
static void newdata(void)
process_event_t resolv_event_found
Event that is broadcasted when a DNS name has been resolved.
Header file for the logging system.
Header file for generating non-cryptographic random numbers.
uIP DNS resolver code header file.
@ RESOLV_STATUS_RESOLVING
This hostname is in the process of being resolved.
@ RESOLV_STATUS_EXPIRED
Hostname was found, but it's status has expired.
@ RESOLV_STATUS_NOT_FOUND
The server has returned a not-found response for this domain name.
@ RESOLV_STATUS_CACHED
Hostname is fresh and usable.
@ RESOLV_STATUS_UNCACHED
Hostname was not found in the cache.
Representation of a uIP UDP connection.
Header for the Contiki/uIP interface.
Header file for IPv6-related data structures.
uIP Name Server interface
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Header file for module for sending UDP packets through uIP.