]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon: ported DNS/TLS preparation code to 1.1
authorMarek Vavrusa <marek@vavrusa.com>
Fri, 8 Jul 2016 03:22:51 +0000 (20:22 -0700)
committerOndřej Surý <ondrej@sury.org>
Fri, 5 Aug 2016 09:47:14 +0000 (11:47 +0200)
daemon/bindings.c
daemon/io.c
daemon/io.h
daemon/main.c
daemon/network.c
daemon/network.h
lib/defines.h

index 3653f5d39d45bd878a8036c52d88e99899a14141..573a47fd11433b2f4b4e866c32ecb1b6ca41b7ed 100644 (file)
@@ -150,6 +150,8 @@ static int net_list_add(const char *key, void *val, void *ext)
                lua_setfield(L, -2, "udp");
                lua_pushboolean(L, ep->flags & NET_TCP);
                lua_setfield(L, -2, "tcp");
+               lua_pushboolean(L, ep->flags & NET_TLS);
+               lua_setfield(L, -2, "tls");
        }
        lua_setfield(L, -2, key);
        return kr_ok();
@@ -165,7 +167,7 @@ static int net_list(lua_State *L)
 }
 
 /** 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 */
        lua_getfield(L, 1, "addr");
@@ -180,7 +182,7 @@ static int net_listen_iface(lua_State *L, int port)
        for (size_t i = 0; i < count; ++i) {
                lua_rawgeti(L, -1, i + 1);
                int ret = network_listen(&engine->net, lua_tostring(L, -1),
-                                        port, NET_TCP|NET_UDP);
+                                        port, flags);
                if (ret != 0) {
                        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)
        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. */
 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)) {
                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)) {
-               return net_listen_iface(L, port);
+               return net_listen_iface(L, port, flags);
        } 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);
        }
 
        /* Open resolution context cache */
        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) {
                format_error(L, kr_strerror(ret));
                lua_error(L);
index 11e4f0e3570c16b98fab5aa8dd73f571024f464e..4058029fc76fbde974bc1aa0aa1afae286c1b1a2 100644 (file)
@@ -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);
 }
 
