diff -ur spamass-milter-0.3.1/spamass-milter.cpp spamass-milter-0.3.1-mine/spamass-milter.cpp --- spamass-milter-0.3.1/spamass-milter.cpp 2010-01-31 11:35:47.000000000 +0000 +++ spamass-milter-0.3.1-mine/spamass-milter.cpp 2008-01-09 01:20:38.000000000 +0000 @@ -88,6 +88,7 @@ #include "subst_poll.h" #endif #include +#include // C++ includes #include @@ -721,12 +722,19 @@ sctx = (struct context *)malloc(sizeof(*sctx)); if (!hostaddr) { + static struct sockaddr_in localhost; + /* not a socket; probably a local user calling sendmail directly */ /* set to 127.0.0.1 */ - sctx->connect_ip.s_addr = htonl(INADDR_LOOPBACK); + strcpy(sctx->connect_ip, "127.0.0.1"); + localhost.sin_family = AF_INET; + localhost.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + hostaddr = (struct sockaddr*) &localhost; } else { - sctx->connect_ip = ((struct sockaddr_in *) hostaddr)->sin_addr; + getnameinfo(hostaddr, sizeof(struct sockaddr_in6), + sctx->connect_ip, 63, NULL, 0, NI_NUMERICHOST); + debug(D_FUNC, "Remote address: %s", sctx->connect_ip); } sctx->assassin = NULL; sctx->helo = NULL; @@ -740,10 +748,12 @@ } /* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */ - if (ip_in_networklist(sctx->connect_ip, &ignorenets)) + //debug(D_FUNC, "sctx->connect_ip: `%d'", sctx->connect_ip.sin_family); + + if (ip_in_networklist(hostaddr, &ignorenets)) { debug(D_NET, "%s is in our ignore list - accepting message", - inet_ntoa(sctx->connect_ip)); + sctx->connect_ip); debug(D_FUNC, "mlfi_connect: exit ignore"); return SMFIS_ACCEPT; } @@ -815,7 +825,7 @@ return SMFIS_TEMPFAIL; }; - assassin->set_connectip(string(inet_ntoa(sctx->connect_ip))); + assassin->set_connectip(string(sctx->connect_ip)); // Store a pointer to the assassin object in our context struct sctx->assassin = assassin; @@ -1024,9 +1034,9 @@ assassin->output((string) "Received: from "+macro_s+" ("+macro__+")\r\n\t"+ - "by "+macro_j+" ("+macro_v+"/"+macro_Z+") with "+macro_r+" id "+macro_i+"\r\n\t"+ + "by "+macro_j+"("+macro_v+"/"+macro_Z+") with "+macro_r+" id "+macro_i+"\r\n\t"+ macro_b+"\r\n\t"+ - "(envelope-from "+assassin->from()+")\r\n"); + "(envelope-from "+assassin->from()+"\r\n"); } else assassin->output((string)"X-Envelope-To: "+envrcpt[0]+"\r\n"); @@ -2089,69 +2099,119 @@ { char *tnet = strsep(&token, "/"); char *tmask = token; - struct in_addr net, mask; + struct in_addr net; + struct in6_addr net6; if (list->num_nets % 10 == 0) - list->nets = (struct net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10)); + list->nets = (union net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10)); - if (!inet_aton(tnet, &net)) + if (inet_pton(AF_INET, tnet, &net)) { - fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet); - exit(1); - } + struct in_addr mask; + + if (tmask) + { + if (strchr(tmask, '.') == NULL) + { + /* CIDR */ + unsigned int bits; + int ret; + ret = sscanf(tmask, "%u", &bits); + if (ret != 1 || bits > 32) + { + fprintf(stderr,"%s: bad CIDR value", tmask); + exit(1); + } + mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff); + } else if (!inet_pton(AF_INET6, tmask, &mask)) + { + fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask); + exit(1); + } + } else + mask.s_addr = 0xffffffff; + + { + char *snet = strdup(inet_ntoa(net)); + debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask)); + free(snet); + } - if (tmask) + net.s_addr = net.s_addr & mask.s_addr; + list->nets[list->num_nets].net4.af = AF_INET; + list->nets[list->num_nets].net4.network = net; + list->nets[list->num_nets].net4.netmask = mask; + list->num_nets++; + } else if (inet_pton(AF_INET6, tnet, &net6)) { - if (strchr(tmask, '.') == NULL) + int mask; + + if (tmask) { - /* CIDR */ - unsigned int bits; - int ret; - ret = sscanf(tmask, "%u", &bits); - if (ret != 1 || bits > 32) + if (sscanf(tmask, "%d", &mask) != 1 || mask > 128) { fprintf(stderr,"%s: bad CIDR value", tmask); exit(1); } - mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff); - } else if (!inet_aton(tmask, &mask)) - { - fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask); - exit(1); - } + } else + mask = 128; + + list->nets[list->num_nets].net6.af = AF_INET6; + list->nets[list->num_nets].net6.network = net6; + list->nets[list->num_nets].net6.netmask = mask; + list->num_nets++; } else - mask.s_addr = 0xffffffff; - { - char *snet = strdup(inet_ntoa(net)); - debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask)); - free(snet); + fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet); + exit(1); } - net.s_addr = net.s_addr & mask.s_addr; - list->nets[list->num_nets].network = net; - list->nets[list->num_nets].netmask = mask; - list->num_nets++; } free(string); } -int ip_in_networklist(struct in_addr ip, struct networklist *list) +int ip_in_networklist(struct sockaddr *addr, struct networklist *list) { int i; if (list->num_nets == 0) return 0; - - debug(D_NET, "Checking %s against:", inet_ntoa(ip)); + + //debug(D_NET, "Checking %s against:", inet_ntoa(ip)); for (i = 0; i < list->num_nets; i++) { - debug(D_NET, "%s", inet_ntoa(list->nets[i].network)); - debug(D_NET, "/%s", inet_ntoa(list->nets[i].netmask)); - if ((ip.s_addr & list->nets[i].netmask.s_addr) == list->nets[i].network.s_addr) - { - debug(D_NET, "Hit!"); - return 1; + if (list->nets[i].net.af == AF_INET && addr->sa_family == AF_INET) + { + struct in_addr ip = ((struct sockaddr_in *)addr)->sin_addr; + + debug(D_NET, "%s", inet_ntoa(list->nets[i].net4.network)); + debug(D_NET, "/%s", inet_ntoa(list->nets[i].net4.netmask)); + if ((ip.s_addr & list->nets[i].net4.netmask.s_addr) == list->nets[i].net4.network.s_addr) + { + debug(D_NET, "Hit!"); + return 1; + } + } else if (list->nets[i].net.af == AF_INET6 && addr->sa_family == AF_INET6) + { + u_int8_t *ip = ((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr; + int mask, j; + + mask = list->nets[i].net6.netmask; + for (j = 0; j < 16 && mask > 0; j++, mask -= 8) + { + unsigned char bytemask; + + bytemask = (mask < 8) ? ~((1L << (8 - mask)) - 1) : 0xff; + + if ((ip[j] & bytemask) != (list->nets[i].net6.network.s6_addr[j] & bytemask)) + break; + } + + if (mask <= 0) + { + debug(D_NET, "Hit!"); + return 1; + } } } diff -ur spamass-milter-0.3.1/spamass-milter.h spamass-milter-0.3.1-mine/spamass-milter.h --- spamass-milter-0.3.1/spamass-milter.h 2006-03-23 22:07:55.000000000 +0000 +++ spamass-milter-0.3.1-mine/spamass-milter.h 2008-01-01 23:55:44.000000000 +0000 @@ -56,16 +56,30 @@ extern struct smfiDesc smfilter; /* struct describing a single network */ -struct net +union net { - struct in_addr network; - struct in_addr netmask; + struct + { + uint8_t af; + } net; + struct + { + uint8_t af; + struct in_addr network; + struct in_addr netmask; + } net4; + struct + { + uint8_t af; + struct in6_addr network; + int netmask; /* Just the number of bits for IPv6 */ + } net6; }; /* an array of networks */ struct networklist { - struct net *nets; + union net *nets; int num_nets; }; @@ -165,7 +179,7 @@ /* Private data structure to carry per-client data between calls */ struct context { - struct in_addr connect_ip; // remote IP address + char connect_ip[64]; // remote IP address char *helo; SpamAssassin *assassin; // pointer to the SA object if we're processing a message }; @@ -182,7 +196,7 @@ int cmp_nocase_partial(const string&, const string&); void closeall(int fd); void parse_networklist(char *string, struct networklist *list); -int ip_in_networklist(struct in_addr ip, struct networklist *list); +int ip_in_networklist(struct sockaddr *addr, struct networklist *list); void parse_debuglevel(char* string); char *strlwr(char *str); void warnmacro(char *macro, char *scope); Only in spamass-milter-0.3.1-mine: spamass-milter.o