MEDIUM: thread/dns: Make DNS thread-safe
diff --git a/src/cfgparse.c b/src/cfgparse.c
index ca2d5d7..d693bfb 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -2182,6 +2182,7 @@
 		LIST_INIT(&curr_resolvers->nameservers);
 		LIST_INIT(&curr_resolvers->resolutions.curr);
 		LIST_INIT(&curr_resolvers->resolutions.wait);
+		SPIN_INIT(&curr_resolvers->lock);
 	}
 	else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
 		struct sockaddr_storage *sk;
diff --git a/src/dns.c b/src/dns.c
index 3383faa..1fdc461 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -45,7 +45,7 @@
 struct list dns_resolvers  = LIST_HEAD_INIT(dns_resolvers);
 struct list dns_srvrq_list = LIST_HEAD_INIT(dns_srvrq_list);
 
-static int64_t dns_query_id_seed = 0;	/* random seed */
+static THREAD_LOCAL int64_t dns_query_id_seed = 0; /* random seed */
 static struct pool_head *dns_answer_item_pool = NULL;
 static struct pool_head *dns_resolution_pool  = NULL;
 static unsigned int resolution_uuid = 1;
@@ -125,6 +125,8 @@
 /* 2 bytes random generator to generate DNS query ID */
 static inline uint16_t dns_rnd16(void)
 {
+	if (!dns_query_id_seed)
+		dns_query_id_seed = now_ms;
 	dns_query_id_seed ^= dns_query_id_seed << 13;
 	dns_query_id_seed ^= dns_query_id_seed >> 7;
 	dns_query_id_seed ^= dns_query_id_seed << 17;
@@ -1444,6 +1446,7 @@
 		return;
 
 	resolvers = ns->resolvers;
+	SPIN_LOCK(DNS_LOCK, &resolvers->lock);
 
 	/* process all pending input messages */
 	while (1) {
@@ -1604,6 +1607,7 @@
 		continue;
 	}
 	dns_update_resolvers_timeout(resolvers);
+	SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
 }
 
 /* Called when a resolvers network socket is ready to send data */
@@ -1628,6 +1632,8 @@
 		return;
 
 	resolvers = ns->resolvers;
+	SPIN_LOCK(DNS_LOCK, &resolvers->lock);
+
 	list_for_each_entry(res, &resolvers->resolutions.curr, list) {
 		int ret;
 
@@ -1653,6 +1659,7 @@
 		ns->counters.snd_error++;
 		res->nb_queries++;
 	}
+	SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
 }
 
 /* Processes DNS resolution. First, it checks the active list to detect expired
@@ -1665,6 +1672,8 @@
 	struct dns_resolution *res, *resback;
 	int exp;
 
+	SPIN_LOCK(DNS_LOCK, &resolvers->lock);
+
 	/* Handle all expired resolutions from the active list */
 	list_for_each_entry_safe(res, resback, &resolvers->resolutions.curr, list) {
 		/* When we find the first resolution in the future, then we can
@@ -1733,6 +1742,7 @@
 	}
 
 	dns_update_resolvers_timeout(resolvers);
+	SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
 	return t;
 }
 
@@ -2015,9 +2025,6 @@
 	dns_answer_item_pool = create_pool("dns_answer_item", sizeof(struct dns_answer_item), MEM_F_SHARED);
 	dns_resolution_pool  = create_pool("dns_resolution",  sizeof(struct dns_resolution),  MEM_F_SHARED);
 
-	/* give a first random value to our dns query_id seed */
-	dns_query_id_seed = random();
-
 	hap_register_post_check(dns_finalize_config);
 	hap_register_post_deinit(dns_deinit);
 
diff --git a/src/server.c b/src/server.c
index 648f3dd..f0b912f 100644
--- a/src/server.c
+++ b/src/server.c
@@ -3751,11 +3751,12 @@
 	char                  *hostname_dn;
 	int                    hostname_len, hostname_dn_len;
 
+	SPIN_LOCK(DNS_LOCK, &srv->resolvers->lock);
 	/* run time DNS resolution was not active for this server
 	 * and we can't enable it at run time for now.
 	 */
 	if (!srv->dns_requester)
-		return -1;
+		goto err;
 
 	chunk_reset(&trash);
 	hostname_len    = strlen(hostname);
@@ -3763,13 +3764,13 @@
 	hostname_dn_len = dns_str_to_dn_label(hostname, hostname_len + 1,
 					      hostname_dn, trash.size);
 	if (hostname_dn_len == -1)
-		return -1;
+		goto err;
 
 	resolution = srv->dns_requester->resolution;
 	if (resolution &&
 	    resolution->hostname_dn &&
 	    !strcmp(resolution->hostname_dn, hostname_dn))
-		return 0;
+		goto end;
 
 	dns_unlink_resolution(srv->dns_requester);
 
@@ -3779,11 +3780,18 @@
 	srv->hostname_dn     = strdup(hostname_dn);
 	srv->hostname_dn_len = hostname_dn_len;
 	if (!srv->hostname || !srv->hostname_dn)
-		return -1;
+		goto err;
 
 	if (dns_link_resolution(srv, OBJ_TYPE_SERVER) == -1)
-		return -1;
+		goto err;
+
+  end:
+	SPIN_UNLOCK(DNS_LOCK, &srv->resolvers->lock);
 	return 0;
+
+  err:
+	SPIN_UNLOCK(DNS_LOCK, &srv->resolvers->lock);
+	return -1;
 }
 
 /* Sets the server's address (srv->addr) from srv->lastaddr which was filled