Browse code

to me merged

git-svn: trunk@4532

aCaB authored on 2008/12/05 01:27:22
Showing 6 changed files
... ...
@@ -51,7 +51,7 @@ struct smfiDesc descr = {
51 51
     clamfi_connect,	/* connection info filter */
52 52
     NULL,		/* SMTP HELO command filter */
53 53
     clamfi_envfrom,	/* envelope sender filter */
54
-    NULL,		/* envelope recipient filter */
54
+    clamfi_envrcpt,	/* envelope recipient filter */
55 55
     clamfi_header,	/* header filter */
56 56
     NULL,		/* end of header */
57 57
     clamfi_body,	/* body block */
... ...
@@ -224,16 +224,10 @@ int main(int argc, char **argv) {
224 224
 	return 1;
225 225
     }
226 226
 
227
-    /* FIXME: find a place for these:
228
-     * maxthreads = cfgopt(copt, "MaxThreads")->numarg;
229
-     */
230
-
231 227
     if(cfgopt(copt, "AddHeader")->enabled) {
232 228
 	char myname[255];
233 229
 
234 230
 	if(!gethostname(myname, sizeof(myname))) {
235
-	    char mydomain[255];
236
-
237 231
 	    myname[sizeof(myname)-1] = '\0';
238 232
 	    snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s", get_version(), myname);
239 233
 	    xvirushdr[sizeof(xvirushdr)-1] = '\0';
... ...
@@ -14,6 +14,7 @@ sfsistat clamfi_eom(SMFICTX *ctx);
14 14
 sfsistat clamfi_header(SMFICTX *ctx, char *headerf, char *headerv);
15 15
 sfsistat clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr);
16 16
 sfsistat clamfi_envfrom(SMFICTX *ctx, char **argv);
17
+sfsistat clamfi_envrcpt(SMFICTX *ctx, char **argv);
17 18
 int init_actions(struct cfgstruct *copt);
18 19
 
19 20
 #endif
... ...
@@ -28,6 +28,7 @@
28 28
 #include <arpa/inet.h>
29 29
 #include <sys/types.h>
30 30
 #include <sys/socket.h>
31
+#include <sys/time.h>
31 32
 #include <sys/un.h>
32 33
 #include <netdb.h>
33 34
 #include <unistd.h>
... ...
@@ -43,8 +44,16 @@
43 43
 #define SETGAI(k, v) {(k)->gai = (void *)(v);} while(0)
44 44
 #define FREESRV(k) { if((k).gai) freeaddrinfo((k).gai); else if((k).server) free((k).server); } while(0)
45 45
 
46
-struct CPOOL *cp = NULL;
46
+#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
47
+#define _UNUSED_ __attribute__ ((__unused__))
48
+#else
49
+#define _UNUSED_
50
+#endif
47 51
 
52
+struct CPOOL *cp = NULL;
53
+static pthread_cond_t mon_cond = PTHREAD_COND_INITIALIZER;
54
+static int quitting = 1;
55
+static pthread_t probe_th;
48 56
 
49 57
 static int cpool_addunix(char *path) {
50 58
     struct sockaddr_un *srv;
... ...
@@ -132,15 +141,22 @@ int addslot(void) {
132 132
     cp->entries++;
133 133
     return 0;
134 134
 }
135
-    
135
+
136
+
137
+/* Probe strategy:
138
+- wake up every minute
139
+- probe alive if last check > 15 min
140
+- probe dead if (last check > 2 min || no clamd available)
141
+*/
136 142
 
137 143
 void cpool_probe(void) {
138 144
     unsigned int i, dead=0;
139 145
     struct CP_ENTRY *cpe = cp->pool;
140
-    time_t lastpoll = time(NULL) - 5*60;
146
+    time_t now = time(NULL);
141 147
 
142 148
     for(i=1; i<=cp->entries; i++) {
143
-	if(cpe->dead && lastpoll > cpe->last_poll) {
149
+	if((cpe->dead && (cpe->last_poll < now - 120 || !cp->alive)) || cpe->last_poll < now - 15*60*60) {
150
+	    cpe->last_poll = time(NULL);
144 151
 	    nc_ping_entry(cpe);
145 152
 	    logg("*Probe for slot %u returned: %s\n", i, cpe->dead ? "failed" : "success");
146 153
 	}
... ...
@@ -148,8 +164,29 @@ void cpool_probe(void) {
148 148
 	cpe++;
149 149
     }
150 150
     cp->alive = cp->entries - dead;
151
+
151 152
     if(!cp->alive)
152
-	logg("^No clamd server appears to be available, trying again in 5 minutes.\n");
153
+	logg("^No clamd server appears to be available\n");
154
+}
155
+
156
+
157
+void *cpool_mon(_UNUSED_ void *v) {
158
+    pthread_mutex_t conv;
159
+
160
+    pthread_mutex_init(&conv, NULL);
161
+    pthread_mutex_lock(&conv);
162
+
163
+    while(!quitting) {
164
+	struct timespec t;
165
+
166
+	cpool_probe();
167
+	t.tv_sec = time(NULL) + 60;
168
+	t.tv_nsec = 0;
169
+	pthread_cond_timedwait(&mon_cond, &conv, &t);
170
+    }
171
+    pthread_mutex_unlock(&conv);
172
+    pthread_mutex_destroy(&conv);
173
+    return NULL;
153 174
 }
154 175
 
155 176
 
... ...
@@ -196,13 +233,21 @@ void cpool_init(struct cfgstruct *copt) {
196 196
 	cpool_free();
197 197
 	return;
198 198
     }
199
-    cpool_probe();
200
-    srand(time(NULL)); /* FIXME: naive ? */
199
+    quitting = 0;
200
+    pthread_create(&probe_th, NULL, cpool_mon, NULL);
201
+    srand(time(NULL));
201 202
 }
202 203
 
203 204
 
204 205
 void cpool_free(void) {
205 206
     unsigned int i;
207
+
208
+    if(!quitting) {
209
+	logg("*Killing the monitor and stopping\n");
210
+	pthread_cond_signal(&mon_cond);
211
+	pthread_join(probe_th, NULL);
212
+    }
213
+
206 214
     if(cp) {
207 215
 	if(cp->pool) {
208 216
 	    for(i=0; i<cp->entries; i++)
... ...
@@ -228,14 +273,12 @@ struct CP_ENTRY *cpool_get_rand(int *s) {
228 228
 		cpe = cp->local_cpe;
229 229
 	    if((*s = nc_connect_entry(cpe)) == -1) {
230 230
 		cpe->dead = 1;
231
-		cp->alive--; /* FIXME mutex */
232 231
 		continue;
233 232
 	    }
234 233
 	    return cpe;
235 234
 	}
236 235
     }
237
-    logg("!No sockets are alive. Probe forced...\n");
238
-    /* FIXME: yeah, actually do force smthng here */
236
+    pthread_cond_signal(&mon_cond);
239 237
     return NULL;
240 238
 }
241 239
 
... ...
@@ -13,15 +13,13 @@
13 13
 #include "shared/cfgparser.h"
14 14
 
15 15
 struct CP_ENTRY {
16
+    struct sockaddr *server;
17
+    void *gai;
18
+    socklen_t socklen;
19
+    time_t last_poll;
16 20
     uint8_t type;
17 21
     uint8_t dead;
18 22
     uint8_t local;
19
-    time_t last_poll;
20
-    struct sockaddr *server;
21
-    socklen_t socklen;
22
-#ifdef HAVE_GETADDRINFO
23
-    void *gai;
24
-#endif
25 23
 };
26 24
 
27 25
 struct CPOOL {
... ...
@@ -99,7 +99,7 @@ int nc_connect(int s, struct CP_ENTRY *cpe) {
99 99
     if (!res) return 0;
100 100
     if (errno != EINPROGRESS) {
101 101
 	strerror_r(errno, er, sizeof(er));
102
-	logg("!connect failed: %s\n", er);
102
+	logg("*connect failed: %s\n", er);
103 103
 	close(s);
104 104
 	return -1;
105 105
     }
... ...
@@ -122,12 +122,12 @@ int nc_connect(int s, struct CP_ENTRY *cpe) {
122 122
 		tv.tv_usec = 0;
123 123
 		continue;
124 124
 	    }
125
-	    logg("!Failed to establish a connection to clamd\n");
125
+	    logg("*Failed to establish a connection to clamd\n");
126 126
 	    close(s);
127 127
 	    return -1;
128 128
 	}
129 129
 	if (getsockopt(s, SOL_SOCKET, SO_ERROR, &s_err, &s_len) || s_err) {
130
-	    logg("!Failed to establish a connection to clamd\n");
130
+	    logg("*Failed to establish a connection to clamd\n");
131 131
 	    close(s);
132 132
 	    return -1;
133 133
 	}
... ...
@@ -219,49 +219,56 @@ int nc_sendmsg(int s, int fd) {
219 219
 }
220 220
 
221 221
 char *nc_recv(int s) {
222
-    char buf[BUFSIZ], *ret=NULL;
223
-    time_t timeout = time(NULL) + readtimeout;
222
+    char buf[128], *ret=NULL;
223
+    time_t now, timeout = time(NULL) + readtimeout;
224 224
     struct timeval tv;
225 225
     fd_set fds;
226 226
     int res;
227
+    unsigned int len = 0;
227 228
 
228
-    tv.tv_sec = readtimeout;
229
-    tv.tv_usec = 0;
230
-
231
-    FD_ZERO(&fds);
232
-    FD_SET(s, &fds);
233 229
     while(1) {
230
+	now = time(NULL);
231
+	if(now >= timeout) {
232
+	    logg("!Timed out while reading clamd reply\n");
233
+	    close(s);
234
+	    return NULL;
235
+	}
236
+	tv.tv_sec = timeout - now;
237
+	tv.tv_usec = 0;
238
+
239
+	FD_ZERO(&fds);
240
+	FD_SET(s, &fds);
241
+
234 242
 	res = select(s+1, &fds, NULL, NULL, &tv);
235 243
 	if(res<1) {
236
-	    time_t now;
244
+	    if (res != -1 || errno != EINTR)
245
+		timeout = 0;
246
+	    continue;
247
+	}
237 248
 
238
-	    if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) {
239
-		tv.tv_sec = timeout - now;
240
-		tv.tv_usec = 0;
241
-		continue;
242
-	    }
243
-	    logg("!Failed to read clamd reply\n");
249
+	res = recv(s, &buf[len], sizeof(buf) - len, 0);
250
+	if(res==-1) {
251
+	    char er[256];
252
+	    strerror_r(errno, er, sizeof(er));
253
+	    logg("!recv failed after successful select: %s\n", er);
254
+	    close(s);
255
+	    return NULL;
256
+	}
257
+	len += res;
258
+	if(len && buf[len-1] == '\n') break;
259
+	if(len >= sizeof(buf)) {
260
+	    logg("!Overlong reply from clamd\n");
244 261
 	    close(s);
245 262
 	    return NULL;
246 263
 	}
247
-	break;
248
-    }
249
-    /* FIXME: check for EOL@EObuf ? */
250
-    res = recv(s, buf, sizeof(buf), 0);
251
-    if (res==-1) {
252
-	char er[256];
253
-	strerror_r(errno, er, sizeof(er));
254
-	logg("!recv failed after successful select: %s\n", er);
255
-	close(s);
256
-	return NULL;
257 264
     }
258
-    if(!(ret = (char *)malloc(res+1))) {
259
-	logg("!malloc(%d) failed\n", res+1);
265
+    if(!(ret = (char *)malloc(len+1))) {
266
+	logg("!malloc(%d) failed\n", len+1);
260 267
 	close(s);
261 268
 	return NULL;
262 269
     }
263
-    memcpy(ret, buf, res);
264
-    ret[res]='\0';
270
+    memcpy(ret, buf, len);
271
+    ret[len]='\0';
265 272
     return ret;
266 273
 }
267 274
 
... ...
@@ -450,7 +457,7 @@ int islocalnet_name(char *name) {
450 450
 
451 451
     if(!lnet) return 0;
452 452
     if(resolve(name, &family, host)) {
453
-	logg("^Cannot resolv %s\n", name);
453
+	logg("*Cannot resolv %s\n", name);
454 454
 	return 0;
455 455
     }
456 456
     return islocalnet(family, host);
... ...
@@ -481,7 +488,6 @@ int islocalnet_sock(struct sockaddr *sa) {
481 481
 	    }
482 482
 	}
483 483
     } else return 0;
484
-
485 484
     return islocalnet(family, host);
486 485
 }
487 486
 
... ...
@@ -3,5 +3,5 @@
3 3
 
4 4
 int whitelist_init(const char *fname);
5 5
 void whitelist_free(void);
6
-
6
+int whitelisted(const char *addr, int from);
7 7
 #endif