Browse code

LocalNet

git-svn: trunk@4522

aCaB authored on 2008/12/05 01:26:24
Showing 5 changed files
... ...
@@ -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
 
... ...
@@ -32,7 +32,7 @@ struct CPOOL {
32 32
 
33 33
 void cpool_init(struct cfgstruct *copt);
34 34
 void cpool_free(void);
35
-struct CP_ENTRY *cpool_get_rand(void);
35
+struct CP_ENTRY *cpool_get_rand(int *s);
36 36
 
37 37
 extern struct CPOOL *cp;
38 38
 
... ...
@@ -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
... ...
@@ -8,6 +8,7 @@ int nc_connect_rand(int *main, int *alt, int *local);
8 8
 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
+int nc_connect_entry(struct CP_ENTRY *cpe);
11 12
 
12 13
 extern long readtimeout;
13 14
 
... ...
@@ -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