diff options
-rw-r--r-- | src/resolv_wrapper.c | 53 | ||||
-rw-r--r-- | tests/fake_hosts.in | 1 | ||||
-rw-r--r-- | tests/test_dns_fake.c | 44 |
3 files changed, 98 insertions, 0 deletions
diff --git a/src/resolv_wrapper.c b/src/resolv_wrapper.c index a262561..455a0af 100644 --- a/src/resolv_wrapper.c +++ b/src/resolv_wrapper.c @@ -192,6 +192,7 @@ struct rwrap_fake_rr { struct rwrap_uri_rrdata uri_rec; struct rwrap_soa_rrdata soa_rec; char cname_rec[MAXDNAME]; + char ptr_rec[MAXDNAME]; } rrdata; char key[MAXDNAME]; @@ -381,6 +382,16 @@ static int rwrap_create_fake_cname_rr(const char *key, return 0; } +static int rwrap_create_fake_ptr_rr(const char *key, + const char *value, + struct rwrap_fake_rr *rr) +{ + memcpy(rr->rrdata.ptr_rec , value, strlen(value) + 1); + memcpy(rr->key, key, strlen(key) + 1); + rr->type = ns_t_ptr; + return 0; +} + /* Prepares a fake header with a single response. Advances header_blob */ static ssize_t rwrap_fake_header(uint8_t **header_blob, size_t remaining, size_t ancount, size_t arcount) @@ -734,6 +745,40 @@ static ssize_t rwrap_fake_cname(struct rwrap_fake_rr *rr, return resp_size; } +static ssize_t rwrap_fake_ptr(struct rwrap_fake_rr *rr, + uint8_t *answer, + size_t anslen) +{ + uint8_t *a = answer; + ssize_t rdata_size; + ssize_t resp_size; + unsigned char hostname_compressed[MAXDNAME]; + + if (rr->type != ns_t_ptr) { + RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n"); + return -1; + } + RWRAP_LOG(RWRAP_LOG_TRACE, "Adding PTR RR"); + + /* Prepare the data to write */ + rdata_size = ns_name_compress(rr->rrdata.ptr_rec, + hostname_compressed, MAXDNAME, + NULL, NULL); + if (rdata_size < 0) { + return -1; + } + + resp_size = rwrap_fake_rdata_common(ns_t_ptr, rdata_size, + rr->key, anslen, &a); + if (resp_size < 0) { + return -1; + } + + memcpy(a, hostname_compressed, rdata_size); + + return resp_size; +} + #define RESOLV_MATCH(line, name) \ (strncmp(line, name, sizeof(name) - 1) == 0 && \ (line[sizeof(name) - 1] == ' ' || \ @@ -873,6 +918,10 @@ static int rwrap_get_record(const char *hostfile, unsigned recursion, value, rr + 1); } break; + } else if (TYPE_MATCH(type, ns_t_ptr, + rec_type, "PTR", key, query)) { + rc = rwrap_create_fake_ptr_rr(key, value, rr); + break; } } @@ -924,6 +973,7 @@ static inline bool rwrap_known_type(int type) case ns_t_uri: case ns_t_soa: case ns_t_cname: + case ns_t_ptr: return true; } @@ -1000,6 +1050,9 @@ static ssize_t rwrap_add_rr(struct rwrap_fake_rr *rr, case ns_t_cname: resp_data = rwrap_fake_cname(rr, answer, anslen); break; + case ns_t_ptr: + resp_data = rwrap_fake_ptr(rr, answer, anslen); + break; default: return -1; } diff --git a/tests/fake_hosts.in b/tests/fake_hosts.in index d7bf9a2..1812979 100644 --- a/tests/fake_hosts.in +++ b/tests/fake_hosts.in @@ -14,3 +14,4 @@ A ns1.cwrap.org 127.0.0.24 A ns2.cwrap.org 127.0.0.25 URI _vpn.cwrap.org https://vpn.cwrap.org/VPN 2 5 URI _ftp.cwrap.org ftp://ftp.cwrap.org/public +PTR 22.0.0.127.in-addr.arpa www.cwrap.org diff --git a/tests/test_dns_fake.c b/tests/test_dns_fake.c index 0702dc8..d3e9ebe 100644 --- a/tests/test_dns_fake.c +++ b/tests/test_dns_fake.c @@ -664,6 +664,49 @@ static void test_res_fake_a_via_cname(void **state) assert_string_equal(addr, "127.0.0.22"); } +static void test_res_fake_ptr_query(void **state) +{ + int rv; + struct __res_state dnsstate; + unsigned char answer[ANSIZE]; + const uint8_t *rrdata; + char ptrname[MAXDNAME]; + ns_msg handle; + ns_rr rr; /* expanded resource record */ + + (void) state; /* unused */ + + memset(&dnsstate, 0, sizeof(struct __res_state)); + rv = res_ninit(&dnsstate); + assert_int_equal(rv, 0); + + rv = res_nquery(&dnsstate, "22.0.0.127.in-addr.arpa", ns_c_in, ns_t_ptr, + answer, sizeof(answer)); + assert_in_range(rv, 1, 100); + + ns_initparse(answer, sizeof(answer), &handle); + + /* + * The query must finish w/o an error, have one answer and the answer + * must be a parseable RR of type PTR and have the name that our + * fake hosts file contains + */ + 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_ptr); + + rrdata = ns_rr_rdata(rr); + + rv = ns_name_uncompress(ns_msg_base(handle), + ns_msg_end(handle), + rrdata, + ptrname, MAXDNAME); + assert_int_not_equal(rv, -1); + + assert_string_equal(ptrname, "www.cwrap.org"); +} + int main(void) { int rc; @@ -682,6 +725,7 @@ int main(void) cmocka_unit_test(test_res_fake_soa_query), cmocka_unit_test(test_res_fake_cname_query), cmocka_unit_test(test_res_fake_a_via_cname), + cmocka_unit_test(test_res_fake_ptr_query), }; rc = cmocka_run_group_tests(fake_tests, NULL, NULL); |