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