git-svn: trunk@4523
aCaB authored on 2008/12/05 01:26:30... | ... |
@@ -197,6 +197,12 @@ int main(int argc, char **argv) { |
197 | 197 |
} |
198 | 198 |
#endif |
199 | 199 |
|
200 |
+ if(localnets_init(copt)) { |
|
201 |
+ logg_close(); |
|
202 |
+ freecfg(copt); |
|
203 |
+ return 1; |
|
204 |
+ } |
|
205 |
+ |
|
200 | 206 |
umask(0007); |
201 | 207 |
if(!(my_socket = cfgopt(copt, "MilterSocket")->strarg)) { |
202 | 208 |
logg("!Please configure the MilterSocket directive\n"); |
... | ... |
@@ -253,6 +259,7 @@ int main(int argc, char **argv) { |
253 | 253 |
|
254 | 254 |
logg_close(); |
255 | 255 |
cpool_free(); |
256 |
+ localnets_free(); |
|
256 | 257 |
return ret; |
257 | 258 |
} |
258 | 259 |
/* |
... | ... |
@@ -39,11 +39,28 @@ |
39 | 39 |
#include "netcode.h" |
40 | 40 |
|
41 | 41 |
|
42 |
+enum { |
|
43 |
+ NON_SMTP, |
|
44 |
+ INET_HOST, |
|
45 |
+ INET6_HOST |
|
46 |
+}; |
|
47 |
+ |
|
48 |
+struct LOCALNET { |
|
49 |
+ struct LOCALNET *next; |
|
50 |
+ /* most significant first */ |
|
51 |
+ uint32_t basehost[4]; |
|
52 |
+ uint32_t mask[4]; |
|
53 |
+ uint32_t family; |
|
54 |
+}; |
|
55 |
+ |
|
56 |
+struct LOCALNET *lnet = NULL; |
|
57 |
+ |
|
42 | 58 |
/* FIXME: for connect and send */ |
43 | 59 |
#define TIMEOUT 60 |
44 | 60 |
/* for recv */ |
45 | 61 |
long readtimeout; |
46 | 62 |
|
63 |
+ |
|
47 | 64 |
int nc_socket(struct CP_ENTRY *cpe) { |
48 | 65 |
int flags, s = socket(cpe->server->sa_family, SOCK_STREAM, 0); |
49 | 66 |
char er[256]; |
... | ... |
@@ -321,18 +338,11 @@ int nc_connect_rand(int *main, int *alt, int *local) { |
321 | 321 |
return 0; |
322 | 322 |
} |
323 | 323 |
|
324 |
- |
|
325 |
- |
|
326 |
-enum { |
|
327 |
- NON_SMTP, |
|
328 |
- INET_HOST, |
|
329 |
- INET6_HOST |
|
330 |
-}; |
|
331 |
- |
|
332 | 324 |
int resolve(char *name, uint32_t *family, uint32_t *host) { |
333 | 325 |
struct addrinfo hints, *res; |
334 | 326 |
|
335 | 327 |
if(!strcasecmp("local", name)) { |
328 |
+ /* l->basehost[0] = l->basehost[1] = l->basehost[2] = l->basehost[3] = 0; DONT BOTHER*/ |
|
336 | 329 |
*family = NON_SMTP; |
337 | 330 |
return 0; |
338 | 331 |
} |
... | ... |
@@ -354,7 +364,7 @@ int resolve(char *name, uint32_t *family, uint32_t *host) { |
354 | 354 |
|
355 | 355 |
*family = INET_HOST; |
356 | 356 |
host[0] = htonl(sa->sin_addr.s_addr); |
357 |
- host[1] = host[2] = host[3] = 0; |
|
357 |
+ /* host[1] = host[2] = host[3] = 0; DONT BOTHER*/ |
|
358 | 358 |
} else if(res->ai_addrlen == sizeof(struct sockaddr_in6) && res->ai_addr->sa_family == AF_INET6) { |
359 | 359 |
struct sockaddr_in6 *sa = (struct sockaddr_in6 *)res->ai_addr; |
360 | 360 |
unsigned int i, j; |
... | ... |
@@ -364,7 +374,7 @@ int resolve(char *name, uint32_t *family, uint32_t *host) { |
364 | 364 |
for(i=0, j=0; i<16; i++) { |
365 | 365 |
u += (sa->sin6_addr.s6_addr[i] << (8*j)); |
366 | 366 |
if(++j == 4) { |
367 |
- host[3-(i>>2)] = u; |
|
367 |
+ host[i>>2] = u; |
|
368 | 368 |
j = u = 0; |
369 | 369 |
} |
370 | 370 |
} |
... | ... |
@@ -378,23 +388,7 @@ int resolve(char *name, uint32_t *family, uint32_t *host) { |
378 | 378 |
} |
379 | 379 |
|
380 | 380 |
|
381 |
-struct LOCALNET { |
|
382 |
- struct LOCALNET *next; |
|
383 |
- uint32_t basehost[4]; |
|
384 |
- uint32_t mask[4]; |
|
385 |
- uint32_t family; |
|
386 |
-}; |
|
387 |
- |
|
388 |
- |
|
389 |
-void applymask(uint32_t *host, uint32_t *mask) { |
|
390 |
- host[0] &= mask[0]; |
|
391 |
- host[1] &= mask[1]; |
|
392 |
- host[2] &= mask[2]; |
|
393 |
- host[3] &= mask[3]; |
|
394 |
-} |
|
395 |
- |
|
396 |
- |
|
397 |
-struct LOCALNET* localnet(char *name, char *mask) { |
|
381 |
+struct LOCALNET *localnet(char *name, char *mask) { |
|
398 | 382 |
struct LOCALNET *l = (struct LOCALNET *)malloc(sizeof(*l)); |
399 | 383 |
uint32_t nmask; |
400 | 384 |
unsigned int i; |
... | ... |
@@ -404,18 +398,17 @@ struct LOCALNET* localnet(char *name, char *mask) { |
404 | 404 |
return NULL; |
405 | 405 |
} |
406 | 406 |
|
407 |
- l->next = NULL; |
|
408 | 407 |
if(resolve(name, &l->family, l->basehost)) { |
409 | 408 |
free(l); |
410 | 409 |
return NULL; |
411 | 410 |
} |
412 | 411 |
|
413 | 412 |
if(l->family == NON_SMTP) { |
414 |
- l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0; |
|
415 |
- l->basehost[0] = l->basehost[1] = l->basehost[2] = l->basehost[3] = 0; |
|
413 |
+ l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0x0; |
|
416 | 414 |
return l; |
417 | 415 |
} |
418 |
- if(!*mask) nmask = 32; |
|
416 |
+ |
|
417 |
+ if(!mask || !*mask) nmask = 32 + 96*(l->family == INET6_HOST); |
|
419 | 418 |
else nmask = atoi(mask); |
420 | 419 |
|
421 | 420 |
if((l->family == INET6_HOST && nmask > 128) || (l->family == INET_HOST && nmask > 32)) { |
... | ... |
@@ -423,32 +416,74 @@ struct LOCALNET* localnet(char *name, char *mask) { |
423 | 423 |
free(l); |
424 | 424 |
return NULL; |
425 | 425 |
} |
426 |
+ |
|
426 | 427 |
l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0; |
427 | 428 |
for(i=0; i<nmask; i++) |
428 |
- l->mask[i>>5] |= 1<<(i&0x1f); |
|
429 |
- applymask(l->basehost, l->mask); |
|
429 |
+ l->mask[i>>5] |= 1<<(31-(i & 31)); |
|
430 |
+ |
|
431 |
+ l->basehost[0] &= l->mask[0]; |
|
432 |
+ l->basehost[1] &= l->mask[1]; |
|
433 |
+ l->basehost[2] &= l->mask[2]; |
|
434 |
+ l->basehost[3] &= l->mask[3]; |
|
435 |
+ |
|
430 | 436 |
return l; |
431 | 437 |
} |
432 | 438 |
|
433 | 439 |
|
434 |
-int belongto(struct LOCALNET* l, char *name) { |
|
440 |
+int islocalnet(char *name) { |
|
435 | 441 |
uint32_t host[4], family; |
442 |
+ struct LOCALNET* l = lnet; |
|
436 | 443 |
|
444 |
+ if(!l) return 0; |
|
437 | 445 |
if(resolve(name, &family, host)) { |
438 | 446 |
logg("^Cannot resolv %s\n", name); |
439 | 447 |
return 0; |
440 | 448 |
} |
441 | 449 |
while(l) { |
442 |
- if ( |
|
443 |
- (l->family == family) && |
|
444 |
- (l->basehost[0] == (host[0] & l->mask[0])) && (l->basehost[1] == (host[1] & l->mask[1])) && |
|
445 |
- (l->basehost[2] == (host[2] & l->mask[2])) && (l->basehost[3] == (host[3] & l->mask[3])) |
|
446 |
- ) return 1; |
|
450 |
+ if( |
|
451 |
+ (l->family == family) && |
|
452 |
+ (l->basehost[0] == (host[0] & l->mask[0])) && (l->basehost[1] == (host[1] & l->mask[1])) && |
|
453 |
+ (l->basehost[2] == (host[2] & l->mask[2])) && (l->basehost[3] == (host[3] & l->mask[3])) |
|
454 |
+ ) return 1; |
|
447 | 455 |
l=l->next; |
448 | 456 |
} |
449 | 457 |
return 0; |
450 | 458 |
} |
451 | 459 |
|
460 |
+void localnets_free(void) { |
|
461 |
+ while(lnet) { |
|
462 |
+ struct LOCALNET *l = lnet->next; |
|
463 |
+ free(lnet); |
|
464 |
+ lnet = l; |
|
465 |
+ } |
|
466 |
+} |
|
467 |
+ |
|
468 |
+int localnets_init(struct cfgstruct *copt) { |
|
469 |
+ const struct cfgstruct *cpt; |
|
470 |
+ |
|
471 |
+ if((cpt = cfgopt(copt, "LocalNet"))->enabled) { |
|
472 |
+ while(cpt) { |
|
473 |
+ char *lnet = cpt->strarg; |
|
474 |
+ struct LOCALNET *l; |
|
475 |
+ char *mask = strrchr(lnet, '/'); |
|
476 |
+ |
|
477 |
+ if(mask) { |
|
478 |
+ *mask='\0'; |
|
479 |
+ mask++; |
|
480 |
+ } |
|
481 |
+ |
|
482 |
+ if((l = localnet(lnet, mask)) == NULL) { |
|
483 |
+ localnets_free(); |
|
484 |
+ return 1; |
|
485 |
+ } |
|
486 |
+ l->next = lnet; |
|
487 |
+ lnet = l; |
|
488 |
+ cpt = (struct cfgstruct *) cpt->nextarg; |
|
489 |
+ } |
|
490 |
+ } |
|
491 |
+ return 0; |
|
492 |
+} |
|
493 |
+ |
|
452 | 494 |
/* |
453 | 495 |
* Local Variables: |
454 | 496 |
* mode: c |
... | ... |
@@ -1,6 +1,7 @@ |
1 | 1 |
#ifndef _NETCODE_H |
2 | 2 |
#define _NETCODE_H |
3 | 3 |
|
4 |
+#include "shared/cfgparser.h" |
|
4 | 5 |
#include "connpool.h" |
5 | 6 |
|
6 | 7 |
void nc_ping_entry(struct CP_ENTRY *cpe); |
... | ... |
@@ -9,6 +10,9 @@ int nc_send(int s, const void *buf, size_t len); |
9 | 9 |
char *nc_recv(int s); |
10 | 10 |
int nc_sendmsg(int s, int fd); |
11 | 11 |
int nc_connect_entry(struct CP_ENTRY *cpe); |
12 |
+int localnets_init(struct cfgstruct *copt); |
|
13 |
+void localnets_free(void); |
|
14 |
+int islocalnet(char *name); |
|
12 | 15 |
|
13 | 16 |
extern long readtimeout; |
14 | 17 |
|
... | ... |
@@ -77,6 +77,20 @@ Example |
77 | 77 |
|
78 | 78 |
|
79 | 79 |
## |
80 |
+## Exclusions |
|
81 |
+## |
|
82 |
+ |
|
83 |
+# Messages originating from these hosts/networks will not be scanned |
|
84 |
+# This option takes a host(name)/mask pair in CIRD notation and can be |
|
85 |
+# repeated several times. If "/mask" is omitted, a host is assumed. |
|
86 |
+# To specify a locally orignated, non-smtp, email use the keyword "local" |
|
87 |
+# Default: unset |
|
88 |
+#LocalNet local |
|
89 |
+#LocalNet 192.168.0.0/24 |
|
90 |
+#LocalNet 1111:2222:3333::/48 |
|
91 |
+ |
|
92 |
+ |
|
93 |
+## |
|
80 | 94 |
## Logging options |
81 | 95 |
## |
82 | 96 |
|
... | ... |
@@ -146,6 +146,7 @@ struct cfgoption cfg_options[] = { |
146 | 146 |
/* Milter specific options */ |
147 | 147 |
{"ClamdSocket", OPT_QUOTESTR, -1, NULL, 1, OPT_MILTER}, |
148 | 148 |
{"MilterSocket", OPT_QUOTESTR, -1, NULL, 1, OPT_MILTER}, |
149 |
+ {"LocalNet", OPT_QUOTESTR, -1, NULL, 1, OPT_MILTER}, |
|
149 | 150 |
|
150 | 151 |
/* Deprecated milter options */ |
151 | 152 |
{"ArchiveBlockEncrypted", OPT_BOOL, 0, NULL, 0, OPT_MILTER | OPT_DEPRECATED}, |