From 0bed4b17a26806119f46076a416653dd2384bd29 Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Thu, 16 May 2013 09:38:42 -0700 Subject: [PATCH] resolv: Fix for word alignment issues in `mdns_prep_host_announce_packet()`. --- core/net/resolv.c | 84 ++++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/core/net/resolv.c b/core/net/resolv.c index 2ffbe54f2..f90124e14 100644 --- a/core/net/resolv.c +++ b/core/net/resolv.c @@ -570,22 +570,55 @@ mdns_write_announce_records(unsigned char *queryptr, uint8_t *count) static size_t mdns_prep_host_announce_packet(void) { + static const struct { + uint16_t type; + uint16_t class; + uint16_t ttl[2]; + uint16_t len; + uint8_t data[8]; + + } nsec_record = { + UIP_HTONS(DNS_TYPE_NSEC), + UIP_HTONS(DNS_CLASS_IN | 0x8000), + { 0, UIP_HTONS(120) }, + UIP_HTONS(8), + + { + 0xc0, + sizeof(struct dns_hdr), /* Name compression. Re-using the name of first record. */ + 0x00, + 0x04, + +#if UIP_CONF_IPV6 + 0x00, + 0x00, + 0x00, + 0x08, +#else /* UIP_CONF_IPV6 */ + 0x40, + 0x00, + 0x00, + 0x00, +#endif /* UIP_CONF_IPV6 */ + } + }; + unsigned char *queryptr; - struct dns_answer *ans; - - struct dns_hdr *hdr; - uint8_t total_answers = 0; - hdr = (struct dns_hdr *)uip_appdata; + struct dns_answer *ans; + + /* Be aware that, unless `ARCH_DOESNT_NEED_ALIGNED_STRUCTS` is set, + * writing directly to the uint16_t members of this struct is an error. */ + struct dns_hdr *hdr = (struct dns_hdr *)uip_appdata; + + /* Zero out the header */ + memset((void *)hdr, 0, sizeof(*hdr)); hdr->flags1 |= DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE; - hdr->numquestions = UIP_HTONS(0); - hdr->numauthrr = 0; - hdr->numextrarr = 0; - queryptr = (unsigned char *)hdr + sizeof(*hdr); + queryptr = (unsigned char *)uip_appdata + sizeof(*hdr); queryptr = mdns_write_announce_records(queryptr, &total_answers); @@ -595,34 +628,17 @@ mdns_prep_host_announce_packet(void) if(!total_answers) { queryptr = encode_name(queryptr, resolv_hostname); } else { + /* Name compression. Re-using the name of first record. */ *queryptr++ = 0xc0; *queryptr++ = sizeof(*hdr); } - ans = (struct dns_answer *)queryptr; - ans->type = UIP_HTONS(DNS_TYPE_NSEC); - ans->class = UIP_HTONS(DNS_CLASS_IN | 0x8000); - ans->ttl[0] = 0; - ans->ttl[1] = UIP_HTONS(120); - ans->len = UIP_HTONS(8); - queryptr += 10; - *queryptr++ = 0xc0; - *queryptr++ = sizeof(*hdr); - *queryptr++ = 0x00; - *queryptr++ = 0x04; -#if UIP_CONF_IPV6 - *queryptr++ = 0x00; - *queryptr++ = 0x00; - *queryptr++ = 0x00; - *queryptr++ = 0x08; -#else /* UIP_CONF_IPV6 */ - *queryptr++ = 0x40; - *queryptr++ = 0x00; - *queryptr++ = 0x00; - *queryptr++ = 0x00; -#endif /* UIP_CONF_IPV6 */ - hdr->numanswers = uip_htons(total_answers); - hdr->numextrarr = UIP_HTONS(1); + memcpy((void *)queryptr, (void *)&nsec_record, sizeof(nsec_record)); + + /* This platform might be picky about alignment. To avoid the possibility + * of doing an unaligned write, we are going to do this manually. */ + ((uint8_t*)&hdr->numanswers)[1] = total_answers; + ((uint8_t*)&hdr->numextrarr)[1] = 1; return (queryptr - (unsigned char *)uip_appdata); } @@ -1485,4 +1501,4 @@ resolv_found(char *name, uip_ipaddr_t * ipaddr) #endif /* UIP_UDP */ /** @} */ -/** @} */ \ No newline at end of file +/** @} */