1 diff -up spamass-milter-0.3.1/spamass-milter.cpp.ipv6 spamass-milter-0.3.1/spamass-milter.cpp
2 --- spamass-milter-0.3.1/spamass-milter.cpp.ipv6 2010-09-23 16:26:36.227224902 +0100
3 +++ spamass-milter-0.3.1/spamass-milter.cpp 2010-09-23 17:25:22.307099331 +0100
5 #include "subst_poll.h"
12 @@ -718,12 +719,18 @@ mlfi_connect(SMFICTX * ctx, char *hostna
13 sctx = (struct context *)malloc(sizeof(*sctx));
16 + static struct sockaddr_in localhost;
18 /* not a socket; probably a local user calling sendmail directly */
19 /* set to 127.0.0.1 */
20 - sctx->connect_ip.s_addr = htonl(INADDR_LOOPBACK);
21 + strcpy(sctx->connect_ip, "127.0.0.1");
22 + localhost.sin_family = AF_INET;
23 + localhost.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
24 + hostaddr = (struct sockaddr*) &localhost;
27 - sctx->connect_ip = ((struct sockaddr_in *) hostaddr)->sin_addr;
28 + getnameinfo(hostaddr, sizeof(struct sockaddr_in6),
29 + sctx->connect_ip, 63, NULL, 0, NI_NUMERICHOST);
31 sctx->assassin = NULL;
33 @@ -758,12 +765,12 @@ mlfi_connect(SMFICTX * ctx, char *hostna
34 debug(D_ALWAYS, "smfi_setpriv failed!");
35 return SMFIS_TEMPFAIL;
37 - /* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */
39 - if (ip_in_networklist(sctx->connect_ip, &ignorenets))
40 + debug(D_NET, "Checking %s against:", sctx->connect_ip);
41 + if (ip_in_networklist(hostaddr, &ignorenets))
43 debug(D_NET, "%s is in our ignore list - accepting message",
44 - inet_ntoa(sctx->connect_ip));
46 debug(D_FUNC, "mlfi_connect: exit ignore");
49 @@ -807,7 +814,6 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro
50 debug(D_ALWAYS, "smfi_getpriv failed!");
51 return SMFIS_TEMPFAIL;
53 - /* debug(D_ALWAYS, "ZZZ got private context %p", sctx); */
55 if (ignore_authenticated_senders)
57 @@ -835,7 +841,7 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro
58 return SMFIS_TEMPFAIL;
61 - assassin->set_connectip(string(inet_ntoa(sctx->connect_ip)));
62 + assassin->set_connectip(string(sctx->connect_ip));
64 // Store a pointer to the assassin object in our context struct
65 sctx->assassin = assassin;
66 @@ -2128,69 +2134,135 @@ void parse_networklist(char *string, str
68 char *tnet = strsep(&token, "/");
70 - struct in_addr net, mask;
72 + struct in6_addr net6;
74 if (list->num_nets % 10 == 0)
75 - list->nets = (struct net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10));
76 + list->nets = (union net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10));
78 - if (!inet_aton(tnet, &net))
79 + if (inet_pton(AF_INET, tnet, &net))
81 - fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet);
84 + struct in_addr mask;
88 + if (strchr(tmask, '.') == NULL)
93 + ret = sscanf(tmask, "%u", &bits);
94 + if (ret != 1 || bits > 32)
96 + fprintf(stderr,"%s: bad CIDR value", tmask);
99 + mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff);
100 + } else if (!inet_pton(AF_INET6, tmask, &mask))
102 + fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask);
106 + mask.s_addr = 0xffffffff;
110 - if (strchr(tmask, '.') == NULL)
111 + net.s_addr = net.s_addr & mask.s_addr;
112 + list->nets[list->num_nets].net4.af = AF_INET;
113 + list->nets[list->num_nets].net4.network = net;
114 + list->nets[list->num_nets].net4.netmask = mask;
115 + } else if (inet_pton(AF_INET6, tnet, &net6))
124 - ret = sscanf(tmask, "%u", &bits);
125 - if (ret != 1 || bits > 32)
126 + if (sscanf(tmask, "%d", &mask) != 1 || mask > 128)
128 fprintf(stderr,"%s: bad CIDR value", tmask);
131 - mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff);
132 - } else if (!inet_aton(tmask, &mask))
134 - fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask);
140 + list->nets[list->num_nets].net6.af = AF_INET6;
141 + list->nets[list->num_nets].net6.network = net6;
142 + list->nets[list->num_nets].net6.netmask = mask;
144 - mask.s_addr = 0xffffffff;
146 + fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet);
151 - char *snet = strdup(inet_ntoa(net));
152 - debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask));
154 + int af = list->nets[list->num_nets].net.af;
155 + char addrbuf[INET6_ADDRSTRLEN];
159 + if (af == AF_INET6) {
160 + inet_ntop(af, &list->nets[list->num_nets].net6.network,
161 + addrbuf, INET6_ADDRSTRLEN);
162 + sprintf(maskbuf, "%d", list->nets[list->num_nets].net6.netmask);
164 + list->nets[list->num_nets].net6.addrstr = strdup(addrbuf);
165 + list->nets[list->num_nets].net6.maskstr = strdup(maskbuf);
168 + inet_ntop(af, &list->nets[list->num_nets].net4.network,
169 + addrbuf, INET6_ADDRSTRLEN);
170 + maskstr = inet_ntoa(list->nets[list->num_nets].net4.netmask);
171 + list->nets[list->num_nets].net4.addrstr = strdup(addrbuf);
172 + list->nets[list->num_nets].net4.maskstr = strdup(maskstr);
174 + debug(D_MISC, "Added %s/%s to network list", addrbuf, maskstr);
177 - net.s_addr = net.s_addr & mask.s_addr;
178 - list->nets[list->num_nets].network = net;
179 - list->nets[list->num_nets].netmask = mask;
185 -int ip_in_networklist(struct in_addr ip, struct networklist *list)
186 +int ip_in_networklist(struct sockaddr *addr, struct networklist *list)
190 if (list->num_nets == 0)
193 - debug(D_NET, "Checking %s against:", inet_ntoa(ip));
195 for (i = 0; i < list->num_nets; i++)
197 - debug(D_NET, "%s", inet_ntoa(list->nets[i].network));
198 - debug(D_NET, "/%s", inet_ntoa(list->nets[i].netmask));
199 - if ((ip.s_addr & list->nets[i].netmask.s_addr) == list->nets[i].network.s_addr)
201 - debug(D_NET, "Hit!");
203 + if (list->nets[i].net.af == AF_INET && addr->sa_family == AF_INET)
205 + struct in_addr ip = ((struct sockaddr_in *)addr)->sin_addr;
207 + debug(D_NET, "%s/%s", list->nets[i].net4.addrstr, list->nets[i].net4.maskstr);
208 + if ((ip.s_addr & list->nets[i].net4.netmask.s_addr) == list->nets[i].net4.network.s_addr)
210 + debug(D_NET, "Hit!");
213 + } else if (list->nets[i].net.af == AF_INET6 && addr->sa_family == AF_INET6)
215 + u_int8_t *ip = ((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr;
218 + debug(D_NET, "%s/%s", list->nets[i].net6.addrstr, list->nets[i].net6.maskstr);
219 + mask = list->nets[i].net6.netmask;
220 + for (j = 0; j < 16 && mask > 0; j++, mask -= 8)
222 + unsigned char bytemask;
224 + bytemask = (mask < 8) ? ~((1L << (8 - mask)) - 1) : 0xff;
226 + if ((ip[j] & bytemask) != (list->nets[i].net6.network.s6_addr[j] & bytemask))
232 + debug(D_NET, "Hit!");
238 diff -up spamass-milter-0.3.1/spamass-milter.h.ipv6 spamass-milter-0.3.1/spamass-milter.h
239 --- spamass-milter-0.3.1/spamass-milter.h.ipv6 2010-09-23 16:26:36.224160445 +0100
240 +++ spamass-milter-0.3.1/spamass-milter.h 2010-09-23 17:00:16.487410690 +0100
241 @@ -56,16 +56,34 @@ sfsistat mlfi_abort(SMFICTX*);
242 extern struct smfiDesc smfilter;
244 /* struct describing a single network */
248 - struct in_addr network;
249 - struct in_addr netmask;
257 + struct in_addr network;
258 + struct in_addr netmask;
265 + struct in6_addr network;
266 + int netmask; /* Just the number of bits for IPv6 */
272 /* an array of networks */
280 @@ -162,7 +180,7 @@ public:
281 /* Private data structure to carry per-client data between calls */
284 - struct in_addr connect_ip; // remote IP address
285 + char connect_ip[64]; // remote IP address
288 char *sender_address;
289 @@ -184,7 +202,7 @@ string::size_type find_nocase(const stri
290 int cmp_nocase_partial(const string&, const string&);
291 void closeall(int fd);
292 void parse_networklist(char *string, struct networklist *list);
293 -int ip_in_networklist(struct in_addr ip, struct networklist *list);
294 +int ip_in_networklist(struct sockaddr *addr, struct networklist *list);
295 void parse_debuglevel(char* string);
296 char *strlwr(char *str);
297 void warnmacro(const char *macro, const char *scope);