| ... | ... |
@@ -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 |
|
| ... | ... |
@@ -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 |
| ... | ... |
@@ -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 |