summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2004-07-20 16:41:51 +0000
committerStef Walter <stef@memberwebs.com>2004-07-20 16:41:51 +0000
commitb73a3b497ff95ebe012c31e4f778a6f776a734b1 (patch)
treeac8fc15515bf39563bd1eecc80e1642f7f1afd44
parent086da0b54d7f5711733febdb27507a5400767be6 (diff)
- Better connection handling
- Route connections without a IP back to incoming IP
-rw-r--r--common/smtppass.c111
-rw-r--r--common/sock_any.c52
-rw-r--r--common/sock_any.h22
-rw-r--r--common/stringx.c7
4 files changed, 140 insertions, 52 deletions
diff --git a/common/smtppass.c b/common/smtppass.c
index b93b636..d32248a 100644
--- a/common/smtppass.c
+++ b/common/smtppass.c
@@ -113,14 +113,12 @@ clamsmtp_thread_t;
* Default Settings
*/
-#define DEFAULT_SOCKET "0.0.0.0:10025"
-#define DEFAULT_PORT 10025
+#define DEFAULT_SOCKET "10025"
#define DEFAULT_CLAMAV "/var/run/clamav/clamd"
#define DEFAULT_MAXTHREADS 64
#define DEFAULT_TIMEOUT 180
#define DEFAULT_HEADER "X-AV-Checked: ClamAV using ClamSMTP\r\n"
-
/* -----------------------------------------------------------------------
* Globals
*/
@@ -265,11 +263,11 @@ int main(int argc, char* argv[])
messagex(NULL, LOG_DEBUG, "starting up...");
/* Parse all the addresses */
- if(sock_any_pton(listensock, &addr, DEFAULT_PORT) == -1)
+ if(sock_any_pton(listensock, &addr, SANY_OPT_DEFANY) == -1)
errx(1, "invalid listen socket name or ip: %s", listensock);
- if(sock_any_pton(g_outname, &g_outaddr, 25) == -1)
+ if(sock_any_pton(g_outname, &g_outaddr, SANY_OPT_DEFPORT(25)) == -1)
errx(1, "invalid connect socket name or ip: %s", g_outname);
- if(sock_any_pton(g_clamname, &g_clamaddr, 0) == -1)
+ if(sock_any_pton(g_clamname, &g_clamaddr, SANY_OPT_DEFLOCAL) == -1)
errx(1, "invalid clam socket name: %s", g_clamname);
if(daemonize)
@@ -492,10 +490,12 @@ static void pid_file(const char* pidfile, int write)
static void* thread_main(void* arg)
{
clamsmtp_thread_t* thread = (clamsmtp_thread_t*)arg;
- char peername[MAXPATHLEN];
struct sockaddr_any addr;
+ struct sockaddr_any* outaddr;
+ const char* outname;
+ char buf[MAXPATHLEN];
clamsmtp_context_t ctx;
- int r;
+ int ret = 0;
ASSERT(thread);
@@ -504,43 +504,88 @@ static void* thread_main(void* arg)
memset(&ctx, 0, sizeof(ctx));
- plock();
- ctx.client = thread->fd;
- punlock();
+ /* Assign a unique id to the connection */
+ ctx.id = g_unique_id++;
ctx.server = -1;
ctx.clam = -1;
- ASSERT(ctx.client != -1);
+ plock();
+ ctx.client = thread->fd;
+ punlock();
- /* Assign a unique id to the connection */
- ctx.id = g_unique_id++;
+ ASSERT(ctx.client != -1);
memset(&addr, 0, sizeof(addr));
SANY_LEN(addr) = sizeof(addr);
/* Get the peer name */
if(getpeername(ctx.client, &SANY_ADDR(addr), &SANY_LEN(addr)) == -1 ||
- sock_any_ntop(&addr, peername, MAXPATHLEN) == -1)
+ sock_any_ntop(&addr, buf, MAXPATHLEN, SANY_OPT_NOPORT) == -1)
message(&ctx, LOG_WARNING, "couldn't get peer address");
else
- messagex(&ctx, LOG_INFO, "accepted connection from: %s", peername);
+ messagex(&ctx, LOG_INFO, "accepted connection from: %s", buf);
+
+
+ /* Create the server connection address */
+ outaddr = &g_outaddr;
+ outname = g_outname;
+
+ if(SANY_TYPE(*outaddr) == AF_INET &&
+ outaddr->s.in.sin_addr.s_addr == 0)
+ {
+ /* Use the incoming IP as the default */
+ in_addr_t in = addr.s.in.sin_addr.s_addr;
+ memcpy(&addr, &g_outaddr, sizeof(addr));
+ addr.s.in.sin_addr.s_addr = in;
+
+ outaddr = &addr;
+
+ if(sock_any_ntop(outaddr, buf, MAXPATHLEN, 0) != -1)
+ outname = buf;
+ }
+
+
+ /* Connect to the server */
+ if((ctx.server = socket(SANY_TYPE(*outaddr), SOCK_STREAM, 0)) < 0 ||
+ connect(ctx.server, &SANY_ADDR(*outaddr), SANY_LEN(*outaddr)) < 0)
+ {
+ message(&ctx, LOG_ERR, "couldn't connect to %s", outname);
+ RETURN(-1);
+ }
+
+ messagex(&ctx, LOG_DEBUG, "connected to server: %s", outname);
+
+
+ if(connect_clam(&ctx) == -1)
+ RETURN(-1);
+
/* call the processor */
- r = smtp_passthru(&ctx);
+ ret = smtp_passthru(&ctx);
+
+cleanup:
+
+ disconnect_clam(&ctx);
- /* Close the incoming connection if neccessary */
if(ctx.client != -1)
+ {
shutdown(ctx.client, SHUT_RDWR);
+ messagex(&ctx, LOG_NOTICE, "closed client connection");
+ }
- messagex(&ctx, LOG_NOTICE, "closed client connection");
+ if(ctx.server != -1)
+ {
+ shutdown(ctx.server, SHUT_RDWR);
+ messagex(&ctx, LOG_DEBUG, "closed server connection");
+ }
/* mark this as done */
plock();
thread->fd = -1;
punlock();
- return (void*)(r == 0 ? 0 : 1);
+ return (void*)(ret == 0 ? 0 : 1);
}
static int smtp_passthru(clamsmtp_context_t* ctx)
@@ -550,19 +595,7 @@ static int smtp_passthru(clamsmtp_context_t* ctx)
int r, ret = 0;
fd_set mask;
- ASSERT(ctx->server == -1);
-
- if((ctx->server = socket(SANY_TYPE(g_outaddr), SOCK_STREAM, 0)) < 0 ||
- connect(ctx->server, &SANY_ADDR(g_outaddr), SANY_LEN(g_outaddr)) < 0)
- {
- message(ctx, LOG_ERR, "couldn't connect to %s", g_outname);
- RETURN(-1);
- }
-
- messagex(ctx, LOG_DEBUG, "connected to server: %s", g_outname);
-
- if(connect_clam(ctx) == -1)
- RETURN(-1);
+ ASSERT(ctx->clam != -1 && ctx->server != -1);
/* This changes the error code sent to the client when an
* error occurs. See cleanup below */
@@ -683,20 +716,12 @@ static int smtp_passthru(clamsmtp_context_t* ctx)
cleanup:
- disconnect_clam(ctx);
-
if(ret == -1 && ctx->client != -1)
{
write_data(ctx, &(ctx->client),
processing ? SMTP_FAILED : SMTP_STARTFAILED);
}
- if(ctx->server != -1)
- {
- shutdown(ctx->server, SHUT_RDWR);
- messagex(ctx, LOG_DEBUG, "closed server connection");
- }
-
return ret;
}
@@ -771,7 +796,7 @@ cleanup:
if(ctx->clam != -1)
{
shutdown(ctx->clam, SHUT_RDWR);
- ctx->clam == -1;
+ ctx->clam = -1;
}
}
@@ -786,8 +811,8 @@ static int disconnect_clam(clamsmtp_context_t* ctx)
if(write_data(ctx, &(ctx->clam), CLAM_DISCONNECT) != -1)
read_junk(ctx, ctx->clam);
- messagex(ctx, LOG_DEBUG, "disconnected from clamd");
shutdown(ctx->clam, SHUT_RDWR);
+ messagex(ctx, LOG_DEBUG, "disconnected from clamd");
ctx->clam = -1;
return 0;
}
diff --git a/common/sock_any.c b/common/sock_any.c
index 49e0390..0018318 100644
--- a/common/sock_any.c
+++ b/common/sock_any.c
@@ -47,12 +47,15 @@
#include <arpa/inet.h>
-int sock_any_pton(const char* addr, struct sockaddr_any* any, int defport)
+#define LOCALHOST_ADDR 0x7F000001
+
+int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts)
{
size_t l;
char buf[256];
char* t;
char* t2;
+ int defport = (opts & 0xFFFF);
memset(any, 0, sizeof(*any));
@@ -69,13 +72,35 @@ int sock_any_pton(const char* addr, struct sockaddr_any* any, int defport)
if(l < PORT_MIN || l > PORT_MAX || addr[l] != 0)
break;
- port = strtol(t, &t2, 10);
+ port = strtol(addr, &t2, 10);
if(*t2 || port <= 0 || port >= 65536)
break;
- any->s.in.sin_family = AF_INET;
- any->s.in.sin_port = htons((unsigned short)(port <= 0 ? defport : port));
- any->s.in.sin_addr.s_addr = 0;
+ any->s.in.sin_port = htons(port);
+
+ /* Fill in the type based on defaults */
+#ifdef HAVE_INET6
+ if(opts & SANY_OPT_DEFINET6)
+ any->s.in.sin_family = AF_INET6;
+ else
+#endif
+ any->s.in.sin_family = AF_INET;
+
+ /* Fill in the address based on defaults */
+ if(opts & SANY_OPT_DEFLOCAL)
+ {
+#ifdef HAVE_INET6
+ if(opts & SANY_OPT_DEFINET6)
+ memcpy(&(any->s.in.sin6_addr), &in6addr_loopback, sizeof(struct in6_addr));
+ else
+#endif
+ any->s.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
+
+ /*
+ * Note the 'any' option is the default since we zero out
+ * the entire structure above.
+ */
any->namelen = sizeof(any->s.in);
return AF_INET;
@@ -274,9 +299,10 @@ int sock_any_pton(const char* addr, struct sockaddr_any* any, int defport)
return -1;
}
-int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen)
+int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen, int opts)
{
int len = 0;
+ int port = 0;
switch(any->s.a.sa_family)
{
@@ -294,12 +320,14 @@ int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen)
case AF_INET:
if(inet_ntop(any->s.a.sa_family, &(any->s.in.sin_addr), addr, addrlen) == NULL)
return -1;
+ port = ntohs(any->s.in.sin_port);
break;
#ifdef HAVE_INET6
case AF_INET6:
if(inet_ntop(any->s.a.sa_family, &(any->s.in6.sin6_addr), addr, addrlen) == NULL)
return -1;
+ port = ntohs(any->s.in6.sin6_port);
break;
#endif
@@ -308,5 +336,17 @@ int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen)
return -1;
}
+ if(!(opts & SANY_OPT_NOPORT) && port != 0)
+ {
+ strncat(addr, ":", addrlen);
+ addr[addrlen - 1] = 0;
+
+ len = strlen(addr);
+ addr += len;
+ addrlen -= len;
+
+ snprintf(addr, addrlen, "%d", port);
+ }
+
return 0;
}
diff --git a/common/sock_any.h b/common/sock_any.h
index 924bf09..0b492b4 100644
--- a/common/sock_any.h
+++ b/common/sock_any.h
@@ -64,7 +64,25 @@ struct sockaddr_any
#define SANY_LEN(any) ((any).namelen)
#define SANY_TYPE(any) ((any).s.a.sa_family)
-int sock_any_pton(const char* addr, struct sockaddr_any* any, int defport);
-int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen);
+int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts);
+
+/* The default port to fill in when no IP/IPv6 port specified */
+#define SANY_OPT_DEFPORT(p) (int)((p) & 0xFFFF)
+
+/* When only port specified default to IPANY */
+#define SANY_OPT_DEFANY 0x00000000
+
+/* When only port specified default to LOCALHOST */
+#define SANY_OPT_DEFLOCAL 0x00100000
+
+/* When only port specified default to IPv6 */
+#ifdef HAVE_INET6
+#define SANY_OPT_DEFINET6 0x00200000
+#endif
+
+int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen, int opts);
+
+/* Don't print the port */
+#define SANY_OPT_NOPORT 0x01000000
#endif /* __SOCK_ANY_H__ */
diff --git a/common/stringx.c b/common/stringx.c
index 8ae70f5..7ee85ae 100644
--- a/common/stringx.c
+++ b/common/stringx.c
@@ -62,6 +62,7 @@ static void vmessage(clamsmtp_context_t* ctx, int level, int err,
size_t len;
char* m;
int e = errno;
+ int x;
if(g_daemonized)
{
@@ -87,7 +88,11 @@ static void vmessage(clamsmtp_context_t* ctx, int level, int err,
snprintf(m, len, "%s%s", msg, err ? ": " : "");
if(err)
- strerror_r(e, m + strlen(m), MAX_MSGLEN);
+ {
+ /* TODO: strerror_r doesn't want to work for us
+ strerror(e, m + strlen(m), MAX_MSGLEN); */
+ strncat(m, strerror(e), len);
+ }
m[len - 1] = 0;
msg = m;