diff --git a/daemon/worker.c b/daemon/worker.c
index 436bfd1a8b14fe96bf5b3ea9c73c89d13bcda766..94fa25aa05f5a988e2062d44fec1c2403407bb85 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -440,18 +440,36 @@ static void on_write(uv_write_t *req, int status)
 	req_release(worker, (struct req *)req);
 }
 
-/** UpdateDNS cookie data in */
-static bool subreq_update_cookies(struct sockaddr *addr, knot_pkt_t *pkt)
+/** Update DNS cookie data in packet. */
+static bool subreq_update_cookies(uv_udp_t *handle, struct sockaddr *srvr_addr,
+                                  knot_pkt_t *pkt)
 {
-	assert(addr);
+	assert(handle);
+	assert(srvr_addr);
 	assert(pkt);
+
+	/* Cookies disabled or packet has no ENDS section. */
 	if (!kr_cookies_control.enabled || !pkt->opt_rr) {
 		return true;
 	}
 
-	kr_pkt_put_cookie(&kr_cookies_control, addr, pkt);
+	/* Libuv does not offer a convenient way how to obtain a source IP
+	 * address from a UDP handle that has been initialised using
+	 * uv_udp_init(). The uv_udp_getsockname() fails because of the lazy
+	 * socket initialisation. */
+
+	struct sockaddr_storage sockaddr = {0, };
+	struct sockaddr_storage *sockaddr_ptr = &sockaddr;
+	int sockaddr_len = sizeof(sockaddr);
+	int ret = uv_udp_getsockname(handle, (struct sockaddr*) &sockaddr,
+	                             &sockaddr_len);
+	if (ret != 0) {
+		sockaddr_ptr = NULL;
+	}
+
+	kr_request_put_cookie(&kr_cookies_control,
+	                      (struct sockaddr*) sockaddr_ptr, srvr_addr, pkt);
 
-	/*TODO */
 	return true;
 }
 
