]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon: correct PROXYv2 handling for TCP sessions
authorOto Šťáva <oto.stava@nic.cz>
Mon, 7 Feb 2022 09:08:21 +0000 (10:08 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 22 Feb 2022 10:52:11 +0000 (10:52 +0000)
daemon/io.c
daemon/session.c
daemon/session.h

index 001ed0f508f7bd2825f24760149f3901eddee5a8..d7ae84e95487187e907d61a5d0564a067120c7be 100644 (file)
@@ -350,8 +350,6 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
        ssize_t data_len = nread;
        const struct sockaddr *src_addr = session_get_peer(s);
        const struct sockaddr *dst_addr = NULL;
-       struct proxy_result proxy;
-       bool has_proxy = false;
        if (!session_flags(s)->outgoing && !session_flags(s)->no_proxy &&
                        proxy_header_present(data, data_len)) {
                if (!proxy_allowed(&the_worker->engine->net, src_addr)) {
@@ -364,7 +362,8 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
                        return;
                }
 
-               ssize_t trimmed = proxy_process_header(&proxy, s, data, data_len);
+               struct proxy_result *proxy = session_proxy_create(s);
+               ssize_t trimmed = proxy_process_header(proxy, s, data, data_len);
                if (trimmed < 0) {
                        if (kr_log_is_debug(IO, NULL)) {
                                if (trimmed == KNOT_EMALF) {
@@ -383,10 +382,9 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
                        return;
                }
 
-               if (proxy.command != PROXY2_CMD_LOCAL && proxy.family != AF_UNSPEC) {
-                       has_proxy = true;
-                       src_addr = &proxy.src_addr.ip;
-                       dst_addr = &proxy.dst_addr.ip;
+               if (proxy->command != PROXY2_CMD_LOCAL && proxy->family != AF_UNSPEC) {
+                       src_addr = &proxy->src_addr.ip;
+                       dst_addr = &proxy->dst_addr.ip;
 
                        if (kr_log_is_debug(IO, NULL)) {
                                kr_log_debug(IO, "<= TCP stream from '%s'\n",
@@ -451,7 +449,7 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
                .src_addr = src_addr,
                .comm_addr = session_get_peer(s),
                .dst_addr = dst_addr,
-               .proxy = (has_proxy) ? &proxy : NULL
+               .proxy = session_proxy_get(s)
        };
        int ret = session_wirebuf_process(s, &comm);
        if (ret < 0) {
index 3d14b951c4df93b01d4dda712df2e30fcf97bdd7..fc606e385c31fbcc94ae15ac46e3be4f129597d7 100644 (file)
@@ -37,6 +37,8 @@ struct session {
        struct tls_ctx *tls_ctx;      /**< server side tls-related data. */
        struct tls_client_ctx *tls_client_ctx;  /**< client side tls-related data. */
 
+       struct proxy_result *proxy;   /**< PROXYv2 data for TCP. May be `NULL` if not proxied. */
+
 #if ENABLE_DOH2
        struct http_ctx *http_ctx;  /**< server side http-related data. */
 #endif
@@ -84,6 +86,9 @@ void session_clear(struct session *session)
        if (session->handle && session->handle->type == UV_TCP) {
                free(session->wire_buf);
        }
+       if (session->proxy) {
+               free(session->proxy);
+       }
 #if ENABLE_DOH2
        http_free(session->http_ctx);
 #endif
@@ -437,6 +442,21 @@ void session_waitinglist_finalize(struct session *session, int status)
        }
 }
 
+struct proxy_result *session_proxy_create(struct session *session)
+{
+       if (!kr_fails_assert(!session->proxy)) {
+               session->proxy = calloc(1, sizeof(struct proxy_result));
+               kr_require(session->proxy);
+       }
+
+       return session->proxy;
+}
+
+struct proxy_result *session_proxy_get(struct session *session)
+{
+       return session->proxy;
+}
+
 void session_tasklist_finalize(struct session *session, int status)
 {
        while (session_tasklist_get_len(session) > 0) {
index 723f71d47d18c8bb2e6eaf866e417a881a44ff54..e27187458cd96f2be09109c55dc26193ccb01f65 100644 (file)
@@ -14,6 +14,7 @@ struct qr_task;
 struct worker_ctx;
 struct session;
 struct io_comm_data;
+struct proxy_result;
 
 struct session_flags {
        bool outgoing : 1;      /**< True: to upstream; false: from a client. */
@@ -58,6 +59,13 @@ void session_waitinglist_retry(struct session *session, bool increase_timeout_cn
 /** Finalize all tasks in the list. */
 void session_waitinglist_finalize(struct session *session, int status);
 
+/** PROXYv2 data. */
+/** Creates zero-initialized PROXYv2 data for the session. Should only be called
+ * once per session. */
+struct proxy_result *session_proxy_create(struct session *session);
+/** Gets the session's PROXYv2 data, if it exists. If it does not, returns `NULL`. */
+struct proxy_result *session_proxy_get(struct session *session);
+
 /** List of tasks associated with session. */
 /** Check if list is empty. */
 bool session_tasklist_is_empty(const struct session *session);