-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) {
                return;
@@ -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
         * is idle and should be terminated, this is an educated guess. */
        struct session *session = client->data;
+       session->has_tls = tls;
        uv_timer_t *timer = &session->timeout;
        uv_timer_init(master->loop, timer);
        timer->data = client;
@@ -251,6 +252,16 @@ static void tcp_accept(uv_stream_t *master, int status)
        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)
 {
        uv_os_fd_t fd = 0;
@@ -307,6 +318,11 @@ int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr)
        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)
 {
        if (!handle) {
index c4974ddad210557a51a33c8a5824a5a9a013736d..ba29cf1e2ac20fabb3dba995b202bed2772705f2 100644 (file)
@@ -28,6 +28,7 @@ struct qr_task;
 struct session {
        bool outgoing;
     bool throttled;
+    bool has_tls;
     uv_timer_t timeout;
     struct qr_task *buffering;
        array_t(struct qr_task *) tasks;
@@ -39,6 +40,7 @@ struct session *session_new(void);
 int udp_bind(uv_udp_t *handle, struct sockaddr *addr);
 int udp_bindfd(uv_udp_t *handle, int fd);
 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);
 
 void io_create(uv_loop_t *loop, uv_handle_t *handle, int type);
index 5bf56c726f28dba5fd09aaa85145c76a36619c81..a4b3df654ec32df2bc24360c7139ee1093efb572 100644 (file)
@@ -276,6 +276,7 @@ static void help(int argc, char *argv[])
        printf("Usage: %s [parameters] [rundir]\n", argv[0]);
        printf("\nParameters:\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"
               " -c, --config=[path]  Config file path (relative to [rundir]) (default: config).\n"
               " -k, --keyfile=[path] File containing trust anchors (DS or DNSKEY).\n"
@@ -382,7 +383,9 @@ int main(int argc, char **argv)
 {
        int forks = 1;
        array_t(char*) addr_set;
+       array_t(char*) tls_set;
        array_init(addr_set);
+       array_init(tls_set);
        array_t(int) fd_set;
        array_init(fd_set);
        char *keyfile = NULL;
@@ -394,6 +397,7 @@ int main(int argc, char **argv)
        int c = 0, li = 0, ret = 0;
        struct option opts[] = {
                {"addr", required_argument,   0, 'a'},
+               {"tls",  required_argument,   0, 't'},
                {"fd",   required_argument,   0, 'S'},
                {"config", required_argument, 0, 'c'},
                {"keyfile",required_argument, 0, 'k'},
@@ -404,12 +408,15 @@ int main(int argc, char **argv)
                {"help",      no_argument,    0, 'h'},
                {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)
                {
                case 'a':
                        array_push(addr_set, optarg);
                        break;
+               case 't':
+                       array_push(tls_set, optarg);
+                       break;
                case 'S':
                        array_push(fd_set,  atoi(optarg));
                        break;
@@ -556,16 +563,33 @@ int main(int argc, char **argv)
                if (ret != 0) {
                        kr_log_error("[system] listen on fd=%d %s\n", fd_set.at[i], kr_strerror(ret));
                        ret = EXIT_FAILURE;
+                       break;
                }
        }
        /* Bind to sockets and run */
-       for (size_t i = 0; i < addr_set.len; ++i) {
-               int port = 53;
-               const char *addr = set_addr(addr_set.at[i], &port);
-               ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP);
-               if (ret != 0) {
-                       kr_log_error("[system] bind to '%s#%d' %s\n", addr, port, kr_strerror(ret));
-                       ret = EXIT_FAILURE;
+       if (ret == 0) {
+               for (size_t i = 0; i < addr_set.len; ++i) {
+                       int port = 53;
+                       const char *addr = set_addr(addr_set.at[i], &port);
+                       ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP);
+                       if (ret != 0) {
+                               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)
        worker_reclaim(worker);
        mp_delete(pool.ctx);
        array_clear(addr_set);
+       array_clear(tls_set);
        kr_crypto_cleanup();
        return ret;
 }
index 4ad0e45d428a3fdefa5073ec2815fc3c8c619808..e0e46e3550a2688b3dedf398915352ceefdf94a9 100644 (file)
@@ -130,6 +130,7 @@ static int insert_endpoint(struct network *net, const char *addr, struct endpoin
 /** Open endpoint protocols. */
 static int open_endpoint(struct network *net, struct endpoint *ep, struct sockaddr *sa, uint32_t flags)
 {
+       int ret = 0;
        if (flags & NET_UDP) {
                ep->udp = malloc(sizeof(*ep->udp));
                if (!ep->udp) {
@@ -137,7 +138,7 @@ static int open_endpoint(struct network *net, struct endpoint *ep, struct sockad
                }
                memset(ep->udp, 0, sizeof(*ep->udp));
                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) {
                        return ret;
                }
@@ -150,13 +151,18 @@ static int open_endpoint(struct network *net, struct endpoint *ep, struct sockad
                }
                memset(ep->tcp, 0, sizeof(*ep->tcp));
                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) {
                        return ret;
                }
                ep->flags |= NET_TCP;
        }
-       return kr_ok();
+       return ret;
 }
 
 /** Open fd as endpoint. */
index 9816420c18c0d8aa513cc477f82bc426c2bea72b..14e91edbe617ad5010072f6d9ef8d4cf0025378f 100644 (file)
@@ -25,6 +25,7 @@ enum endpoint_flag {
     NET_DOWN = 0 << 0,
     NET_UDP  = 1 << 0,
     NET_TCP  = 1 << 1,
+    NET_TLS  = 1 << 2,
 };
 
 struct endpoint {
index 0acc273a139ca0436fd4eb08618eb43e08d3f523..a9baf643bcf90ef7125667b5c85da817256bfa9b 100644 (file)
@@ -61,6 +61,7 @@ static inline int __attribute__((__cold__)) kr_error(int x) {
  * Defines.
  */
 #define KR_DNS_PORT   53
+#define KR_DNS_TLS_PORT 853
 #define KR_EDNS_VERSION 0
 #define KR_EDNS_PAYLOAD 4096 /* Default UDP payload (max unfragmented UDP is 1452B) */