From e0bf7227b1c5f162b8148eb5e852be1ef55b09cd Mon Sep 17 00:00:00 2001 From: Darell Tan Date: Tue, 11 Dec 2012 23:38:08 +0800 Subject: [PATCH] Bugfix: read/write 16 and 32-bit values manually to avoid alignment issues. --- mdns.c | 98 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 39 deletions(-) diff --git a/mdns.c b/mdns.c index 9e333fd..c5cc45a 100644 --- a/mdns.c +++ b/mdns.c @@ -500,6 +500,32 @@ void rr_group_destroy(struct rr_group *group) { } } +uint8_t *mdns_write_u16(uint8_t *ptr, const uint16_t v) { + *ptr++ = (uint8_t) (v >> 8) & 0xFF; + *ptr++ = (uint8_t) (v >> 0) & 0xFF; + return ptr; +} + +uint8_t *mdns_write_u32(uint8_t *ptr, const uint32_t v) { + *ptr++ = (uint8_t) (v >> 24) & 0xFF; + *ptr++ = (uint8_t) (v >> 16) & 0xFF; + *ptr++ = (uint8_t) (v >> 8) & 0xFF; + *ptr++ = (uint8_t) (v >> 0) & 0xFF; + return ptr; +} + +uint16_t mdns_read_u16(const uint8_t *ptr) { + return ((ptr[0] & 0xFF) << 8) | + ((ptr[1] & 0xFF) << 0); +} + +uint32_t mdns_read_u32(const uint8_t *ptr) { + return ((ptr[0] & 0xFF) << 24) | + ((ptr[1] & 0xFF) << 16) | + ((ptr[2] & 0xFF) << 8) | + ((ptr[3] & 0xFF) << 0); +} + // initialize the packet for reply // clears the packet of list structures but not its list items void mdns_init_reply(struct mdns_pkt *pkt, uint16_t id) { @@ -553,11 +579,11 @@ static size_t mdns_parse_qn(uint8_t *pkt_buf, size_t pkt_len, size_t off, p += label_len(pkt_buf, pkt_len, off); rr->name = name; - rr->type = ntohs( * (uint16_t *) p ); + rr->type = mdns_read_u16(p); p += sizeof(uint16_t); rr->unicast_query = (*p & 0x80) == 0x80; - rr->rr_class = ntohs( * (uint16_t *) p) & ~0x80; + rr->rr_class = mdns_read_u16(p) & ~0x80; p += sizeof(uint16_t); rr_list_append(&pkt->rr_qn, rr); @@ -589,18 +615,18 @@ static size_t mdns_parse_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, p += label_len(pkt_buf, pkt_len, off); rr->name = name; - rr->type = ntohs( * (uint16_t *) p ); + rr->type = mdns_read_u16(p); p += sizeof(uint16_t); rr->cache_flush = (*p & 0x80) == 0x80; - rr->rr_class = ntohs( * (uint16_t *) p) & ~0x80; + rr->rr_class = mdns_read_u16(p) & ~0x80; p += sizeof(uint16_t); - rr->ttl = ntohl( * (uint32_t *) p ); + rr->ttl = mdns_read_u32(p); p += sizeof(uint32_t); // RR data - rr_data_len = ntohs( * (uint16_t *) p ); + rr_data_len = mdns_read_u16(p); p += sizeof(uint16_t); if (p + rr_data_len > e) { @@ -619,7 +645,7 @@ static size_t mdns_parse_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, parse_error = 1; break; } - rr->data.A.addr = ntohl( * (uint32_t *) p ); + rr->data.A.addr = ntohl(mdns_read_u32(p)); /* addr already in net order */ p += sizeof(uint32_t); break; @@ -680,7 +706,7 @@ static size_t mdns_parse_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, // parse a MDNS packet into an mdns_pkt struct struct mdns_pkt *mdns_parse_pkt(uint8_t *pkt_buf, size_t pkt_len) { - uint16_t *p = (uint16_t *) pkt_buf; + uint8_t *p = pkt_buf; size_t off; struct mdns_pkt *pkt; int i; @@ -691,14 +717,14 @@ struct mdns_pkt *mdns_parse_pkt(uint8_t *pkt_buf, size_t pkt_len) { MALLOC_ZERO_STRUCT(pkt, mdns_pkt); // parse header - pkt->id = ntohs(*p); p++; - pkt->flags = ntohs(*p); p++; - pkt->num_qn = ntohs(*p); p++; - pkt->num_ans_rr = ntohs(*p); p++; - pkt->num_auth_rr = ntohs(*p); p++; - pkt->num_add_rr = ntohs(*p); p++; + pkt->id = mdns_read_u16(p); p += sizeof(uint16_t); + pkt->flags = mdns_read_u16(p); p += sizeof(uint16_t); + pkt->num_qn = mdns_read_u16(p); p += sizeof(uint16_t); + pkt->num_ans_rr = mdns_read_u16(p); p += sizeof(uint16_t); + pkt->num_auth_rr = mdns_read_u16(p); p += sizeof(uint16_t); + pkt->num_add_rr = mdns_read_u16(p); p += sizeof(uint16_t); - off = (uint8_t *) p - pkt_buf; + off = p - pkt_buf; // parse questions for (i = 0; i < pkt->num_qn; i++) { @@ -742,7 +768,7 @@ static size_t mdns_encode_name(uint8_t *pkt_buf, size_t pkt_len, size_t off, // find match for compression for (c = comp; c; c = c->next) { if (cmp_nlabel(name, c->label) == 0) { - *(uint16_t *) p = htons(0xC000 | (c->pos & ~0xC000)); + mdns_write_u16(p, 0xC000 | (c->pos & ~0xC000)); return len + sizeof(uint16_t); } @@ -792,16 +818,13 @@ static size_t mdns_encode_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, p += l; // type - *(uint16_t *) p = htons(rr->type); - p += sizeof(uint16_t); + p = mdns_write_u16(p, rr->type); // class & cache flush - *(uint16_t *) p = htons((rr->rr_class & ~0x8000) | (rr->cache_flush << 15)); - p += sizeof(uint16_t); + p = mdns_write_u16(p, (rr->rr_class & ~0x8000) | (rr->cache_flush << 15)); // TTL - *(uint32_t *) p = htonl(rr->ttl); - p += sizeof(uint32_t); + p = mdns_write_u32(p, rr->ttl); // data length (filled in later) p += sizeof(uint16_t); @@ -811,8 +834,8 @@ static size_t mdns_encode_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, switch (rr->type) { case RR_A: - *(uint32_t *) p = (rr->data.A.addr); - p += sizeof(uint32_t); + /* htonl() needed coz addr already in net order */ + p = mdns_write_u32(p, htonl(rr->data.A.addr)); break; case RR_PTR: @@ -832,14 +855,11 @@ static size_t mdns_encode_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, break; case RR_SRV: - *(uint16_t *) p = htons(rr->data.SRV.priority); - p += sizeof(uint16_t); + p = mdns_write_u16(p, rr->data.SRV.priority); - *(uint16_t *) p = htons(rr->data.SRV.weight); - p += sizeof(uint16_t); + p = mdns_write_u16(p, rr->data.SRV.weight); - *(uint16_t *) p = htons(rr->data.SRV.port); - p += sizeof(uint16_t); + p = mdns_write_u16(p, rr->data.SRV.port); p += mdns_encode_name(pkt_buf, pkt_len, p - pkt_buf, rr->data.SRV.target, comp); @@ -866,7 +886,7 @@ static size_t mdns_encode_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, l = p - p_data; // fill in the length - *(uint16_t *) (p - l - sizeof(uint16_t)) = htons(l); + mdns_write_u16(p - l - sizeof(uint16_t), l); return p - pkt_buf - off; } @@ -875,7 +895,7 @@ static size_t mdns_encode_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, // returns the size of the entire MDNS packet size_t mdns_encode_pkt(struct mdns_pkt *answer, uint8_t *pkt_buf, size_t pkt_len) { struct name_comp *comp; - uint16_t *p = (uint16_t *) pkt_buf; + uint8_t *p = pkt_buf; //uint8_t *e = pkt_buf + pkt_len; size_t off; int i; @@ -889,14 +909,14 @@ size_t mdns_encode_pkt(struct mdns_pkt *answer, uint8_t *pkt_buf, size_t pkt_len // this is an Answer - number of qns should be zero assert(answer->num_qn == 0); - *p++ = htons(answer->id); - *p++ = htons(answer->flags); - *p++ = htons(answer->num_qn); - *p++ = htons(answer->num_ans_rr); - *p++ = htons(answer->num_auth_rr); - *p++ = htons(answer->num_add_rr); + p = mdns_write_u16(p, answer->id); + p = mdns_write_u16(p, answer->flags); + p = mdns_write_u16(p, answer->num_qn); + p = mdns_write_u16(p, answer->num_ans_rr); + p = mdns_write_u16(p, answer->num_auth_rr); + p = mdns_write_u16(p, answer->num_add_rr); - off = (uint8_t *) p - pkt_buf; + off = p - pkt_buf; // allocate list for name compression comp = malloc(sizeof(struct name_comp));