Commit Diff


commit - ba153e30ab30865884e14f8d96ec0d3e7a633386
commit + 57cbfccc70a86c36f9d4eb2a34af40008446f119
blob - 4f77a04cf6f65653b40d1dcc2354aab472a27900
blob + b3485b1bfa8478c7739de10ae713686503cd2173
--- main.c
+++ main.c
@@ -13,7 +13,7 @@
 static char **blacklists = NULL;
 static size_t nblacklists = 0;
 int retries = 0;
-enum filter_decision onfailure = FILTER_PROCEED;
+int reject_onfailure = 0;
 
 void usage(void);
 enum filter_decision dnsbl_connect(char *, int, time_t, char *, char *,
@@ -46,16 +46,7 @@ main(int argc, char *argv[])
 			nblacklists++;
 			break;
 		case 'f':
-			if (strcasecmp(optarg, "proceed") == 0)
-				onfailure = FILTER_PROCEED;
-			else if (strcasecmp(optarg, "reject") == 0)
-				onfailure = FILTER_REJECT;
-			else if (strcasecmp(optarg, "disconnect") == 0)
-				onfailure = FILTER_DISCONNECT;
-			else if (strcasecmp(optarg, "rewrite") == 0)
-				onfailure = FILTER_REWRITE;
-			else
-				errx(1, "Invalid on failure case");
+			reject_onfailure = 1;
 		case 'r':
 			if ((retries = strtonum(optarg, 0, 10, &errstr)) == 0 &&
 			    errstr != NULL)
@@ -83,7 +74,7 @@ dnsbl_connect(char *type, int version, time_t tm, char
 	char reply[1500];
 	struct hostent *hent;
 	u_char *addr;
-	int i;
+	int i, try;
 
 	addr = (u_char *)&(params->addr);
 	for (i = 0; i < nblacklists; i++) {
@@ -117,17 +108,28 @@ dnsbl_connect(char *type, int version, time_t tm, char
 				errx(1, "Can't create query, domain too long");
 		} else
 			errx(1, "Invalid address family received");
-	}
 
-	for (i = -1; i < retries; i++) {
-		if ((hent = gethostbyname(query)) == NULL) {
-			if (h_errno == HOST_NOT_FOUND)
-				return FILTER_PROCEED;
-			if (h_errno != TRY_AGAIN)
-				return onfailure;
+		for (try = -1; try < retries; try++) {
+			if ((hent = gethostbyname(query)) == NULL) {
+				if (h_errno == HOST_NOT_FOUND)
+					break;
+				if (h_errno != TRY_AGAIN) {
+					if (!reject_onfailure)
+						break;
+					else
+						smtp_filter_disconnect(reqid,
+						    token,
+						    "Blacklist check failed");
+						return FILTER_DISCONNECT;
+				}
+			} else {
+				smtp_filter_disconnect(reqid, token,
+				    "Listed at %s", blacklists[i]);
+				return FILTER_DISCONNECT;
+			}
 		}
 	}
-	return FILTER_REJECT;
+	return FILTER_PROCEED;
 }
 
 void
blob - 468875bd2912e308bd8e68deb977ec893466a3c0
blob + 4000129f96cc995befbc2ff68e0ad978b7feb60b
--- smtp_proc.c
+++ smtp_proc.c
@@ -5,6 +5,7 @@
 #include <err.h>
 #include <errno.h>
 #include <inttypes.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -60,6 +61,7 @@ struct smtp_callback {
 };
 
 static int ready = 0;
+static int resolved = 1;
 
 int
 smtp_register_filter_connect(enum filter_decision (*cb)(char *, int, time_t,
@@ -216,27 +218,80 @@ static void
 smtp_handle(struct smtp_callback *cb, int version, time_t tm, uint64_t reqid,
     uint64_t token, void *params)
 {
-	int ret;
+	enum filter_decision fdes;
 
-	switch (cb->cb(cb->type, version, tm, cb->direction, cb->phase, reqid,
-	    token, params)) {
-	case FILTER_PROCEED:
-		printf("filter-result|%016"PRIx64"|%016"PRIx64"|proceed\n",
-		    token, reqid);
-		break;
-	case FILTER_REJECT:
-		printf("filter-result|%016"PRIx64"|%016"PRIx64"|reject|%s\n",
-		    token, reqid, "451 Proper message later");
-		break;
-	case FILTER_DISCONNECT:
-		printf("filter-result|%016"PRIx64"|%016"PRIx64"|disconnect|"
-		    "%s\n", token, reqid, "421 Proper message later");
-		break;
-	case FILTER_REWRITE:
-		errx(1, "Not sure what is intended here yet");
+	if (!resolved)
+		errx(1, "Handling unexpected second request");
+	resolved = 0;
+	fdes = cb->cb(cb->type, version, tm, cb->direction, cb->phase, reqid,
+	    token, params);
+	if (!resolved) {
+		switch (fdes) {
+		case FILTER_PROCEED:
+			smtp_filter_proceed(reqid, token);
+			break;
+		case FILTER_REJECT:
+			smtp_filter_reject(reqid, token, 451,
+			    "Rejected by filter");
+			break;
+		case FILTER_DISCONNECT:
+			smtp_filter_disconnect(reqid, token,
+			    "Rejected by filter");
+			break;
+		case FILTER_REWRITE:
+			errx(1, "Not sure what is intended here yet");
+		}
 	}
 }
 
+void
+smtp_filter_proceed(uint64_t reqid, uint64_t token)
+{
+	if (resolved)
+		errx(1, "reqid: %016"PRIx64" token: %016"PRIx64" already "
+		    "resolved", reqid, token);
+	printf("filter-result|%016"PRIx64"|%016"PRIx64"|proceed\n", token, reqid);
+	resolved = 1;
+}
+
+void
+smtp_filter_reject(uint64_t reqid, uint64_t token, int code,
+    const char *reason, ...)
+{
+	va_list ap;
+
+	if (resolved)
+		errx(1, "reqid: %016"PRIx64" token: %016"PRIx64" already "
+		    "resolved", reqid, token);
+	if (code < 200 || code > 599)
+		errx(1, "Invalid reject code");
+
+	printf("filter-result|%016"PRIx64"|%016"PRIx64"|reject|%d ", token,
+	    reqid, code);
+	va_start(ap, reason);
+	vprintf(reason, ap);
+	va_end(ap);
+	putchar('\n');
+	resolved = 1;
+}
+
+void
+smtp_filter_disconnect(uint64_t reqid, uint64_t token, const char *reason, ...)
+{
+	va_list ap;
+
+	if (resolved)
+		errx(1, "reqid: %016"PRIx64" token: %016"PRIx64" already "
+		    "resolved", reqid, token);
+	printf("filter-result|%016"PRIx64"|%016"PRIx64"|disconnect|421 ",
+	    token, reqid);
+	va_start(ap, reason);
+	vprintf(reason, ap);
+	va_end(ap);
+	putchar('\n');
+	resolved = 1;
+}
+
 static int
 smtp_register(char *type, char *phase, char *direction, smtp_cb cb)
 {
blob - e190c1c0fa454eb54f08eb9c220e6d24132495f3
blob + 32f5edae76536f943271a670f009dbabaca1ed72
--- smtp_proc.h
+++ smtp_proc.h
@@ -18,4 +18,9 @@ enum filter_decision {
 
 int smtp_register_filter_connect(enum filter_decision (*cb)(char *, int, time_t,
     char *, char *, uint64_t, uint64_t, struct smtp_filter_connect *));
+void smtp_filter_proceed(uint64_t, uint64_t);
+void smtp_filter_reject(uint64_t, uint64_t, int, const char *, ...)
+	__attribute__((__format__ (printf, 4, 5)));
+void smtp_filter_disconnect(uint64_t, uint64_t, const char *, ...)
+	__attribute__((__format__ (printf, 3, 4)));
 void smtp_run(void);