aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/0tDNS.c423
-rw-r--r--src/ask_resolver.c140
-rw-r--r--src/receive_respond.c323
3 files changed, 0 insertions, 886 deletions
diff --git a/src/0tDNS.c b/src/0tDNS.c
deleted file mode 100644
index 180b336..0000000
--- a/src/0tDNS.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Code in examine_result() is taken from official libunbound examples:
- * https://nlnetlabs.nl/documentation/unbound/libunbound-tutorial-3/
- * The rest of this file is
- * Copyright (C) 2020 by Wojtek Kosior <echo a3dvanR1c0Bwcm90b25tYWlsLmNvbQo= | base64 --decode>
-
- * Permission to use, copy, modify, and/or distribute this software
- * for any purpose with or without fee is hereby granted.
-
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#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
- */
-#define DEFAULT_DEBUGLEVEL 0
-
-/*
- * This is the path in Debian - in other systems it will be different
- * and we will need to either somehow find it dynamically or get the path
- * from the user.
- */
-#define CA_BUNDLE_FILE "/etc/ssl/certs/ca-certificates.crt"
-
-/* In the long run me might rename this file to somewhere else... */
-#define TRUST_ANCHOR_FILE "./root.key"
-
-#define MALLOC_FAILURE_STRING "Couldn't allocate memory.\n"
-
-/* examine the result structure in detail */
-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");
- printf("qname: %s\n", result->qname);
- printf("qtype: %d\n", result->qtype);
- printf("qclass: %d\n", result->qclass);
- if(result->canonname)
- printf("canonical name: %s\n",
- result->canonname);
- else printf("canonical name: <none>\n");
-
- if(result->havedata)
- printf("has data\n");
- else printf("has no data\n");
-
- if(result->nxdomain)
- printf("nxdomain (name does not exist)\n");
- else printf("not an nxdomain (name exists)\n");
-
- if(result->secure)
- printf("validated to be secure\n");
- else printf("not validated as secure\n");
-
- if(result->bogus)
- printf("a security failure! (bogus)\n");
- else printf("not a security failure (not bogus)\n");
-
- printf("DNS rcode: %d\n", result->rcode);
-
- if(!result->havedata)
- 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_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 {
- RECURSIVE,
- FULL,
- RESOLV_CONF
-};
-
-struct ub_ctx *ztdns_create_ub_context(enum resolution_mode mode,
- const char *resolver_addr,
- int debuglevel)
-{
- int rc;
- struct ub_ctx* ctx;
- const char *error_message_format;
-
- ctx = ub_ctx_create();
- if (!ctx) {
- fprintf(stderr, "Couldn't create libunbound context.\n");
- return NULL;
- }
-
- if (mode == RECURSIVE) {
- error_message_format = "Couldn't set forward server: %s\n";
- rc = ub_ctx_set_fwd(ctx, resolver_addr);
- if (rc)
- goto out;
- /* Make DNS over TLS mandatory for recursive resolvers */
- /* TODO tls not working for some reason - this has to be fixed */
- /* error_message_format = "Couldn't enable DNS over TLS: %s\n"; */
- /* rc = ub_ctx_set_tls(ctx, 1); */
- /* if (rc) */
- /* goto out; */
- /* rc = ub_ctx_set_option(ctx, "tls-cert-bundle:", CA_BUNDLE_FILE); */
- } else if (mode == FULL) {
- /* TODO use root_hints here for better reliability */
- /* For iterative queries we use DNSSEC if possible */
- error_message_format = "Couldn't set trust anchors: %s\n";
- rc = ub_ctx_add_ta_autr(ctx, TRUST_ANCHOR_FILE);
- } else /* if (mode == RESOLV_CONF) */ {
- /* NULL can be passed to use system's default resolv.conf */
- error_message_format = "Couldn't use system resolv.conf: %s\n";
- rc = ub_ctx_resolvconf(ctx, NULL);
- }
-
- if (rc)
- goto out;
-
- error_message_format = "Couldn't set debuglevel: %s\n";
- rc = ub_ctx_debuglevel(ctx, debuglevel);
-
-out:
- if (rc) {
- fprintf(stderr, error_message_format, ub_strerror(rc));
- ub_ctx_delete(ctx);
- return NULL;
- }
-
- return ctx;
-}
-
-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 {
- ipaddr = examine_result(name, result, ipaddr_buf);
- ub_resolve_free(result);
- }
-
- return ipaddr;
-}
-
-struct ztdns_resolver {
- struct ub_ctx *ctx;
- const char *name; /* arbitrary name - only used for printing to user */
- const char *address; /* IP addr in dot notation stored as string */
- /* Compatible answer must be returned by resolvers with their
- * trust levels summing to at least 100 - otherwise the answer is
- * considered unreliable.
- */
- uint8_t trust_level;
- /* Whether we want ztdns to report when this resolver gives answer,
- * that is not confirmed by others (i.e. trust levels sum for this
- * answer doesn't reach 100).
- */
- bool report_errors;
- struct ztdns_resolver *next;
-};
-
-struct ztdns_resolver *ztdns_create_recursive_resolver
-(const char *name, const char *address, uint8_t trust_level, bool report_errors,
- int debuglevel)
-{
- struct ztdns_resolver *resolver;
- resolver = malloc(sizeof(struct ztdns_resolver));
- if (!resolver) {
- fprintf(stderr, MALLOC_FAILURE_STRING);
- return NULL;
- }
-
- resolver->ctx = ztdns_create_ub_context(RECURSIVE, address, debuglevel);
- if (!resolver->ctx)
- goto out_err;
-
- resolver->name = name;
- resolver->address = address;
- resolver->trust_level = trust_level;
- resolver->report_errors = report_errors;
- resolver->next = NULL;
- return resolver;
-
-out_err:
- free(resolver);
- return NULL;
-}
-
-void ztdns_delete_recursive_resolver(struct ztdns_resolver *resolver)
-{
- ub_ctx_delete(resolver->ctx);
- free(resolver);
-}
-
-struct ztdns_instance {
- struct ub_ctx *ctx_resolv_conf, *ctx_full;
- struct ztdns_resolver *recursive_resolvers;
-};
-
-/*
- * 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"};
-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 3
-
-struct ztdns_instance *ztdns_create_instance(int argc, char **argv)
-{
- struct ztdns_instance *ztdns;
- int i;
- struct ztdns_resolver *tmp;
-
- ztdns = malloc(sizeof(struct ztdns_instance));
- if (!ztdns) {
- /* This is an example of how rest of the code shold be
- * written/rewritten to use our logging facility.
- */
- ztdns_error("No memory, no fun :(\n");
- return NULL;
- }
-
- /* Create context for performing full resolution */
- ztdns->ctx_full =
- ztdns_create_ub_context(FULL, NULL, DEFAULT_DEBUGLEVEL);
- if (!ztdns->ctx_full)
- goto out_err_cleanup_instance;
-
- /* Create context for performing resolution with default resolver */
- ztdns->ctx_resolv_conf =
- ztdns_create_ub_context(RESOLV_CONF, NULL, DEFAULT_DEBUGLEVEL);
- if (!ztdns->ctx_resolv_conf)
- goto out_err_cleanup_ctx_full;
-
- /* Create contexts for performing resolution with resolvers provided
- * by user (well, hardcoded ones in this case)
- */
- ztdns->recursive_resolvers = NULL;
- for (i = 0; i < RESOLVERS_COUNT; i++) {
- tmp = ztdns_create_recursive_resolver
- (resolvers_names[i], resolvers_addresses[i],
- resolvers_trust_levels[i], resolvers_report_errors[i],
- DEFAULT_DEBUGLEVEL);
- if (!tmp)
- goto out_err_cleanup_recursive_resolvers;
-
- tmp->next = ztdns->recursive_resolvers;
- ztdns->recursive_resolvers = tmp;
- }
-
- return ztdns;
-
-out_err_cleanup_recursive_resolvers:
- while (ztdns->recursive_resolvers) {
- tmp = ztdns->recursive_resolvers->next;
- ztdns_delete_recursive_resolver(ztdns->recursive_resolvers);
- ztdns->recursive_resolvers = tmp;
- }
-
- ub_ctx_delete(ztdns->ctx_resolv_conf);
-out_err_cleanup_ctx_full:
- ub_ctx_delete(ztdns->ctx_full);
-out_err_cleanup_instance:
- free(ztdns);
- return NULL;
-}
-
-void ztdns_delete_instance(struct ztdns_instance *ztdns)
-{
- struct ztdns_resolver *tmp;
-
- while (ztdns->recursive_resolvers) {
- tmp = ztdns->recursive_resolvers->next;
- ztdns_delete_recursive_resolver(ztdns->recursive_resolvers);
- ztdns->recursive_resolvers = tmp;
- }
-
- ub_ctx_delete(ztdns->ctx_resolv_conf);
- ub_ctx_delete(ztdns->ctx_full);
- free(ztdns);
-}
-
-const char *smart_resolve(struct ztdns_instance *ztdns,
- const char *queried_name,
- char ipaddr_buf[IPADDR_BUFLEN])
-{
- struct ztdns_resolver *tmp;
-
- printf("* FULL RESOLUTION\n");
- 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, 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, 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);
-
-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/ask_resolver.c b/src/ask_resolver.c
deleted file mode 100644
index dc7c660..0000000
--- a/src/ask_resolver.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Code in examine_result() is taken from official libunbound examples:
- * https://nlnetlabs.nl/documentation/unbound/libunbound-tutorial-3/
- * The rest of this file is
- * Copyright (C) 2020 by Wojtek Kosior <echo a3dvanR1c0Bwcm90b25tYWlsLmNvbQo= | base64 --decode>
-
- * Permission to use, copy, modify, and/or distribute this software
- * for any purpose with or without fee is hereby granted.
-
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * This is a simple helper program for testing our resolver.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-
-#include <unbound.h>
-
-/* examine the result structure in detail */
-void examine_result(const char *query, struct ub_result *result)
-{
- int i;
- int num;
-
- printf("The query is for: %s\n", query);
- printf("The result has:\n");
- printf("qname: %s\n", result->qname);
- printf("qtype: %d\n", result->qtype);
- printf("qclass: %d\n", result->qclass);
- if(result->canonname)
- printf("canonical name: %s\n",
- result->canonname);
- else printf("canonical name: <none>\n");
-
- if(result->havedata)
- printf("has data\n");
- else printf("has no data\n");
-
- if(result->nxdomain)
- printf("nxdomain (name does not exist)\n");
- else printf("not an nxdomain (name exists)\n");
-
- if(result->secure)
- printf("validated to be secure\n");
- else printf("not validated as secure\n");
-
- if(result->bogus)
- printf("a security failure! (bogus)\n");
- else printf("not a security failure (not bogus)\n");
-
- printf("DNS rcode: %d\n", result->rcode);
-
- if(!result->havedata)
- return;
-
- 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]));
- num++;
- }
- printf("result has %d data element(s)\n", num);
-}
-
-struct ub_ctx *create_ub_context(char *forwarder_addr, int debuglevel)
-{
- int rc;
- struct ub_ctx* ctx;
- char *error_message_format;
-
- ctx = ub_ctx_create();
- if (!ctx) {
- fprintf(stderr, "Couldn't create libunbound context.\n");
- return NULL;
- }
-
- error_message_format = "Couldn't set forwarder: %s\n";
- rc = ub_ctx_set_fwd(ctx, forwarder_addr);
- if (rc)
- goto out;
-
- error_message_format = "Couldn't set debuglevel: %s\n";
- rc = ub_ctx_debuglevel(ctx, debuglevel);
-
-out:
- if (rc) {
- fprintf(stderr, error_message_format, ub_strerror(rc));
- ub_ctx_delete(ctx);
- return NULL;
- }
-
- return ctx;
-}
-
-void ztdns_try_resolve(struct ub_ctx *ctx, const char *name)
-{
- struct ub_result* result;
- int rc;
- 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);
- ub_resolve_free(result);
- }
-}
-
-int main(int argc, char** argv)
-{
- struct ub_ctx *ctx;
-
- if (argc != 3) {
- printf("Usage: %s DNS_SERVER DOMAINNAME\n", argv[0]);
- return EXIT_FAILURE;
- }
-
- ctx = create_ub_context(argv[1], 3);
- if (!ctx)
- return EXIT_FAILURE;
-
- ztdns_try_resolve(ctx, argv[2]);
-
- ub_ctx_delete(ctx);
-
- return EXIT_SUCCESS;
-}
diff --git a/src/receive_respond.c b/src/receive_respond.c
deleted file mode 100644
index a3b1e8e..0000000
--- a/src/receive_respond.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 2009 - 2012 Marco Peereboom <marco@peereboom.us>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* for strdup() */
-#define _POSIX_C_SOURCE 200809L
-#include <string.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <err.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <ldns/ldns.h>
-
-#define MAXLINE 256
-#define INBUF_SIZE 4096
-
-struct sockaddr paddr;
-socklen_t plen = (socklen_t)sizeof(paddr);
-
-int
-udp_bind(int sock, uint16_t port)
-{
- struct sockaddr_in addr;
- in_addr_t maddr = INADDR_ANY;
-
- addr.sin_family = AF_INET;
- addr.sin_port = (in_port_t) htons((uint16_t)port);
- addr.sin_addr.s_addr = maddr;
- return (bind(sock, (struct sockaddr*)&addr, (socklen_t) sizeof(addr)));
-}
-
-int
-socket_create(uint16_t port) {
- int so = socket(AF_INET, SOCK_DGRAM, 0);
- if (so == -1)
- err(1, "can't open socket");
- if (udp_bind(so, port))
- err(1, "can't udp bind");
- return so;
-}
-
-void
-printpacket(ldns_pkt *pkt)
-{
- char *str = ldns_pkt2str(pkt);
-
- if (str) {
- printf("%s", str);
- LDNS_FREE(str);
- } else
- warnx("could not convert packet to string");
-}
-
-ldns_pkt *
-receive_and_print(int so) {
- uint8_t inbuf[INBUF_SIZE];
- ssize_t nb;
- ldns_status status;
- ldns_pkt *query_pkt;
-
- nb = recvfrom(so, inbuf, INBUF_SIZE, 0, &paddr, &plen);
- if (nb == -1) {
- if (errno == EINTR || errno == EAGAIN)
- return NULL;
- else
- err(EXIT_FAILURE, "recvfrom");
- }
-
- status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)nb);
- if (status != LDNS_STATUS_OK) {
- warnx("bad packet: %s", ldns_get_errorstr_by_id(status));
- return NULL;
- } else {
- puts("received packet:");
- printpacket(query_pkt);
- }
-
- return query_pkt;
-}
-
-int
-send_response(int so, const char *hostname, ldns_pkt *respkt, uint16_t id)
-{
- size_t answer_size;
- ldns_status status;
- uint8_t *outbuf = NULL;
- int rv = 1;
-
- if (hostname == NULL || respkt == NULL) {
- warnx("send_response: invalid parameters");
- return (0);
- }
-
- ldns_pkt_set_id(respkt, id);
- status = ldns_pkt2wire(&outbuf, respkt, &answer_size);
- if (status != LDNS_STATUS_OK)
- warnx("can't create answer: %s",
- ldns_get_errorstr_by_id(status));
- else {
- puts("response packet:");
- printpacket(respkt);
-
- if (sendto(so, outbuf, answer_size, 0, &paddr, plen) == -1)
- warn("send_response: sendto");
- else {
- rv = 0;
-
- printf("send_response: resolved %s", hostname);
- }
- }
-
- if (outbuf)
- LDNS_FREE(outbuf);
-
- return (rv);
-}
-
-char *
-hostnamefrompkt(ldns_pkt *pkt, ldns_rr **qrr)
-{
- ldns_rr *query_rr;
- ldns_buffer *out = NULL;
- ldns_rdf *rdf;
- char *ret = NULL;
-
- if (pkt == NULL)
- return (NULL);
-
- query_rr = ldns_rr_list_rr(ldns_pkt_question(pkt), 0);
- if (query_rr == NULL) {
- warnx("hostnamefrompkt invalid parameters");
- goto done;
- }
-
- out = ldns_buffer_new(LDNS_MAX_DOMAINLEN);
- if (out == NULL) {
- warnx("no memory for out buffer");
- goto done;
- }
-
- rdf = ldns_rr_owner(query_rr);
- if (ldns_rdf2buffer_str_dname(out, rdf) != LDNS_STATUS_OK) {
- warnx("can't get hostname");
- goto done;
- }
-
- ret = strdup((char *)ldns_buffer_begin(out));
- if (ret == NULL) {
- warn("no memory for hostname");
- goto done;
- }
-
- if (qrr)
- *qrr = query_rr;
-done:
- if (out)
- ldns_buffer_free(out);
-
- return (ret);
-}
-
-int
-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;
- ldns_rr_list *answer_ns = NULL;
- ldns_rr_list *answer_ad = NULL;
- ldns_rr_list *answer_qr = NULL;
- ldns_pkt *answer_pkt = NULL;
- ldns_rr *myrr = NULL, *myaurr = NULL, *myasrr = NULL;
- ldns_rdf *prev = NULL;
- char buf[MAXLINE * 2];
- uint8_t *outbuf = NULL;
- int rv = 1;
-
- /* answer section */
- answer_an = ldns_rr_list_new();
- if (answer_an == NULL)
- goto unwind;
-
- /* authority section */
- answer_ns = ldns_rr_list_new();
- if (answer_ns == NULL)
- goto unwind;
-
- /* if we have an ip spoof it there */
- if (ipaddr) {
- /* an */
- snprintf(buf, sizeof buf, "%s\t%d\tIN\tA\t%s",
- hostname, 259200, ipaddr);
- status = ldns_rr_new_frm_str(&myrr, buf, 0, NULL, &prev);
- if (status != LDNS_STATUS_OK) {
- fprintf(stderr, "can't create answer section: %s\n",
- ldns_get_errorstr_by_id(status));
- goto unwind;
- }
- ldns_rr_list_push_rr(answer_an, myrr);
- ldns_rdf_deep_free(prev);
- prev = NULL;
-
- /* ns */
- snprintf(buf, sizeof buf, "%s\t%d\tIN\tNS\t%s.",
- hostname, 259200, "localhost");
- status = ldns_rr_new_frm_str(&myaurr, buf, 0, NULL, &prev);
- if (status != LDNS_STATUS_OK) {
- fprintf(stderr, "can't create authority section: %s\n",
- ldns_get_errorstr_by_id(status));
- goto unwind;
- }
- ldns_rr_list_push_rr(answer_ns, myaurr);
- ldns_rdf_deep_free(prev);
- prev = NULL;
- } else {
- snprintf(buf, sizeof buf, "%s\t3600\tIN\tSOA\t%s root.%s %s",
- hostname,
- hostname,
- hostname,
- "2 3600 900 3600000 3600");
- status = ldns_rr_new_frm_str(&myaurr, buf, 0, NULL, &prev);
- if (status != LDNS_STATUS_OK) {
- fprintf(stderr, "can't create authority section: %s\n",
- ldns_get_errorstr_by_id(status));
- goto unwind;
- }
- ldns_rr_list_push_rr(answer_ns, myaurr);
- ldns_rdf_deep_free(prev);
- prev = NULL;
- }
-
- /* question section */
- answer_qr = ldns_rr_list_new();
- if (answer_qr == NULL)
- goto unwind;
- ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr));
-
- /* additional section */
- answer_ad = ldns_rr_list_new();
- if (answer_ad == NULL)
- goto unwind;
- if (ipaddr) {
- snprintf(buf, sizeof buf, "%s\t%d\tIN\tA\t%s",
- "localhost",
- 259200,
- "127.0.0.1");
- status = ldns_rr_new_frm_str(&myasrr, buf, 0, NULL, &prev);
- if (status != LDNS_STATUS_OK) {
- fprintf(stderr, "can't create additional section: %s\n",
- ldns_get_errorstr_by_id(status));
- goto unwind;
- }
- ldns_rr_list_push_rr(answer_ad, myasrr);
- ldns_rdf_deep_free(prev);
- prev = NULL;
-
- /* V6 */
- snprintf(buf, sizeof buf, "%s\t%d\tIN\tAAAA\t%s",
- "localhost",
- 259200,
- "::1");
- status = ldns_rr_new_frm_str(&myasrr, buf, 0, NULL, &prev);
- if (status != LDNS_STATUS_OK) {
- fprintf(stderr, "can't create additional section: %s\n",
- ldns_get_errorstr_by_id(status));
- goto unwind;
- }
- ldns_rr_list_push_rr(answer_ad, myasrr);
- ldns_rdf_deep_free(prev);
- prev = NULL;
- }
-
- /* actual packet */
- answer_pkt = ldns_pkt_new();
- if (answer_pkt == NULL)
- goto unwind;
-
- ldns_pkt_set_qr(answer_pkt, 1);
- ldns_pkt_set_aa(answer_pkt, 1);
- if (ipaddr == NULL)
- ldns_pkt_set_rcode(answer_pkt, LDNS_RCODE_NXDOMAIN);
-
- ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_QUESTION, answer_qr);
- ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ANSWER, answer_an);
- ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_AUTHORITY, answer_ns);
- ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ADDITIONAL, answer_ad);
-
- /* reply to caller */
- if (send_response(so, hostname, answer_pkt, id))
- warnx("send_response failed");
-
-unwind:
- if (answer_pkt)
- ldns_pkt_free(answer_pkt);
- if (outbuf)
- LDNS_FREE(outbuf);
- if (answer_qr)
- ldns_rr_list_free(answer_qr);
- if (answer_an)
- ldns_rr_list_free(answer_an);
- if (answer_ns)
- ldns_rr_list_free(answer_ns);
- if (answer_ad)
- ldns_rr_list_free(answer_ad);
-
- return (rv);
-}