Browse code

add LocalIPAddress/--local-address

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@1416 77e5149b-7576-45b1-b177-96237e5ba77b

Tomasz Kojm authored on 2005/03/21 10:27:50
Showing 9 changed files
... ...
@@ -1,3 +1,7 @@
1
+Mon Mar 21 02:24:33 CET 2005 (tk)
2
+---------------------------------
3
+  * freshclam: add LocalIPAddress/--local-address (patch by Thomas Lamy)
4
+
1 5
 Mon Mar 21 01:13:41 CET 2005 (tk)
2 6
 ---------------------------------
3 7
   * libclamav/pe.c: add W32.Magistr.A/B detection
... ...
@@ -55,6 +55,9 @@ Check #n times per day for a new database. #n must be between 1 and 50.
55 55
 \fB\-\-daemon\-notify=/path/to/clamd.conf\fR
56 56
 Notify the daemon about the new database. By default it reads a hardcoded config file but you can use an another one. Both local and TCP sockets are supported.
57 57
 .TP 
58
+\fB\-a IP, \-\-local-address=IP\fR
59
+Use (local) IP for HTTP downloads. Useful for multi-homed systems. If binding fails for whatever reason, a warning is issued and freshclam behaves like without this flag.
60
+.TP 
58 61
 \fB\-\-on\-error\-execute=COMMAND\fR
59 62
 Execute COMMAND if error occured. Remeber, that virus database freshness is the most important thing in anti\-virus system. With this option freshclam can alert you (eg. send SMS) when something is going wrong.
60 63
 .TP 
... ...
@@ -92,6 +92,11 @@ Proxy usage is authenticated through given username and password.
92 92
 .br .
93 93
 Default: no proxy authentication
94 94
 .TP 
95
+\fBLocalIPAddress IP\fR
96
+Use \fBIP\fR as client address for downloading databases. Useful for multi homed systems.
97
+.br .
98
+Default: Use OS\'es default outgoing IP address.
99
+.TP 
95 100
 \fBNotifyClamd \[STRING\]\fR
96 101
 Notify a running clamd(8) to reload it\'s database after a download has occured. Optionally a clamd.conf(5) file location may be given to tell freshclam(1) how to communicate with clamd(8).
97 102
 .br .
... ...
@@ -75,6 +75,11 @@ DatabaseMirror database.clamav.net
75 75
 #HTTPProxyUsername myusername
76 76
 #HTTPProxyPassword mypass
77 77
 
78
+# Use aaa.bbb.ccc.ddd as client address for downloading databases. Useful for multi-
79
+# homed systems.
80
+# Default: Use OS'es default outgoing IP address.
81
+#LocalIPAddress aaa.bbb.ccc.ddd
82
+
78 83
 # Send the RELOAD command to clamd.
79 84
 # Default: disabled
80 85
 #NotifyClamd
... ...
@@ -445,6 +445,7 @@ void help(void)
445 445
 #ifdef BUILD_CLAMD
446 446
     mprintf("    --daemon-notify[=/path/clamd.conf]   send RELOAD command to clamd\n");
447 447
 #endif
448
+    mprintf("    --local-address=IP   -a IP           bind to IP for HTTP downloads\n");
448 449
     mprintf("    --on-update-execute=COMMAND          execute COMMAND after successful update\n");
449 450
     mprintf("    --on-error-execute=COMMAND           execute COMMAND if errors occured\n");
450 451
 
... ...
@@ -38,6 +38,7 @@
38 38
 #include <fcntl.h>
39 39
 #include <sys/stat.h>
40 40
 #include <clamav.h>
41
+#include <errno.h>
41 42
 
42 43
 #include "options.h"
43 44
 #include "defaults.h"
... ...
@@ -56,6 +57,7 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c
56 56
 	int ret, updated = 0, signo = 0, ttl = -1;
57 57
 	char ipaddr[16], *dnsreply = NULL, *pt;
58 58
 	struct cfgstruct *cpt;
59
+	char *localip = NULL;
59 60
 #ifdef HAVE_RESOLV_H
60 61
 	const char *dnsdbinfo;
61 62
 #endif
... ...
@@ -131,9 +133,15 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c
131 131
     }
132 132
 #endif /* HAVE_RESOLV_H */
133 133
 
134
+    if(optl(opt, "localip")) {
135
+        localip = getargl(opt, "localip");
136
+    } else if((cpt = cfgopt(copt, "LocalIPAddress"))) {
137
+	localip = cpt->strarg;
138
+    }
139
+
134 140
     memset(ipaddr, 0, sizeof(ipaddr));
135 141
 
