dnsd: fix one big-endian goof; add a TODO about RA bit
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 6 Feb 2010 21:48:10 +0000 (22:48 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 6 Feb 2010 21:48:10 +0000 (22:48 +0100)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
include/platform.h
networking/dnsd.c

index dcc61a77b7bd54f09cf3aba9cc4a4967569af0e0..a134a9e4252ade616aa7aa50005d4df933297674 100644 (file)
@@ -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); \
index 56ede3fca2ccf1e2223860451a22545a4868b670..91d66edccfa5db5239e3261579ba1815ae96a69e 100644 (file)
@@ -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);