Reduced code size.

Combined recent changes from darconeous...
- Refactor to decrease minimum code footprint.
- Added `RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION`.
...with a few additional changes to reduce code size.
This commit is contained in:
Oliver Schmidt 2013-03-14 22:53:52 +01:00
parent d8862bd243
commit 46cb6013ae

View file

@ -139,6 +139,28 @@ strcasecmp(const char *s1, const char *s2)
#define RESOLV_CONF_MAX_DOMAIN_NAME_SIZE 32 #define RESOLV_CONF_MAX_DOMAIN_NAME_SIZE 32
#endif #endif
#ifdef RESOLV_CONF_AUTO_REMOVE_TRAILING_DOTS
#define RESOLV_AUTO_REMOVE_TRAILING_DOTS RESOLV_CONF_AUTO_REMOVE_TRAILING_DOTS
#else
#define RESOLV_AUTO_REMOVE_TRAILING_DOTS RESOLV_CONF_SUPPORTS_MDNS
#endif
#ifdef RESOLV_CONF_VERIFY_ANSWER_NAMES
#define RESOLV_VERIFY_ANSWER_NAMES RESOLV_CONF_VERIFY_ANSWER_NAMES
#else
#define RESOLV_VERIFY_ANSWER_NAMES RESOLV_CONF_SUPPORTS_MDNS
#endif
#ifdef RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION
#define RESOLV_SUPPORTS_RECORD_EXPIRATION RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION
#else
#define RESOLV_SUPPORTS_RECORD_EXPIRATION 1
#endif
#if RESOLV_CONF_SUPPORTS_MDNS && !RESOLV_VERIFY_ANSWER_NAMES
#error RESOLV_CONF_SUPPORTS_MDNS cannot be set without RESOLV_CONF_VERIFY_ANSWER_NAMES
#endif
#if !defined(CONTIKI_TARGET_NAME) && defined(BOARD) #if !defined(CONTIKI_TARGET_NAME) && defined(BOARD)
#define stringy2(x) #x #define stringy2(x) #x
#define stringy(x) stringy2(x) #define stringy(x) stringy2(x)
@ -163,6 +185,12 @@ strcasecmp(const char *s1, const char *s2)
#define DNS_TYPE_ANY 255 #define DNS_TYPE_ANY 255
#define DNS_TYPE_NSEC 47 #define DNS_TYPE_NSEC 47
#if UIP_CONF_IPV6
#define NATIVE_DNS_TYPE DNS_TYPE_AAAA /* IPv6 */
#else
#define NATIVE_DNS_TYPE DNS_TYPE_A /* IPv4 */
#endif
#define DNS_CLASS_IN 1 #define DNS_CLASS_IN 1
#define DNS_CLASS_ANY 255 #define DNS_CLASS_ANY 255
@ -238,12 +266,14 @@ struct namemap {
uint8_t tmr; uint8_t tmr;
uint8_t retries; uint8_t retries;
uint8_t seqno; uint8_t seqno;
#if RESOLV_SUPPORTS_RECORD_EXPIRATION
unsigned long expiration; unsigned long expiration;
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
uip_ipaddr_t ipaddr;
uint8_t err; uint8_t err;
#if RESOLV_CONF_SUPPORTS_MDNS #if RESOLV_CONF_SUPPORTS_MDNS
uint8_t is_mdns:1, is_probe:1; uint8_t is_mdns:1, is_probe:1;
#endif #endif
uip_ipaddr_t ipaddr;
char name[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1]; char name[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
}; };
@ -271,12 +301,13 @@ enum {
EVENT_NEW_SERVER = 0 EVENT_NEW_SERVER = 0
}; };
#if RESOLV_CONF_SUPPORTS_MDNS
/** \internal The DNS question message structure. */ /** \internal The DNS question message structure. */
struct dns_question { struct dns_question {
uint16_t type; uint16_t type;
uint16_t class; uint16_t class;
}; };
#if RESOLV_CONF_SUPPORTS_MDNS
static char resolv_hostname[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1]; static char resolv_hostname[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
enum { enum {
@ -300,11 +331,13 @@ static int mdns_needs_host_announce;
PROCESS(mdns_probe_process, "mDNS probe"); PROCESS(mdns_probe_process, "mDNS probe");
#endif /* RESOLV_CONF_SUPPORTS_MDNS */ #endif /* RESOLV_CONF_SUPPORTS_MDNS */
#if RESOLV_AUTO_REMOVE_TRAILING_DOTS
/* For removing trailing dots in resolv_query() and resolve_lookup2(). */ /* For removing trailing dots in resolv_query() and resolve_lookup2(). */
static char dns_name_without_dots[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1]; static char dns_name_without_dots[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
#endif /* RESOLV_AUTO_REMOVE_TRAILING_DOTS */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if RESOLV_CONF_SUPPORTS_MDNS || VERBOSE_DEBUG #if RESOLV_VERIFY_ANSWER_NAMES || VERBOSE_DEBUG
/** \internal /** \internal
* \brief Decodes a DNS name from the DNS format into the given string. * \brief Decodes a DNS name from the DNS format into the given string.
* \return 1 upon success, 0 if the size of the name would be too large. * \return 1 upon success, 0 if the size of the name would be too large.
@ -312,7 +345,7 @@ static char dns_name_without_dots[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
* \note `dest` must point to a buffer with at least * \note `dest` must point to a buffer with at least
* `RESOLV_CONF_MAX_DOMAIN_NAME_SIZE+1` bytes large. * `RESOLV_CONF_MAX_DOMAIN_NAME_SIZE+1` bytes large.
*/ */
static int static uint8_t
decode_name(const unsigned char *query, char *dest, decode_name(const unsigned char *query, char *dest,
const unsigned char *packet) const unsigned char *packet)
{ {
@ -334,7 +367,7 @@ decode_name(const unsigned char *query, char *dest,
if(!n) if(!n)
break; break;
for(; n; n--) { for(; n; --n) {
//DEBUG_PRINTF("%c",*query); //DEBUG_PRINTF("%c",*query);
*dest++ = *query++; *dest++ = *query++;
@ -358,11 +391,10 @@ decode_name(const unsigned char *query, char *dest,
*dest = 0; *dest = 0;
return len != 0; return len != 0;
} }
#endif /* RESOLV_CONF_SUPPORTS_MDNS || VERBOSE_DEBUG */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \internal /** \internal
*/ */
static int static uint8_t
dns_name_isequal(const unsigned char *queryptr, const char *name, dns_name_isequal(const unsigned char *queryptr, const char *name,
const unsigned char *packet) const unsigned char *packet)
{ {
@ -399,6 +431,7 @@ dns_name_isequal(const unsigned char *queryptr, const char *name,
return name[0] == 0; return name[0] == 0;
} }
#endif /* RESOLV_VERIFY_ANSWER_NAMES */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \internal /** \internal
*/ */
@ -496,13 +529,14 @@ mdns_write_announce_records(unsigned char *queryptr, uint8_t *count)
if(!*count) { if(!*count) {
queryptr = encode_name(queryptr, resolv_hostname); queryptr = encode_name(queryptr, resolv_hostname);
} else { } else {
/* Use name compression to refer back to the first name */
*queryptr++ = 0xc0; *queryptr++ = 0xc0;
*queryptr++ = sizeof(struct dns_hdr); *queryptr++ = sizeof(struct dns_hdr);
} }
ans = (struct dns_answer *)queryptr; ans = (struct dns_answer *)queryptr;
*queryptr++ = (uint8_t) ((DNS_TYPE_AAAA) >> 8); *queryptr++ = (uint8_t) ((NATIVE_DNS_TYPE) >> 8);
*queryptr++ = (uint8_t) ((DNS_TYPE_AAAA)); *queryptr++ = (uint8_t) ((NATIVE_DNS_TYPE));
*queryptr++ = (uint8_t) ((DNS_CLASS_IN | 0x8000) >> 8); *queryptr++ = (uint8_t) ((DNS_CLASS_IN | 0x8000) >> 8);
*queryptr++ = (uint8_t) ((DNS_CLASS_IN | 0x8000)); *queryptr++ = (uint8_t) ((DNS_CLASS_IN | 0x8000));
@ -515,8 +549,7 @@ mdns_write_announce_records(unsigned char *queryptr, uint8_t *count)
*queryptr++ = 0; *queryptr++ = 0;
*queryptr++ = sizeof(uip_ipaddr_t); *queryptr++ = sizeof(uip_ipaddr_t);
uip_ipaddr_copy((uip_ipaddr_t *) queryptr, uip_ipaddr_copy((uip_ipaddr_t*)queryptr, &uip_ds6_if.addr_list[i].ipaddr);
&uip_ds6_if.addr_list[i].ipaddr);
queryptr += sizeof(uip_ipaddr_t); queryptr += sizeof(uip_ipaddr_t);
++(*count); ++(*count);
} }
@ -524,7 +557,7 @@ mdns_write_announce_records(unsigned char *queryptr, uint8_t *count)
#else /* UIP_CONF_IPV6 */ #else /* UIP_CONF_IPV6 */
queryptr = encode_name(queryptr, resolv_hostname); queryptr = encode_name(queryptr, resolv_hostname);
ans = (struct dns_answer *)queryptr; ans = (struct dns_answer *)queryptr;
ans->type = UIP_HTONS(DNS_TYPE_A); ans->type = UIP_HTONS(NATIVE_DNS_TYPE);
ans->class = UIP_HTONS(DNS_CLASS_IN | 0x8000); ans->class = UIP_HTONS(DNS_CLASS_IN | 0x8000);
ans->ttl[0] = 0; ans->ttl[0] = 0;
ans->ttl[1] = UIP_HTONS(120); ans->ttl[1] = UIP_HTONS(120);
@ -632,8 +665,10 @@ check_entries(void)
/* STATE_ERROR basically means "not found". */ /* STATE_ERROR basically means "not found". */
namemapptr->state = STATE_ERROR; namemapptr->state = STATE_ERROR;
#if RESOLV_SUPPORTS_RECORD_EXPIRATION
/* Keep the "not found" error valid for 30 seconds */ /* Keep the "not found" error valid for 30 seconds */
namemapptr->expiration = clock_seconds() + 30; namemapptr->expiration = clock_seconds() + 30;
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
resolv_found(namemapptr->name, NULL); resolv_found(namemapptr->name, NULL);
continue; continue;
@ -671,7 +706,7 @@ check_entries(void)
hdr->flags1 = DNS_FLAG1_RD; hdr->flags1 = DNS_FLAG1_RD;
#endif /* RESOLV_CONF_SUPPORTS_MDNS */ #endif /* RESOLV_CONF_SUPPORTS_MDNS */
hdr->numquestions = UIP_HTONS(1); hdr->numquestions = UIP_HTONS(1);
query = (char *)uip_appdata + sizeof(*hdr); query = (unsigned char *)uip_appdata + sizeof(*hdr);
query = encode_name(query, namemapptr->name); query = encode_name(query, namemapptr->name);
#if RESOLV_CONF_SUPPORTS_MDNS #if RESOLV_CONF_SUPPORTS_MDNS
if(namemapptr->is_probe) { if(namemapptr->is_probe) {
@ -680,19 +715,13 @@ check_entries(void)
} else } else
#endif /* RESOLV_CONF_SUPPORTS_MDNS */ #endif /* RESOLV_CONF_SUPPORTS_MDNS */
{ {
#if UIP_CONF_IPV6 *query++ = (uint8_t) ((NATIVE_DNS_TYPE) >> 8);
*query++ = (uint8_t) ((DNS_TYPE_AAAA) >> 8); *query++ = (uint8_t) ((NATIVE_DNS_TYPE));
*query++ = (uint8_t) ((DNS_TYPE_AAAA));
#else /* UIP_CONF_IPV6 */
*query++ = (uint8_t) ((DNS_TYPE_A) >> 8);
*query++ = (uint8_t) ((DNS_TYPE_A));
#endif /* UIP_CONF_IPV6 */
} }
*query++ = (uint8_t) ((DNS_CLASS_IN) >> 8); *query++ = (uint8_t) ((DNS_CLASS_IN) >> 8);
*query++ = (uint8_t) ((DNS_CLASS_IN)); *query++ = (uint8_t) ((DNS_CLASS_IN));
#if RESOLV_CONF_SUPPORTS_MDNS #if RESOLV_CONF_SUPPORTS_MDNS
if(namemapptr->is_mdns) { if(namemapptr->is_mdns) {
#if RESOLV_CONF_SUPPORTS_MDNS
if(namemapptr->is_probe) { if(namemapptr->is_probe) {
/* This is our conflict detection request. /* This is our conflict detection request.
* In order to be in compliance with the MDNS * In order to be in compliance with the MDNS
@ -704,13 +733,12 @@ check_entries(void)
query = mdns_write_announce_records(query, &count); query = mdns_write_announce_records(query, &count);
hdr->numauthrr = UIP_HTONS(count); hdr->numauthrr = UIP_HTONS(count);
} }
#endif /* RESOLV_CONF_SUPPORTS_MDNS */
uip_udp_packet_sendto(resolv_conn, uip_appdata, uip_udp_packet_sendto(resolv_conn, uip_appdata,
(query - (uint8_t *) uip_appdata), (query - (uint8_t *) uip_appdata),
&resolv_mdns_addr, UIP_HTONS(MDNS_PORT)); &resolv_mdns_addr, UIP_HTONS(MDNS_PORT));
PRINTF("resolver: (i=%d) Sent MDNS request for \"%s\".\n", i, PRINTF("resolver: (i=%d) Sent MDNS %s for \"%s\".\n", i,
namemapptr->name); namemapptr->is_probe?"probe":"request",namemapptr->name);
} else { } else {
uip_udp_packet_sendto(resolv_conn, uip_appdata, uip_udp_packet_sendto(resolv_conn, uip_appdata,
(query - (uint8_t *) uip_appdata), (query - (uint8_t *) uip_appdata),
@ -737,17 +765,19 @@ check_entries(void)
static void static void
newdata(void) newdata(void)
{ {
struct dns_answer *ans; static uint8_t nquestions, nanswers, nauthrr;
struct dns_hdr const *hdr = (struct dns_hdr *)uip_appdata; static int8_t i;
unsigned char *queryptr = (unsigned char *)hdr + sizeof(*hdr);
register struct namemap *namemapptr; register struct namemap *namemapptr;
static uint8_t nquestions, nanswers, nauthrr = 0; struct dns_answer *ans;
static int8_t i; register struct dns_hdr const *hdr = (struct dns_hdr *)uip_appdata;
unsigned char *queryptr = (unsigned char *)hdr + sizeof(*hdr);
const uint8_t is_request = ((hdr->flags1 & ~1) == 0) && (hdr->flags2 == 0);
/* We only care about the question(s) and the answers. The authrr /* We only care about the question(s) and the answers. The authrr
* and the extrarr are simply discarded. * and the extrarr are simply discarded.
@ -755,48 +785,52 @@ newdata(void)
nquestions = (uint8_t) uip_ntohs(hdr->numquestions); nquestions = (uint8_t) uip_ntohs(hdr->numquestions);
nanswers = (uint8_t) uip_ntohs(hdr->numanswers); nanswers = (uint8_t) uip_ntohs(hdr->numanswers);
queryptr = (unsigned char *)hdr + sizeof(*hdr);
i = 0;
DEBUG_PRINTF DEBUG_PRINTF
("resolver: flags1=0x%02X flags2=0x%02X nquestions=%d, nanswers=%d, nauthrr=%d, nextrarr=%d\n", ("resolver: flags1=0x%02X flags2=0x%02X nquestions=%d, nanswers=%d, nauthrr=%d, nextrarr=%d\n",
hdr->flags1, hdr->flags2, (uint8_t) nquestions, (uint8_t) nanswers, hdr->flags1, hdr->flags2, (uint8_t) nquestions, (uint8_t) nanswers,
(uint8_t) uip_ntohs(hdr->numauthrr), (uint8_t) uip_ntohs(hdr->numauthrr),
(uint8_t) uip_ntohs(hdr->numextrarr)); (uint8_t) uip_ntohs(hdr->numextrarr));
#if RESOLV_CONF_SUPPORTS_MDNS if(is_request && (nquestions == 0)) {
/** QUESTION HANDLING SECTION ************************************************/
if(((hdr->flags1 & ~1) == 0) && (hdr->flags2 == 0)) {
/* This is an DNS request! */
/* Skip requests with no questions. */ /* Skip requests with no questions. */
if(!nquestions) { DEBUG_PRINTF("resolver: Skipping request with no questions.\n");
return; return;
} }
queryptr = (unsigned char *)hdr + sizeof(*hdr); /** QUESTION HANDLING SECTION ************************************************/
i = 0;
for(; nquestions > 0; for(; nquestions > 0;
queryptr = skip_name(queryptr) + sizeof(struct dns_question), queryptr = skip_name(queryptr) + sizeof(struct dns_question),
nquestions--) { --nquestions
struct dns_question *question = ) {
(struct dns_question *)skip_name(queryptr);
#if __ARM__ if(!is_request) {
/* If this isn't a request, we don't need to bother
* looking at the individual questions. For the most
* part, this loop to just used to skip past them.
*/
continue;
}
#if RESOLV_CONF_SUPPORTS_MDNS
{
struct dns_question *question = (struct dns_question *)skip_name(queryptr);
#if !ARCH_DOESNT_NEED_ALIGNED_STRUCTS
static struct dns_question aligned; static struct dns_question aligned;
memcpy(&aligned, question, sizeof(aligned)); memcpy(&aligned, question, sizeof(aligned));
question = &aligned; question = &aligned;
#endif /* __ARM__ */ #endif /* !ARCH_DOESNT_NEED_ALIGNED_STRUCTS */
DEBUG_PRINTF("resolver: Question %d: type=%d class=%d\n", ++i, DEBUG_PRINTF("resolver: Question %d: type=%d class=%d\n", ++i,
uip_htons(question->type), uip_htons(question->class)); uip_htons(question->type), uip_htons(question->class));
if(((uip_ntohs(question->class) & 0x7FFF) != DNS_CLASS_IN) if(((uip_ntohs(question->class) & 0x7FFF) != DNS_CLASS_IN) ||
|| ((question->type != UIP_HTONS(DNS_TYPE_ANY)) ((question->type != UIP_HTONS(DNS_TYPE_ANY)) &&
&& (question->type != UIP_HTONS(DNS_TYPE_AAAA)) (question->type != UIP_HTONS(NATIVE_DNS_TYPE)))) {
&& (question->type != UIP_HTONS(DNS_TYPE_A))
)) {
/* Skip unrecognised records. */ /* Skip unrecognised records. */
continue; continue;
} }
@ -834,23 +868,23 @@ newdata(void)
* but this should eventually converge to something reasonable. * but this should eventually converge to something reasonable.
*/ */
if(nauthrr) { if(nauthrr) {
start_name_collision_check(CLOCK_SECOND * 1.5); start_name_collision_check(CLOCK_SECOND);
}
} }
} }
} }
#endif /* RESOLV_CONF_SUPPORTS_MDNS */ #endif /* RESOLV_CONF_SUPPORTS_MDNS */
}
/** ANSWER HANDLING SECTION **************************************************/ /** ANSWER HANDLING SECTION **************************************************/
if(!nanswers) { if(nanswers == 0) {
DEBUG_PRINTF("resolver: Skipping request/response with no answers.\n"); /* Skip responses with no answers. */
/* We demand answers! */
return; return;
} }
#if RESOLV_CONF_SUPPORTS_MDNS #if RESOLV_CONF_SUPPORTS_MDNS
if(UIP_UDP_BUF->srcport == UIP_HTONS(MDNS_PORT) if(UIP_UDP_BUF->srcport == UIP_HTONS(MDNS_PORT) &&
&& hdr->id == 0) { hdr->id == 0) {
/* OK, this was from MDNS. Things get a little weird here, /* OK, this was from MDNS. Things get a little weird here,
* because we can't use the `id` field. We will look up the * because we can't use the `id` field. We will look up the
* appropriate request in a later step. */ * appropriate request in a later step. */
@ -866,8 +900,7 @@ newdata(void)
namemapptr = &names[i]; namemapptr = &names[i];
if(i >= RESOLV_ENTRIES || i < 0 || namemapptr->state != STATE_ASKING) { if(i >= RESOLV_ENTRIES || i < 0 || namemapptr->state != STATE_ASKING) {
PRINTF("resolver: Bad ID (%04X) on incoming DNS response\n", PRINTF("resolver: DNS response has bad ID (%04X) \n", uip_ntohs(hdr->id));
uip_ntohs(hdr->id));
return; return;
} }
@ -875,10 +908,13 @@ newdata(void)
/* We'll change this to DONE when we find the record. */ /* We'll change this to DONE when we find the record. */
namemapptr->state = STATE_ERROR; namemapptr->state = STATE_ERROR;
namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK; namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
#if RESOLV_SUPPORTS_RECORD_EXPIRATION
/* If we remain in the error state, keep it cached for 30 seconds. */ /* If we remain in the error state, keep it cached for 30 seconds. */
namemapptr->expiration = clock_seconds() + 30; namemapptr->expiration = clock_seconds() + 30;
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
/* Check for error. If so, call callback to inform. */ /* Check for error. If so, call callback to inform. */
if(namemapptr->err != 0) { if(namemapptr->err != 0) {
@ -888,32 +924,23 @@ newdata(void)
} }
} }
/* Discard all remaining questions */ i = 0;
for(; nquestions > 0; queryptr += 4, --nquestions) {
if(namemapptr && dns_name_isequal(queryptr, namemapptr->name, uip_appdata) != 0) {
DEBUG_PRINTF("resolver: Question name doesn't look familiar...!\n");
return;
}
queryptr = skip_name(queryptr);
}
/* Answer parsing loop */ /* Answer parsing loop */
while(nanswers > 0) { while(nanswers > 0) {
ans = (struct dns_answer *)skip_name(queryptr); ans = (struct dns_answer *)skip_name(queryptr);
#if __ARM__ #if !ARCH_DOESNT_NEED_ALIGNED_STRUCTS
static struct dns_answer aligned; static struct dns_answer aligned;
memcpy(&aligned, ans, sizeof(aligned)); memcpy(&aligned, ans, sizeof(aligned));
ans = &aligned; ans = &aligned;
#endif /* __ARM__ */ #endif /* !ARCH_DOESNT_NEED_ALIGNED_STRUCTS */
#if VERBOSE_DEBUG #if VERBOSE_DEBUG
static char debug_name[40]; static char debug_name[40];
decode_name(queryptr, debug_name, uip_appdata); decode_name(queryptr, debug_name, uip_appdata);
DEBUG_PRINTF("resolver: \"%s\", type %d, class %d, ttl %d, length %d\n", DEBUG_PRINTF("resolver: Answer %d: \"%s\", type %d, class %d, ttl %d, length %d\n",
debug_name, uip_ntohs(ans->type), ++i, debug_name, uip_ntohs(ans->type),
uip_ntohs(ans->class) & 0x7FFF, uip_ntohs(ans->class) & 0x7FFF,
(int)((uint32_t) uip_ntohs(ans->ttl[0]) << 16) | (uint32_t) (int)((uint32_t) uip_ntohs(ans->ttl[0]) << 16) | (uint32_t)
uip_ntohs(ans->ttl[1]), uip_ntohs(ans->len)); uip_ntohs(ans->ttl[1]), uip_ntohs(ans->len));
@ -927,15 +954,9 @@ newdata(void)
goto skip_to_next_answer; goto skip_to_next_answer;
} }
#if UIP_CONF_IPV6 if(ans->type != UIP_HTONS(NATIVE_DNS_TYPE)) {
if(ans->type != UIP_HTONS(DNS_TYPE_AAAA)) {
goto skip_to_next_answer; goto skip_to_next_answer;
} }
#else /* UIP_CONF_IPV6 */
if(ans->type != UIP_HTONS(DNS_TYPE_A)) {
goto skip_to_next_answer;
}
#endif /* UIP_CONF_IPV6 */
#if RESOLV_CONF_SUPPORTS_MDNS #if RESOLV_CONF_SUPPORTS_MDNS
if(UIP_UDP_BUF->srcport == UIP_HTONS(MDNS_PORT) && if(UIP_UDP_BUF->srcport == UIP_HTONS(MDNS_PORT) &&
@ -952,9 +973,11 @@ newdata(void)
if(dns_name_isequal(queryptr, namemapptr->name, uip_appdata)) { if(dns_name_isequal(queryptr, namemapptr->name, uip_appdata)) {
break; break;
} }
if((namemapptr->state == STATE_UNUSED) || if((namemapptr->state == STATE_UNUSED)
(namemapptr->state == STATE_DONE && #if RESOLV_SUPPORTS_RECORD_EXPIRATION
clock_seconds() > namemapptr->expiration)) { || (namemapptr->state == STATE_DONE && clock_seconds() > namemapptr->expiration)
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
) {
available_i = i; available_i = i;
} }
} }
@ -988,17 +1011,22 @@ newdata(void)
nanswers = 1; nanswers = 1;
} }
if(namemapptr && !dns_name_isequal(queryptr, namemapptr->name, uip_appdata)) { #if RESOLV_VERIFY_ANSWER_NAMES
if(namemapptr &&
!dns_name_isequal(queryptr, namemapptr->name, uip_appdata)) {
DEBUG_PRINTF("resolver: Answer name doesn't match question...!\n"); DEBUG_PRINTF("resolver: Answer name doesn't match question...!\n");
goto skip_to_next_answer; goto skip_to_next_answer;
} }
#endif
DEBUG_PRINTF("resolver: Answer for \"%s\" is usable.\n", DEBUG_PRINTF("resolver: Answer for \"%s\" is usable.\n",
namemapptr->name); namemapptr->name);
namemapptr->state = STATE_DONE; namemapptr->state = STATE_DONE;
#if RESOLV_SUPPORTS_RECORD_EXPIRATION
namemapptr->expiration = ans->ttl[1] + (ans->ttl[0] << 8); namemapptr->expiration = ans->ttl[1] + (ans->ttl[0] << 8);
namemapptr->expiration += clock_seconds(); namemapptr->expiration += clock_seconds();
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
uip_ipaddr_copy(&namemapptr->ipaddr, (uip_ipaddr_t *) ans->ipaddr); uip_ipaddr_copy(&namemapptr->ipaddr, (uip_ipaddr_t *) ans->ipaddr);
@ -1100,15 +1128,13 @@ PROCESS_THREAD(resolv_process, ev, data)
resolv_conn->rport = 0; resolv_conn->rport = 0;
#if RESOLV_CONF_SUPPORTS_MDNS #if RESOLV_CONF_SUPPORTS_MDNS
PRINTF("resolver: Supports MDNS name resolution.\n"); PRINTF("resolver: Supports MDNS.\n");
#endif
#if RESOLV_CONF_SUPPORTS_MDNS
PRINTF("resolver: Supports MDNS responder.\n");
uip_udp_bind(resolv_conn, UIP_HTONS(MDNS_PORT)); uip_udp_bind(resolv_conn, UIP_HTONS(MDNS_PORT));
#if UIP_CONF_IPV6 #if UIP_CONF_IPV6
uip_ds6_maddr_add(&resolv_mdns_addr); uip_ds6_maddr_add(&resolv_mdns_addr);
#else
/* TODO: Is there anything we need to do here for IPv4 multicast? */
#endif #endif
resolv_set_hostname(CONTIKI_CONF_DEFAULT_HOSTNAME); resolv_set_hostname(CONTIKI_CONF_DEFAULT_HOSTNAME);
@ -1164,6 +1190,24 @@ PROCESS_THREAD(resolv_process, ev, data)
PROCESS_END(); PROCESS_END();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if RESOLV_AUTO_REMOVE_TRAILING_DOTS
static const char *
remove_trailing_dots(const char *name) {
size_t len = strlen(name);
if(name[len - 1] == '.') {
strncpy(dns_name_without_dots, name, sizeof(dns_name_without_dots));
while(len && (dns_name_without_dots[len - 1] == '.')) {
dns_name_without_dots[--len] = 0;
}
name = dns_name_without_dots;
}
return name;
}
#else /* RESOLV_AUTO_REMOVE_TRAILING_DOTS */
#define remove_trailing_dots(x) (x)
#endif /* RESOLV_AUTO_REMOVE_TRAILING_DOTS */
/*---------------------------------------------------------------------------*/
/** /**
* Queues a name so that a question for the name will be sent out. * Queues a name so that a question for the name will be sent out.
* *
@ -1181,26 +1225,18 @@ resolv_query(const char *name)
lseq = lseqi = 0; lseq = lseqi = 0;
/* Remove trailing dots, if present. */ /* Remove trailing dots, if present. */
{ name = remove_trailing_dots(name);
size_t len = strlen(name);
if(name[len - 1] == '.') {
strncpy(dns_name_without_dots, name, sizeof(dns_name_without_dots));
while(len && (dns_name_without_dots[len - 1] == '.')) {
dns_name_without_dots[--len] = 0;
}
name = dns_name_without_dots;
}
}
for(i = 0; i < RESOLV_ENTRIES; ++i) { for(i = 0; i < RESOLV_ENTRIES; ++i) {
nameptr = &names[i]; nameptr = &names[i];
if(strcasecmp(nameptr->name, name) == 0) { if(0 == strcasecmp(nameptr->name, name)) {
break; break;
} }
if((nameptr->state == STATE_UNUSED) || if((nameptr->state == STATE_UNUSED)
(nameptr->state == STATE_DONE && #if RESOLV_SUPPORTS_RECORD_EXPIRATION
clock_seconds() > nameptr->expiration)) { || (nameptr->state == STATE_DONE && clock_seconds() > nameptr->expiration)
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
) {
lseqi = i; lseqi = i;
lseq = 255; lseq = 255;
} else if(seqno - nameptr->seqno > lseq) { } else if(seqno - nameptr->seqno > lseq) {
@ -1230,7 +1266,7 @@ resolv_query(const char *name)
static const char local_suffix[] = "local"; static const char local_suffix[] = "local";
if((name_len > (sizeof(local_suffix) - 1)) && if((name_len > (sizeof(local_suffix) - 1)) &&
(strcasecmp(name + name_len - (sizeof(local_suffix) - 1), local_suffix) == 0)) { (0 == strcasecmp(name + name_len - (sizeof(local_suffix) - 1), local_suffix))) {
PRINTF("resolver: Using MDNS to look up \"%s\".\n", name); PRINTF("resolver: Using MDNS to look up \"%s\".\n", name);
nameptr->is_mdns = 1; nameptr->is_mdns = 1;
} else { } else {
@ -1238,7 +1274,7 @@ resolv_query(const char *name)
} }
} }
nameptr->is_probe = (mdns_state == MDNS_STATE_PROBING) && nameptr->is_probe = (mdns_state == MDNS_STATE_PROBING) &&
(strcmp(nameptr->name, resolv_hostname) == 0); (0 == strcmp(nameptr->name, resolv_hostname));
#endif /* RESOLV_CONF_SUPPORTS_MDNS */ #endif /* RESOLV_CONF_SUPPORTS_MDNS */
/* Force check_entires() to run on our process. */ /* Force check_entires() to run on our process. */
@ -1264,17 +1300,7 @@ resolv_lookup(const char *name, uip_ipaddr_t **ipaddr)
struct namemap *nameptr; struct namemap *nameptr;
/* Remove trailing dots, if present. */ /* Remove trailing dots, if present. */
{ name = remove_trailing_dots(name);
size_t len = strlen(name);
if(name[len - 1] == '.') {
strncpy(dns_name_without_dots, name, sizeof(dns_name_without_dots) - 1);
name = dns_name_without_dots;
while(len && (dns_name_without_dots[len - 1] == '.')) {
dns_name_without_dots[--len] = 0;
}
}
}
#if UIP_CONF_LOOPBACK_INTERFACE #if UIP_CONF_LOOPBACK_INTERFACE
if(strcmp(name, "localhost")) { if(strcmp(name, "localhost")) {
@ -1299,11 +1325,12 @@ resolv_lookup(const char *name, uip_ipaddr_t **ipaddr)
if(strcasecmp(name, nameptr->name) == 0) { if(strcasecmp(name, nameptr->name) == 0) {
switch (nameptr->state) { switch (nameptr->state) {
case STATE_DONE: case STATE_DONE:
ret = RESOLV_STATUS_CACHED;
#if RESOLV_SUPPORTS_RECORD_EXPIRATION
if(clock_seconds() > nameptr->expiration) { if(clock_seconds() > nameptr->expiration) {
ret = RESOLV_STATUS_EXPIRED; ret = RESOLV_STATUS_EXPIRED;
} else {
ret = RESOLV_STATUS_CACHED;
} }
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
break; break;
case STATE_NEW: case STATE_NEW:
case STATE_ASKING: case STATE_ASKING:
@ -1311,9 +1338,12 @@ resolv_lookup(const char *name, uip_ipaddr_t **ipaddr)
break; break;
/* Almost certainly a not-found error from server */ /* Almost certainly a not-found error from server */
case STATE_ERROR: case STATE_ERROR:
if(clock_seconds() >= nameptr->expiration) {
ret = RESOLV_STATUS_NOT_FOUND; ret = RESOLV_STATUS_NOT_FOUND;
#if RESOLV_SUPPORTS_RECORD_EXPIRATION
if(clock_seconds() > nameptr->expiration) {
ret = RESOLV_STATUS_UNCACHED;
} }
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
break; break;
} }
@ -1386,8 +1416,8 @@ static void
resolv_found(char *name, uip_ipaddr_t * ipaddr) resolv_found(char *name, uip_ipaddr_t * ipaddr)
{ {
#if RESOLV_CONF_SUPPORTS_MDNS #if RESOLV_CONF_SUPPORTS_MDNS
if(strncasecmp(resolv_hostname, name, strlen(resolv_hostname)) == 0 if(strncasecmp(resolv_hostname, name, strlen(resolv_hostname)) == 0 &&
&& ipaddr ipaddr
#if UIP_CONF_IPV6 #if UIP_CONF_IPV6
&& !uip_ds6_is_my_addr(ipaddr) && !uip_ds6_is_my_addr(ipaddr)
#else #else