resolv: Implement SOA faking
authorJakub Hrozek <jhrozek@redhat.com>
Sat, 4 Oct 2014 15:55:50 +0000 (17:55 +0200)
committerMichael Adam <obnox@samba.org>
Tue, 21 Oct 2014 11:39:39 +0000 (13:39 +0200)
Signed-off-by: Jakub Hrozek <jhrozek@redhat.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
src/resolv_wrapper.c
tests/fake_hosts.in
tests/test_dns_fake.c

index 60781ef..ab741b3 100644 (file)
@@ -405,6 +405,79 @@ static int rwrap_fake_srv(const char *key,
        return 0;
 }
 
+static int rwrap_fake_soa(const char *key,
+                         const char *value,
+                         uint8_t *answer,
+                         size_t anslen)
+{
+       uint8_t *a = answer;
+       int rv;
+       const char *nameserver;
+       char *mailbox;
+       char *str_serial;
+       char *str_refresh;
+       char *str_retry;
+       char *str_expire;
+       char *str_minimum;
+       size_t rdata_size;
+       unsigned char nameser_compressed[MAXDNAME];
+       ssize_t compressed_ns_len;
+       unsigned char mailbox_compressed[MAXDNAME];
+       ssize_t compressed_mb_len;
+
+       /*
+        * parse the value into nameserver, mailbox, serial, refresh,
+        * retry, expire, minimum and check the validity
+        */
+       nameserver = value;
+       NEXT_KEY(nameserver, mailbox);
+       NEXT_KEY(mailbox, str_serial);
+       NEXT_KEY(str_serial, str_refresh);
+       NEXT_KEY(str_refresh, str_retry);
+       NEXT_KEY(str_retry, str_expire);
+       NEXT_KEY(str_expire, str_minimum);
+       if (nameserver == NULL || mailbox == NULL || str_serial == NULL ||
+           str_refresh == NULL || str_retry == NULL || str_expire == NULL ||
+           str_minimum == NULL)
+       {
+               RWRAP_LOG(RWRAP_LOG_ERROR,
+                         "Malformed SOA entry [%s]\n", value);
+               return -1;
+       }
+       rdata_size = 5 * sizeof(uint16_t);
+
+       compressed_ns_len = ns_name_compress(nameserver, nameser_compressed,
+                                            MAXDNAME, NULL, NULL);
+       if (compressed_ns_len < 0) {
+               return -1;
+       }
+       rdata_size += compressed_ns_len;
+
+       compressed_mb_len = ns_name_compress(mailbox, mailbox_compressed,
+                                            MAXDNAME, NULL, NULL);
+       if (compressed_mb_len < 0) {
+               return -1;
+       }
+       rdata_size += compressed_mb_len;
+
+       rv = rwrap_fake_common(ns_t_soa, key, rdata_size, &a, anslen);
+       if (rv < 0) {
+               return -1;
+       }
+
+       memcpy(a, nameser_compressed, compressed_ns_len);
+       a += compressed_ns_len;
+       memcpy(a, mailbox_compressed, compressed_mb_len);
+       a += compressed_mb_len;
+       NS_PUT32(atoi(str_serial), a);
+       NS_PUT32(atoi(str_refresh), a);
+       NS_PUT32(atoi(str_retry), a);
+       NS_PUT32(atoi(str_expire), a);
+       NS_PUT32(atoi(str_minimum), a);
+
+       return 0;
+}
+
 static int rwrap_fake_empty_query(const char *key,
                                  uint16_t type,
                                  uint8_t *answer,
@@ -494,6 +567,10 @@ static int rwrap_res_fake_hosts(const char *hostfile,
                                      rec_type, "SRV", key, query)) {
                        rc = rwrap_fake_srv(key, value, answer, anslen);
                        break;
+               } else if (TYPE_MATCH(type, ns_t_soa,
+                                     rec_type, "SOA", key, query)) {
+                       rc = rwrap_fake_soa(key, value, answer, anslen);
+                       break;
                }
        }
 
index 7e28052..ed82fd6 100644 (file)
@@ -2,3 +2,4 @@ A cwrap.org 127.0.0.21
 AAAA cwrap6.org 2a00:1450:4013:c01::63
 SRV _ldap._tcp.cwrap.org ldap.cwrap.org 389 1 5
 SRV _krb5._tcp.cwrap.org krb5.cwrap.org 88
+SOA cwrap.org ns1.cwrap.org admin.cwrap.org 2014100457 3600 300 1814400 600
index 2897893..eec0548 100644 (file)
@@ -270,6 +270,76 @@ static void test_res_fake_srv_query_minimal(void **state)
        assert_string_equal(hostname, "krb5.cwrap.org");
 }
 
+static void test_res_fake_soa_query(void **state)
+{
+       int rv;
+       struct __res_state dnsstate;
+       unsigned char answer[ANSIZE];
+       ns_msg handle;
+       ns_rr rr;   /* expanded resource record */
+       const uint8_t *rrdata;
+       char nameser[MAXDNAME];
+       char admin[MAXDNAME];
+       int serial;
+       int refresh;
+       int retry;
+       int expire;
+       int minimum;
+
+       (void) state; /* unused */
+
+       memset(&dnsstate, 0, sizeof(struct __res_state));
+       rv = res_ninit(&dnsstate);
+       assert_int_equal(rv, 0);
+
+       rv = res_nquery(&dnsstate, "cwrap.org", ns_c_in, ns_t_soa,
+                       answer, ANSIZE);
+       assert_int_not_equal(rv, -1);
+
+       ns_initparse(answer, 256, &handle);
+
+       /*
+        * The query must finish w/o an error, have one answer and the answer
+        * must be a parseable RR of type SOA and have the data as in the fake
+        * hosts file
+        */
+       assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
+       assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
+       assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
+       assert_int_equal(ns_rr_type(rr), ns_t_soa);
+
+       rrdata = ns_rr_rdata(rr);
+
+       rv = ns_name_uncompress(ns_msg_base(handle),
+                               ns_msg_end(handle),
+                               rrdata,
+                               nameser, MAXDNAME);
+       assert_int_not_equal(rv, -1);
+       rrdata += rv;
+
+       rv = ns_name_uncompress(ns_msg_base(handle),
+                               ns_msg_end(handle),
+                               rrdata,
+                               admin, MAXDNAME);
+       assert_int_not_equal(rv, -1);
+       rrdata += rv;
+
+       NS_GET32(serial, rrdata);
+       NS_GET32(refresh, rrdata);
+       NS_GET32(retry, rrdata);
+       NS_GET32(expire, rrdata);
+       NS_GET32(minimum, rrdata);
+
+       assert_string_equal(nameser, "ns1.cwrap.org");
+       assert_string_equal(admin, "admin.cwrap.org");
+       assert_int_equal(serial, 2014100457);
+       assert_int_equal(refresh, 3600);
+       assert_int_equal(retry, 300);
+       assert_int_equal(expire, 1814400);
+       assert_int_equal(minimum, 600);
+}
+
+
 int main(void)
 {
        int rc;
@@ -281,6 +351,7 @@ int main(void)
                unit_test(test_res_fake_aaaa_query_notfound),
                unit_test(test_res_fake_srv_query),
                unit_test(test_res_fake_srv_query_minimal),
+               unit_test(test_res_fake_soa_query),
        };
 
        rc = run_tests(tests);