Browse code

LocalNet parser complete

git-svn: trunk@4523

aCaB authored on 2008/12/05 01:26:30
Showing 5 changed files
... ...
@@ -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},