diff options
author | Wojciech Kosior <kwojtus@protonmail.com> | 2020-05-08 00:01:23 +0200 |
---|---|---|
committer | Wojciech Kosior <kwojtus@protonmail.com> | 2020-05-08 00:01:23 +0200 |
commit | f91c8395cec54efb8908e4cc9dd261983cca639b (patch) | |
tree | cead9add643875dfcf7a631df7436a393b677ecb | |
parent | 79447dfd0de73e9159576d5f493404f586eff80b (diff) | |
download | 0tdns-f91c8395cec54efb8908e4cc9dd261983cca639b.tar.gz 0tdns-f91c8395cec54efb8908e4cc9dd261983cca639b.zip |
join querying and responding in one program
-rw-r--r-- | Makefile | 17 | ||||
-rw-r--r-- | src/0tDNS.c | 144 | ||||
-rw-r--r-- | src/receive_respond.c | 52 |
3 files changed, 123 insertions, 90 deletions
@@ -1,30 +1,21 @@ CC ?= gcc CFLAGS = -std=c99 -Wall -Werror -I include -0tDNS : build/0tDNS.o - $(CC) $^ -lunbound -o $@ - -build/0tDNS.o : src/0tDNS.c | build - gcc $(CFLAGS) $^ -c -o $@ +0tDNS : build/0tDNS.o build/receive_respond.o + $(CC) $^ -lunbound -lldns -o $@ -receive_respond : build/receive_respond.o - $(CC) $^ -lldns -o $@ - -build/receive_respond.o : src/receive_respond.c | build +build/%.o : src/%.c | build gcc $(CFLAGS) $^ -c -o $@ ask_localhost : build/ask_localhost.o $(CC) $^ -lunbound -o $@ -build/ask_localhost.o : src/ask_localhost.c | build - gcc $(CFLAGS) $^ -c -o $@ - build : mkdir build all : 0tDNS receive_respond clean : - -rm -r build 0tDNS receive_respond ask_localhost + -rm -r build 0tDNS ask_localhost .PHONY : clean diff --git a/src/0tDNS.c b/src/0tDNS.c index f48fca7..180b336 100644 --- a/src/0tDNS.c +++ b/src/0tDNS.c @@ -24,10 +24,23 @@ #include <errno.h> #include <arpa/inet.h> #include <stdbool.h> + #include <unbound.h> +#include <ldns/ldns.h> #include "log.h" +#define LISTEN_PORT 53 +#define IPADDR_BUFLEN 50 + +/* From receive_respond.c */ +int udp_bind(int, uint16_t); +int socket_create(uint16_t); +ldns_pkt *receive_and_print(int); +int respond_query(int, const char*, const char*, ldns_rr*, uint16_t); +char *hostnamefrompkt(ldns_pkt*, ldns_rr**); + + /* To specify when creating unbound context - has nothing to do with * out logging facility */ @@ -46,10 +59,15 @@ #define MALLOC_FAILURE_STRING "Couldn't allocate memory.\n" /* examine the result structure in detail */ -void examine_result(const char *query, struct ub_result *result) +const char *examine_result(const char *query, struct ub_result *result, + char *ipaddr_buf) { int i; int num; + char buf[IPADDR_BUFLEN]; + char *ipaddr_buf_used; + + ipaddr_buf_used = ipaddr_buf ? ipaddr_buf : buf; printf("The query is for: %s\n", query); printf("The result has:\n"); @@ -80,17 +98,20 @@ void examine_result(const char *query, struct ub_result *result) printf("DNS rcode: %d\n", result->rcode); if(!result->havedata) - return; + return NULL; num = 0; for(i=0; result->data[i]; i++) { printf("result data element %d has length %d\n", i, result->len[i]); - printf("result data element %d is: %s\n", - i, inet_ntoa(*(struct in_addr*)result->data[i])); + printf("result data element %d is: %s\n", i, + inet_ntop(AF_INET, (struct in_addr*) result->data[i], + ipaddr_buf_used, IPADDR_BUFLEN)); num++; } printf("result has %d data element(s)\n", num); + + return ipaddr_buf; } enum resolution_mode { @@ -101,7 +122,8 @@ enum resolution_mode { struct ub_ctx *ztdns_create_ub_context(enum resolution_mode mode, const char *resolver_addr, - int debuglevel) { + int debuglevel) +{ int rc; struct ub_ctx* ctx; const char *error_message_format; @@ -151,18 +173,24 @@ out: return ctx; } -void ztdns_try_resolve(struct ub_ctx *ctx, const char *name) { +const char *ztdns_try_resolve(struct ub_ctx *ctx, const char *name, + char *ipaddr_buf) +{ struct ub_result* result; int rc; + const char *ipaddr = NULL; + rc = ub_resolve(ctx, name, 1 /* TYPE A (IPv4 address) */, 1 /* CLASS IN (internet) */, &result); if(rc) printf("resolve error: %s\n", ub_strerror(rc)); else { - examine_result(name, result); + ipaddr = examine_result(name, result, ipaddr_buf); ub_resolve_free(result); } + + return ipaddr; } struct ztdns_resolver { @@ -209,7 +237,8 @@ out_err: return NULL; } -void ztdns_delete_recursive_resolver(struct ztdns_resolver *resolver) { +void ztdns_delete_recursive_resolver(struct ztdns_resolver *resolver) +{ ub_ctx_delete(resolver->ctx); free(resolver); } @@ -223,14 +252,12 @@ struct ztdns_instance { * Hardcoded recursive DNS servers. A temporary solution - those should * ideally by obtained from command line or configuration file. */ -const char *resolvers_addresses[] = {"8.8.8.8", "8.8.4.4", - "1.1.1.1", "127.0.0.1"}; -const char *resolvers_names[] = {"google", "google", - "cloudflare", "localhost"}; -uint8_t resolvers_trust_levels[] = {40, 40, 80, 20}; -uint8_t resolvers_report_errors[] = {false, false, false, true}; +const char *resolvers_addresses[] = {"8.8.8.8", "8.8.4.4", "1.1.1.1"}; +const char *resolvers_names[] = {"google", "google", "cloudflare"}; +uint8_t resolvers_trust_levels[] = {40, 40, 80}; +uint8_t resolvers_report_errors[] = {true, true, false}; -#define RESOLVERS_COUNT 4 +#define RESOLVERS_COUNT 3 struct ztdns_instance *ztdns_create_instance(int argc, char **argv) { @@ -307,27 +334,90 @@ void ztdns_delete_instance(struct ztdns_instance *ztdns) free(ztdns); } -int main(int argc, char** argv) +const char *smart_resolve(struct ztdns_instance *ztdns, + const char *queried_name, + char ipaddr_buf[IPADDR_BUFLEN]) { - struct ztdns_instance *ztdns; struct ztdns_resolver *tmp; - const char *queried_name = "google.com"; - - ztdns = ztdns_create_instance(argc, argv); - if (!ztdns) - return EXIT_FAILURE; - + printf("* FULL RESOLUTION\n"); - ztdns_try_resolve(ztdns->ctx_full, queried_name); + ztdns_try_resolve(ztdns->ctx_full, queried_name, ipaddr_buf); printf("* USING RESOLVER FROM resolv.conf\n"); - ztdns_try_resolve(ztdns->ctx_resolv_conf, queried_name); + ztdns_try_resolve(ztdns->ctx_resolv_conf, queried_name, NULL); for (tmp = ztdns->recursive_resolvers; tmp; tmp = tmp->next) { printf("* VIA %s (%s)\n", tmp->name, tmp->address); - ztdns_try_resolve(tmp->ctx, queried_name); + ztdns_try_resolve(tmp->ctx, queried_name, NULL); } + return NULL; +} + +int handle_query(struct ztdns_instance *ztdns, int socket) +{ + ldns_pkt *query; + ldns_rr *query_rr; + uint16_t id; + int rc = 1; + char *queried_name; + char ipaddr[IPADDR_BUFLEN]; + + query = receive_and_print(socket); + if (!query) + return 1; + + queried_name = hostnamefrompkt(query, &query_rr); + if (!queried_name) + goto out_cleanup_query; + + id = ldns_pkt_id(query); + + smart_resolve(ztdns, queried_name, ipaddr); /* fill ipaddr[] */ + rc = respond_query(socket, queried_name, ipaddr, query_rr, id); + + free(queried_name); + +out_cleanup_query: + ldns_pkt_free(query); + return rc; +} + +int main(int argc, char** argv) +{ + int rc = EXIT_FAILURE; + struct ztdns_instance *ztdns; + int socket; + + if (geteuid()) { + ztdns_error("need root privileges\n"); + return EXIT_FAILURE; + } + + socket = socket_create(LISTEN_PORT); + if (socket < 0) + return EXIT_FAILURE; + + ztdns = ztdns_create_instance(argc, argv); + if (!ztdns) + goto out_cleanup_socket; + + while (1) + handle_query(ztdns, socket); + + /* Later on we'll have some way of stopping the daemon - for now this + * line is unreachable */ ztdns_delete_instance(ztdns); - return EXIT_SUCCESS; +out_cleanup_socket: + close(socket); + return rc; + + /* + * The adsuck program would additionally do many cool things in main(), + * i.e. parse command line options, drop root privileges, setup signal + * handlers, etc. We could incorporate some of this into our program + * later. I omitted it for now for simplicity and to ease porting to + * windoze if You guys want to do that (but don't count on me in this + * matter). + */ } diff --git a/src/receive_respond.c b/src/receive_respond.c index 59697d3..a3b1e8e 100644 --- a/src/receive_respond.c +++ b/src/receive_respond.c @@ -29,7 +29,6 @@ #define MAXLINE 256 #define INBUF_SIZE 4096 -#define PORT 53 struct sockaddr paddr; socklen_t plen = (socklen_t)sizeof(paddr); @@ -177,7 +176,8 @@ done: } int -spoofquery(int so, const char *hostname, ldns_rr *query_rr, u_int16_t id) +respond_query(int so, const char *hostname, const char *ipaddr, + ldns_rr *query_rr, uint16_t id) { ldns_status status; ldns_rr_list *answer_an = NULL; @@ -190,7 +190,6 @@ spoofquery(int so, const char *hostname, ldns_rr *query_rr, u_int16_t id) char buf[MAXLINE * 2]; uint8_t *outbuf = NULL; int rv = 1; - const char *ipaddr = "127.0.0.1"; /* answer section */ answer_an = ldns_rr_list_new(); @@ -322,50 +321,3 @@ unwind: return (rv); } - -int handle_query(int so) { - ldns_pkt *query_pkt; - ldns_rr *query_rr; - uint16_t id; - int rv = 1; - char *hostname; - - query_pkt = receive_and_print(so); - if (!query_pkt) - return 1; - - hostname = hostnamefrompkt(query_pkt, &query_rr); - if (!hostname) - goto out_cleanup_pkt; - - id = ldns_pkt_id(query_pkt); - - rv = spoofquery(so, hostname, query_rr, id); - - free(hostname); - -out_cleanup_pkt: - ldns_pkt_free(query_pkt); - return rv; -} - -int main(int argc, char **argv) { - int so; - - if (geteuid()) - errx(1, "need root privileges"); - - so = socket_create(PORT); - - /* - * The original adsuck program would additionally do many cool things - * in main(), i.e. parse command line options, drop root privileges, - * setup signal handlers, etc. We could incorporate some of this into - * our program later. I omitted it for now for simplicity and to - * ease porting to windoze if You guys want to do that (but don't - * count on me in this matter). - */ - - while (1) - handle_query(so); -} |