]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon: check source in udp answer
authorGrigorii Demidov <grigorii.demidov@nic.cz>
Wed, 14 Mar 2018 13:21:01 +0000 (14:21 +0100)
committerPetr Špaček <petr.spacek@nic.cz>
Wed, 9 May 2018 16:55:53 +0000 (18:55 +0200)
daemon/io.c
daemon/worker.c
lib/utils.c
lib/utils.h

index 63bca9f71716aa88cde0759426f795fa7a938a1d..494a5eb376894d927d51dbcba82cc0bafbceaa78 100644 (file)
@@ -160,6 +160,12 @@ void udp_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
        if (addr->sa_family == AF_UNSPEC) {
                return;
        }
+       if (s->outgoing) {
+               assert(s->peer.ip.sa_family != AF_UNSPEC);
+               if (kr_sockaddr_cmp(&s->peer.ip, addr) != 0) {
+                       return;
+               }
+       }
        knot_pkt_t *query = knot_pkt_new(buf->base, nread, &worker->pkt_pool);
        if (query) {
                query->max_size = KNOT_WIRE_MAX_PKTSIZE;
index adf4c4f64f378628a0a7c56b0f014a4bd7ee4de0..6e17eee395468f71e2e5d1f3603863cad66cd65e 100644 (file)
@@ -1384,8 +1384,15 @@ static uv_handle_t *retransmit(struct qr_task *task)
                        return ret;
                }
                ret = ioreq_spawn(task, SOCK_DGRAM, choice->sin6_family);
-               if (ret &&
-                   qr_task_send(task, ret, (struct sockaddr *)choice,
+               if (!ret) {
+                       return ret;
+               }
+               struct sockaddr *addr = (struct sockaddr *)choice;
+               struct session *session = ret->data;
+               assert (session->peer.ip.sa_family == AF_UNSPEC);
+               session->outgoing = true;
+               memcpy(&session->peer, addr, sizeof(session->peer));
+               if (qr_task_send(task, ret, (struct sockaddr *)choice,
                                 task->pktbuf) == 0) {
                        task->addrlist_turn = (task->addrlist_turn + 1) %
                                              task->addrlist_count; /* Round robin */
index 91bad8fdcf2dd45627bedcb1400853a6f346e249..62c61e3b8050580e3ac932d40e340c48efac6c17 100644 (file)
@@ -365,6 +365,33 @@ int kr_sockaddr_len(const struct sockaddr *addr)
        }
 }
 
+int kr_sockaddr_cmp(const struct sockaddr *left, const struct sockaddr *right)
+{
+       if (!left || !right) {
+               return kr_error(EINVAL);
+       }
+       if (left->sa_family != right->sa_family) {
+               return kr_error(EFAULT);
+       }
+       if (left->sa_family == AF_INET) {
+               struct sockaddr_in *left_in = (struct sockaddr_in *)left;
+               struct sockaddr_in *right_in = (struct sockaddr_in *)right;
+               if (left_in->sin_addr.s_addr != right_in->sin_addr.s_addr) {
+                       return kr_error(EFAULT);
+               }
+       } else if (left->sa_family == AF_INET6) {
+               struct sockaddr_in6 *left_in6 = (struct sockaddr_in6 *)left;
+               struct sockaddr_in6 *right_in6 = (struct sockaddr_in6 *)right;
+               if (memcmp(&left_in6->sin6_addr, &right_in6->sin6_addr,
+                          sizeof(struct in6_addr)) != 0) {
+                       return kr_error(EFAULT);
+               }
+       } else {
+               return kr_error(ENOENT);
+       }
+       return kr_ok();
+}
+
 uint16_t kr_inaddr_port(const struct sockaddr *addr)
 {
        if (!addr) {
index b990a17567956396754189d4b89e964151a90bc5..dfdb6912de559a727c373dad3be543e333c5af3d 100644 (file)
@@ -233,6 +233,11 @@ int kr_inaddr_len(const struct sockaddr *addr);
 /** Sockaddr length for given family, i.e. sizeof(struct sockaddr_in*). */
 KR_EXPORT KR_PURE
 int kr_sockaddr_len(const struct sockaddr *addr);
+/** Compare two given sockaddr.
+ * return 0 - addresses are equal, error code otherwise.
+ */
+KR_EXPORT KR_PURE
+int kr_sockaddr_cmp(const struct sockaddr *left, const struct sockaddr *right);
 /** Port. */
 KR_EXPORT KR_PURE
 uint16_t kr_inaddr_port(const struct sockaddr *addr);