git-svn: trunk@4522
aCaB authored on 2008/12/05 01:26:24... | ... |
@@ -25,8 +25,6 @@ |
25 | 25 |
#include <stdlib.h> |
26 | 26 |
#include <string.h> |
27 | 27 |
#include <strings.h> |
28 |
-#include <sys/socket.h> |
|
29 |
-#include <netinet/in.h> |
|
30 | 28 |
#include <arpa/inet.h> |
31 | 29 |
#include <sys/types.h> |
32 | 30 |
#include <sys/socket.h> |
... | ... |
@@ -34,6 +32,7 @@ |
34 | 34 |
#include <netdb.h> |
35 | 35 |
#include <unistd.h> |
36 | 36 |
#include <time.h> |
37 |
+#include <netdb.h> |
|
37 | 38 |
|
38 | 39 |
#include "shared/cfgparser.h" |
39 | 40 |
#include "shared/output.h" |
... | ... |
@@ -45,13 +44,13 @@ |
45 | 45 |
#define SETGAI(k, v) {(k)->gai = (void *)(v);} while(0) |
46 | 46 |
#define FREESRV(k) { if((k).gai) freeaddrinfo((k).gai); else if((k).server) free((k).server); } while(0) |
47 | 47 |
#else |
48 |
-#include <netdb.h> |
|
49 | 48 |
#define SETGAI |
50 | 49 |
#define FREESRV(k) { if ((k).server) free((k).server); } while(0) |
51 | 50 |
#endif |
52 | 51 |
|
53 | 52 |
struct CPOOL *cp = NULL; |
54 | 53 |
|
54 |
+ |
|
55 | 55 |
static int cpool_addunix(char *path) { |
56 | 56 |
struct sockaddr_un *srv; |
57 | 57 |
struct CP_ENTRY *cpe = &cp->pool[cp->entries-1]; |
... | ... |
@@ -293,23 +292,27 @@ void cpool_free(void) { |
293 | 293 |
} |
294 | 294 |
|
295 | 295 |
|
296 |
-struct CP_ENTRY *cpool_get_rand(void) { |
|
296 |
+struct CP_ENTRY *cpool_get_rand(int *s) { |
|
297 | 297 |
unsigned int start, i; |
298 | 298 |
struct CP_ENTRY *cpe; |
299 | 299 |
|
300 |
- if(!cp->alive) { |
|
301 |
- logg("!No sockets are alive. Probe forced...\n"); |
|
302 |
- /* FIXME: yeah, actually do force smthng here */ |
|
303 |
- return NULL; |
|
304 |
- } |
|
305 |
- start = rand() % cp->entries; |
|
306 |
- for(i=0; i<cp->entries; i++) { |
|
307 |
- cpe = &cp->pool[(i+start) % cp->entries]; |
|
308 |
- if(cpe->dead) continue; |
|
309 |
- if(cpe->local && cp->local_cpe && !cp->local_cpe->dead) |
|
310 |
- return cp->local_cpe; |
|
311 |
- return cpe; |
|
300 |
+ if(cp->alive) { |
|
301 |
+ start = rand() % cp->entries; |
|
302 |
+ for(i=0; i<cp->entries; i++) { |
|
303 |
+ cpe = &cp->pool[(i+start) % cp->entries]; |
|
304 |
+ if(cpe->dead) continue; |
|
305 |
+ if(cpe->local && cp->local_cpe && !cp->local_cpe->dead) |
|
306 |
+ cpe = cp->local_cpe; |
|
307 |
+ if((*s = nc_connect_entry(cpe)) == -1) { |
|
308 |
+ cpe->dead = 1; |
|
309 |
+ cp->alive--; /* FIXME mutex */ |
|
310 |
+ continue; |
|
311 |
+ } |
|
312 |
+ return cpe; |
|
313 |
+ } |
|
312 | 314 |
} |
315 |
+ logg("!No sockets are alive. Probe forced...\n"); |
|
316 |
+ /* FIXME: yeah, actually do force smthng here */ |
|
313 | 317 |
return NULL; |
314 | 318 |
} |
315 | 319 |
|
... | ... |
@@ -33,6 +33,7 @@ |
33 | 33 |
#include <sys/select.h> |
34 | 34 |
#include <time.h> |
35 | 35 |
#include <errno.h> |
36 |
+#include <netdb.h> |
|
36 | 37 |
|
37 | 38 |
#include "shared/output.h" |
38 | 39 |
#include "netcode.h" |
... | ... |
@@ -265,15 +266,10 @@ void nc_ping_entry(struct CP_ENTRY *cpe) { |
265 | 265 |
|
266 | 266 |
|
267 | 267 |
int nc_connect_rand(int *main, int *alt, int *local) { |
268 |
- struct CP_ENTRY *cpe = cpool_get_rand(); |
|
268 |
+ struct CP_ENTRY *cpe = cpool_get_rand(main); |
|
269 | 269 |
|
270 |
- /* FIXME logic is broken here: |
|
271 |
- 1- we must not fail on the 1st dead socket but keep on trying |
|
272 |
- 2- we must not set *local unless we enforce local_cpe |
|
273 |
- */ |
|
274 | 270 |
if(!cpe) return 1; |
275 |
- *local = cpe->local; |
|
276 |
- if ((*main = nc_connect_entry(cpe)) == -1) return 1; /* FIXME : this should be delayed till eom if local */ |
|
271 |
+ *local = (cpe->server->sa_family == AF_UNIX); |
|
277 | 272 |
if(*local) { |
278 | 273 |
char tmpn[] = "/tmp/clamav-milter-XXXXXX"; |
279 | 274 |
if((*alt = mkstemp(tmpn))==-1) { /* FIXME */ |
... | ... |
@@ -325,6 +321,134 @@ int nc_connect_rand(int *main, int *alt, int *local) { |
325 | 325 |
return 0; |
326 | 326 |
} |
327 | 327 |
|
328 |
+ |
|
329 |
+ |
|
330 |
+enum { |
|
331 |
+ NON_SMTP, |
|
332 |
+ INET_HOST, |
|
333 |
+ INET6_HOST |
|
334 |
+}; |
|
335 |
+ |
|
336 |
+int resolve(char *name, uint32_t *family, uint32_t *host) { |
|
337 |
+ struct addrinfo hints, *res; |
|
338 |
+ |
|
339 |
+ if(!strcasecmp("local", name)) { |
|
340 |
+ *family = NON_SMTP; |
|
341 |
+ return 0; |
|
342 |
+ } |
|
343 |
+ |
|
344 |
+ memset(&hints, 0, sizeof(hints)); |
|
345 |
+#ifdef SUPPORT_IPv6 |
|
346 |
+ hints.ai_family = AF_UNSPEC; |
|
347 |
+#else |
|
348 |
+ hints.ai_family = AF_INET; |
|
349 |
+#endif |
|
350 |
+ hints.ai_socktype = SOCK_STREAM; |
|
351 |
+ |
|
352 |
+ if(getaddrinfo(name, NULL, &hints, &res)) { |
|
353 |
+ logg("!Can't resolve LocalNet hostname %s\n", name); |
|
354 |
+ return 1; |
|
355 |
+ } |
|
356 |
+ if(res->ai_addrlen == sizeof(struct sockaddr_in) && res->ai_addr->sa_family == AF_INET) { |
|
357 |
+ struct sockaddr_in *sa = (struct sockaddr_in *)res->ai_addr; |
|
358 |
+ |
|
359 |
+ *family = INET_HOST; |
|
360 |
+ host[0] = htonl(sa->sin_addr.s_addr); |
|
361 |
+ host[1] = host[2] = host[3] = 0; |
|
362 |
+ } else if(res->ai_addrlen == sizeof(struct sockaddr_in6) && res->ai_addr->sa_family == AF_INET6) { |
|
363 |
+ struct sockaddr_in6 *sa = (struct sockaddr_in6 *)res->ai_addr; |
|
364 |
+ unsigned int i, j; |
|
365 |
+ uint32_t u = 0; |
|
366 |
+ |
|
367 |
+ *family = INET6_HOST; |
|
368 |
+ for(i=0, j=0; i<16; i++) { |
|
369 |
+ u += (sa->sin6_addr.s6_addr[i] << (8*j)); |
|
370 |
+ if(++j == 4) { |
|
371 |
+ host[3-(i>>2)] = u; |
|
372 |
+ j = u = 0; |
|
373 |
+ } |
|
374 |
+ } |
|
375 |
+ } else { |
|
376 |
+ logg("!Unsupported address type for LocalNet %s\n", name); |
|
377 |
+ freeaddrinfo(res); |
|
378 |
+ return 1; |
|
379 |
+ } |
|
380 |
+ freeaddrinfo(res); |
|
381 |
+ return 0; |
|
382 |
+} |
|
383 |
+ |
|
384 |
+ |
|
385 |
+struct LOCALNET { |
|
386 |
+ struct LOCALNET *next; |
|
387 |
+ uint32_t basehost[4]; |
|
388 |
+ uint32_t mask[4]; |
|
389 |
+ uint32_t family; |
|
390 |
+}; |
|
391 |
+ |
|
392 |
+ |
|
393 |
+void applymask(uint32_t *host, uint32_t *mask) { |
|
394 |
+ host[0] &= mask[0]; |
|
395 |
+ host[1] &= mask[1]; |
|
396 |
+ host[2] &= mask[2]; |
|
397 |
+ host[3] &= mask[3]; |
|
398 |
+} |
|
399 |
+ |
|
400 |
+ |
|
401 |
+struct LOCALNET* localnet(char *name, char *mask) { |
|
402 |
+ struct LOCALNET *l = (struct LOCALNET *)malloc(sizeof(*l)); |
|
403 |
+ uint32_t nmask; |
|
404 |
+ unsigned int i; |
|
405 |
+ |
|
406 |
+ if(!l) { |
|
407 |
+ logg("!Out of memory while resolving LocalNet\n"); |
|
408 |
+ return NULL; |
|
409 |
+ } |
|
410 |
+ |
|
411 |
+ l->next = NULL; |
|
412 |
+ if(resolve(name, &l->family, l->basehost)) { |
|
413 |
+ free(l); |
|
414 |
+ return NULL; |
|
415 |
+ } |
|
416 |
+ |
|
417 |
+ if(l->family == NON_SMTP) { |
|
418 |
+ l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0; |
|
419 |
+ l->basehost[0] = l->basehost[1] = l->basehost[2] = l->basehost[3] = 0; |
|
420 |
+ return l; |
|
421 |
+ } |
|
422 |
+ if(!*mask) nmask = 32; |
|
423 |
+ else nmask = atoi(mask); |
|
424 |
+ |
|
425 |
+ if((l->family == INET6_HOST && nmask > 128) || (l->family == INET_HOST && nmask > 32)) { |
|
426 |
+ logg("!Bad netmask '/%s' for LocalNet %s\n", mask, name); |
|
427 |
+ free(l); |
|
428 |
+ return NULL; |
|
429 |
+ } |
|
430 |
+ l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0; |
|
431 |
+ for(i=0; i<nmask; i++) |
|
432 |
+ l->mask[i>>5] |= 1<<(i&0x1f); |
|
433 |
+ applymask(l->basehost, l->mask); |
|
434 |
+ return l; |
|
435 |
+} |
|
436 |
+ |
|
437 |
+ |
|
438 |
+int belongto(struct LOCALNET* l, char *name) { |
|
439 |
+ uint32_t host[4], family; |
|
440 |
+ |
|
441 |
+ if(resolve(name, &family, host)) { |
|
442 |
+ logg("^Cannot resolv %s\n", name); |
|
443 |
+ return 0; |
|
444 |
+ } |
|
445 |
+ while(l) { |
|
446 |
+ if ( |
|
447 |
+ (l->family == family) && |
|
448 |
+ (l->basehost[0] == (host[0] & l->mask[0])) && (l->basehost[1] == (host[1] & l->mask[1])) && |
|
449 |
+ (l->basehost[2] == (host[2] & l->mask[2])) && (l->basehost[3] == (host[3] & l->mask[3])) |
|
450 |
+ ) return 1; |
|
451 |
+ l=l->next; |
|
452 |
+ } |
|
453 |
+ return 0; |
|
454 |
+} |
|
455 |
+ |
|
328 | 456 |
/* |
329 | 457 |
* Local Variables: |
330 | 458 |
* mode: c |
... | ... |
@@ -22,7 +22,7 @@ Example |
22 | 22 |
|
23 | 23 |
# Remove stale socket after unclean shutdown. |
24 | 24 |
# Default: yes |
25 |
-#FixStaleSocket yes |
|
25 |
+##FixStaleSocket yes |
|
26 | 26 |
|
27 | 27 |
# Maximum number of threads running at the same time. |
28 | 28 |
# Default: 10 |
... | ... |
@@ -164,3 +164,49 @@ Example |
164 | 164 |
#ScanPE |
165 | 165 |
#TemporaryDirectory |
166 | 166 |
|
167 |
+ |
|
168 |
+#Todo |
|
169 |
+#-C --chroot |
|
170 |
+#-D --debug |
|
171 |
+#-i --pidfile |
|
172 |
+#-I --ignore |
|
173 |
+#-W --whitelist-file |
|
174 |
+ |
|
175 |
+#Deprecated switches |
|
176 |
+#-a --from |
|
177 |
+#-H --headers |
|
178 |
+#-x --debug-level |
|
179 |
+#-b --bounce |
|
180 |
+#-B --broadcast |
|
181 |
+#-f --force-scan |
|
182 |
+#-e --external |
|
183 |
+#-k --blacklist-time |
|
184 |
+#-K --dont-blacklist |
|
185 |
+#-l --local |
|
186 |
+#-M --freshclam-monitor |
|
187 |
+#-o --outgoing |
|
188 |
+#-p --postmaster |
|
189 |
+#-P --postmaster-only |
|
190 |
+#-q --quiet |
|
191 |
+#-r --report-phish |
|
192 |
+#-R --report-phish-false-positives |
|
193 |
+#-s --sign |
|
194 |
+#-F --signature-file |
|
195 |
+#-m --max-children |
|
196 |
+#--dont-wait |
|
197 |
+#--dont-sanitise |
|
198 |
+#-t --template-file |
|
199 |
+#--template-headers |
|
200 |
+#-T --timeout |
|
201 |
+#-L --detect-forged-local-address |
|
202 |
+#--sendmail-cf |
|
203 |
+#--black-hole-mode |
|
204 |
+#--server |
|
205 |
+ |
|
206 |
+#Reworked |
|
207 |
+#-A --advisory |
|
208 |
+#-d --dont-scan-on-error |
|
209 |
+#-n --noxheader |
|
210 |
+#-N --noreject |
|
211 |
+#-Q --quarantine |
|
212 |
+#-U, --quarantine-dir |