@@ -476,7 +494,7 @@ static int qr_task_send(struct qr_task *task, uv_handle_t *handle, struct sockad
 	}
 	if (handle->type == UV_UDP) {
 		/* Update DNS cookies data. */
-		subreq_update_cookies(addr, pkt);
+		subreq_update_cookies((uv_udp_t *) handle, addr, pkt);
 
 		uv_buf_t buf = { (char *)pkt->wire, pkt->size };
 		send_req->as.send.data = task;
diff --git a/lib/cookies/control.c b/lib/cookies/control.c
index 582b9c58c92a66c6b0cba50ca29ed9189caa0ab7..55623c402d959146155f87a074f98df2996821b1 100644
--- a/lib/cookies/control.c
+++ b/lib/cookies/control.c
@@ -69,8 +69,9 @@ static int opt_rr_add_cookies(knot_rrset_t *opt_rr,
 }
 
 int prepare_client_cookie(uint8_t cc[KNOT_OPT_COOKIE_CLNT],
-                           const void *srvr_addr,
-                           const struct secret_quantity *csq)
+                          const void *clnt_addr,
+                          const void *srvr_addr,
+                          const struct secret_quantity *csq)
 {
 	assert(cc);
 	assert(srvr_addr);
@@ -81,27 +82,53 @@ int prepare_client_cookie(uint8_t cc[KNOT_OPT_COOKIE_CLNT],
 	/* According to the draft (section A.1) the recommended sequence is
 	 * client IP address | server IP address , client secret. */
 
-	int addr_family = ((struct sockaddr *) srvr_addr)->sa_family;
-	if (addr_family == AF_INET) {
-		srvr_addr = &((struct sockaddr_in *) srvr_addr)->sin_addr;
-	} else if (addr_family == AF_INET6) {
-		srvr_addr = &((struct sockaddr_in6 *) srvr_addr)->sin6_addr;
-	} else {
-		assert(0);
-		return kr_error(EINVAL);
+	if (clnt_addr) {
+		int addr_family = ((struct sockaddr *) clnt_addr)->sa_family;
+		if (addr_family == AF_INET) {
+			clnt_addr = &((struct sockaddr_in *) clnt_addr)->sin_addr;
+		} else if (addr_family == AF_INET6) {
+			clnt_addr = &((struct sockaddr_in6 *) clnt_addr)->sin6_addr;
+		} else {
+			//assert(0);
+			//return kr_error(EINVAL);
+			addr_family = AF_UNSPEC;
+			DEBUG_MSG(NULL, "%s\n", "could not obtain client IP address for client cookie");
+		}
+
+		if (addr_family != AF_UNSPEC) {
+			WITH_DEBUG {
+				char ns_str[INET6_ADDRSTRLEN];
+				inet_ntop(addr_family, clnt_addr, ns_str, sizeof(ns_str));
+				DEBUG_MSG(NULL, "adding client IP address '%s' into client cookie\n", ns_str);
+			}
+		}
 	}
 
-	WITH_DEBUG {
-		char ns_str[INET6_ADDRSTRLEN];
-		inet_ntop(addr_family, srvr_addr, ns_str, sizeof(ns_str));
-		DEBUG_MSG(NULL, "adding server address '%s' into client cookie\n", ns_str);
+	if (srvr_addr) {
+		int addr_family = ((struct sockaddr *) srvr_addr)->sa_family;
+		if (addr_family == AF_INET) {
+			srvr_addr = &((struct sockaddr_in *) srvr_addr)->sin_addr;
+		} else if (addr_family == AF_INET6) {
+			srvr_addr = &((struct sockaddr_in6 *) srvr_addr)->sin6_addr;
+		} else {
+			addr_family = AF_UNSPEC;
+			DEBUG_MSG(NULL, "%s\n", "could not obtain server IP address for client cookie");
+		}
+
+		if (addr_family != AF_UNSPEC) {
+			WITH_DEBUG {
+				char ns_str[INET6_ADDRSTRLEN];
+				inet_ntop(addr_family, srvr_addr, ns_str, sizeof(ns_str));
+				DEBUG_MSG(NULL, "adding server address '%s' into client cookie\n", ns_str);
+			}
+		}
 	}
 
 	memcpy(cc, csq->secret, KNOT_OPT_COOKIE_CLNT);
 }
 
-int kr_pkt_put_cookie(struct cookies_control *cntrl, void *sockaddr,
-                      knot_pkt_t *pkt)
+int kr_request_put_cookie(struct cookies_control *cntrl, void *clnt_sockaddr,
+                          void *srvr_sockaddr, knot_pkt_t *pkt)
 {
 	assert(cntrl);
 	assert(pkt);
@@ -116,7 +143,8 @@ int kr_pkt_put_cookie(struct cookies_control *cntrl, void *sockaddr,
 		return kr_error(EINVAL);
 	}
 
-	int ret = prepare_client_cookie(cc, sockaddr, cntrl->client);
+	int ret = prepare_client_cookie(cc, clnt_sockaddr, srvr_sockaddr,
+	                                cntrl->client);
 
 	/* Reclaim reserved size. */
 	ret = knot_pkt_reclaim(pkt, knot_edns_wire_size(pkt->opt_rr));
@@ -124,8 +152,8 @@ int kr_pkt_put_cookie(struct cookies_control *cntrl, void *sockaddr,
 		return ret;
 	}
 
-	/* TODO -- generate cleitn cookie from client address, server address
-	 * and secret quentity. */
+	/* TODO -- generate client cookie from client address, server address
+	 * and secret quantity. */
 	ret = opt_rr_add_cookies(pkt->opt_rr, cc, NULL, 0, &pkt->mm);
 
 	/* Write to packet. */
diff --git a/lib/cookies/control.h b/lib/cookies/control.h
index f204ee7282aa3dad2465fbbfc08e400c4d9fc11b..dedc094c7f067d0532d4d91968dbf06d90025409 100644
--- a/lib/cookies/control.h
+++ b/lib/cookies/control.h
@@ -41,11 +41,13 @@ KR_EXPORT
 extern struct cookies_control kr_cookies_control;
 
 /**
- * Insert a DNS cookie into the packet.
+ * Insert a DNS cookie into query packet.
  * @note The packet must already contain ENDS section.
- * @param cntrl Cookie control structure.
- * @param pkt   Packet.
+ * @param cntrl         Cookie control structure.
+ * @param clnt_sockaddr Client address.
+ * @param srvr_sockaddr Server address.
+ * @param pkt           DNS request packet.
  */
 KR_EXPORT
-int kr_pkt_put_cookie(struct cookies_control *cntrl, void *sockaddr,
-                      knot_pkt_t *pkt);
+int kr_request_put_cookie(struct cookies_control *cntrl, void *clnt_sockaddr,
+                          void *srvr_sockaddr, knot_pkt_t *pkt);