diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-02-06 22:48:10 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-02-06 22:48:10 +0100 |
commit | 5fb38491e3ef093fb9cf642f0f3da5f2ed051f33 (patch) | |
tree | 3566bdff9b5ce23b1bd4531653a66cf112715dca | |
parent | cb7edc26611f8df6b81ef4337206d5833ea98771 (diff) | |
download | busybox-5fb38491e3ef093fb9cf642f0f3da5f2ed051f33.tar.gz |
dnsd: fix one big-endian goof; add a TODO about RA bit
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | include/platform.h | 5 | ||||
-rw-r--r-- | networking/dnsd.c | 39 |
2 files changed, 26 insertions, 18 deletions
diff --git a/include/platform.h b/include/platform.h index dcc61a77b..a134a9e42 100644 --- a/include/platform.h +++ b/include/platform.h @@ -208,6 +208,7 @@ typedef uint32_t bb__aliased_uint32_t FIX_ALIASING; # define move_from_unaligned_int(v, intp) ((v) = *(bb__aliased_int*)(intp)) # define move_from_unaligned16(v, u16p) ((v) = *(bb__aliased_uint16_t*)(u16p)) # define move_from_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p)) +# define move_to_unaligned16(u16p, v) (*(bb__aliased_uint16_t*)(u16p) = (v)) # define move_to_unaligned32(u32p, v) (*(bb__aliased_uint32_t*)(u32p) = (v)) /* #elif ... - add your favorite arch today! */ #else @@ -215,6 +216,10 @@ typedef uint32_t bb__aliased_uint32_t FIX_ALIASING; # define move_from_unaligned_int(v, intp) (memcpy(&(v), (intp), sizeof(int))) # define move_from_unaligned16(v, u16p) (memcpy(&(v), (u16p), 2)) # define move_from_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4)) +# define move_to_unaligned16(u16p, v) do { \ + uint16_t __t = (v); \ + memcpy((u16p), &__t, 4); \ +} while (0) # define move_to_unaligned32(u32p, v) do { \ uint32_t __t = (v); \ memcpy((u32p), &__t, 4); \ diff --git a/networking/dnsd.c b/networking/dnsd.c index 56ede3fca..91d66edcc 100644 --- a/networking/dnsd.c +++ b/networking/dnsd.c @@ -44,7 +44,7 @@ struct dns_head { uint16_t nauth; uint16_t nadd; }; -struct dns_prop { +struct type_and_class { uint16_t type; uint16_t class; }; @@ -291,7 +291,7 @@ QCLASS a two octet code that specifies the class of the query. (others are historic only) 255 any class -4.1.3. Resource record format +4.1.3. Resource Record format The answer, authority, and additional sections all share the same format: a variable number of resource records, where the number of records @@ -353,14 +353,14 @@ static int process_packet(struct dns_entry *conf_data, { char *answstr; struct dns_head *head; - struct dns_prop *unaligned_qprop; + struct type_and_class *unaligned_type_class; char *query_string; uint8_t *answb; uint16_t outr_rlen; uint16_t outr_flags; uint16_t type; uint16_t class; - int querystr_len; + int query_len; head = (struct dns_head *)buf; if (head->nquer == 0) { @@ -376,22 +376,22 @@ static int process_packet(struct dns_entry *conf_data, /* start of query string */ query_string = (void *)(head + 1); /* caller guarantees strlen is <= MAX_PACK_LEN */ - querystr_len = strlen(query_string) + 1; + query_len = strlen(query_string) + 1; /* may be unaligned! */ - unaligned_qprop = (void *)(query_string + querystr_len); - querystr_len += sizeof(unaligned_qprop); + unaligned_type_class = (void *)(query_string + query_len); + query_len += sizeof(unaligned_type_class); /* where to append answer block */ - answb = (void *)(unaligned_qprop + 1); + answb = (void *)(unaligned_type_class + 1); /* QR = 1 "response", RCODE = 4 "Not Implemented" */ outr_flags = htons(0x8000 | 4); - move_from_unaligned16(type, &unaligned_qprop->type); + move_from_unaligned16(type, &unaligned_type_class->type); if (type != htons(REQ_A) && type != htons(REQ_PTR)) { /* we can't handle the query type */ goto empty_packet; } - move_from_unaligned16(class, &unaligned_qprop->class); + move_from_unaligned16(class, &unaligned_type_class->class); if (class != htons(1)) { /* not class INET? */ goto empty_packet; } @@ -408,11 +408,11 @@ static int process_packet(struct dns_entry *conf_data, answstr = table_lookup(conf_data, type, query_string); outr_rlen = 4; if (answstr && type == htons(REQ_PTR)) { - /* return a host name */ + /* returning a host name */ outr_rlen = strlen(answstr) + 1; } if (!answstr - || (unsigned)(answb - buf) + querystr_len + 4 + 2 + outr_rlen > MAX_PACK_LEN + || (unsigned)(answb - buf) + query_len + 4 + 2 + outr_rlen > MAX_PACK_LEN ) { /* QR = 1 "response" * AA = 1 "Authoritative Answer" @@ -421,20 +421,23 @@ static int process_packet(struct dns_entry *conf_data, goto empty_packet; } - /* copy query block to answer block */ - memcpy(answb, query_string, querystr_len); - answb += querystr_len; - /* append answer Resource Record */ + /* Append answer Resource Record */ + memcpy(answb, query_string, query_len); /* name, type, class */ + answb += query_len; move_to_unaligned32((uint32_t *)answb, htonl(conf_ttl)); answb += 4; - move_to_unaligned32((uint16_t *)answb, htons(outr_rlen)); + move_to_unaligned16((uint16_t *)answb, htons(outr_rlen)); answb += 2; memcpy(answb, answstr, outr_rlen); answb += outr_rlen; /* QR = 1 "response", * AA = 1 "Authoritative Answer", - * RCODE = 0 "success" */ + * TODO: need to set RA bit 0x80? One user says nslookup complains + * "Got recursion not available from SERVER, trying next server" + * "** server can't find HOSTNAME" + * RCODE = 0 "success" + */ outr_flags = htons(0x8000 | 0x0400 | 0); /* we have one answer */ head->nansw = htons(1); |