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