diff options
author | Marius Halden <marius.h@lden.org> | 2016-01-11 01:37:26 +0100 |
---|---|---|
committer | Marius Halden <marius.h@lden.org> | 2016-01-11 01:37:26 +0100 |
commit | afc2c4818834efb1fd45c267515ef26e674f63f8 (patch) | |
tree | ef1f8d103a0bd852f16057c2f6d7e76bb2a626fd /spamd.patch | |
download | spamd-patches-afc2c4818834efb1fd45c267515ef26e674f63f8.tar.gz spamd-patches-afc2c4818834efb1fd45c267515ef26e674f63f8.tar.bz2 spamd-patches-afc2c4818834efb1fd45c267515ef26e674f63f8.tar.xz |
initial
Diffstat (limited to 'spamd.patch')
-rw-r--r-- | spamd.patch | 938 |
1 files changed, 938 insertions, 0 deletions
diff --git a/spamd.patch b/spamd.patch new file mode 100644 index 0000000..3e7c986 --- /dev/null +++ b/spamd.patch @@ -0,0 +1,938 @@ +Index: grey.c +=================================================================== +RCS file: /cvs/src/libexec/spamd/grey.c,v +retrieving revision 1.62 +diff -u -r1.62 grey.c +--- grey.c 10 Dec 2015 16:06:29 -0000 1.62 ++++ grey.c 31 Dec 2015 20:25:24 -0000 +@@ -54,8 +54,10 @@ + #define satosin(sa) ((struct sockaddr_in *)(sa)) + #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) + +-void configure_spamd(char **, u_int, FILE *); +-int configure_pf(char **, int); ++struct listentry; ++ ++void configure_spamd(struct listentry *, u_int, FILE *); ++int configure_pf(struct listentry *, int); + char *dequotetolower(const char *); + void readsuffixlists(void); + void freeaddrlists(void); +@@ -69,11 +71,10 @@ + int greyreader(void); + void greyscanner(void); + +- + u_int whitecount, whitealloc; + u_int trapcount, trapalloc; +-char **whitelist; +-char **traplist; ++struct listentry *whitelist; ++struct listentry *traplist; + + char *traplist_name = "spamd-greytrap"; + char *traplist_msg = "\"Your address %A has mailed to spamtraps here\\n\""; +@@ -89,6 +90,18 @@ + int act; + }; + ++struct listentry { ++ char *entry; ++ int af; ++}; ++ ++struct address_list { ++ int count; ++ char *addrs; ++ size_t size; ++ size_t len; ++}; ++ + #define DBC_ADD 1 + #define DBC_DEL 2 + +@@ -124,6 +137,37 @@ + _exit(1); + } + ++static int ++add_address(struct address_list *rec, struct listentry *addr) ++{ ++ size_t entry_len = strlen(addr->entry); ++ size_t extra_len = (addr->af == AF_INET6) ? 6 : 5; /* semicolon, prefix and nul */ ++ if (rec->len + entry_len + extra_len >= rec->size) { ++ char *tmp = reallocarray(rec->addrs, rec->size + 1024, ++ sizeof(char)); ++ if (tmp == NULL) { ++ syslog_r(LOG_ERR, &sdata, ++ "configure_spamd: malloc failed"); ++ return(-1); ++ } ++ rec->addrs = tmp; ++ if (rec->size == 0) ++ rec->addrs[0] = '\0'; ++ rec->size += 1024; ++ } ++ ++ strlcat(rec->addrs, ";", rec->size); ++ strlcat(rec->addrs, addr->entry, rec->size); ++ if (addr->af == AF_INET6) ++ strlcat(rec->addrs, "/128", rec->size); ++ else ++ strlcat(rec->addrs, "/32", rec->size); ++ rec->len += entry_len; ++ rec->count++; ++ ++ return(0); ++} ++ + /* + * Greatly simplified version from spamd_setup.c - only + * sends one blacklist to an already open stream. Has no need +@@ -131,24 +175,36 @@ + * host hits. + */ + void +-configure_spamd(char **addrs, u_int count, FILE *sdc) ++configure_spamd(struct listentry *addrs, u_int count, FILE *sdc) + { + u_int i; ++ struct address_list inet = { 0, NULL, 0, 0 }; ++ struct address_list inet6 = { 0, NULL, 0, 0 }; + +- /* XXX - doesn't support IPV6 yet */ + fprintf(sdc, "%s;", traplist_name); + if (count != 0) { +- fprintf(sdc, "%s;inet;%u", traplist_msg, count); +- for (i = 0; i < count; i++) +- fprintf(sdc, ";%s/32", addrs[i]); ++ for (i = 0; i < count; i++) { ++ if (addrs[i].af == AF_INET6) ++ (void)add_address(&inet6, &addrs[i]); ++ else ++ (void)add_address(&inet, &addrs[i]); ++ } ++ ++ fprintf(sdc, "%s", traplist_msg); ++ if (inet.count > 0) ++ fprintf(sdc, ";inet;%u%s", inet.count, inet.addrs); ++ if (inet6.count > 0) ++ fprintf(sdc, ";inet6;%u%s", inet6.count, inet6.addrs); + } ++ free(inet.addrs); ++ free(inet6.addrs); + fputc('\n', sdc); + if (fflush(sdc) == EOF) + syslog_r(LOG_DEBUG, &sdata, "configure_spamd: fflush failed (%m)"); + } + + int +-configure_pf(char **addrs, int count) ++configure_pf(struct listentry *addrs, int count) + { + FILE *pf = NULL; + int i, pdes[2], status; +@@ -210,8 +266,9 @@ + return(-1); + } + for (i = 0; i < count; i++) +- if (addrs[i] != NULL) +- fprintf(pf, "%s/32\n", addrs[i]); ++ if (addrs[i].entry != NULL) ++ fprintf(pf, "%s/%s\n", addrs[i].entry, ++ (addrs[i].af == AF_INET6) ? "128" : "32"); + fclose(pf); + + waitpid(pid, &status, 0); +@@ -305,14 +362,14 @@ + + if (whitelist != NULL) + for (i = 0; i < whitecount; i++) { +- free(whitelist[i]); +- whitelist[i] = NULL; ++ free(whitelist[i].entry); ++ whitelist[i].entry = NULL; + } + whitecount = 0; + if (traplist != NULL) { + for (i = 0; i < trapcount; i++) { +- free(traplist[i]); +- traplist[i] = NULL; ++ free(traplist[i].entry); ++ traplist[i].entry = NULL; + } + } + trapcount = 0; +@@ -325,17 +382,17 @@ + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(hints)); +- hints.ai_family = AF_INET; /*for now*/ ++ hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_protocol = IPPROTO_UDP; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + + if (getaddrinfo(addr, NULL, &hints, &res) == 0) { + if (whitecount == whitealloc) { +- char **tmp; ++ struct listentry *tmp; + + tmp = reallocarray(whitelist, +- whitealloc + 1024, sizeof(char *)); ++ whitealloc + 1024, sizeof(struct listentry)); + if (tmp == NULL) { + freeaddrinfo(res); + return(-1); +@@ -343,11 +400,12 @@ + whitelist = tmp; + whitealloc += 1024; + } +- whitelist[whitecount] = strdup(addr); +- if (whitelist[whitecount] == NULL) { ++ whitelist[whitecount].entry = strdup(addr); ++ if (whitelist[whitecount].entry == NULL) { + freeaddrinfo(res); + return(-1); + } ++ whitelist[whitecount].af = res->ai_family; + whitecount++; + freeaddrinfo(res); + } else +@@ -362,17 +420,17 @@ + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(hints)); +- hints.ai_family = AF_INET; /*for now*/ ++ hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_protocol = IPPROTO_UDP; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + + if (getaddrinfo(addr, NULL, &hints, &res) == 0) { + if (trapcount == trapalloc) { +- char **tmp; ++ struct listentry *tmp; + + tmp = reallocarray(traplist, +- trapalloc + 1024, sizeof(char *)); ++ trapalloc + 1024, sizeof(struct listentry)); + if (tmp == NULL) { + freeaddrinfo(res); + return(-1); +@@ -380,11 +438,12 @@ + traplist = tmp; + trapalloc += 1024; + } +- traplist[trapcount] = strdup(addr); +- if (traplist[trapcount] == NULL) { ++ traplist[trapcount].entry = strdup(addr); ++ if (traplist[trapcount].entry == NULL) { + freeaddrinfo(res); + return(-1); + } ++ traplist[trapcount].af = res->ai_family; + trapcount++; + freeaddrinfo(res); + } else +@@ -719,6 +778,7 @@ + gd.bcount++; + } else + gd.pcount++; ++ gd.expire = expire; + memset(&dbk, 0, sizeof(dbk)); + dbk.size = strlen(ip); + dbk.data = ip; +@@ -880,13 +940,13 @@ + int + twread(char *buf) + { +- if ((strncmp(buf, "WHITE:", 6) == 0) || +- (strncmp(buf, "TRAP:", 5) == 0)) { ++ if ((strncmp(buf, "WHITE;", 6) == 0) || ++ (strncmp(buf, "TRAP;", 5) == 0)) { + char **ap, *argv[5]; + int argc = 0; + + for (ap = argv; +- ap < &argv[4] && (*ap = strsep(&buf, ":")) != NULL;) { ++ ap < &argv[4] && (*ap = strsep(&buf, ";")) != NULL;) { + if (**ap != '\0') + ap++; + argc++; +@@ -910,7 +970,7 @@ + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(hints)); +- hints.ai_family = AF_INET; /*for now*/ ++ hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_protocol = IPPROTO_UDP; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; +Index: spamd.c +=================================================================== +RCS file: /cvs/src/libexec/spamd/spamd.c,v +retrieving revision 1.137 +diff -u -r1.137 spamd.c +--- spamd.c 12 Dec 2015 20:09:28 -0000 1.137 ++++ spamd.c 31 Dec 2015 20:25:24 -0000 +@@ -56,8 +56,8 @@ + int il; + struct sockaddr_storage ss; + void *ia; +- char addr[32]; +- char caddr[32]; ++ char addr[40]; ++ char caddr[40]; + char helo[MAX_MAIL], mail[MAX_MAIL], rcpt[MAX_MAIL]; + struct sdlist **blacklists; + struct tls *cctx; +@@ -113,6 +113,7 @@ + int read_configline(FILE *); + void spamd_tls_init(void); + void check_spamd_db(void); ++void accept_connection(int, struct sockaddr *, socklen_t, struct con *); + + char hostname[HOST_NAME_MAX+1]; + struct syslog_data sdata = SYSLOG_DATA_INIT; +@@ -709,9 +710,6 @@ + time_t tt; + int error; + +- if (sa->sa_family != AF_INET) +- errx(1, "not supported yet"); +- + time(&tt); + free(cp->obuf); + free(cp->blacklists); +@@ -723,7 +721,10 @@ + cp->pfd->fd = fd; + memcpy(&cp->ss, sa, sa->sa_len); + cp->af = sa->sa_family; +- cp->ia = &((struct sockaddr_in *)&cp->ss)->sin_addr; ++ if (sa->sa_family == AF_INET) ++ cp->ia = &((struct sockaddr_in *)&cp->ss)->sin_addr; ++ else ++ cp->ia = &((struct sockaddr_in6 *)&cp->ss)->sin6_addr; + cp->blacklists = sdl_lookup(blacklists, cp->af, cp->ia); + cp->stutter = (greylist && !grey_stutter && cp->blacklists == NULL) ? + 0 : stutter; +@@ -1208,13 +1209,54 @@ + return(maxfiles - 200); + } + ++void ++accept_connection(int sfd, struct sockaddr *sin, ++ socklen_t sinlen, struct con *con) ++{ ++ int s2, i; ++ ++ s2 = accept(sfd, sin, &sinlen); ++ if (s2 == -1) { ++ switch (errno) { ++ case EINTR: ++ case ECONNABORTED: ++ break; ++ case EMFILE: ++ case ENFILE: ++ slowdowntill = time(NULL) + 1; ++ break; ++ default: ++ errx(1, "accept"); ++ } ++ } else { ++ /* Check if we hit the chosen fd limit */ ++ for (i = 0; i < maxcon; i++) ++ if (con->pfd->fd == -1) ++ break; ++ if (i == maxcon) { ++ close(s2); ++ slowdowntill = 0; ++ } else { ++ initcon(&con[i], s2, sin); ++ syslog_r(LOG_INFO, &sdata, ++ "%s: connected (%d/%d)%s%s", ++ con[i].addr, clients, blackcount, ++ ((con[i].lists == NULL) ? "" : ++ ", lists:"), ++ ((con[i].lists == NULL) ? "": ++ con[i].lists)); ++ } ++ } ++} ++ + /* Symbolic indexes for pfd[] below */ + #define PFD_SMTPLISTEN 0 +-#define PFD_CONFLISTEN 1 +-#define PFD_SYNCFD 2 +-#define PFD_CONFFD 3 +-#define PFD_TRAPFD 4 +-#define PFD_FIRSTCON 5 ++#define PFD_SMTPLISTEN6 1 ++#define PFD_CONFLISTEN 2 ++#define PFD_SYNCFD 3 ++#define PFD_CONFFD 4 ++#define PFD_TRAPFD 5 ++#define PFD_FIRSTCON 6 + + int + main(int argc, char *argv[]) +@@ -1222,15 +1264,24 @@ + struct pollfd *pfd; + struct sockaddr_in sin; + struct sockaddr_in lin; +- int ch, smtplisten, conflisten, syncfd = -1, i, one = 1; ++ struct sockaddr_in6 sin6; ++ int ch, smtplisten, smtplisten6, conflisten, syncfd = -1, i, one = 1; + u_short port; + long long passt, greyt, whitet; + struct servent *ent; + struct rlimit rlp; + char *bind_address = NULL; ++ char *bind6_address = NULL; + const char *errstr; + char *sync_iface = NULL; + char *sync_baddr = NULL; ++ struct addrinfo hints, *res; ++ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_family = PF_UNSPEC; ++ hints.ai_socktype = SOCK_DGRAM; /* dummy */ ++ hints.ai_protocol = IPPROTO_UDP; /* dummy */ ++ hints.ai_flags = AI_NUMERICHOST; + + tzset(); + openlog_r("spamd", LOG_PID | LOG_NDELAY, LOG_DAEMON, &sdata); +@@ -1262,7 +1313,13 @@ + nreply = "550"; + break; + case 'l': +- bind_address = optarg; ++ if (getaddrinfo(optarg, NULL, &hints, &res) != 0) ++ errx(1, "-l %s: invalid address", optarg); ++ if (res->ai_family == AF_INET6) ++ bind6_address = optarg; ++ else ++ bind_address = optarg; ++ freeaddrinfo(res); + break; + case 'B': + maxblack = strtonum(optarg, 0, INT_MAX, &errstr); +@@ -1413,6 +1470,14 @@ + sizeof(one)) == -1) + return (-1); + ++ smtplisten6 = socket(AF_INET6, SOCK_STREAM, 0); ++ if (smtplisten6 == -1) ++ err(1, "socket"); ++ ++ if (setsockopt(smtplisten6, SOL_SOCKET, SO_REUSEADDR, &one, ++ sizeof(sin6)) == -1) ++ return (-1); ++ + conflisten = socket(AF_INET, SOCK_STREAM, 0); + if (conflisten == -1) + err(1, "socket"); +@@ -1434,6 +1499,19 @@ + if (bind(smtplisten, (struct sockaddr *)&sin, sizeof sin) == -1) + err(1, "bind"); + ++ memset(&sin6, 0, sizeof sin6); ++ sin6.sin6_len = sizeof(sin6); ++ if (bind6_address) { ++ if (inet_pton(AF_INET6, bind6_address, &sin6.sin6_addr) != 1) ++ err(1, "inet_pton"); ++ } else ++ sin6.sin6_addr = (struct in6_addr)IN6ADDR_LOOPBACK_INIT; ++ sin6.sin6_family = AF_INET6; ++ sin6.sin6_port = htons(port); ++ ++ if (bind(smtplisten6, (struct sockaddr *)&sin6, sizeof sin6) == -1) ++ err(1, "bind"); ++ + memset(&lin, 0, sizeof sin); + lin.sin_len = sizeof(sin); + lin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +@@ -1532,6 +1610,9 @@ + if (listen(smtplisten, 10) == -1) + err(1, "listen"); + ++ if (listen(smtplisten6, 10) == -1) ++ err(1, "listen"); ++ + if (listen(conflisten, 10) == -1) + err(1, "listen"); + +@@ -1557,6 +1638,7 @@ + + /* events and pfd entries for con[] are filled in below. */ + pfd[PFD_SMTPLISTEN].fd = smtplisten; ++ pfd[PFD_SMTPLISTEN6].fd = smtplisten6; + pfd[PFD_CONFLISTEN].fd = conflisten; + + while (1) { +@@ -1595,11 +1677,13 @@ + numcon = i + 1; + } + pfd[PFD_SMTPLISTEN].events = 0; ++ pfd[PFD_SMTPLISTEN6].events = 0; + pfd[PFD_CONFLISTEN].events = 0; + pfd[PFD_CONFFD].events = 0; + pfd[PFD_CONFFD].fd = conffd; + if (slowdowntill == 0) { + pfd[PFD_SMTPLISTEN].events = POLLIN; ++ pfd[PFD_SMTPLISTEN6].events = POLLIN; + + /* only one active config conn at a time */ + if (conffd == -1) +@@ -1647,45 +1731,12 @@ + handlew(&con[i], clients + 5 < maxcon); + } + } +- if (pfd[PFD_SMTPLISTEN].revents & (POLLIN|POLLHUP)) { +- socklen_t sinlen; +- int s2; +- +- sinlen = sizeof(sin); +- s2 = accept(smtplisten, (struct sockaddr *)&sin, &sinlen); +- if (s2 == -1) { +- switch (errno) { +- case EINTR: +- case ECONNABORTED: +- break; +- case EMFILE: +- case ENFILE: +- slowdowntill = time(NULL) + 1; +- break; +- default: +- errx(1, "accept"); +- } +- } else { +- /* Check if we hit the chosen fd limit */ +- for (i = 0; i < maxcon; i++) +- if (con[i].pfd->fd == -1) +- break; +- if (i == maxcon) { +- close(s2); +- slowdowntill = 0; +- } else { +- initcon(&con[i], s2, +- (struct sockaddr *)&sin); +- syslog_r(LOG_INFO, &sdata, +- "%s: connected (%d/%d)%s%s", +- con[i].addr, clients, blackcount, +- ((con[i].lists == NULL) ? "" : +- ", lists:"), +- ((con[i].lists == NULL) ? "": +- con[i].lists)); +- } +- } +- } ++ if (pfd[PFD_SMTPLISTEN].revents & (POLLIN|POLLHUP)) ++ accept_connection(smtplisten, (struct sockaddr *)&sin, ++ sizeof(sin), con); ++ if (pfd[PFD_SMTPLISTEN6].revents & (POLLIN|POLLHUP)) ++ accept_connection(smtplisten6, (struct sockaddr *)&sin6, ++ sizeof(sin6), con); + if (pfd[PFD_CONFLISTEN].revents & (POLLIN|POLLHUP)) { + socklen_t sinlen; + +Index: sync.c +=================================================================== +RCS file: /cvs/src/libexec/spamd/sync.c,v +retrieving revision 1.11 +diff -u -r1.11 sync.c +--- sync.c 23 Nov 2014 21:19:47 -0000 1.11 ++++ sync.c 31 Dec 2015 20:25:24 -0000 +@@ -241,11 +241,15 @@ + struct sockaddr_in addr; + struct spam_synctlv_hdr *tlv; + struct spam_synctlv_grey *sg; ++ struct spam_synctlv_grey6 *sg6; + struct spam_synctlv_addr *sd; ++ struct spam_synctlv_addr6 *sd6; + u_int8_t buf[SPAM_SYNC_MAXSIZE]; + u_int8_t hmac[2][SPAM_SYNC_HMAC_LEN]; + struct in_addr ip; ++ struct in6_addr ip6; + char *from, *to, *helo; ++ char ipstr[40] = { '\0' }; + u_int8_t *p; + socklen_t addr_len; + ssize_t len; +@@ -268,7 +272,7 @@ + hdr = (struct spam_synchdr *)buf; + if (len < sizeof(struct spam_synchdr) || + hdr->sh_version != SPAM_SYNC_VERSION || +- hdr->sh_af != AF_INET || ++ (hdr->sh_af != AF_INET && hdr->sh_af != AF_INET6) || + len < ntohs(hdr->sh_length)) + goto trunc; + len = ntohs(hdr->sh_length); +@@ -296,72 +300,120 @@ + + switch (ntohs(tlv->st_type)) { + case SPAM_SYNC_GREY: +- sg = (struct spam_synctlv_grey *)tlv; +- if ((sizeof(*sg) + +- ntohs(sg->sg_from_length) + +- ntohs(sg->sg_to_length) + +- ntohs(sg->sg_helo_length)) > +- ntohs(tlv->st_length)) +- goto trunc; +- +- ip.s_addr = sg->sg_ip; +- from = (char *)(sg + 1); +- to = from + ntohs(sg->sg_from_length); +- helo = to + ntohs(sg->sg_to_length); ++ if (hdr->sh_af == AF_INET) { ++ sg = (struct spam_synctlv_grey *)tlv; ++ if ((sizeof(*sg) + ++ ntohs(sg->sg_from_length) + ++ ntohs(sg->sg_to_length) + ++ ntohs(sg->sg_helo_length)) > ++ ntohs(tlv->st_length)) ++ goto trunc; ++ ++ ip.s_addr = sg->sg_ip; ++ inet_ntop(AF_INET, &ip, ipstr, sizeof(ipstr)); ++ ++ from = (char *)(sg + 1); ++ to = from + ntohs(sg->sg_from_length); ++ helo = to + ntohs(sg->sg_to_length); ++ } else { ++ sg6 = (struct spam_synctlv_grey6 *)tlv; ++ if ((sizeof(*sg6)) + ++ ntohs(sg6->sg6_from_length) + ++ ntohs(sg6->sg6_to_length) + ++ ntohs(sg6->sg6_helo_length) > ++ ntohs(tlv->st_length)) ++ goto trunc; ++ ++ memcpy(&ip6.s6_addr, &sg6->sg6_ip, sizeof(ip6.s6_addr)); ++ inet_ntop(AF_INET6, &ip6, ipstr, sizeof(ipstr)); ++ ++ from = (char *)(sg6 + 1); ++ to = from + ntohs(sg6->sg6_from_length); ++ helo = to + ntohs(sg6->sg6_to_length); ++ } ++ + if (debug) { + fprintf(stderr, "%s(sync): " + "received grey entry ", + inet_ntoa(addr.sin_addr)); + fprintf(stderr, "helo %s ip %s " + "from %s to %s\n", +- helo, inet_ntoa(ip), from, to); ++ helo, ipstr, from, to); + } + if (greylist) { + /* send this info to the greylister */ + fprintf(grey, + "SYNC\nHE:%s\nIP:%s\nFR:%s\nTO:%s\n", +- helo, inet_ntoa(ip), from, to); ++ helo, ipstr, from, to); + fflush(grey); + } + break; + case SPAM_SYNC_WHITE: +- sd = (struct spam_synctlv_addr *)tlv; +- if (sizeof(*sd) != ntohs(tlv->st_length)) +- goto trunc; ++ if (hdr->sh_af == AF_INET) { ++ sd = (struct spam_synctlv_addr *)tlv; ++ if (sizeof(*sd) != ntohs(tlv->st_length)) ++ goto trunc; ++ ++ ip.s_addr = sd->sd_ip; ++ inet_ntop(AF_INET, &ip, ipstr, sizeof(ipstr)); ++ ++ expire = ntohl(sd->sd_expire); ++ } else { ++ sd6 = (struct spam_synctlv_addr6 *)tlv; ++ if (sizeof(*sd6) != ntohs(tlv->st_length)) ++ goto trunc; ++ ++ memcpy(&ip6.s6_addr, &sd6->sd6_ip, sizeof(ip6.s6_addr)); ++ inet_ntop(AF_INET6, &ip6, ipstr, sizeof(ipstr)); ++ ++ expire = ntohl(sd6->sd6_expire); ++ } + +- ip.s_addr = sd->sd_ip; +- expire = ntohl(sd->sd_expire); + if (debug) { + fprintf(stderr, "%s(sync): " + "received white entry ", + inet_ntoa(addr.sin_addr)); +- fprintf(stderr, "ip %s ", inet_ntoa(ip)); ++ fprintf(stderr, "ip %s ", ipstr); + } + if (greylist) { + /* send this info to the greylister */ +- fprintf(grey, "WHITE:%s:", inet_ntoa(ip)); +- fprintf(grey, "%s:%u\n", ++ fprintf(grey, "WHITE;%s;", ipstr); ++ fprintf(grey, "%s;%u\n", + inet_ntoa(addr.sin_addr), expire); + fflush(grey); + } + break; + case SPAM_SYNC_TRAPPED: +- sd = (struct spam_synctlv_addr *)tlv; +- if (sizeof(*sd) != ntohs(tlv->st_length)) +- goto trunc; ++ if (hdr->sh_af == AF_INET) { ++ sd = (struct spam_synctlv_addr *)tlv; ++ if (sizeof(*sd) != ntohs(tlv->st_length)) ++ goto trunc; ++ ++ ip.s_addr = sd->sd_ip; ++ inet_ntop(AF_INET, &ip, ipstr, sizeof(ipstr)); ++ ++ expire = ntohl(sd->sd_expire); ++ } else { ++ sd6 = (struct spam_synctlv_addr6 *)tlv; ++ if (sizeof(*sd6) != ntohs(tlv->st_length)) ++ goto trunc; ++ ++ memcpy(&ip6.s6_addr, &sd6->sd6_ip, sizeof(ip6.s6_addr)); ++ inet_ntop(AF_INET6, &ip6, ipstr, sizeof(ipstr)); ++ ++ expire = ntohl(sd6->sd6_expire); ++ } + +- ip.s_addr = sd->sd_ip; +- expire = ntohl(sd->sd_expire); + if (debug) { + fprintf(stderr, "%s(sync): " + "received trapped entry ", + inet_ntoa(addr.sin_addr)); +- fprintf(stderr, "ip %s ", inet_ntoa(ip)); ++ fprintf(stderr, "ip %s ", ipstr); + } + if (greylist) { + /* send this info to the greylister */ +- fprintf(grey, "TRAP:%s:", inet_ntoa(ip)); +- fprintf(grey, "%s:%u\n", ++ fprintf(grey, "TRAP;%s;", ipstr); ++ fprintf(grey, "%s;%u\n", + inet_ntoa(addr.sin_addr), expire); + fflush(grey); + } +@@ -420,7 +472,10 @@ + struct iovec iov[7]; + struct spam_synchdr hdr; + struct spam_synctlv_grey sg; ++ struct spam_synctlv_grey6 sg6; ++ + struct spam_synctlv_hdr end; ++ struct addrinfo hints, *res; + u_int16_t sglen, fromlen, tolen, helolen, padlen; + char pad[SPAM_ALIGNBYTES]; + int i = 0; +@@ -434,8 +489,20 @@ + + bzero(&hdr, sizeof(hdr)); + bzero(&sg, sizeof(sg)); ++ bzero(&sg6, sizeof(sg6)); + bzero(&pad, sizeof(pad)); + ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_family = PF_UNSPEC; ++ hints.ai_socktype = SOCK_DGRAM; /* dummy */ ++ hints.ai_protocol = IPPROTO_UDP; /* dummy */ ++ hints.ai_flags = AI_NUMERICHOST; ++ ++ if (getaddrinfo(ip, NULL, &hints, &res) != 0) { ++ warnx("Invalid ip address: %s", ip); ++ return; ++ } ++ + fromlen = strlen(from) + 1; + tolen = strlen(to) + 1; + helolen = strlen(helo) + 1; +@@ -443,12 +510,15 @@ + HMAC_CTX_init(&ctx); + HMAC_Init(&ctx, sync_key, strlen(sync_key), EVP_sha1()); + +- sglen = sizeof(sg) + fromlen + tolen + helolen; ++ if (res->ai_family == AF_INET) ++ sglen = sizeof(sg) + fromlen + tolen + helolen; ++ else ++ sglen = sizeof(sg6) + fromlen + tolen + helolen; + padlen = SPAM_ALIGN(sglen) - sglen; + + /* Add SPAM sync packet header */ + hdr.sh_version = SPAM_SYNC_VERSION; +- hdr.sh_af = AF_INET; ++ hdr.sh_af = res->ai_family; + hdr.sh_counter = htonl(sync_counter++); + hdr.sh_length = htons(sizeof(hdr) + sglen + padlen + sizeof(end)); + iov[i].iov_base = &hdr; +@@ -456,16 +526,35 @@ + HMAC_Update(&ctx, iov[i].iov_base, iov[i].iov_len); + i++; + +- /* Add single SPAM sync greylisting entry */ +- sg.sg_type = htons(SPAM_SYNC_GREY); +- sg.sg_length = htons(sglen + padlen); +- sg.sg_timestamp = htonl(now); +- sg.sg_ip = inet_addr(ip); +- sg.sg_from_length = htons(fromlen); +- sg.sg_to_length = htons(tolen); +- sg.sg_helo_length = htons(helolen); +- iov[i].iov_base = &sg; +- iov[i].iov_len = sizeof(sg); ++ if (res->ai_family == AF_INET) { ++ /* Add single SPAM sync greylisting entry */ ++ sg.sg_type = htons(SPAM_SYNC_GREY); ++ sg.sg_length = htons(sglen + padlen); ++ sg.sg_timestamp = htonl(now); ++ ++ inet_pton(AF_INET, ip, &sg.sg_ip); ++ ++ sg.sg_from_length = htons(fromlen); ++ sg.sg_to_length = htons(tolen); ++ sg.sg_helo_length = htons(helolen); ++ iov[i].iov_base = &sg; ++ iov[i].iov_len = sizeof(sg); ++ } else { ++ /* Add single SPAM sync greylisting entry */ ++ sg6.sg6_type = htons(SPAM_SYNC_GREY); ++ sg6.sg6_length = htons(sglen + padlen); ++ sg6.sg6_timestamp = htonl(now); ++ ++ inet_pton(AF_INET6, ip, &sg6.sg6_ip); ++ ++ sg6.sg6_from_length = htons(fromlen); ++ sg6.sg6_to_length = htons(tolen); ++ sg6.sg6_helo_length = htons(helolen); ++ iov[i].iov_base = &sg6; ++ iov[i].iov_len = sizeof(sg6); ++ } ++ freeaddrinfo(res); ++ + HMAC_Update(&ctx, iov[i].iov_base, iov[i].iov_len); + i++; + +@@ -510,7 +599,9 @@ + struct iovec iov[3]; + struct spam_synchdr hdr; + struct spam_synctlv_addr sd; ++ struct spam_synctlv_addr6 sd6; + struct spam_synctlv_hdr end; ++ struct addrinfo hints, *res; + int i = 0; + HMAC_CTX ctx; + u_int hmac_len; +@@ -521,28 +612,60 @@ + + bzero(&hdr, sizeof(hdr)); + bzero(&sd, sizeof(sd)); ++ bzero(&sd6, sizeof(sd6)); ++ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_family = PF_UNSPEC; ++ hints.ai_socktype = SOCK_DGRAM; /* dummy */ ++ hints.ai_protocol = IPPROTO_UDP; /* dummy */ ++ hints.ai_flags = AI_NUMERICHOST; ++ ++ if (getaddrinfo(ip, NULL, &hints, &res) != 0) { ++ warnx("Invalid ip address: %s", ip); ++ return; ++ } + + HMAC_CTX_init(&ctx); + HMAC_Init(&ctx, sync_key, strlen(sync_key), EVP_sha1()); + + /* Add SPAM sync packet header */ + hdr.sh_version = SPAM_SYNC_VERSION; +- hdr.sh_af = AF_INET; ++ hdr.sh_af = res->ai_family; + hdr.sh_counter = htonl(sync_counter++); +- hdr.sh_length = htons(sizeof(hdr) + sizeof(sd) + sizeof(end)); ++ if (res->ai_family == AF_INET) ++ hdr.sh_length = htons(sizeof(hdr) + sizeof(sd) + sizeof(end)); ++ else ++ hdr.sh_length = htons(sizeof(hdr) + sizeof(sd6) + sizeof(end)); + iov[i].iov_base = &hdr; + iov[i].iov_len = sizeof(hdr); + HMAC_Update(&ctx, iov[i].iov_base, iov[i].iov_len); + i++; + +- /* Add single SPAM sync address entry */ +- sd.sd_type = htons(type); +- sd.sd_length = htons(sizeof(sd)); +- sd.sd_timestamp = htonl(now); +- sd.sd_expire = htonl(expire); +- sd.sd_ip = inet_addr(ip); +- iov[i].iov_base = &sd; +- iov[i].iov_len = sizeof(sd); ++ if (res->ai_family == AF_INET) { ++ /* Add single SPAM sync address entry */ ++ sd.sd_type = htons(type); ++ sd.sd_length = htons(sizeof(sd)); ++ sd.sd_timestamp = htonl(now); ++ sd.sd_expire = htonl(expire); ++ ++ inet_pton(AF_INET, ip, &sd.sd_ip); ++ ++ iov[i].iov_base = &sd; ++ iov[i].iov_len = sizeof(sd); ++ } else { ++ /* Add single SPAM sync address entry */ ++ sd6.sd6_type = htons(type); ++ sd6.sd6_length = htons(sizeof(sd)); ++ sd6.sd6_timestamp = htonl(now); ++ sd6.sd6_expire = htonl(expire); ++ ++ inet_pton(AF_INET6, ip, &sd6.sd6_ip); ++ ++ iov[i].iov_base = &sd6; ++ iov[i].iov_len = sizeof(sd6); ++ } ++ freeaddrinfo(res); ++ + HMAC_Update(&ctx, iov[i].iov_base, iov[i].iov_len); + i++; + +Index: sync.h +=================================================================== +RCS file: /cvs/src/libexec/spamd/sync.h,v +retrieving revision 1.3 +diff -u -r1.3 sync.h +--- sync.h 22 May 2008 19:54:11 -0000 1.3 ++++ sync.h 31 Dec 2015 20:25:24 -0000 +@@ -68,12 +68,31 @@ + /* strings go here, then packet code re-aligns packet */ + } __packed; + ++struct spam_synctlv_grey6 { ++ u_int16_t sg6_type; ++ u_int16_t sg6_length; ++ u_int32_t sg6_timestamp; ++ u_int32_t sg6_ip[4]; ++ u_int16_t sg6_from_length; ++ u_int16_t sg6_to_length; ++ u_int16_t sg6_helo_length; ++ /* strings go here, then packet code re-aligns packet */ ++} __packed; ++ + struct spam_synctlv_addr { + u_int16_t sd_type; + u_int16_t sd_length; + u_int32_t sd_timestamp; + u_int32_t sd_expire; + u_int32_t sd_ip; ++} __packed; ++ ++struct spam_synctlv_addr6 { ++ u_int16_t sd6_type; ++ u_int16_t sd6_length; ++ u_int32_t sd6_timestamp; ++ u_int32_t sd6_expire; ++ u_int32_t sd6_ip[4]; + } __packed; + + #define SPAM_SYNC_END 0x0000 |