Commit f22f5226 authored by Marek Vavrusa's avatar Marek Vavrusa Committed by Ondřej Surý

daemon: ported DNS/TLS preparation code to 1.1

parent 316f24fb
...@@ -150,6 +150,8 @@ static int net_list_add(const char *key, void *val, void *ext) ...@@ -150,6 +150,8 @@ static int net_list_add(const char *key, void *val, void *ext)
lua_setfield(L, -2, "udp"); lua_setfield(L, -2, "udp");
lua_pushboolean(L, ep->flags & NET_TCP); lua_pushboolean(L, ep->flags & NET_TCP);
lua_setfield(L, -2, "tcp"); lua_setfield(L, -2, "tcp");
lua_pushboolean(L, ep->flags & NET_TLS);
lua_setfield(L, -2, "tls");
} }
lua_setfield(L, -2, key); lua_setfield(L, -2, key);
return kr_ok(); return kr_ok();
...@@ -165,7 +167,7 @@ static int net_list(lua_State *L) ...@@ -165,7 +167,7 @@ static int net_list(lua_State *L)
} }
/** Listen on interface address list. */ /** Listen on interface address list. */
static int net_listen_iface(lua_State *L, int port) static int net_listen_iface(lua_State *L, int port, int flags)
{ {
/* Expand 'addr' key if exists */ /* Expand 'addr' key if exists */
lua_getfield(L, 1, "addr"); lua_getfield(L, 1, "addr");
...@@ -180,7 +182,7 @@ static int net_listen_iface(lua_State *L, int port) ...@@ -180,7 +182,7 @@ static int net_listen_iface(lua_State *L, int port)
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
lua_rawgeti(L, -1, i + 1); lua_rawgeti(L, -1, i + 1);
int ret = network_listen(&engine->net, lua_tostring(L, -1), int ret = network_listen(&engine->net, lua_tostring(L, -1),
port, NET_TCP|NET_UDP); port, flags);
if (ret != 0) { if (ret != 0) {
kr_log_info("[system] bind to '%s#%d' %s\n", lua_tostring(L, -1), port, kr_strerror(ret)); kr_log_info("[system] bind to '%s#%d' %s\n", lua_tostring(L, -1), port, kr_strerror(ret));
} }
...@@ -191,6 +193,17 @@ static int net_listen_iface(lua_State *L, int port) ...@@ -191,6 +193,17 @@ static int net_listen_iface(lua_State *L, int port)
return 1; return 1;
} }
static bool table_get_flag(lua_State *L, int index, const char *key, bool def)
{
bool result = def;
lua_getfield(L, index, key);
if (lua_isboolean(L, -1)) {
result = lua_toboolean(L, -1);
}
lua_pop(L, 1);
return result;
}
/** Listen on endpoint. */ /** Listen on endpoint. */
static int net_listen(lua_State *L) static int net_listen(lua_State *L)
{ {
...@@ -200,18 +213,23 @@ static int net_listen(lua_State *L) ...@@ -200,18 +213,23 @@ static int net_listen(lua_State *L)
if (n > 1 && lua_isnumber(L, 2)) { if (n > 1 && lua_isnumber(L, 2)) {
port = lua_tointeger(L, 2); port = lua_tointeger(L, 2);
} }
bool tls = (port == KR_DNS_TLS_PORT);
if (n > 2 && lua_istable(L, 3)) {
tls = table_get_flag(L, 3, "tls", tls);
}
/* Process interface or (address, port) pair. */ /* Process interface or (address, port, flags) triple. */
int flags = tls ? (NET_TCP|NET_TLS) : (NET_TCP|NET_UDP);
if (lua_istable(L, 1)) { if (lua_istable(L, 1)) {
return net_listen_iface(L, port); return net_listen_iface(L, port, flags);
} else if (n < 1 || !lua_isstring(L, 1)) { } else if (n < 1 || !lua_isstring(L, 1)) {
format_error(L, "expected 'listen(string addr, number port = 53)'"); format_error(L, "expected 'listen(string addr, number port = 53[, bool tls = false])'");
lua_error(L); lua_error(L);
} }
/* Open resolution context cache */ /* Open resolution context cache */
struct engine *engine = engine_luaget(L); struct engine *engine = engine_luaget(L);
int ret = network_listen(&engine->net, lua_tostring(L, 1), port, NET_TCP|NET_UDP); int ret = network_listen(&engine->net, lua_tostring(L, 1), port, flags);
if (ret != 0) { if (ret != 0) {
format_error(L, kr_strerror(ret)); format_error(L, kr_strerror(ret));
lua_error(L); lua_error(L);
......
...@@ -224,7 +224,7 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) ...@@ -224,7 +224,7 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
mp_flush(worker->pkt_pool.ctx); mp_flush(worker->pkt_pool.ctx);
} }
static void tcp_accept(uv_stream_t *master, int status) static void _tcp_accept(uv_stream_t *master, int status, bool tls)
{ {
if (status != 0) { if (status != 0) {
return; return;
...@@ -244,6 +244,7 @@ static void tcp_accept(uv_stream_t *master, int status) ...@@ -244,6 +244,7 @@ static void tcp_accept(uv_stream_t *master, int status)
* It will re-check every half of a request time limit if the connection * It will re-check every half of a request time limit if the connection
* is idle and should be terminated, this is an educated guess. */ * is idle and should be terminated, this is an educated guess. */
struct session *session = client->data; struct session *session = client->data;
session->has_tls = tls;
uv_timer_t *timer = &session->timeout; uv_timer_t *timer = &session->timeout;
uv_timer_init(master->loop, timer); uv_timer_init(master->loop, timer);
timer->data = client; timer->data = client;
...@@ -251,6 +252,16 @@ static void tcp_accept(uv_stream_t *master, int status) ...@@ -251,6 +252,16 @@ static void tcp_accept(uv_stream_t *master, int status)
io_start_read((uv_handle_t *)client); io_start_read((uv_handle_t *)client);
} }
static void tcp_accept(uv_stream_t *master, int status)
{
_tcp_accept(master, status, false);
}
static void tls_accept(uv_stream_t *master, int status)
{
_tcp_accept(master, status, true);
}
static int set_tcp_option(uv_handle_t *handle, int option, int val) static int set_tcp_option(uv_handle_t *handle, int option, int val)
{ {
uv_os_fd_t fd = 0; uv_os_fd_t fd = 0;
...@@ -307,6 +318,11 @@ int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr) ...@@ -307,6 +318,11 @@ int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr)
return _tcp_bind(handle, addr, tcp_accept); return _tcp_bind(handle, addr, tcp_accept);
} }
int tcp_bind_tls(uv_tcp_t *handle, struct sockaddr *addr)
{
return _tcp_bind(handle, addr, tls_accept);
}
int tcp_bindfd(uv_tcp_t *handle, int fd) int tcp_bindfd(uv_tcp_t *handle, int fd)
{ {
if (!handle) { if (!handle) {
......
...@@ -28,6 +28,7 @@ struct qr_task; ...@@ -28,6 +28,7 @@ struct qr_task;
struct session { struct session {
bool outgoing; bool outgoing;
bool throttled; bool throttled;
bool has_tls;
uv_timer_t timeout; uv_timer_t timeout;
struct qr_task *buffering; struct qr_task *buffering;
array_t(struct qr_task *) tasks; array_t(struct qr_task *) tasks;
...@@ -39,6 +40,7 @@ struct session *session_new(void); ...@@ -39,6 +40,7 @@ struct session *session_new(void);
int udp_bind(uv_udp_t *handle, struct sockaddr *addr); int udp_bind(uv_udp_t *handle, struct sockaddr *addr);
int udp_bindfd(uv_udp_t *handle, int fd); int udp_bindfd(uv_udp_t *handle, int fd);
int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr); int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr);
int tcp_bind_tls(uv_tcp_t *handle, struct sockaddr *addr);
int tcp_bindfd(uv_tcp_t *handle, int fd); int tcp_bindfd(uv_tcp_t *handle, int fd);
void io_create(uv_loop_t *loop, uv_handle_t *handle, int type); void io_create(uv_loop_t *loop, uv_handle_t *handle, int type);
......
...@@ -276,6 +276,7 @@ static void help(int argc, char *argv[]) ...@@ -276,6 +276,7 @@ static void help(int argc, char *argv[])
printf("Usage: %s [parameters] [rundir]\n", argv[0]); printf("Usage: %s [parameters] [rundir]\n", argv[0]);
printf("\nParameters:\n" printf("\nParameters:\n"
" -a, --addr=[addr] Server address (default: localhost#53).\n" " -a, --addr=[addr] Server address (default: localhost#53).\n"
" -t, --addr=[addr] Server address for TLS (default: off).\n"
" -S, --fd=[fd] Listen on given fd (handed out by supervisor).\n" " -S, --fd=[fd] Listen on given fd (handed out by supervisor).\n"
" -c, --config=[path] Config file path (relative to [rundir]) (default: config).\n" " -c, --config=[path] Config file path (relative to [rundir]) (default: config).\n"
" -k, --keyfile=[path] File containing trust anchors (DS or DNSKEY).\n" " -k, --keyfile=[path] File containing trust anchors (DS or DNSKEY).\n"
...@@ -382,7 +383,9 @@ int main(int argc, char **argv) ...@@ -382,7 +383,9 @@ int main(int argc, char **argv)
{ {
int forks = 1; int forks = 1;
array_t(char*) addr_set; array_t(char*) addr_set;
array_t(char*) tls_set;
array_init(addr_set); array_init(addr_set);
array_init(tls_set);
array_t(int) fd_set; array_t(int) fd_set;
array_init(fd_set); array_init(fd_set);
char *keyfile = NULL; char *keyfile = NULL;
...@@ -394,6 +397,7 @@ int main(int argc, char **argv) ...@@ -394,6 +397,7 @@ int main(int argc, char **argv)
int c = 0, li = 0, ret = 0; int c = 0, li = 0, ret = 0;
struct option opts[] = { struct option opts[] = {
{"addr", required_argument, 0, 'a'}, {"addr", required_argument, 0, 'a'},
{"tls", required_argument, 0, 't'},
{"fd", required_argument, 0, 'S'}, {"fd", required_argument, 0, 'S'},
{"config", required_argument, 0, 'c'}, {"config", required_argument, 0, 'c'},
{"keyfile",required_argument, 0, 'k'}, {"keyfile",required_argument, 0, 'k'},
...@@ -404,12 +408,15 @@ int main(int argc, char **argv) ...@@ -404,12 +408,15 @@ int main(int argc, char **argv)
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
while ((c = getopt_long(argc, argv, "a:S:c:f:k:vqVh", opts, &li)) != -1) { while ((c = getopt_long(argc, argv, "a:t:S:c:f:k:vqVh", opts, &li)) != -1) {
switch (c) switch (c)
{ {
case 'a': case 'a':
array_push(addr_set, optarg); array_push(addr_set, optarg);
break; break;
case 't':
array_push(tls_set, optarg);
break;
case 'S': case 'S':
array_push(fd_set, atoi(optarg)); array_push(fd_set, atoi(optarg));
break; break;
...@@ -556,16 +563,33 @@ int main(int argc, char **argv) ...@@ -556,16 +563,33 @@ int main(int argc, char **argv)
if (ret != 0) { if (ret != 0) {
kr_log_error("[system] listen on fd=%d %s\n", fd_set.at[i], kr_strerror(ret)); kr_log_error("[system] listen on fd=%d %s\n", fd_set.at[i], kr_strerror(ret));
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
break;
} }
} }
/* Bind to sockets and run */ /* Bind to sockets and run */
for (size_t i = 0; i < addr_set.len; ++i) { if (ret == 0) {
int port = 53; for (size_t i = 0; i < addr_set.len; ++i) {
const char *addr = set_addr(addr_set.at[i], &port); int port = 53;
ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP); const char *addr = set_addr(addr_set.at[i], &port);
if (ret != 0) { ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP);
kr_log_error("[system] bind to '%s#%d' %s\n", addr, port, kr_strerror(ret)); if (ret != 0) {
ret = EXIT_FAILURE; kr_log_error("[system] bind to '%s#%d' %s\n", addr, port, kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
}
}
/* Bind to TLS sockets */
if (ret == 0) {
for (size_t i = 0; i < tls_set.len; ++i) {
int port = 853;
const char *addr = set_addr(tls_set.at[i], &port);
ret = network_listen(&engine.net, addr, (uint16_t)port, NET_TCP|NET_TLS);
if (ret != 0) {
kr_log_error("[system] bind to '%s#%d' (TLS) %s\n", addr, port, kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
} }
} }
...@@ -604,6 +628,7 @@ int main(int argc, char **argv) ...@@ -604,6 +628,7 @@ int main(int argc, char **argv)
worker_reclaim(worker); worker_reclaim(worker);
mp_delete(pool.ctx); mp_delete(pool.ctx);
array_clear(addr_set); array_clear(addr_set);
array_clear(tls_set);
kr_crypto_cleanup(); kr_crypto_cleanup();
return ret; return ret;
} }
...@@ -130,6 +130,7 @@ static int insert_endpoint(struct network *net, const char *addr, struct endpoin ...@@ -130,6 +130,7 @@ static int insert_endpoint(struct network *net, const char *addr, struct endpoin
/** Open endpoint protocols. */ /** Open endpoint protocols. */
static int open_endpoint(struct network *net, struct endpoint *ep, struct sockaddr *sa, uint32_t flags) static int open_endpoint(struct network *net, struct endpoint *ep, struct sockaddr *sa, uint32_t flags)
{ {
int ret = 0;
if (flags & NET_UDP) { if (flags & NET_UDP) {
ep->udp = malloc(sizeof(*ep->udp)); ep->udp = malloc(sizeof(*ep->udp));
if (!ep->udp) { if (!ep->udp) {
...@@ -137,7 +138,7 @@ static int open_endpoint(struct network *net, struct endpoint *ep, struct sockad ...@@ -137,7 +138,7 @@ static int open_endpoint(struct network *net, struct endpoint *ep, struct sockad
} }
memset(ep->udp, 0, sizeof(*ep->udp)); memset(ep->udp, 0, sizeof(*ep->udp));
handle_init(udp, net->loop, ep->udp, sa->sa_family); handle_init(udp, net->loop, ep->udp, sa->sa_family);
int ret = udp_bind(ep->udp, sa); ret = udp_bind(ep->udp, sa);
if (ret != 0) { if (ret != 0) {
return ret; return ret;
} }
...@@ -150,13 +151,18 @@ static int open_endpoint(struct network *net, struct endpoint *ep, struct sockad ...@@ -150,13 +151,18 @@ static int open_endpoint(struct network *net, struct endpoint *ep, struct sockad
} }
memset(ep->tcp, 0, sizeof(*ep->tcp)); memset(ep->tcp, 0, sizeof(*ep->tcp));
handle_init(tcp, net->loop, ep->tcp, sa->sa_family); handle_init(tcp, net->loop, ep->tcp, sa->sa_family);
int ret = tcp_bind(ep->tcp, sa); if (flags & NET_TLS) {
ret = tcp_bind_tls(ep->tcp, sa);
ep->flags |= NET_TLS;
} else {
ret = tcp_bind(ep->tcp, sa);
}
if (ret != 0) { if (ret != 0) {
return ret; return ret;
} }
ep->flags |= NET_TCP; ep->flags |= NET_TCP;
} }
return kr_ok(); return ret;
} }
/** Open fd as endpoint. */ /** Open fd as endpoint. */
......
...@@ -25,6 +25,7 @@ enum endpoint_flag { ...@@ -25,6 +25,7 @@ enum endpoint_flag {
NET_DOWN = 0 << 0, NET_DOWN = 0 << 0,
NET_UDP = 1 << 0, NET_UDP = 1 << 0,
NET_TCP = 1 << 1, NET_TCP = 1 << 1,
NET_TLS = 1 << 2,
}; };
struct endpoint { struct endpoint {
......
...@@ -61,6 +61,7 @@ static inline int __attribute__((__cold__)) kr_error(int x) { ...@@ -61,6 +61,7 @@ static inline int __attribute__((__cold__)) kr_error(int x) {
* Defines. * Defines.
*/ */
#define KR_DNS_PORT 53 #define KR_DNS_PORT 53
#define KR_DNS_TLS_PORT 853
#define KR_EDNS_VERSION 0 #define KR_EDNS_VERSION 0
#define KR_EDNS_PAYLOAD 4096 /* Default UDP payload (max unfragmented UDP is 1452B) */ #define KR_EDNS_PAYLOAD 4096 /* Default UDP payload (max unfragmented UDP is 1452B) */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment