Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configurable --upstream recursive resolver for non-HNS queries #62

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions src/daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ typedef struct hsk_options_s {
uint8_t *identity_key;
char *seeds;
int pool_size;
char *upstream;

} hsk_options_t;

static void
Expand All @@ -52,6 +54,7 @@ hsk_options_init(hsk_options_t *opt) {
opt->identity_key = NULL;
opt->seeds = NULL;
opt->pool_size = HSK_POOL_SIZE;
opt->upstream = NULL;
}

static void
Expand Down Expand Up @@ -141,6 +144,11 @@ help(int r) {
" -l, --log-file <filename>\n"
" Redirect output to a log file.\n"
"\n"
" -t, --upstream <ip[:port]>\n"
" IP address and port to forward queries that fail HNS lookup.\n"
" Example:\n"
" -t 1.1.1.1\n"
"\n"
#ifndef _WIN32
" -d, --daemon\n"
" Fork and background the process.\n"
Expand All @@ -156,7 +164,7 @@ help(int r) {

static void
parse_arg(int argc, char **argv, hsk_options_t *opt) {
const static char *optstring = "c:n:r:i:u:p:k:s:l:h"
const static char *optstring = "c:n:r:i:u:p:k:s:l:t:h"
#ifndef _WIN32
"d"
#endif
Expand All @@ -172,6 +180,7 @@ parse_arg(int argc, char **argv, hsk_options_t *opt) {
{ "identity-key", required_argument, NULL, 'k' },
{ "seeds", required_argument, NULL, 's' },
{ "log-file", required_argument, NULL, 'l' },
{ "upstream", required_argument, NULL, 't' },
#ifndef _WIN32
{ "daemon", no_argument, NULL, 'd' },
#endif
Expand Down Expand Up @@ -307,6 +316,18 @@ parse_arg(int argc, char **argv, hsk_options_t *opt) {
break;
}

case 't': {
if (!optarg || strlen(optarg) == 0)
return help(1);

if (opt->upstream)
free(opt->upstream);

opt->upstream = strdup(optarg);

break;
}

#ifndef _WIN32
case 'd': {
background = true;
Expand Down Expand Up @@ -428,7 +449,7 @@ hsk_daemon_init(hsk_daemon_t *daemon, uv_loop_t *loop, hsk_options_t *opt) {
goto fail;
}

daemon->ns = hsk_ns_alloc(loop, daemon->pool);
daemon->ns = hsk_ns_alloc(loop, daemon->pool, (bool)opt->upstream);

if (!daemon->ns) {
fprintf(stderr, "failed initializing ns\n");
Expand All @@ -450,7 +471,7 @@ hsk_daemon_init(hsk_daemon_t *daemon, uv_loop_t *loop, hsk_options_t *opt) {
}
}

daemon->rs = hsk_rs_alloc(loop, opt->ns_host);
daemon->rs = hsk_rs_alloc(loop, opt->ns_host, opt->upstream);

if (!daemon->rs) {
fprintf(stderr, "failed initializing rns\n");
Expand Down Expand Up @@ -492,7 +513,7 @@ hsk_daemon_open(hsk_daemon_t *daemon, hsk_options_t *opt) {
return rc;
}

rc = hsk_ns_open(daemon->ns, opt->ns_host);
rc = hsk_ns_open(daemon->ns, opt->ns_host, daemon->rs);

if (rc != HSK_SUCCESS) {
fprintf(stderr, "failed opening ns: %s\n", hsk_strerror(rc));
Expand Down
1 change: 1 addition & 0 deletions src/error.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static const char *errstrs[] = {
"EACTTHREE",
"EBADSIZE",
"EBADTAG",
"EREFUSED",
"EUNKNOWN"
};

Expand Down
5 changes: 4 additions & 1 deletion src/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@
#define HSK_EBADSIZE 30
#define HSK_EBADTAG 31

// DNS
#define HSK_EREFUSED 32

// Max
#define HSK_MAXERROR 32
#define HSK_MAXERROR 33

const char *
hsk_strerror(int code);
Expand Down
60 changes: 48 additions & 12 deletions src/ns.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "utils.h"
#include "uv.h"
#include "dnssec.h"
#include "rs_worker.h"
#include "rs.h"

// A RRSIG NSEC
static const uint8_t hsk_type_map_a[] = {
Expand Down Expand Up @@ -100,7 +102,12 @@ hsk_icann_lookup(const char *name);
*/

int
hsk_ns_init(hsk_ns_t *ns, const uv_loop_t *loop, const hsk_pool_t *pool) {
hsk_ns_init(
hsk_ns_t *ns,
const uv_loop_t *loop,
const hsk_pool_t *pool,
const bool upstream
) {
if (!ns || !loop || !pool)
return HSK_EBADARGS;

Expand All @@ -121,6 +128,8 @@ hsk_ns_init(hsk_ns_t *ns, const uv_loop_t *loop, const hsk_pool_t *pool) {
memset(ns->pubkey, 0x00, sizeof(ns->pubkey));
memset(ns->read_buffer, 0x00, sizeof(ns->read_buffer));
ns->receiving = false;
ns->upstream = upstream;
ns->rs = NULL;

return HSK_SUCCESS;
}
Expand Down Expand Up @@ -180,7 +189,7 @@ hsk_ns_set_key(hsk_ns_t *ns, const uint8_t *key) {
}

int
hsk_ns_open(hsk_ns_t *ns, const struct sockaddr *addr) {
hsk_ns_open(hsk_ns_t *ns, const struct sockaddr *addr, hsk_rs_t *rs) {
if (!ns || !addr)
return HSK_EBADARGS;

Expand Down Expand Up @@ -215,6 +224,8 @@ hsk_ns_open(hsk_ns_t *ns, const struct sockaddr *addr) {
char host[HSK_MAX_HOST];
assert(hsk_sa_to_string(addr, host, HSK_MAX_HOST, HSK_NS_PORT));

ns->rs = rs;

hsk_ns_log(ns, "root nameserver listening on: %s\n", host);

return HSK_SUCCESS;
Expand All @@ -241,13 +252,17 @@ hsk_ns_close(hsk_ns_t *ns) {
}

hsk_ns_t *
hsk_ns_alloc(const uv_loop_t *loop, const hsk_pool_t *pool) {
hsk_ns_alloc(
const uv_loop_t *loop,
const hsk_pool_t *pool,
const bool upstream
) {
hsk_ns_t *ns = malloc(sizeof(hsk_ns_t));

if (!ns)
return NULL;

if (hsk_ns_init(ns, loop, pool) != HSK_SUCCESS) {
if (hsk_ns_init(ns, loop, pool, upstream) != HSK_SUCCESS) {
free(ns);
return NULL;
}
Expand Down Expand Up @@ -726,16 +741,37 @@ after_resolve(

if (status == HSK_SUCCESS) {
if (!exists || data_len == 0) {
const uint8_t *item = hsk_icann_lookup(name);
if (ns->upstream) {
// User has requested that all non-HNS queries
// get forwarded to a specific upstream resolver.
hsk_ns_log(ns, "forwarding to upstream resolver: %s\n", req->name);

int rc;
rc = hsk_rs_worker_resolve(
ns->rs->fallback_worker,
req->name,
req->type,
req->class,
(void *)req,
rs_after_resolve
);

if (res)
hsk_resource_free(res);

return;
} else {
const uint8_t *item = hsk_icann_lookup(name);

if (item) {
const uint8_t *raw = &item[2];
size_t raw_len = (((size_t)item[1]) << 8) | ((size_t)item[0]);
if (item) {
const uint8_t *raw = &item[2];
size_t raw_len = (((size_t)item[1]) << 8) | ((size_t)item[0]);

if (!hsk_resource_decode(raw, raw_len, &res)) {
hsk_ns_log(ns, "could not decode root resource for: %s\n", name);
status = HSK_EFAILURE;
res = NULL;
if (!hsk_resource_decode(raw, raw_len, &res)) {
hsk_ns_log(ns, "could not decode root resource for: %s\n", name);
status = HSK_EFAILURE;
res = NULL;
}
}
}
} else {
Expand Down
18 changes: 15 additions & 3 deletions src/ns.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "cache.h"
#include "ec.h"
#include "pool.h"
#include "rs.h"

/*
* Defs
Expand All @@ -33,14 +34,21 @@ typedef struct {
uint8_t pubkey[33];
uint8_t read_buffer[HSK_UDP_BUFFER];
bool receiving;
bool upstream;
hsk_rs_t *rs;
} hsk_ns_t;

/*
* Root Nameserver
*/

int
hsk_ns_init(hsk_ns_t *ns, const uv_loop_t *loop, const hsk_pool_t *pool);
hsk_ns_init(
hsk_ns_t *ns,
const uv_loop_t *loop,
const hsk_pool_t *pool,
const bool upstream
);

void
hsk_ns_uninit(hsk_ns_t *ns);
Expand All @@ -52,13 +60,17 @@ bool
hsk_ns_set_key(hsk_ns_t *ns, const uint8_t *key);

int
hsk_ns_open(hsk_ns_t *ns, const struct sockaddr *addr);
hsk_ns_open(hsk_ns_t *ns, const struct sockaddr *addr, hsk_rs_t *rs);

int
hsk_ns_close(hsk_ns_t *ns);

hsk_ns_t *
hsk_ns_alloc(const uv_loop_t *loop, const hsk_pool_t *pool);
hsk_ns_alloc(
const uv_loop_t *loop,
const hsk_pool_t *pool,
const bool upstream
);

void
hsk_ns_free(hsk_ns_t *ns);
Expand Down
12 changes: 12 additions & 0 deletions src/resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,18 @@ hsk_resource_to_notimp(void) {
return msg;
}

hsk_dns_msg_t *
hsk_resource_to_refused(void) {
hsk_dns_msg_t *msg = hsk_dns_msg_alloc();

if (!msg)
return NULL;

msg->code = HSK_DNS_REFUSED;

return msg;
}

/*
* Helpers
*/
Expand Down
3 changes: 3 additions & 0 deletions src/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ hsk_resource_to_servfail(void);
hsk_dns_msg_t *
hsk_resource_to_notimp(void);

hsk_dns_msg_t *
hsk_resource_to_refused(void);

bool
hsk_resource_is_ptr(const char *name);

Expand Down
Loading