68 #include "lib/random.h"
71 #define DEBUG CONTIKI_TARGET_COOJA
81 #define NULL (void *)0
84 #if !defined(__SDCC) && defined(SDCC_REVISION)
89 #define DEBUG_PRINTF(...) printf(__VA_ARGS__)
91 #define DEBUG_PRINTF(...) do { } while(0)
94 #if DEBUG || VERBOSE_DEBUG
95 #define PRINTF(...) printf(__VA_ARGS__)
97 #define PRINTF(...) do { } while(0)
102 strncasecmp(
const char *s1,
const char *s2,
size_t n)
105 return strncmp(s1, s2, n);
108 strcasecmp(
const char *s1,
const char *s2)
111 return strcmp(s1, s2);
115 #define UIP_UDP_BUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
121 #ifndef RESOLV_CONF_SUPPORTS_MDNS
122 #define RESOLV_CONF_SUPPORTS_MDNS 1
125 #ifndef RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS
126 #define RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS 0
130 #ifndef RESOLV_CONF_MAX_RETRIES
131 #define RESOLV_CONF_MAX_RETRIES 4
134 #ifndef RESOLV_CONF_MAX_MDNS_RETRIES
135 #define RESOLV_CONF_MAX_MDNS_RETRIES 3
138 #ifndef RESOLV_CONF_MAX_DOMAIN_NAME_SIZE
139 #define RESOLV_CONF_MAX_DOMAIN_NAME_SIZE 32
142 #ifdef RESOLV_CONF_AUTO_REMOVE_TRAILING_DOTS
143 #define RESOLV_AUTO_REMOVE_TRAILING_DOTS RESOLV_CONF_AUTO_REMOVE_TRAILING_DOTS
145 #define RESOLV_AUTO_REMOVE_TRAILING_DOTS RESOLV_CONF_SUPPORTS_MDNS
148 #ifdef RESOLV_CONF_VERIFY_ANSWER_NAMES
149 #define RESOLV_VERIFY_ANSWER_NAMES RESOLV_CONF_VERIFY_ANSWER_NAMES
151 #define RESOLV_VERIFY_ANSWER_NAMES RESOLV_CONF_SUPPORTS_MDNS
154 #ifdef RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION
155 #define RESOLV_SUPPORTS_RECORD_EXPIRATION RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION
157 #define RESOLV_SUPPORTS_RECORD_EXPIRATION 1
160 #if RESOLV_CONF_SUPPORTS_MDNS && !RESOLV_VERIFY_ANSWER_NAMES
161 #error RESOLV_CONF_SUPPORTS_MDNS cannot be set without RESOLV_CONF_VERIFY_ANSWER_NAMES
164 #if !defined(CONTIKI_TARGET_NAME) && defined(BOARD)
165 #define stringy2(x) #x
166 #define stringy(x) stringy2(x)
167 #define CONTIKI_TARGET_NAME stringy(BOARD)
170 #ifndef CONTIKI_CONF_DEFAULT_HOSTNAME
171 #ifdef CONTIKI_TARGET_NAME
172 #define CONTIKI_CONF_DEFAULT_HOSTNAME "contiki-"CONTIKI_TARGET_NAME
174 #define CONTIKI_CONF_DEFAULT_HOSTNAME "contiki"
179 #define DNS_TYPE_CNAME 5
180 #define DNS_TYPE_PTR 12
181 #define DNS_TYPE_MX 15
182 #define DNS_TYPE_TXT 16
183 #define DNS_TYPE_AAAA 28
184 #define DNS_TYPE_SRV 33
185 #define DNS_TYPE_ANY 255
186 #define DNS_TYPE_NSEC 47
189 #define NATIVE_DNS_TYPE DNS_TYPE_AAAA
191 #define NATIVE_DNS_TYPE DNS_TYPE_A
194 #define DNS_CLASS_IN 1
195 #define DNS_CLASS_ANY 255
202 #define MDNS_PORT 5353
205 #ifndef MDNS_RESPONDER_PORT
206 #define MDNS_RESPONDER_PORT 5354
212 uint8_t flags1, flags2;
213 #define DNS_FLAG1_RESPONSE 0x80
214 #define DNS_FLAG1_OPCODE_STATUS 0x10
215 #define DNS_FLAG1_OPCODE_INVERSE 0x08
216 #define DNS_FLAG1_OPCODE_STANDARD 0x00
217 #define DNS_FLAG1_AUTHORATIVE 0x04
218 #define DNS_FLAG1_TRUNC 0x02
219 #define DNS_FLAG1_RD 0x01
220 #define DNS_FLAG2_RA 0x80
221 #define DNS_FLAG2_ERR_MASK 0x0f
222 #define DNS_FLAG2_ERR_NONE 0x00
223 #define DNS_FLAG2_ERR_NAME 0x03
224 uint16_t numquestions;
230 #define RESOLV_ENCODE_INDEX(i) (uip_htons(i+1))
231 #define RESOLV_DECODE_INDEX(i) (unsigned char)(uip_ntohs(i-1))
236 static uip_ipaddr_t resolv_default_dns_server =
238 { { 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00,
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 } };
260 #define STATE_UNUSED 0
261 #define STATE_ERROR 1
263 #define STATE_ASKING 3
269 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
270 unsigned long expiration;
274 #if RESOLV_CONF_SUPPORTS_MDNS
275 int is_mdns:1, is_probe:1;
277 char name[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
280 #ifndef UIP_CONF_RESOLV_ENTRIES
281 #define RESOLV_ENTRIES 4
283 #define RESOLV_ENTRIES UIP_CONF_RESOLV_ENTRIES
286 static struct namemap names[RESOLV_ENTRIES];
288 static uint8_t seqno;
292 static struct etimer retry;
296 PROCESS(resolv_process,
"DNS resolver");
298 static void resolv_found(
char *name, uip_ipaddr_t * ipaddr);
301 struct dns_question {
306 #if RESOLV_CONF_SUPPORTS_MDNS
307 static char resolv_hostname[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
310 MDNS_STATE_WAIT_BEFORE_PROBE,
315 static uint8_t mdns_state;
317 static const uip_ipaddr_t resolv_mdns_addr =
319 { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb } };
323 { { 224, 0, 0, 251 } };
325 static int mdns_needs_host_announce;
327 PROCESS(mdns_probe_process,
"mDNS probe");
331 #if RESOLV_VERIFY_ANSWER_NAMES || VERBOSE_DEBUG
340 decode_name(
const unsigned char *query,
char *dest,
341 const unsigned char *packet)
343 int len = RESOLV_CONF_MAX_DOMAIN_NAME_SIZE;
345 unsigned char n = *query++;
351 const uint16_t offset = query[0] + ((n & ~0xC0) << 8);
354 query = packet + offset;
389 dns_name_isequal(
const unsigned char *queryptr,
const char *name,
390 const unsigned char *packet)
392 unsigned char n = *queryptr++;
399 queryptr = packet + queryptr[0] + ((n & ~0xC0) << 8);
408 if(tolower(*name++) != tolower(*queryptr++)) {
415 if((n != 0) && (*name++ !=
'.')) {
429 static unsigned char *
430 skip_name(
unsigned char *query)
434 DEBUG_PRINTF(
"resolver: skip name: ");
439 DEBUG_PRINTF(
"<skip-to-%d>", query[0] + ((n & ~0xC0) << 8));
447 DEBUG_PRINTF(
"%c", *query);
452 }
while(*query != 0);
459 static unsigned char *
460 encode_name(
unsigned char *query,
const char *nameptr)
470 nptr = (
char *)query;
472 for(n = 0; *nameptr !=
'.' && *nameptr != 0; ++nameptr) {
478 }
while(*nameptr != 0);
486 #if RESOLV_CONF_SUPPORTS_MDNS
490 mdns_announce_requested(
void)
492 mdns_needs_host_announce = 1;
498 start_name_collision_check(clock_time_t after)
506 static unsigned char *
507 mdns_write_announce_records(
unsigned char *queryptr, uint8_t *count)
509 struct dns_answer *ans;
514 for(i = 0; i < UIP_DS6_ADDR_NB; ++i) {
515 if(uip_ds6_if.addr_list[i].isused
516 #
if !RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS
521 queryptr = encode_name(queryptr, resolv_hostname);
525 *queryptr++ =
sizeof(
struct dns_hdr);
527 ans = (
struct dns_answer *)queryptr;
529 *queryptr++ = (uint8_t) ((NATIVE_DNS_TYPE) >> 8);
530 *queryptr++ = (uint8_t) ((NATIVE_DNS_TYPE));
532 *queryptr++ = (uint8_t) ((DNS_CLASS_IN | 0x8000) >> 8);
533 *queryptr++ = (uint8_t) ((DNS_CLASS_IN | 0x8000));
541 *queryptr++ =
sizeof(uip_ipaddr_t);
543 uip_ipaddr_copy((uip_ipaddr_t*)queryptr, &uip_ds6_if.addr_list[i].ipaddr);
544 queryptr +=
sizeof(uip_ipaddr_t);
549 queryptr = encode_name(queryptr, resolv_hostname);
550 ans = (
struct dns_answer *)queryptr;
552 ans->class =
UIP_HTONS(DNS_CLASS_IN | 0x8000);
555 ans->len =
UIP_HTONS(
sizeof(uip_ipaddr_t));
557 queryptr = (
unsigned char *)ans +
sizeof(*ans);
567 mdns_prep_host_announce_packet(
void)
569 static const struct {
584 sizeof(
struct dns_hdr),
602 unsigned char *queryptr;
604 uint8_t total_answers = 0;
606 struct dns_answer *ans;
610 struct dns_hdr *hdr = (
struct dns_hdr *)
uip_appdata;
613 memset((
void *)hdr, 0,
sizeof(*hdr));
615 hdr->flags1 |= DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE;
617 queryptr = (
unsigned char *)
uip_appdata +
sizeof(*hdr);
619 queryptr = mdns_write_announce_records(queryptr, &total_answers);
625 queryptr = encode_name(queryptr, resolv_hostname);
629 *queryptr++ =
sizeof(*hdr);
632 memcpy((
void *)queryptr, (
void *)&nsec_record,
sizeof(nsec_record));
634 queryptr +=
sizeof(nsec_record);
638 ((uint8_t*)&hdr->numanswers)[1] = total_answers;
639 ((uint8_t*)&hdr->numextrarr)[1] = 1;
656 register struct dns_hdr *hdr;
658 register struct namemap *namemapptr;
660 for(i = 0; i < RESOLV_ENTRIES; ++i) {
661 namemapptr = &names[i];
662 if(namemapptr->state == STATE_NEW || namemapptr->state == STATE_ASKING) {
664 if(namemapptr->state == STATE_ASKING) {
665 if(--namemapptr->tmr == 0) {
666 #if RESOLV_CONF_SUPPORTS_MDNS
667 if(++namemapptr->retries ==
668 (namemapptr->is_mdns ? RESOLV_CONF_MAX_MDNS_RETRIES :
669 RESOLV_CONF_MAX_RETRIES))
671 if(++namemapptr->retries == RESOLV_CONF_MAX_RETRIES)
675 namemapptr->state = STATE_ERROR;
677 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
682 resolv_found(namemapptr->name,
NULL);
685 namemapptr->tmr = namemapptr->retries * namemapptr->retries * 3;
687 #if RESOLV_CONF_SUPPORTS_MDNS
688 if(namemapptr->is_probe) {
700 namemapptr->state = STATE_ASKING;
702 namemapptr->retries = 0;
705 memset(hdr, 0,
sizeof(
struct dns_hdr));
706 hdr->id = RESOLV_ENCODE_INDEX(i);
707 #if RESOLV_CONF_SUPPORTS_MDNS
708 if(!namemapptr->is_mdns || namemapptr->is_probe) {
709 hdr->flags1 = DNS_FLAG1_RD;
711 if(namemapptr->is_mdns) {
715 hdr->flags1 = DNS_FLAG1_RD;
718 query = (
unsigned char *)
uip_appdata +
sizeof(*hdr);
719 query = encode_name(query, namemapptr->name);
720 #if RESOLV_CONF_SUPPORTS_MDNS
721 if(namemapptr->is_probe) {
722 *query++ = (uint8_t) ((DNS_TYPE_ANY) >> 8);
723 *query++ = (uint8_t) ((DNS_TYPE_ANY));
727 *query++ = (uint8_t) ((NATIVE_DNS_TYPE) >> 8);
728 *query++ = (uint8_t) ((NATIVE_DNS_TYPE));
730 *query++ = (uint8_t) ((DNS_CLASS_IN) >> 8);
731 *query++ = (uint8_t) ((DNS_CLASS_IN));
732 #if RESOLV_CONF_SUPPORTS_MDNS
733 if(namemapptr->is_mdns) {
734 if(namemapptr->is_probe) {
742 query = mdns_write_announce_records(query, &count);
747 &resolv_mdns_addr,
UIP_HTONS(MDNS_PORT));
749 PRINTF(
"resolver: (i=%d) Sent MDNS %s for \"%s\".\n", i,
750 namemapptr->is_probe?
"probe":
"request",namemapptr->name);
754 &resolv_default_dns_server,
UIP_HTONS(DNS_PORT));
756 PRINTF(
"resolver: (i=%d) Sent DNS request for \"%s\".\n", i,
762 &resolv_default_dns_server,
UIP_HTONS(DNS_PORT));
763 PRINTF(
"resolver: (i=%d) Sent DNS request for \"%s\".\n", i,
777 static uint8_t nquestions, nanswers;
781 register struct namemap *namemapptr;
783 struct dns_answer *ans;
785 register struct dns_hdr const *hdr = (
struct dns_hdr *)
uip_appdata;
787 unsigned char *queryptr = (
unsigned char *)hdr +
sizeof(*hdr);
789 const uint8_t is_request = ((hdr->flags1 & ~1) == 0) && (hdr->flags2 == 0);
794 nquestions = (uint8_t) uip_ntohs(hdr->numquestions);
795 nanswers = (uint8_t) uip_ntohs(hdr->numanswers);
797 queryptr = (
unsigned char *)hdr +
sizeof(*hdr);
801 (
"resolver: flags1=0x%02X flags2=0x%02X nquestions=%d, nanswers=%d, nauthrr=%d, nextrarr=%d\n",
802 hdr->flags1, hdr->flags2, (uint8_t) nquestions, (uint8_t) nanswers,
803 (uint8_t) uip_ntohs(hdr->numauthrr),
804 (uint8_t) uip_ntohs(hdr->numextrarr));
806 if(is_request && (nquestions == 0)) {
808 DEBUG_PRINTF(
"resolver: Skipping request with no questions.\n");
814 for(; nquestions > 0;
815 queryptr = skip_name(queryptr) +
sizeof(
struct dns_question),
818 #if RESOLV_CONF_SUPPORTS_MDNS
828 struct dns_question *question = (
struct dns_question *)skip_name(queryptr);
830 #if !ARCH_DOESNT_NEED_ALIGNED_STRUCTS
831 static struct dns_question aligned;
832 memcpy(&aligned, question,
sizeof(aligned));
836 DEBUG_PRINTF(
"resolver: Question %d: type=%d class=%d\n", ++i,
839 if(((uip_ntohs(question->class) & 0x7FFF) != DNS_CLASS_IN) ||
840 ((question->type !=
UIP_HTONS(DNS_TYPE_ANY)) &&
841 (question->type !=
UIP_HTONS(NATIVE_DNS_TYPE)))) {
846 if(!dns_name_isequal(queryptr, resolv_hostname,
uip_appdata)) {
850 PRINTF(
"resolver: THIS IS A REQUEST FOR US!!!\n");
852 if(mdns_state == MDNS_STATE_READY) {
856 if(UIP_UDP_BUF->srcport ==
UIP_HTONS(MDNS_PORT)) {
857 mdns_announce_requested();
860 mdns_prep_host_announce_packet(),
861 &UIP_UDP_BUF->srcipaddr,
862 UIP_UDP_BUF->srcport);
866 static uint8_t nauthrr;
867 PRINTF(
"resolver: But we are still probing. Waiting...\n");
872 nauthrr = (uint8_t)uip_ntohs(hdr->numauthrr);
894 #if RESOLV_CONF_SUPPORTS_MDNS
895 if(UIP_UDP_BUF->srcport ==
UIP_HTONS(MDNS_PORT) &&
907 i = RESOLV_DECODE_INDEX(hdr->id);
909 namemapptr = &names[i];
911 if(i >= RESOLV_ENTRIES || i < 0 || namemapptr->state != STATE_ASKING) {
912 PRINTF(
"resolver: DNS response has bad ID (%04X) \n", uip_ntohs(hdr->id));
916 PRINTF(
"resolver: Incoming response for \"%s\".\n", namemapptr->name);
919 namemapptr->state = STATE_ERROR;
921 namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
923 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
929 if(namemapptr->err != 0) {
930 namemapptr->state = STATE_ERROR;
931 resolv_found(namemapptr->name,
NULL);
939 while(nanswers > 0) {
940 ans = (
struct dns_answer *)skip_name(queryptr);
942 #if !ARCH_DOESNT_NEED_ALIGNED_STRUCTS
944 static struct dns_answer aligned;
945 memcpy(&aligned, ans,
sizeof(aligned));
951 static char debug_name[40];
953 DEBUG_PRINTF(
"resolver: Answer %d: \"%s\", type %d, class %d, ttl %d, length %d\n",
954 ++i, debug_name, uip_ntohs(ans->type),
955 uip_ntohs(ans->class) & 0x7FFF,
956 (
int)((uint32_t) uip_ntohs(ans->ttl[0]) << 16) | (uint32_t)
957 uip_ntohs(ans->ttl[1]), uip_ntohs(ans->len));
963 if(((uip_ntohs(ans->class) & 0x7FFF) != DNS_CLASS_IN) ||
964 (ans->len !=
UIP_HTONS(
sizeof(uip_ipaddr_t)))) {
965 goto skip_to_next_answer;
968 if(ans->type !=
UIP_HTONS(NATIVE_DNS_TYPE)) {
969 goto skip_to_next_answer;
972 #if RESOLV_CONF_SUPPORTS_MDNS
973 if(UIP_UDP_BUF->srcport ==
UIP_HTONS(MDNS_PORT) &&
975 int8_t available_i = RESOLV_ENTRIES;
977 DEBUG_PRINTF(
"resolver: MDNS query.\n");
982 for(i = 0; i < RESOLV_ENTRIES; ++i) {
983 namemapptr = &names[i];
984 if(dns_name_isequal(queryptr, namemapptr->name,
uip_appdata)) {
987 if((namemapptr->state == STATE_UNUSED)
988 #
if RESOLV_SUPPORTS_RECORD_EXPIRATION
989 || (namemapptr->state == STATE_DONE &&
clock_seconds() > namemapptr->expiration)
995 if(i == RESOLV_ENTRIES) {
996 DEBUG_PRINTF(
"resolver: Unsolicited MDNS response.\n");
998 namemapptr = &names[i];
999 if(!decode_name(queryptr, namemapptr->name,
uip_appdata)) {
1000 DEBUG_PRINTF(
"resolver: MDNS name too big to cache.\n");
1002 goto skip_to_next_answer;
1005 if(i == RESOLV_ENTRIES) {
1007 (
"resolver: Not enough room to keep track of unsolicited MDNS answer.\n");
1009 if(dns_name_isequal(queryptr, resolv_hostname,
uip_appdata)) {
1011 resolv_found(resolv_hostname, (uip_ipaddr_t *) ans->ipaddr);
1014 goto skip_to_next_answer;
1016 namemapptr = &names[i];
1034 DEBUG_PRINTF(
"resolver: Answer for \"%s\" is usable.\n", namemapptr->name);
1036 namemapptr->state = STATE_DONE;
1037 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
1038 namemapptr->expiration = ans->ttl[1] + (ans->ttl[0] << 8);
1044 resolv_found(namemapptr->name, &namemapptr->ipaddr);
1046 skip_to_next_answer:
1047 queryptr = (
unsigned char *)skip_name(queryptr) + 10 +
uip_htons(ans->len);
1052 #if RESOLV_CONF_SUPPORTS_MDNS
1058 resolv_set_hostname(
const char *hostname)
1060 strncpy(resolv_hostname, hostname, RESOLV_CONF_MAX_DOMAIN_NAME_SIZE);
1063 if(strlen(resolv_hostname) < 7 ||
1064 strcasecmp(resolv_hostname + strlen(resolv_hostname) - 6,
".local") != 0) {
1065 strncat(resolv_hostname,
".local", RESOLV_CONF_MAX_DOMAIN_NAME_SIZE);
1068 PRINTF(
"resolver: hostname changed to \"%s\"\n", resolv_hostname);
1070 start_name_collision_check(0);
1078 resolv_get_hostname(
void)
1080 return resolv_hostname;
1088 static struct etimer delay;
1091 mdns_state = MDNS_STATE_WAIT_BEFORE_PROBE;
1093 PRINTF(
"mdns-probe: Process (re)started.\n");
1097 PRINTF(
"mdns-probe: Probing will begin in %ld clocks.\n",
1098 (
long)*(clock_time_t *) data);
1109 mdns_state = MDNS_STATE_PROBING;
1110 resolv_query(resolv_hostname);
1114 }
while(strcasecmp(resolv_hostname, data) != 0);
1116 mdns_state = MDNS_STATE_READY;
1117 mdns_announce_requested();
1119 PRINTF(
"mdns-probe: Finished probing.\n");
1132 memset(names, 0,
sizeof(names));
1136 PRINTF(
"resolver: Process started.\n");
1140 #if RESOLV_CONF_SUPPORTS_MDNS
1141 PRINTF(
"resolver: Supports MDNS.\n");
1145 uip_ds6_maddr_add(&resolv_mdns_addr);
1150 resolv_set_hostname(CONTIKI_CONF_DEFAULT_HOSTNAME);
1156 if(ev == PROCESS_EVENT_TIMER) {
1164 #if RESOLV_CONF_SUPPORTS_MDNS
1165 if(mdns_needs_host_announce) {
1168 PRINTF(
"resolver: Announcing that we are \"%s\".\n",
1173 len = mdns_prep_host_announce_packet();
1176 len, &resolv_mdns_addr,
UIP_HTONS(MDNS_PORT));
1178 mdns_needs_host_announce = 0;
1193 #if RESOLV_CONF_SUPPORTS_MDNS
1194 if(mdns_needs_host_announce) {
1203 #if RESOLV_AUTO_REMOVE_TRAILING_DOTS
1205 remove_trailing_dots(
const char *name) {
1206 static char dns_name_without_dots[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
1207 size_t len = strlen(name);
1209 if(name[len - 1] ==
'.') {
1210 strncpy(dns_name_without_dots, name,
sizeof(dns_name_without_dots));
1211 while(len && (dns_name_without_dots[len - 1] ==
'.')) {
1212 dns_name_without_dots[--len] = 0;
1214 name = dns_name_without_dots;
1219 #define remove_trailing_dots(x) (x)
1228 resolv_query(
const char *name)
1232 static uint8_t lseq, lseqi;
1234 register struct namemap *nameptr = 0;
1239 name = remove_trailing_dots(name);
1241 for(i = 0; i < RESOLV_ENTRIES; ++i) {
1242 nameptr = &names[i];
1243 if(0 == strcasecmp(nameptr->name, name)) {
1246 if((nameptr->state == STATE_UNUSED)
1247 #
if RESOLV_SUPPORTS_RECORD_EXPIRATION
1248 || (nameptr->state == STATE_DONE &&
clock_seconds() > nameptr->expiration)
1253 }
else if(seqno - nameptr->seqno > lseq) {
1254 lseq = seqno - nameptr->seqno;
1259 if(i == RESOLV_ENTRIES) {
1261 nameptr = &names[i];
1264 PRINTF(
"resolver: Starting query for \"%s\".\n", name);
1266 memset(nameptr, 0,
sizeof(*nameptr));
1268 strncpy(nameptr->name, name,
sizeof(nameptr->name));
1269 nameptr->state = STATE_NEW;
1270 nameptr->seqno = seqno;
1273 #if RESOLV_CONF_SUPPORTS_MDNS
1275 size_t name_len = strlen(name);
1277 static const char local_suffix[] =
"local";
1279 if((name_len > (
sizeof(local_suffix) - 1)) &&
1280 (0 == strcasecmp(name + name_len - (
sizeof(local_suffix) - 1), local_suffix))) {
1281 PRINTF(
"resolver: Using MDNS to look up \"%s\".\n", name);
1282 nameptr->is_mdns = 1;
1284 nameptr->is_mdns = 0;
1287 nameptr->is_probe = (mdns_state == MDNS_STATE_PROBING) &&
1288 (0 == strcmp(nameptr->name, resolv_hostname));
1305 resolv_lookup(
const char *name, uip_ipaddr_t ** ipaddr)
1311 struct namemap *nameptr;
1314 name = remove_trailing_dots(name);
1316 #if UIP_CONF_LOOPBACK_INTERFACE
1317 if(strcmp(name,
"localhost")) {
1318 static uip_ipaddr_t loopback =
1320 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } };
1323 { { 127, 0, 0, 1 } };
1326 *ipaddr = &loopback;
1333 for(i = 0; i < RESOLV_ENTRIES; ++i) {
1334 nameptr = &names[i];
1336 if(strcasecmp(name, nameptr->name) == 0) {
1337 switch (nameptr->state) {
1340 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
1353 #if RESOLV_SUPPORTS_RECORD_EXPIRATION
1362 *ipaddr = &nameptr->ipaddr;
1373 PRINTF(
"resolver: Found \"%s\" in cache.\n", name);
1374 const uip_ipaddr_t *addr = *ipaddr;
1377 (
"resolver: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x \n",
1378 ((uint8_t *) addr)[0], ((uint8_t *) addr)[1], ((uint8_t *) addr)[2],
1379 ((uint8_t *) addr)[3], ((uint8_t *) addr)[4], ((uint8_t *) addr)[5],
1380 ((uint8_t *) addr)[6], ((uint8_t *) addr)[7], ((uint8_t *) addr)[8],
1381 ((uint8_t *) addr)[9], ((uint8_t *) addr)[10],
1382 ((uint8_t *) addr)[11], ((uint8_t *) addr)[12],
1383 ((uint8_t *) addr)[13], ((uint8_t *) addr)[14],
1384 ((uint8_t *) addr)[15]);
1388 DEBUG_PRINTF(
"resolver: \"%s\" is NOT cached.\n", name);
1404 resolv_getserver(
void)
1406 return &resolv_default_dns_server;
1416 resolv_conf(
const uip_ipaddr_t * dnsserver)
1426 resolv_found(
char *name, uip_ipaddr_t * ipaddr)
1428 #if RESOLV_CONF_SUPPORTS_MDNS
1429 if(strncasecmp(resolv_hostname, name, strlen(resolv_hostname)) == 0 &&
1432 && !uip_ds6_is_my_addr(ipaddr)
1434 && uip_ipaddr_cmp(&uip_hostaddr, ipaddr) != 0
1439 if(mdns_state == MDNS_STATE_PROBING) {
1443 PRINTF(
"resolver: Name collision detected for \"%s\".\n", name);
1446 resolv_hostname[strlen(resolv_hostname) - 6] = 0;
1449 for(i = 0; i < 3; ++i) {
1450 uint8_t val =
uip_lladdr.addr[(UIP_LLADDR_LEN - 3) + i];
1452 char append_str[4] =
"-XX";
1454 append_str[2] = (((val & 0xF) > 9) ?
'a' :
'0') + (val & 0xF);
1456 append_str[1] = (((val & 0xF) > 9) ?
'a' :
'0') + (val & 0xF);
1457 strncat(resolv_hostname, append_str,
1458 sizeof(resolv_hostname) - strlen(resolv_hostname) - 1);
1462 strncat(resolv_hostname,
".local", RESOLV_CONF_MAX_DOMAIN_NAME_SIZE);
1465 }
else if(mdns_state == MDNS_STATE_READY) {
1470 PRINTF(
"resolver: Possible name collision, probing...\n");
1471 start_name_collision_check(0);
1479 PRINTF(
"resolver: Found address for \"%s\".\n", name);
1481 (
"resolver: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x \n",
1482 ((uint8_t *) ipaddr)[0], ((uint8_t *) ipaddr)[1],
1483 ((uint8_t *) ipaddr)[2], ((uint8_t *) ipaddr)[3],
1484 ((uint8_t *) ipaddr)[4], ((uint8_t *) ipaddr)[5],
1485 ((uint8_t *) ipaddr)[6], ((uint8_t *) ipaddr)[7],
1486 ((uint8_t *) ipaddr)[8], ((uint8_t *) ipaddr)[9],
1487 ((uint8_t *) ipaddr)[10], ((uint8_t *) ipaddr)[11],
1488 ((uint8_t *) ipaddr)[12], ((uint8_t *) ipaddr)[13],
1489 ((uint8_t *) ipaddr)[14], ((uint8_t *) ipaddr)[15]);
1491 PRINTF(
"resolver: Unable to retrieve address for \"%s\".\n", name);
Hostname was not found in the cache.
#define uip_gethostaddr(addr)
Get the IP address of this host.
#define uip_is_addr_link_local(a)
is addr (a) a link local unicast address, see RFC3513 i.e.
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
Hostname is fresh and usable.
#define PROCESS_BEGIN()
Define the beginning of a process.
Header for the Contiki/uIP interface.
CCIF struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
#define uip_newdata()
Is new incoming data available?
Network interface and stateless autoconfiguration (RFC 4862)
#define uip_udp_bind(conn, port)
Bind a UDP connection to a local port.
This hostname is in the process of being resolved.
#define NULL
The null pointer.
#define uip_poll()
Is the connection being polled by uIP?
process_event_t process_alloc_event(void)
Allocate a global event number.
Hostname was found, but it's status has expired.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
The server has returned a not-found response for this domain name.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
CCIF void tcpip_poll_udp(struct uip_udp_conn *conn)
Cause a specified UDP connection to be polled.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PROCESS_END()
Define the end of a process.
Header file for module for sending UDP packets through uIP.
CCIF process_event_t resolv_event_found
Event that is broadcasted when a DNS name has been resolved.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
#define PROCESS(name, strname)
Declare a process.
CCIF unsigned long clock_seconds(void)
Get the current value of the platform seconds.
process_event_t tcpip_event
The uIP event.
void process_start(struct process *p, process_data_t data)
Start a process.
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Representation of a uIP UDP connection.
uIP DNS resolver code header file.
unsigned short random_rand(void)
Generate the next state and return the upper part of it.
void process_exit(struct process *p)
Cause a process to exit.
uip_appdata
Pointer to the application data in the packet buffer.
#define CLOCK_SECOND
A second, measured in system clock time.