136
-    if((ret = downloaddb(DB1NAME, "main.cvd", hostname, ipaddr, &signo, copt, dnsreply)) > 50) {
142
+    if((ret = downloaddb(DB1NAME, "main.cvd", hostname, ipaddr, &signo, copt, dnsreply, localip)) > 50) {
137 143
 	if(dnsreply)
138 144
 	    free(dnsreply);
139 145
 
... ...
@@ -143,7 +151,7 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c
143 143
 	updated = 1;
144 144
 
145 145
     /* if ipaddr[0] != 0 it will use it to connect to the web host */
146
-    if((ret = downloaddb(DB2NAME, "daily.cvd", hostname, ipaddr, &signo, copt, dnsreply)) > 50) {
146
+    if((ret = downloaddb(DB2NAME, "daily.cvd", hostname, ipaddr, &signo, copt, dnsreply, localip)) > 50) {
147 147
 	if(dnsreply)
148 148
 	    free(dnsreply);
149 149
 
... ...
@@ -202,7 +210,7 @@ static int isnumb(const char *str)
202 202
     return 1;
203 203
 }
204 204
 
205
-int downloaddb(const char *localname, const char *remotename, const char *hostname, char *ip, int *signo, const struct cfgstruct *copt, const char *dnsreply)
205
+int downloaddb(const char *localname, const char *remotename, const char *hostname, char *ip, int *signo, const struct cfgstruct *copt, const char *dnsreply, char *localip)
206 206
 {
207 207
 	struct cl_cvd *current, *remote;
208 208
 	struct cfgstruct *cpt;
... ...
@@ -271,9 +279,9 @@ int downloaddb(const char *localname, const char *remotename, const char *hostna
271 271
 
272 272
     if(!nodb && dbver == -1) {
273 273
 	if(ip[0]) /* use ip to connect */
274
-	    hostfd = wwwconnect(ip, proxy, port, ipaddr);
274
+	    hostfd = wwwconnect(ip, proxy, port, ipaddr, localip);
275 275
 	else
276
-	    hostfd = wwwconnect(hostname, proxy, port, ipaddr);
276
+	    hostfd = wwwconnect(hostname, proxy, port, ipaddr, localip);
277 277
 
278 278
 	if(hostfd < 0) {
279 279
             mprintf("@No servers could be reached. Giving up\n");
... ...
@@ -335,9 +343,9 @@ int downloaddb(const char *localname, const char *remotename, const char *hostna
335 335
 
336 336
     if(ipaddr[0]) {
337 337
 	/* use ipaddr in order to connect to the same mirror */
338
-	hostfd = wwwconnect(ipaddr, proxy, port, NULL);
338
+	hostfd = wwwconnect(ipaddr, proxy, port, NULL, localip);
339 339
     } else {
340
-	hostfd = wwwconnect(hostname, proxy, port, ipaddr);
340
+	hostfd = wwwconnect(hostname, proxy, port, ipaddr, localip);
341 341
 	if(!ip[0])
342 342
 	    strcpy(ip, ipaddr);
343 343
     }
... ...
@@ -418,7 +426,7 @@ int downloaddb(const char *localname, const char *remotename, const char *hostna
418 418
 
419 419
 /* this function returns socket descriptor */
420 420
 /* proxy support finshed by njh@bandsman.co.uk */
421
-int wwwconnect(const char *server, const char *proxy, int pport, char *ip)
421
+int wwwconnect(const char *server, const char *proxy, int pport, char *ip, char *localip)
422 422
 {
423 423
 	int socketfd = -1, port, i;
424 424
 	struct sockaddr_in name;
... ...
@@ -426,13 +434,54 @@ int wwwconnect(const char *server, const char *proxy, int pport, char *ip)
426 426
 	char ipaddr[16];
427 427
 	unsigned char *ia;
428 428
 	const char *hostpt;
429
-
429
+	struct hostent *he = NULL;
430 430
 
431 431
     if(ip)
432 432
 	strcpy(ip, "???");
433 433
 
434 434
     name.sin_family = AF_INET;
435 435
 
436
+    if (localip) {
437
+	if ((he = gethostbyname(localip)) == NULL) {
438
+	    char *herr;
439
+	    switch(h_errno) {
440
+	        case HOST_NOT_FOUND:
441
+		    herr = "Host not found";
442
+		    break;
443
+
444
+		case NO_DATA:
445
+		    herr = "No IP address";
446
+		    break;
447
+
448
+		case NO_RECOVERY:
449
+		    herr = "Unrecoverable DNS error";
450
+		    break;
451
+
452
+		case TRY_AGAIN:
453
+		    herr = "Temporary DNS error";
454
+		    break;
455
+
456
+		default:
457
+		    herr = "Unknown error";
458
+		    break;
459
+	    }
460
+	    mprintf("!Could not resolve local ip address '%s': %s\n", localip, herr);
461
+	    mprintf("^Using standard local ip address and port for fetching.\n");
462
+	} else {
463
+	    struct sockaddr_in client;
464
+	    memset ((char *) &client, 0, sizeof(struct sockaddr_in));
465
+	    client.sin_family = AF_INET;
466
+	    client.sin_addr = *(struct in_addr *) he->h_addr_list[0];
467
+	    if (bind(socketfd, (struct sockaddr *) &client, sizeof(struct sockaddr_in)) != 0) {
468
+		mprintf("!Could not bind to local ip address '%s': %s\n", localip, strerror(errno));
469
+		mprintf("^Using default client ip.\n");
470
+	    } else {
471
+		ia = (unsigned char *) he->h_addr_list[0];
472
+		sprintf(ipaddr, "%u.%u.%u.%u", ia[0], ia[1], ia[2], ia[3]);
473
+		mprintf("*Using ip '%s' for fetching.\n", ipaddr);
474
+	    }
475
+	}
476
+    }
436 477
     if(proxy) {
437 478
 	hostpt = proxy;
438 479
 
... ...
@@ -457,7 +506,29 @@ int wwwconnect(const char *server, const char *proxy, int pport, char *ip)
457 457
     }
458 458
 
459 459
     if((host = gethostbyname(hostpt)) == NULL) {
460
-        mprintf("@Can't get information about %s host.\n", hostpt);
460
+	char *herr;
461
+	switch(h_errno) {
462
+	    case HOST_NOT_FOUND:
463
+		herr = "Host not found";
464
+		break;
465
+
466
+	    case NO_DATA:
467
+		herr = "No IP address";
468
+		break;
469
+
470
+	    case NO_RECOVERY:
471
+		herr = "Unrecoverable DNS error";
472
+		break;
473
+
474
+	    case TRY_AGAIN:
475
+		herr = "Temporary DNS error";
476
+		break;
477
+
478
+	    default:
479
+		herr = "Unknown error";
480
+		break;
481
+	}
482
+        mprintf("@Can't get information about %s: %s\n", hostpt, herr);
461 483
 	return -1;
462 484
     }
463 485
 
... ...
@@ -24,9 +24,9 @@
24 24
 
25 25
 int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, const char *hostname);
26 26
 
27
-int downloaddb(const char *localname, const char *remotename, const char *hostname, char *ip, int *signo, const struct cfgstruct *copt, const char *dnsreply);
27
+int downloaddb(const char *localname, const char *remotename, const char *hostname, char *ip, int *signo, const struct cfgstruct *copt, const char *dnsreply, char *localip);
28 28
 
29
-int wwwconnect(const char *server, const char *proxy, int pport, char *ip);
29
+int wwwconnect(const char *server, const char *proxy, int pport, char *remoteip, char *localip);
30 30
 
31 31
 struct cl_cvd *remote_cvdhead(const char *file, int socketfd, const char *hostname, const char *proxy, const char *user, const char *pass, int *ims);
32 32
 
... ...
@@ -38,7 +38,7 @@ int main(int argc, char **argv)
38 38
 	int ret, opt_index, i, len;
39 39
 	struct optstruct *opt;
40 40
 
41
-	const char *getopt_parameters = "hvdp:Vl:c:u:";
41
+	const char *getopt_parameters = "hvdp:Vl:c:u:a:";
42 42
 
43 43
 	static struct option long_options[] = {
44 44
 	    /* 
... ...
@@ -61,6 +61,7 @@ int main(int argc, char **argv)
61 61
 	    {"no-dns", 0, 0, 0},
62 62
 	    {"checks", 1, 0, 'c'},
63 63
 	    {"http-proxy", 1, 0, 0},
64
+	    {"client-address", 1, 0, 'a'},
64 65
 	    {"proxy-user", 1, 0, 0},
65 66
 	    {"daemon-notify", 2, 0, 0},
66 67
 	    {"on-update-execute", 1, 0, 0},
... ...
@@ -123,6 +123,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
123 123
 	    {"NotifyClamd", OPT_OPTARG}, /* freshclam */
124 124
 	    {"OnUpdateExecute", OPT_FULLSTR}, /* freshclam */
125 125
 	    {"OnErrorExecute", OPT_FULLSTR}, /* freshclam */
126
+	    {"LocalIPAddress", OPT_STR}, /* freshclam */
126 127
 	    {0, 0}
127 128
 	};
128 129