From: Miek Gieben Date: Mon, 7 Mar 2005 13:31:39 +0000 (+0000) Subject: calculate the reverse for ip4/6 X-Git-Tag: release-0.50~298 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d82c784ef425562528290ca354cef69d7dfdcb6;p=thirdparty%2Fldns.git calculate the reverse for ip4/6 --- diff --git a/Makefile.in b/Makefile.in index 56b332e6..0e5a231b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -50,7 +50,7 @@ LIBDNS_OBJECTS = $(LIBDNS_SOURCES:.c=.o) TEST_SOURCES = run-test0.c run-test1.c run-test2.c run-test3.c \ run-test4.c run-test5.c run-test6.c run-test7.c \ run-test8.c run-test9.c run-test10.c run-test11.c \ - run-test13.c run-test14.c run-test15.c \ + run-test13.c run-test14.c run-test15.c run-test16.c ALL_SOURCES = $(TEST_SOURCES) $(LIBDNS_SOURCES) $(PROG_SOURCES) @@ -118,6 +118,8 @@ run-test14: run-test14.o $(LIBDNS_OBJECTS) $(LIBOBJS) $(LINK) ${LIBS} -o $@ $+ run-test15: run-test15.o $(LIBDNS_OBJECTS) $(LIBOBJS) $(LINK) ${LIBS} -o $@ $+ +run-test16: run-test16.o $(LIBDNS_OBJECTS) $(LIBOBJS) + $(LINK) ${LIBS} -o $@ $+ run-test-trace: run-test-trace.o $(LIBDNS_OBJECTS) $(LIBOBJS) $(LINK) ${LIBS} -o $@ $+ diff --git a/host2str.c b/host2str.c index 782850f8..a8e0d27c 100644 --- a/host2str.c +++ b/host2str.c @@ -1078,6 +1078,7 @@ char * ldns_rdf2str(ldns_rdf *rdf) { char *result = NULL; + /* XXX buffersize!!! */ ldns_buffer *tmp_buffer = ldns_buffer_new(1000); if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) { diff --git a/ldns/rdata.h b/ldns/rdata.h index 48d9d528..930e83ea 100644 --- a/ldns/rdata.h +++ b/ldns/rdata.h @@ -119,5 +119,6 @@ uint8_t ldns_rdf2native_int8(ldns_rdf *); uint16_t ldns_rdf2native_int16(ldns_rdf *); uint32_t ldns_rdf2native_int32(ldns_rdf *); uint32_t ldns_str2period(const char *, const char **); +ldns_rdf *ldns_rdf_address_reverse(ldns_rdf *); #endif /* !_LDNS_RDATA_H */ diff --git a/rdata.c b/rdata.c index bc46675c..82a6b567 100644 --- a/rdata.c +++ b/rdata.c @@ -353,6 +353,118 @@ ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str) } } +/** + * reverse an rdf, only actually usefull for AAAA and A records + * the returned rdf has the type LDNS_RDF_TYPE_DNAME! + * \param[in] *rdf rdf to be reversed + * \return the reversed rdf (a newly created rdf) + */ +ldns_rdf * +ldns_rdf_address_reverse(ldns_rdf *rdf) +{ + uint8_t buf_4[LDNS_IP4ADDRLEN]; + uint8_t buf_6[LDNS_IP6ADDRLEN * 2]; + ldns_rdf *rev; + ldns_rdf *in_addr; + ldns_rdf *ret_dname; + uint8_t octet; + uint8_t nnibble; + uint8_t nibble; + uint8_t i, j; + + char *char_dname; + int nbit; + + if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_A && + ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_AAAA) { + return NULL; + } + + in_addr = NULL; + ret_dname = NULL; + + switch(ldns_rdf_get_type(rdf)) { + case LDNS_RDF_TYPE_A: + /* the length of the buffer is 4 */ + buf_4[3] = ldns_rdf_data(rdf)[0]; + buf_4[2] = ldns_rdf_data(rdf)[1]; + buf_4[1] = ldns_rdf_data(rdf)[2]; + buf_4[0] = ldns_rdf_data(rdf)[3]; + in_addr = ldns_dname_new_frm_str("in-addr.arpa."); + if (!in_addr) { + return NULL; + } + /* make a new rdf and convert that back */ + rev = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_A, + LDNS_IP4ADDRLEN, + (void*)&buf_4); + + /* convert rev to a string */ + char_dname = ldns_rdf2str(rev); + if (!char_dname) { + return NULL; + } + /* transform back to rdf with type dname */ + ret_dname = ldns_dname_new_frm_str(char_dname); + if (!ret_dname) { + return NULL; + } + /* not needed anymore */ + ldns_rdf_free(rev); + FREE(char_dname); + break; + case LDNS_RDF_TYPE_AAAA: + /* some foo magic to reverse the nibbles ... */ + + for (nbit = 127; nbit >= 0; nbit = nbit - 4) { + /* calculate octett (8 bit) */ + octet = ( ((unsigned int) nbit) & 0x78) >> 3; + /* calculate nibble */ + nnibble = ( ((unsigned int) nbit) & 0x04) >> 2; + /* extract nibble */ + nibble = (ldns_rdf_data(rdf)[octet] & ( 0xf << (4 * (1 - nnibble)) ) ) >> ( 4 * (1 - nnibble)); + buf_6[(LDNS_IP6ADDRLEN * 2 - 1) - + (octet * 2 + nnibble)] = (uint8_t)int_to_hexdigit((int)nibble); + } + + char_dname = XMALLOC(char, (LDNS_IP6ADDRLEN * 4)); + if (!char_dname) { + return NULL; + } + char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */ + + /* walk the string and add . 's */ + for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) { + char_dname[j] = (char)buf_6[i]; + if (i != LDNS_IP6ADDRLEN * 2 - 1) { + char_dname[j + 1] = '.'; + } + } + in_addr = ldns_dname_new_frm_str("ip6.arpa."); + if (!in_addr) { + return NULL; + } + + /* convert rev to a string */ + ret_dname = ldns_dname_new_frm_str(char_dname); + if (!ret_dname) { + return NULL; + } + FREE(char_dname); + break; + default: + break; + } + /* add the suffix */ + rev = ldns_dname_cat(ret_dname, in_addr); + + ldns_rdf_free(ret_dname); + ldns_rdf_free(in_addr); + return rev; +} + + /** * remove \\DDD, \\[space] and other escapes from the input * See RFC 1035, section 5.1 diff --git a/run-test13.c b/run-test13.c index 40c8546f..4784e9f9 100644 --- a/run-test13.c +++ b/run-test13.c @@ -19,6 +19,7 @@ main(int argc, char **argv) ldns_rr_list *rrset; ldns_rr_list *rrset2; + printf("General test and DNSSEC tests\n"); keys_rrset = ldns_rr_list_new(); rrset = ldns_rr_list_new(); diff --git a/run-test16.c b/run-test16.c new file mode 100644 index 00000000..4d969635 --- /dev/null +++ b/run-test16.c @@ -0,0 +1,56 @@ +/** + * An example ldns program + * + * Setup a resolver + * Query a nameserver + * Print the result + */ + +#include +#include + +void +doit(void) +{ + ldns_rdf *a_rec; + ldns_rdf *aaaa_rec; + ldns_rdf *rev; + + rev = a_rec = NULL; + + a_rec = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, "192.168.10.1"); + rev = ldns_rdf_address_reverse(a_rec); + + printf("printing the reverse of\n"); + if (a_rec) + ldns_rdf_print(stdout, a_rec); + printf("\n"); + + /* this should be someones reverse.. */ + if (rev) + ldns_rdf_print(stdout, rev); + printf("\n"); + + aaaa_rec = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, "2001:7b8:206:1::53"); + printf("printing the reverse of\n"); + if (aaaa_rec) + ldns_rdf_print(stdout, aaaa_rec); + printf("\n"); + + rev = ldns_rdf_address_reverse(aaaa_rec); + /* this should be someones reverse.. */ + if (rev) + ldns_rdf_print(stdout, rev); + printf("\n"); +} + +int +main(void) +{ + printf("Test some simple ipvX reverse functions\n"); + doit(); + doit(); + doit(); + doit(); + return 0; +} diff --git a/util.c b/util.c index a2903577..765c4ef2 100644 --- a/util.c +++ b/util.c @@ -127,6 +127,32 @@ hexdigit_to_int(char ch) } } +char +int_to_hexdigit(int i) +{ + switch (i) { + case 0: return '0'; + case 1: return '1'; + case 2: return '2'; + case 3: return '3'; + case 4: return '4'; + case 5: return '5'; + case 6: return '6'; + case 7: return '7'; + case 8: return '8'; + case 9: return '9'; + case 10: return 'a'; + case 11: return 'b'; + case 12: return 'c'; + case 13: return 'd'; + case 14: return 'e'; + case 15: return 'f'; + default: + abort(); + } +} + + /** * read a word from a stream. Return the number * of character read or -1 on failure or EOF diff --git a/util.h b/util.h index b8aa6b71..8a19537b 100644 --- a/util.h +++ b/util.h @@ -157,6 +157,11 @@ long power(long a, long b); */ int hexdigit_to_int(char ch); +/** + * Returns the char (hex) representation of the given int + */ +char int_to_hexdigit(int ch); + /** * return a word from a stream */