--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <netinet/in.h>
+#include <event.h>
+#include <sys/queue.h>
+#include "smtpsink.h"
+
+#include "msgproc.h"
+
+#include <nmsg.h>
+
+struct ssm_nmsg_state {
+ msgproc *urlproc;
+ nmsg_message_t msg;
+ unsigned nurl;
+};
+
+static void
+addurl(msgproc *m, char *s, void *data)
+{
+ struct ssm_nmsg_state *nms = (struct ssm_nmsg_state *)data;
+ const uint8_t *url = (const uint8_t *)s;
+ size_t len = strlen(s) + 1;
+
+ if (nms->msg)
+ nmsg_message_set_field(nms->msg, "bodyurl", nms->nurl++,
+ url, len);
+}
+
+static nmsg_msgmod_t nmsg_emailmod;
+static nmsg_output_t nmsg_out;
+static char *nmsg_output_filename;
+static int nmsg_output_fd = -1;
+
+static void
+ssm_nmsg_reload(void)
+{
+ if (nmsg_output_fd >= 0)
+ close(nmsg_output_fd);
+
+ nmsg_output_fd = open(nmsg_output_filename, O_CREAT|O_APPEND, 0644);
+
+ if (nmsg_out) nmsg_output_close(&nmsg_out);
+ nmsg_out = nmsg_output_open_file(nmsg_output_fd, 4096);
+ nmsg_output_set_buffered(nmsg_out, 0);
+}
+
+static void
+ssm_nmsg_init(char *config)
+{
+ nmsg_res res;
+
+ res = nmsg_init();
+ if (res != nmsg_res_success) {
+ errx(1, "unable to initialize libnmsg");
+ }
+ nmsg_emailmod = nmsg_msgmod_lookup_byname("ISC", "email");
+ msgproc_module_init(&msgproc_message);
+
+ nmsg_output_filename = strdup(config);
+ ssm_nmsg_reload();
+}
+
+struct smtpsink_module ss_module;
+
+static int
+ssm_nmsg_connect(struct conn *c)
+{
+ struct ssm_nmsg_state *nms = malloc(sizeof(struct ssm_nmsg_state));
+ char ip[80];
+ const uint8_t *addr = (const uint8_t *)ip;
+
+ if (nms) {
+ nms->msg = nmsg_message_init(nmsg_emailmod);
+ nms->nurl = 0;
+ nms->urlproc = msgproc_create(NULL, &msgproc_message);
+
+ if (nms->msg) {
+ inet_ntop(AF_INET, &c->peer.sin_addr, ip, sizeof(ip));
+ nmsg_message_set_field(nms->msg, "srchost", 0,
+ addr, strnlen(ip, sizeof(ip)) + 1);
+ }
+
+ if (nms->urlproc) {
+ msgproc_setcallback(nms->urlproc, addurl, nms);
+ msgproc_start(nms->urlproc);
+ }
+ }
+
+ ssm_setpriv(&ss_module, c, nms);
+ return SSM_PASS;
+}
+
+#define SAVEPARM(x) \
+static int \
+ssm_nmsg_##x(struct conn *c, const char *cmd, int len, int argoff) { \
+ struct ssm_nmsg_state *nms = ssm_getpriv(&ss_module, c); \
+ const uint8_t *data = (const uint8_t *)cmd; \
+ if (nms && nms->msg) \
+ nmsg_message_set_field(nms->msg, #x, 0, data + argoff, \
+ len - argoff + 1); \
+ return SSM_PASS; \
+}
+
+SAVEPARM(helo)
+SAVEPARM(from)
+SAVEPARM(rcpt)
+
+static void
+ssm_nmsg_body(struct conn *c, const char *data, int len)
+{
+ struct ssm_nmsg_state *nms = ssm_getpriv(&ss_module, c);
+
+ if (nms && nms->urlproc)
+ msgproc_process(nms->urlproc, (char *)data, len);
+}
+
+static void
+ssm_nmsg_cleanup(struct conn *c)
+{
+ struct ssm_nmsg_state *nms = ssm_getpriv(&ss_module, c);
+ if (!nms) return;
+ if (nms->msg) {
+ nmsg_message_destroy(&nms->msg);
+ nms->msg = 0;
+ }
+ if (nms->urlproc) {
+ msgproc_finish(nms->urlproc);
+ nms->urlproc = 0;
+ }
+}
+
+static int
+ssm_nmsg_enddata(struct conn *c)
+{
+ struct ssm_nmsg_state *nms = ssm_getpriv(&ss_module, c);
+ fprintf(stderr, "ssm_nmsg_enddata(%p)\n", c);
+ if (nms && nms->msg && nmsg_out) {
+ nmsg_output_write(nmsg_out, nms->msg);
+ }
+ ssm_nmsg_cleanup(c);
+ return SSM_PASS;
+}
+
+struct smtpsink_module ss_module = {
+ 0,
+
+ ssm_nmsg_init,
+ ssm_nmsg_reload,
+
+ ssm_nmsg_connect,
+ ssm_nmsg_helo,
+ ssm_nmsg_from,
+ ssm_nmsg_rcpt,
+ 0,
+ ssm_nmsg_body,
+ ssm_nmsg_enddata,
+ ssm_nmsg_cleanup,
+ ssm_nmsg_cleanup
+};