$NetBSD: patch-ba,v 1.1.2.2 2008/02/19 11:24:54 ghen Exp $

Fix pkg/36853

--- clamav-milter/clamav-milter.c.orig	2008-02-12 16:03:08.000000000 +0200
+++ clamav-milter/clamav-milter.c	2008-02-12 16:04:59.000000000 +0200
@@ -90,6 +90,9 @@
 #if	HAVE_RESOLV_H
 #include <arpa/nameser.h>	/* for HEADER */
 #include <resolv.h>
+#if __RES >= 20030124
+#define	HAVE_BIND9
+#endif
 #endif
 #ifdef	HAVE_UNISTD_H
 #include <unistd.h>
@@ -505,6 +508,20 @@
 #endif	/*SESSION*/
 
 static	pthread_cond_t	watchdog_cond = PTHREAD_COND_INITIALIZER;
+#ifndef HAVE_BIND9
+static	pthread_mutex_t res_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define RES_QUERY(len, h, c, t, q, s) \
+	do { \
+		pthread_mutex_lock(&res_mutex); \
+		len = res_query((h), (c), (t), (q), (s)); \
+		pthread_mutex_unlock(&res_mutex); \
+	} while (/*CONSTCOND*/0)
+#else
+static	pthread_key_t res_key;
+#define RES_QUERY(len, h, c, t, q, s) \
+	len = res_nquery((res_state)pthread_getspecific(res_key), \
+	    (h), (c), (t), (q), (s))
+#endif
 
 #ifndef	SHUT_RD
 #define	SHUT_RD		0
@@ -2061,12 +2078,19 @@
 	logg(_("Starting %s\n"), clamav_version);
 	logg(_("*Debugging is on\n"));
 
+#ifndef HAVE_BIND9
 	if(!(_res.options&RES_INIT))
 		if(res_init() < 0) {
 			fprintf(stderr, "%s: Can't initialise the resolver\n",
 				argv[0]);
 			return EX_UNAVAILABLE;
 		}
+#else
+	if (pthread_key_create(&res_key, free)) {
+		perror("pthread_key_create");
+		return EX_UNAVAILABLE;
+	}
+#endif
 
 	if(blacklist_time) {
 		char name[MAXHOSTNAMELEN + 1];
@@ -2577,6 +2601,18 @@
 	int sock = s->sock;
 	struct sockaddr *server = (struct sockaddr *)s->server;
 	int server_index = s->server_index;
+#ifdef HAVE_BIND9
+	res_state res = cli_calloc(1, sizeof(*res));
+	if (pthread_setspecific(res_key, res)) {
+		perror("pthread_setspecific");
+		free(res);
+		return NULL;
+	}
+	if (res_ninit(res) < 0) {
+		perror("res_ninit");
+		return NULL;
+	}
+#endif
 
 	if(last_failed_pings[server_index]) {
 		s->rc = 0;
@@ -6137,7 +6173,7 @@
 			return NULL;
 	}
 
-	len = res_query(host, C_IN, T_MX, (u_char *)&q, sizeof(q));
+	RES_QUERY(len, host, C_IN, T_MX, (u_char *)&q, sizeof(q));
 	if(len < 0)
 		return t;	/* Host has no MX records */
 
@@ -6206,7 +6242,7 @@
 	if((host == NULL) || (*host == '\0'))
 		return t;
 
-	len = res_query(host, C_IN, T_A, (u_char *)&q, sizeof(q));
+	RES_QUERY(len, host, C_IN, T_A, (u_char *)&q, sizeof(q));
 	if(len < 0)
 		return t;	/* Host has no A records */
 
@@ -6265,7 +6301,6 @@
  *	an SPF system, we ONLY use SPF records to reduce phish false positives
  * TODO: IPv6?
  * TODO: cache queries?
- * TODO: check res_query is thread safe
  *
  * INPUT: prevhosts, a list of hosts already searched: stops include loops
  *	e.g. mercado.com includes medrcadosw.com which includes mercado.com,
@@ -6317,7 +6352,7 @@
 		*ptr = '\0';
 
 	logg("*SPF query '%s'\n", host);
-	len = res_query(host, C_IN, T_TXT, (u_char *)&q, sizeof(q));
+	RES_QUERY(len, host, C_IN, T_TXT, (u_char *)&q, sizeof(q));
 	if(len < 0) {
 		free(host);
 		return 0;	/* Host has no TXT records */
