Browse code

milter: use reentrant resolv apis - bb#668

git-svn: trunk@3981

aCaB authored on 2008/07/24 05:14:28
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Jul 23 21:53:10 CEST 2008 (acab)
2
+------------------------------------
3
+  * clamav-milter: use thread safe resolv calls - bb#668 
4
+
1 5
 Wed Jul 23 16:32:32 EEST 2008 (edwin)
2 6
 ------------------------------------
3 7
   * libclamav: performance improvements for URL matching (bb #725, bb #650):
... ...
@@ -591,6 +591,39 @@ static	int	useful_header(const char *cmd);
591 591
 
592 592
 extern	short	logg_foreground;
593 593
 
594
+
595
+res_state res_pool;
596
+uint8_t *res_pool_state;
597
+
598
+pthread_cond_t res_pool_cond = PTHREAD_COND_INITIALIZER;
599
+pthread_mutex_t	res_pool_mutex = PTHREAD_MUTEX_INITIALIZER;
600
+
601
+int safe_res_query(const char *d, int c, int t, u_char *a, int l) {
602
+	int i = -1, ret;
603
+
604
+	pthread_mutex_lock(&res_pool_mutex);
605
+	while(i==-1) {
606
+		int j;
607
+		for(j=0; j<max_children+1; j++) {
608
+			if(!res_pool_state[j]) continue;
609
+			i = j;
610
+			break;
611
+		}
612
+		if(i!=-1) break;
613
+		pthread_cond_wait(&res_pool_cond, &res_pool_mutex);
614
+	}
615
+	res_pool_state[i]=0;
616
+	pthread_mutex_unlock(&res_pool_mutex);
617
+
618
+	ret = res_nquery(&res_pool[i], d, c, t, a, l);
619
+  
620
+	pthread_mutex_lock(&res_pool_mutex);
621
+	res_pool_state[i]=1;
622
+	pthread_cond_signal(&res_pool_cond);
623
+	pthread_mutex_unlock(&res_pool_mutex);
624
+	return ret;
625
+} 
626
+
594 627
 static void
595 628
 help(void)
596 629
 {
... ...
@@ -1362,6 +1395,15 @@ main(int argc, char **argv)
1362 1362
 	if((max_children == 0) && ((cpt = cfgopt(copt, "MaxThreads")) != NULL))
1363 1363
 		max_children = cfgopt(copt, "MaxThreads")->numarg;
1364 1364
 
1365
+	/* allocate a pool of resolvers */
1366
+	if(!(res_pool=cli_calloc(max_children+1, sizeof(*res_pool))))
1367
+		return EX_OSERR;
1368
+	if(!(res_pool_state=cli_malloc(max_children+1)))
1369
+		return EX_OSERR;
1370
+	memset(res_pool_state, 1, max_children+1);
1371
+	for(i = 0; i < max_children+1; i++)
1372
+		res_ninit(&res_pool[i]);
1373
+
1365 1374
 	if((cpt = cfgopt(copt, "ReadTimeout")) != NULL) {
1366 1375
 		readTimeout = cpt->numarg;
1367 1376
 
... ...
@@ -6190,7 +6232,7 @@ mx(const char *host, table_t *t)
6190 6190
 			return NULL;
6191 6191
 	}
6192 6192
 
6193
-	len = res_query(host, C_IN, T_MX, (u_char *)&q, sizeof(q));
6193
+	len = safe_res_query(host, C_IN, T_MX, (u_char *)&q, sizeof(q));
6194 6194
 	if(len < 0)
6195 6195
 		return t;	/* Host has no MX records */
6196 6196
 
... ...
@@ -6259,7 +6301,7 @@ resolve(const char *host, table_t *t)
6259 6259
 	if((host == NULL) || (*host == '\0'))
6260 6260
 		return t;
6261 6261
 
6262
-	len = res_query(host, C_IN, T_A, (u_char *)&q, sizeof(q));
6262
+	len = safe_res_query(host, C_IN, T_A, (u_char *)&q, sizeof(q));
6263 6263
 	if(len < 0)
6264 6264
 		return t;	/* Host has no A records */
6265 6265
 
... ...
@@ -6318,7 +6360,6 @@ resolve(const char *host, table_t *t)
6318 6318
  *	an SPF system, we ONLY use SPF records to reduce phish false positives
6319 6319
  * TODO: IPv6?
6320 6320
  * TODO: cache queries?
6321
- * TODO: check res_query is thread safe
6322 6321
  *
6323 6322
  * INPUT: prevhosts, a list of hosts already searched: stops include loops
6324 6323
  *	e.g. mercado.com includes medrcadosw.com which includes mercado.com,
... ...
@@ -6370,7 +6411,7 @@ spf(struct privdata *privdata, table_t *prevhosts)
6370 6370
 		*ptr = '\0';
6371 6371
 
6372 6372
 	logg("*SPF query '%s'\n", host);
6373
-	len = res_query(host, C_IN, T_TXT, (u_char *)&q, sizeof(q));
6373
+	len = safe_res_query(host, C_IN, T_TXT, (u_char *)&q, sizeof(q));
6374 6374
 	if(len < 0) {
6375 6375
 		free(host);
6376 6376
 		return 0;	/* Host has no TXT records */