... | ... |
@@ -117,7 +117,8 @@ int main(int argc, char **argv) |
117 | 117 |
char *pua_cats = NULL, *pt; |
118 | 118 |
int ret, tcpsock = 0, localsock = 0, i, min_port, max_port; |
119 | 119 |
unsigned int sigs = 0; |
120 |
- int lsockets[2], nlsockets = 0; |
|
120 |
+ int *lsockets=NULL; |
|
121 |
+ unsigned int nlsockets = 0; |
|
121 | 122 |
unsigned int dboptions = 0; |
122 | 123 |
#ifdef C_LINUX |
123 | 124 |
STATBUF sb; |
... | ... |
@@ -537,15 +538,48 @@ int main(int argc, char **argv) |
537 | 537 |
} |
538 | 538 |
|
539 | 539 |
if(tcpsock) { |
540 |
- if ((lsockets[nlsockets] = tcpserver(opts)) == -1) { |
|
541 |
- ret = 1; |
|
542 |
- break; |
|
540 |
+ int *t; |
|
541 |
+ |
|
542 |
+ opt = optget(opts, "TCPAddr"); |
|
543 |
+ if (opt->enabled) { |
|
544 |
+ int breakout = 0; |
|
545 |
+ |
|
546 |
+ while (opt && opt->strarg) { |
|
547 |
+ char *ipaddr = (!strcmp(opt->strarg, "all") ? NULL : opt->strarg); |
|
548 |
+ |
|
549 |
+ if (tcpserver(&lsockets, &nlsockets, ipaddr, opts) == -1) { |
|
550 |
+ ret = 1; |
|
551 |
+ breakout = 1; |
|
552 |
+ break; |
|
553 |
+ } |
|
554 |
+ |
|
555 |
+ opt = opt->nextarg; |
|
556 |
+ } |
|
557 |
+ |
|
558 |
+ if (breakout) |
|
559 |
+ break; |
|
560 |
+ } else { |
|
561 |
+ if (tcpserver(&lsockets, &nlsockets, NULL, opts) == -1) { |
|
562 |
+ ret = 1; |
|
563 |
+ break; |
|
564 |
+ } |
|
543 | 565 |
} |
544 |
- nlsockets++; |
|
545 | 566 |
} |
546 | 567 |
#ifndef _WIN32 |
547 | 568 |
if(localsock) { |
569 |
+ int *t; |
|
548 | 570 |
mode_t sock_mode, umsk = umask(0777); /* socket is created with 000 to avoid races */ |
571 |
+ |
|
572 |
+ t = realloc(lsockets, sizeof(int) * (nlsockets + 1)); |
|
573 |
+ if (!(t)) { |
|
574 |
+ if ((lsockets)) |
|
575 |
+ free(lsockets); |
|
576 |
+ |
|
577 |
+ ret = 1; |
|
578 |
+ break; |
|
579 |
+ } |
|
580 |
+ lsockets = t; |
|
581 |
+ |
|
549 | 582 |
if ((lsockets[nlsockets] = localserver(opts)) == -1) { |
550 | 583 |
ret = 1; |
551 | 584 |
umask(umsk); |
... | ... |
@@ -46,50 +46,77 @@ |
46 | 46 |
#include "server.h" |
47 | 47 |
#include "tcpserver.h" |
48 | 48 |
|
49 |
-int tcpserver(const struct optstruct *opts) |
|
49 |
+int tcpserver(int **lsockets, unsigned int *nlsockets, char *ipaddr, const struct optstruct *opts) |
|
50 | 50 |
{ |
51 |
- struct sockaddr_in server; |
|
51 |
+ struct addrinfo hints, *info, *p; |
|
52 |
+ int *sockets; |
|
52 | 53 |
int sockfd, backlog; |
53 |
- char *estr; |
|
54 |
- int true = 1; |
|
54 |
+ int *t; |
|
55 |
+ char *estr, port[10]; |
|
56 |
+ int yes = 1; |
|
57 |
+ int res; |
|
55 | 58 |
|
56 |
- if (cfg_tcpsock(opts, &server, INADDR_ANY) == -1) { |
|
57 |
- logg("!TCP: Couldn't configure socket, check your configuration\n"); |
|
58 |
- return -1; |
|
59 |
- } |
|
59 |
+ sockets = *lsockets; |
|
60 | 60 |
|
61 |
- if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { |
|
62 |
- estr = strerror(errno); |
|
63 |
- logg("!TCP: socket() error: %s\n", estr); |
|
64 |
- return -1; |
|
65 |
- } |
|
61 |
+ snprintf(port, sizeof(port), "%lld", optget(opts, "TCPSocket")->numarg); |
|
66 | 62 |
|
67 |
- if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &true, sizeof(true)) == -1) { |
|
68 |
- logg("!TCP: setsocktopt(SO_REUSEADDR) error: %s\n", strerror(errno)); |
|
69 |
- } |
|
63 |
+ memset(&hints, 0x00, sizeof(struct addrinfo)); |
|
64 |
+ hints.ai_family = AF_UNSPEC; |
|
65 |
+ hints.ai_socktype = SOCK_STREAM; |
|
66 |
+ hints.ai_flags = AI_PASSIVE; |
|
70 | 67 |
|
71 |
- if(bind(sockfd, (struct sockaddr *) &server, (socklen_t)sizeof(struct sockaddr_in)) == -1) { |
|
72 |
- estr = strerror(errno); |
|
73 |
- logg("!TCP: bind() error: %s\n", estr); |
|
74 |
- closesocket(sockfd); |
|
75 |
- return -1; |
|
76 |
- } else { |
|
77 |
- const struct optstruct *taddr = optget(opts, "TCPAddr"); |
|
78 |
- if(taddr->enabled) |
|
79 |
- logg("#TCP: Bound to address %s on port %u\n", taddr->strarg, (unsigned int) optget(opts, "TCPSocket")->numarg); |
|
80 |
- else |
|
81 |
- logg("#TCP: Bound to port %u\n", (unsigned int) optget(opts, "TCPSocket")->numarg); |
|
68 |
+ if ((res = getaddrinfo(ipaddr, port, &hints, &info))) { |
|
69 |
+ logg("!TCP: getaddrinfo: %s\n", gai_strerror(res)); |
|
70 |
+ return -1; |
|
82 | 71 |
} |
83 | 72 |
|
84 |
- backlog = optget(opts, "MaxConnectionQueueLength")->numarg; |
|
85 |
- logg("#TCP: Setting connection queue length to %d\n", backlog); |
|
73 |
+ for (p = info; p != NULL; p = p->ai_next) { |
|
74 |
+ t = realloc(sockets, sizeof(int) * (*nlsockets + 1)); |
|
75 |
+ if (!(t)) { |
|
76 |
+ return -1; |
|
77 |
+ } |
|
78 |
+ sockets = t; |
|
79 |
+ |
|
80 |
+ if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { |
|
81 |
+ estr = strerror(errno); |
|
82 |
+ logg("!TCP: socket() error: %s\n", estr); |
|
83 |
+ continue; |
|
84 |
+ } |
|
85 |
+ |
|
86 |
+ if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof(yes)) == -1) { |
|
87 |
+ logg("!TCP: setsocktopt(SO_REUSEADDR) error: %s\n", strerror(errno)); |
|
88 |
+ } |
|
89 |
+ |
|
90 |
+ if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { |
|
91 |
+ estr = strerror(errno); |
|
92 |
+ logg("!TCP: bind() error when trying to listen on [%s]:%s: %s\n", ipaddr, port, estr); |
|
93 |
+ closesocket(sockfd); |
|
86 | 94 |
|
87 |
- if(listen(sockfd, backlog) == -1) { |
|
88 |
- estr = strerror(errno); |
|
89 |
- logg("!TCP: listen() error: %s\n", estr); |
|
90 |
- closesocket(sockfd); |
|
91 |
- return -1; |
|
95 |
+ continue; |
|
96 |
+ } else { |
|
97 |
+ if((ipaddr)) |
|
98 |
+ logg("#TCP: Bound to address %s on port %u\n", ipaddr, (unsigned int) optget(opts, "TCPSocket")->numarg); |
|
99 |
+ else |
|
100 |
+ logg("#TCP: Bound to port %u\n", (unsigned int) optget(opts, "TCPSocket")->numarg); |
|
101 |
+ } |
|
102 |
+ |
|
103 |
+ backlog = optget(opts, "MaxConnectionQueueLength")->numarg; |
|
104 |
+ logg("#TCP: Setting connection queue length to %d\n", backlog); |
|
105 |
+ |
|
106 |
+ if(listen(sockfd, backlog) == -1) { |
|
107 |
+ estr = strerror(errno); |
|
108 |
+ logg("!TCP: listen() error: %s\n", estr); |
|
109 |
+ closesocket(sockfd); |
|
110 |
+ |
|
111 |
+ continue; |
|
112 |
+ } |
|
113 |
+ |
|
114 |
+ sockets[*nlsockets] = sockfd; |
|
115 |
+ (*nlsockets)++; |
|
92 | 116 |
} |
93 | 117 |
|
94 |
- return sockfd; |
|
118 |
+ freeaddrinfo(info); |
|
119 |
+ *lsockets = sockets; |
|
120 |
+ |
|
121 |
+ return 0; |
|
95 | 122 |
} |
... | ... |
@@ -83,38 +83,50 @@ static int isremote(const struct optstruct *opts) { |
83 | 83 |
int s, ret; |
84 | 84 |
const struct optstruct *opt; |
85 | 85 |
static struct sockaddr_in testsock; |
86 |
+ char *ipaddr; |
|
86 | 87 |
|
87 | 88 |
#ifndef _WIN32 |
88 | 89 |
if((opt = optget(clamdopts, "LocalSocket"))->enabled) { |
89 |
- memset((void *)&nixsock, 0, sizeof(nixsock)); |
|
90 |
- nixsock.sun_family = AF_UNIX; |
|
91 |
- strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path)); |
|
92 |
- nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0'; |
|
93 |
- mainsa = (struct sockaddr *)&nixsock; |
|
94 |
- mainsasz = sizeof(nixsock); |
|
95 |
- return 0; |
|
90 |
+ memset((void *)&nixsock, 0, sizeof(nixsock)); |
|
91 |
+ nixsock.sun_family = AF_UNIX; |
|
92 |
+ strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path)); |
|
93 |
+ nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0'; |
|
94 |
+ mainsa = (struct sockaddr *)&nixsock; |
|
95 |
+ mainsasz = sizeof(nixsock); |
|
96 |
+ return 0; |
|
96 | 97 |
} |
97 | 98 |
#endif |
98 | 99 |
if(!(opt = optget(clamdopts, "TCPSocket"))->enabled) |
99 |
- return 0; |
|
100 |
+ return 0; |
|
100 | 101 |
|
101 | 102 |
mainsa = (struct sockaddr *)&tcpsock; |
102 | 103 |
mainsasz = sizeof(tcpsock); |
103 | 104 |
|
104 |
- if (cfg_tcpsock(clamdopts, &tcpsock, INADDR_LOOPBACK) == -1) { |
|
105 |
- logg("!Can't lookup clamd hostname: %s.\n", strerror(errno)); |
|
106 |
- mainsa = NULL; |
|
107 |
- return 0; |
|
108 |
- } |
|
109 |
- memcpy((void *)&testsock, (void *)&tcpsock, sizeof(testsock)); |
|
110 |
- testsock.sin_port = htons(INADDR_ANY); |
|
111 |
- if((s = socket(testsock.sin_family, SOCK_STREAM, 0)) < 0) { |
|
112 |
- logg("isremote: socket() returning: %s.\n", strerror(errno)); |
|
113 |
- mainsa = NULL; |
|
114 |
- return 0; |
|
105 |
+ opt = optget(clamdopts, "TCPAddr"); |
|
106 |
+ while (opt) { |
|
107 |
+ ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg); |
|
108 |
+ |
|
109 |
+ if (cfg_tcpsock(ipaddr, clamdopts, &tcpsock, INADDR_LOOPBACK) == -1) { |
|
110 |
+ logg("!Can't lookup clamd hostname: %s.\n", strerror(errno)); |
|
111 |
+ mainsa = NULL; |
|
112 |
+ return 0; |
|
113 |
+ } |
|
114 |
+ |
|
115 |
+ memcpy((void *)&testsock, (void *)&tcpsock, sizeof(testsock)); |
|
116 |
+ testsock.sin_port = htons(INADDR_ANY); |
|
117 |
+ if((s = socket(testsock.sin_family, SOCK_STREAM, 0)) < 0) { |
|
118 |
+ logg("isremote: socket() returning: %s.\n", strerror(errno)); |
|
119 |
+ mainsa = NULL; |
|
120 |
+ return 0; |
|
121 |
+ } |
|
122 |
+ |
|
123 |
+ ret = (bind(s, (struct sockaddr *)&testsock, (socklen_t)sizeof(testsock)) != 0); |
|
124 |
+ closesocket(s); |
|
125 |
+ if (ret) |
|
126 |
+ return ret; |
|
127 |
+ |
|
128 |
+ opt = opt->nextarg; |
|
115 | 129 |
} |
116 |
- ret = (bind(s, (struct sockaddr *)&testsock, (socklen_t)sizeof(testsock)) != 0); |
|
117 |
- closesocket(s); |
|
118 | 130 |
return ret; |
119 | 131 |
} |
120 | 132 |
|
... | ... |
@@ -319,25 +319,28 @@ int match_regex(const char *filename, const char *pattern) |
319 | 319 |
return match; |
320 | 320 |
} |
321 | 321 |
|
322 |
-int cfg_tcpsock(const struct optstruct *opts, struct sockaddr_in *tcpsock, in_addr_t defaultbind) |
|
322 |
+int cfg_tcpsock(char *ipaddr, const struct optstruct *opts, struct sockaddr_in *tcpsock, in_addr_t defaultbind) |
|
323 | 323 |
{ |
324 | 324 |
struct hostent *he; |
325 | 325 |
const struct optstruct *opt = optget(opts, "TCPSocket"); |
326 | 326 |
|
327 | 327 |
if(opt->numarg > 65535) |
328 |
- return -1; |
|
328 |
+ return -1; |
|
329 | 329 |
|
330 | 330 |
memset(tcpsock, 0, sizeof(*tcpsock)); |
331 | 331 |
tcpsock->sin_family = AF_INET; |
332 | 332 |
tcpsock->sin_port = htons(opt->numarg); |
333 | 333 |
|
334 |
- if(!(opt = optget(opts, "TCPAddr"))->enabled) { |
|
335 |
- tcpsock->sin_addr.s_addr = htonl(defaultbind); |
|
336 |
- return 0; |
|
334 |
+ if(!(ipaddr)) { |
|
335 |
+ tcpsock->sin_addr.s_addr = htonl(defaultbind); |
|
336 |
+ return 0; |
|
337 |
+ } |
|
338 |
+ |
|
339 |
+ he = gethostbyname(ipaddr); |
|
340 |
+ if(!he) { |
|
341 |
+ cli_errmsg("gethostbyname: %s\n", strerror(errno)); |
|
342 |
+ return -1; |
|
337 | 343 |
} |
338 |
- he = gethostbyname(opt->strarg); |
|
339 |
- if(!he) |
|
340 |
- return -1; |
|
341 | 344 |
|
342 | 345 |
tcpsock->sin_addr = *(struct in_addr *) he->h_addr_list[0]; |
343 | 346 |
return 0; |
... | ... |
@@ -51,7 +51,7 @@ int filecopy(const char *src, const char *dest); |
51 | 51 |
int daemonize(void); |
52 | 52 |
const char *get_version(void); |
53 | 53 |
int match_regex(const char *filename, const char *pattern); |
54 |
-int cfg_tcpsock(const struct optstruct *opts, struct sockaddr_in *server, in_addr_t defaultbind); |
|
54 |
+int cfg_tcpsock(char *ipaddr, const struct optstruct *opts, struct sockaddr_in *server, in_addr_t defaultbind); |
|
55 | 55 |
int cli_is_abspath(const char *path); |
56 | 56 |
unsigned int countlines(const char *filename); |
57 | 57 |
|
... | ... |
@@ -217,7 +217,7 @@ const struct clam_option __clam_options[] = { |
217 | 217 |
{ "TCPSocket", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD, "A TCP port number the daemon will listen on.", "3310" }, |
218 | 218 |
|
219 | 219 |
/* FIXME: add a regex for IP addr */ |
220 |
- { "TCPAddr", NULL, 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "By default clamd binds to INADDR_ANY.\nThis option allows you to restrict the TCP address and provide\nsome degree of protection from the outside world.", "127.0.0.1" }, |
|
220 |
+ { "TCPAddr", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "By default clamd binds to INADDR_ANY.\nThis option allows you to restrict the TCP address and provide\nsome degree of protection from the outside world.", "127.0.0.1" }, |
|
221 | 221 |
|
222 | 222 |
{ "MaxConnectionQueueLength", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 200, NULL, 0, OPT_CLAMD, "Maximum length the queue of pending connections may grow to.", "30" }, |
223 | 223 |
|