Link Here
|
1 |
diff -ur orig/spamass-milter.cpp spamass-milter.cpp |
2 |
--- orig/spamass-milter.cpp 2010-01-31 11:35:47.000000000 +0000 |
3 |
+++ spamass-milter.cpp 2008-01-09 01:20:38.000000000 +0000 |
4 |
@@ -88,6 +88,7 @@ |
5 |
#include "subst_poll.h" |
6 |
#endif |
7 |
#include <errno.h> |
8 |
+#include <netdb.h> |
9 |
|
10 |
// C++ includes |
11 |
#include <cstdio> |
12 |
@@ -721,12 +722,19 @@ |
13 |
sctx = (struct context *)malloc(sizeof(*sctx)); |
14 |
if (!hostaddr) |
15 |
{ |
16 |
+ static struct sockaddr_in localhost; |
17 |
+ |
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; |
25 |
} else |
26 |
{ |
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); |
30 |
+ debug(D_FUNC, "Remote address: %s", sctx->connect_ip); |
31 |
} |
32 |
sctx->assassin = NULL; |
33 |
sctx->helo = NULL; |
34 |
@@ -740,10 +748,12 @@ |
35 |
} |
36 |
/* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */ |
37 |
|
38 |
- if (ip_in_networklist(sctx->connect_ip, &ignorenets)) |
39 |
+ //debug(D_FUNC, "sctx->connect_ip: `%d'", sctx->connect_ip.sin_family); |
40 |
+ |
41 |
+ if (ip_in_networklist(hostaddr, &ignorenets)) |
42 |
{ |
43 |
debug(D_NET, "%s is in our ignore list - accepting message", |
44 |
- inet_ntoa(sctx->connect_ip)); |
45 |
+ sctx->connect_ip); |
46 |
debug(D_FUNC, "mlfi_connect: exit ignore"); |
47 |
return SMFIS_ACCEPT; |
48 |
} |
49 |
@@ -815,7 +825,7 @@ |
50 |
return SMFIS_TEMPFAIL; |
51 |
}; |
52 |
|
53 |
- assassin->set_connectip(string(inet_ntoa(sctx->connect_ip))); |
54 |
+ assassin->set_connectip(string(sctx->connect_ip)); |
55 |
|
56 |
// Store a pointer to the assassin object in our context struct |
57 |
sctx->assassin = assassin; |
58 |
@@ -2089,69 +2099,119 @@ |
59 |
{ |
60 |
char *tnet = strsep(&token, "/"); |
61 |
char *tmask = token; |
62 |
- struct in_addr net, mask; |
63 |
+ struct in_addr net; |
64 |
+ struct in6_addr net6; |
65 |
|
66 |
if (list->num_nets % 10 == 0) |
67 |
- list->nets = (struct net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10)); |
68 |
+ list->nets = (union net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10)); |
69 |
|
70 |
- if (!inet_aton(tnet, &net)) |
71 |
+ if (inet_pton(AF_INET, tnet, &net)) |
72 |
{ |
73 |
- fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet); |
74 |
- exit(1); |
75 |
- } |
76 |
+ struct in_addr mask; |
77 |
+ |
78 |
+ if (tmask) |
79 |
+ { |
80 |
+ if (strchr(tmask, '.') == NULL) |
81 |
+ { |
82 |
+ /* CIDR */ |
83 |
+ unsigned int bits; |
84 |
+ int ret; |
85 |
+ ret = sscanf(tmask, "%u", &bits); |
86 |
+ if (ret != 1 || bits > 32) |
87 |
+ { |
88 |
+ fprintf(stderr,"%s: bad CIDR value", tmask); |
89 |
+ exit(1); |
90 |
+ } |
91 |
+ mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff); |
92 |
+ } else if (!inet_pton(AF_INET6, tmask, &mask)) |
93 |
+ { |
94 |
+ fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask); |
95 |
+ exit(1); |
96 |
+ } |
97 |
+ } else |
98 |
+ mask.s_addr = 0xffffffff; |
99 |
+ |
100 |
+ { |
101 |
+ char *snet = strdup(inet_ntoa(net)); |
102 |
+ debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask)); |
103 |
+ free(snet); |
104 |
+ } |
105 |
|
106 |
- if (tmask) |
107 |
+ net.s_addr = net.s_addr & mask.s_addr; |
108 |
+ list->nets[list->num_nets].net4.af = AF_INET; |
109 |
+ list->nets[list->num_nets].net4.network = net; |
110 |
+ list->nets[list->num_nets].net4.netmask = mask; |
111 |
+ list->num_nets++; |
112 |
+ } else if (inet_pton(AF_INET6, tnet, &net6)) |
113 |
{ |
114 |
- if (strchr(tmask, '.') == NULL) |
115 |
+ int mask; |
116 |
+ |
117 |
+ if (tmask) |
118 |
{ |
119 |
- /* CIDR */ |
120 |
- unsigned int bits; |
121 |
- int ret; |
122 |
- ret = sscanf(tmask, "%u", &bits); |
123 |
- if (ret != 1 || bits > 32) |
124 |
+ if (sscanf(tmask, "%d", &mask) != 1 || mask > 128) |
125 |
{ |
126 |
fprintf(stderr,"%s: bad CIDR value", tmask); |
127 |
exit(1); |
128 |
} |
129 |
- mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff); |
130 |
- } else if (!inet_aton(tmask, &mask)) |
131 |
- { |
132 |
- fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask); |
133 |
- exit(1); |
134 |
- } |
135 |
+ } else |
136 |
+ mask = 128; |
137 |
+ |
138 |
+ list->nets[list->num_nets].net6.af = AF_INET6; |
139 |
+ list->nets[list->num_nets].net6.network = net6; |
140 |
+ list->nets[list->num_nets].net6.netmask = mask; |
141 |
+ list->num_nets++; |
142 |
} else |
143 |
- mask.s_addr = 0xffffffff; |
144 |
- |
145 |
{ |
146 |
- char *snet = strdup(inet_ntoa(net)); |
147 |
- debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask)); |
148 |
- free(snet); |
149 |
+ fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet); |
150 |
+ exit(1); |
151 |
} |
152 |
|
153 |
- net.s_addr = net.s_addr & mask.s_addr; |
154 |
- list->nets[list->num_nets].network = net; |
155 |
- list->nets[list->num_nets].netmask = mask; |
156 |
- list->num_nets++; |
157 |
} |
158 |
free(string); |
159 |
} |
160 |
|
161 |
-int ip_in_networklist(struct in_addr ip, struct networklist *list) |
162 |
+int ip_in_networklist(struct sockaddr *addr, struct networklist *list) |
163 |
{ |
164 |
int i; |
165 |
|
166 |
if (list->num_nets == 0) |
167 |
return 0; |
168 |
- |
169 |
- debug(D_NET, "Checking %s against:", inet_ntoa(ip)); |
170 |
+ |
171 |
+ //debug(D_NET, "Checking %s against:", inet_ntoa(ip)); |
172 |
for (i = 0; i < list->num_nets; i++) |
173 |
{ |
174 |
- debug(D_NET, "%s", inet_ntoa(list->nets[i].network)); |
175 |
- debug(D_NET, "/%s", inet_ntoa(list->nets[i].netmask)); |
176 |
- if ((ip.s_addr & list->nets[i].netmask.s_addr) == list->nets[i].network.s_addr) |
177 |
- { |
178 |
- debug(D_NET, "Hit!"); |
179 |
- return 1; |
180 |
+ if (list->nets[i].net.af == AF_INET && addr->sa_family == AF_INET) |
181 |
+ { |
182 |
+ struct in_addr ip = ((struct sockaddr_in *)addr)->sin_addr; |
183 |
+ |
184 |
+ debug(D_NET, "%s", inet_ntoa(list->nets[i].net4.network)); |
185 |
+ debug(D_NET, "/%s", inet_ntoa(list->nets[i].net4.netmask)); |
186 |
+ if ((ip.s_addr & list->nets[i].net4.netmask.s_addr) == list->nets[i].net4.network.s_addr) |
187 |
+ { |
188 |
+ debug(D_NET, "Hit!"); |
189 |
+ return 1; |
190 |
+ } |
191 |
+ } else if (list->nets[i].net.af == AF_INET6 && addr->sa_family == AF_INET6) |
192 |
+ { |
193 |
+ u_int8_t *ip = ((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr; |
194 |
+ int mask, j; |
195 |
+ |
196 |
+ mask = list->nets[i].net6.netmask; |
197 |
+ for (j = 0; j < 16 && mask > 0; j++, mask -= 8) |
198 |
+ { |
199 |
+ unsigned char bytemask; |
200 |
+ |
201 |
+ bytemask = (mask < 8) ? ~((1L << (8 - mask)) - 1) : 0xff; |
202 |
+ |
203 |
+ if ((ip[j] & bytemask) != (list->nets[i].net6.network.s6_addr[j] & bytemask)) |
204 |
+ break; |
205 |
+ } |
206 |
+ |
207 |
+ if (mask <= 0) |
208 |
+ { |
209 |
+ debug(D_NET, "Hit!"); |
210 |
+ return 1; |
211 |
+ } |
212 |
} |
213 |
} |
214 |
|
215 |
diff -ur orig/spamass-milter.h spamass-milter.h |
216 |
--- orig/spamass-milter.h 2006-03-23 22:07:55.000000000 +0000 |
217 |
+++ spamass-milter.h 2008-01-01 23:55:44.000000000 +0000 |
218 |
@@ -56,16 +56,30 @@ |
219 |
extern struct smfiDesc smfilter; |
220 |
|
221 |
/* struct describing a single network */ |
222 |
-struct net |
223 |
+union net |
224 |
{ |
225 |
- struct in_addr network; |
226 |
- struct in_addr netmask; |
227 |
+ struct |
228 |
+ { |
229 |
+ uint8_t af; |
230 |
+ } net; |
231 |
+ struct |
232 |
+ { |
233 |
+ uint8_t af; |
234 |
+ struct in_addr network; |
235 |
+ struct in_addr netmask; |
236 |
+ } net4; |
237 |
+ struct |
238 |
+ { |
239 |
+ uint8_t af; |
240 |
+ struct in6_addr network; |
241 |
+ int netmask; /* Just the number of bits for IPv6 */ |
242 |
+ } net6; |
243 |
}; |
244 |
|
245 |
/* an array of networks */ |
246 |
struct networklist |
247 |
{ |
248 |
- struct net *nets; |
249 |
+ union net *nets; |
250 |
int num_nets; |
251 |
}; |
252 |
|
253 |
@@ -165,7 +179,7 @@ |
254 |
/* Private data structure to carry per-client data between calls */ |
255 |
struct context |
256 |
{ |
257 |
- struct in_addr connect_ip; // remote IP address |
258 |
+ char connect_ip[64]; // remote IP address |
259 |
char *helo; |
260 |
SpamAssassin *assassin; // pointer to the SA object if we're processing a message |
261 |
}; |
262 |
@@ -182,7 +196,7 @@ |
263 |
int cmp_nocase_partial(const string&, const string&); |
264 |
void closeall(int fd); |
265 |
void parse_networklist(char *string, struct networklist *list); |
266 |
-int ip_in_networklist(struct in_addr ip, struct networklist *list); |
267 |
+int ip_in_networklist(struct sockaddr *addr, struct networklist *list); |
268 |
void parse_debuglevel(char* string); |
269 |
char *strlwr(char *str); |
270 |
void warnmacro(char *macro, char *scope); |