summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2015-07-03 16:20:57 +0200
committermanuel <manuel@mausz.at>2015-07-03 16:20:57 +0200
commitb2318b35c1f191f2500b69e547cddb05fe9b5ba4 (patch)
tree34db0035856fe2fbc6102d7ea7901018805769b8
parentc76a0244565136c708d945f3ef1d4e14c7d3e1f8 (diff)
downloadqmail-getdns.tar.gz
qmail-getdns.tar.bz2
qmail-getdns.zip
convert dns handling to getdnsgetdns
-rw-r--r--dns.c645
1 files changed, 312 insertions, 333 deletions
diff --git a/dns.c b/dns.c
index bed2bd2..5f8ba77 100644
--- a/dns.c
+++ b/dns.c
@@ -5,8 +5,8 @@
5#include <arpa/nameser.h> 5#include <arpa/nameser.h>
6#include <resolv.h> 6#include <resolv.h>
7#include <errno.h> 7#include <errno.h>
8extern int res_query(); 8#include <getdns/getdns.h>
9extern int res_search(); 9#include <string.h>
10#include "ip.h" 10#include "ip.h"
11#include "ipalloc.h" 11#include "ipalloc.h"
12#include "fmt.h" 12#include "fmt.h"
@@ -16,405 +16,384 @@ extern int res_search();
16#include "dns.h" 16#include "dns.h"
17#include "case.h" 17#include "case.h"
18 18
19static unsigned short getshort(c) unsigned char *c; 19static getdns_context *context = NULL;
20{ unsigned short u; u = c[0]; return (u << 8) + c[1]; } 20static stralloc glue = {0};
21 21
22static struct { unsigned char *buf; } response; 22static int getdns_resolve_query(const char *name, uint16_t type,
23static int responsebuflen = 0; 23 getdns_dict **response)
24static int responselen; 24{
25static unsigned char *responseend; 25 if (getdns_general_sync(context, name, type, NULL, response)
26static unsigned char *responsepos; 26 != GETDNS_RETURN_GOOD)
27static u_long saveresoptions; 27 return DNS_HARD;
28 28
29static int numanswers; 29 uint32_t error;
30static char name[MAXDNAME]; 30 getdns_dict_get_int(*response, "status", &error);
31static struct ip_address ip; 31 if (error != GETDNS_RESPSTATUS_GOOD)
32unsigned short pref; 32 return DNS_HARD;
33 33
34static stralloc glue = {0}; 34 return 0;
35 35}
36static int (*lookup)() = res_query;
37 36
38static int resolve(domain,type) 37static int getdns_resolve_loop(getdns_dict *response, uint16_t type,
39stralloc *domain; 38 int (*cb_rr)(getdns_dict *response, getdns_dict *rdata, void *userarg),
40int type; 39 void *userarg)
41{ 40{
42 int n; 41 getdns_list *answers;
43 int i; 42 if (getdns_dict_get_list(response, "replies_tree", &answers)
44 43 != GETDNS_RETURN_GOOD)
45 errno = 0; 44 return DNS_HARD;
46 if (!stralloc_copy(&glue,domain)) return DNS_MEM; 45
47 if (!stralloc_0(&glue)) return DNS_MEM; 46 size_t num_answers, rec_ix, num_cb = 0;
48 if (!responsebuflen) 47 getdns_list_get_length(answers, &num_answers);
49 if (response.buf = (unsigned char *)alloc(PACKETSZ+1)) 48 for (rec_ix = 0; rec_ix < num_answers; ++rec_ix) {
50 responsebuflen = PACKETSZ+1; 49 getdns_dict *record;
51 else return DNS_MEM; 50 getdns_list_get_dict(answers, rec_ix, &record);
52 51
53 responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen); 52 getdns_list *answer;
54 if ((responselen >= responsebuflen) || 53 getdns_dict_get_list(record, "answer", &answer);
55 (responselen > 0 && (((HEADER *)response.buf)->tc))) 54
56 { 55 size_t num_rr, rr_ix;
57 if (responsebuflen < 65536) 56 getdns_list_get_length(answer, &num_rr);
58 if (alloc_re(&response.buf, responsebuflen, 65536)) 57 for (rr_ix = 0; rr_ix < num_rr; ++rr_ix) {
59 responsebuflen = 65536; 58 getdns_dict *rr, *rr_rdata;
60 else return DNS_MEM; 59 uint32_t rr_type;
61 saveresoptions = _res.options; 60
62 _res.options |= RES_USEVC; 61 getdns_list_get_dict(answer, rr_ix, &rr);
63 responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen); 62 getdns_dict_get_int(rr, "type", &rr_type);
64 _res.options = saveresoptions; 63 if (rr_type != type)
65 } 64 continue;
66 if (responselen <= 0) 65
67 { 66 if (cb_rr != NULL)
68 if (errno == ECONNREFUSED) return DNS_SOFT; 67 {
69 if (h_errno == TRY_AGAIN) return DNS_SOFT; 68 getdns_dict_get_dict(rr, "rdata", &rr_rdata);
70 return DNS_HARD; 69 int cb = cb_rr(response, rr_rdata, userarg);
71 } 70 if (cb != 0)
72 responseend = response.buf + responselen; 71 return cb;
73 responsepos = response.buf + sizeof(HEADER); 72 }
74 n = ntohs(((HEADER *)response.buf)->qdcount); 73 ++num_cb;
75 while (n-- > 0) 74 }
76 {
77 i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
78 if (i < 0) return DNS_SOFT;
79 responsepos += i;
80 i = responseend - responsepos;
81 if (i < QFIXEDSZ) return DNS_SOFT;
82 responsepos += QFIXEDSZ;
83 } 75 }
84 numanswers = ntohs(((HEADER *)response.buf)->ancount); 76
85 return 0; 77 return num_cb;
86} 78}
87 79
88static int findname(wanttype) 80static int getdns_resolve(const char *name, uint16_t type,
89int wanttype; 81 int (*cb_rr)(getdns_dict *response, getdns_dict *rdata, void *userarg),
82 void *userarg)
90{ 83{
91 unsigned short rrtype; 84 getdns_dict *response = NULL;
92 unsigned short rrdlen; 85 int r = getdns_resolve_query(name, type, &response);
93 int i; 86 r |= getdns_resolve_loop(response, type, cb_rr, userarg);
94 87 getdns_dict_destroy(response);
95 if (numanswers <= 0) return 2; 88 return r;
96 --numanswers;
97 if (responsepos == responseend) return DNS_SOFT;
98
99 i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
100 if (i < 0) return DNS_SOFT;
101 responsepos += i;
102
103 i = responseend - responsepos;
104 if (i < 4 + 3 * 2) return DNS_SOFT;
105
106 rrtype = getshort(responsepos);
107 rrdlen = getshort(responsepos + 8);
108 responsepos += 10;
109
110 if (rrtype == wanttype)
111 {
112 if (dn_expand(response.buf,responseend,responsepos,name,MAXDNAME) < 0)
113 return DNS_SOFT;
114 responsepos += rrdlen;
115 return 1;
116 }
117
118 responsepos += rrdlen;
119 return 0;
120} 89}
121 90
122static int findip(wanttype) 91static int getdns_resolve_num(getdns_dict *response, uint16_t type, size_t *num)
123int wanttype;
124{ 92{
125 unsigned short rrtype; 93 int r = getdns_resolve_loop(response, type, NULL, NULL);
126 unsigned short rrdlen; 94 if (r < 0)
127 int i; 95 return r;
128 96 *num = r;
129 if (numanswers <= 0) return 2; 97 return 0;
130 --numanswers;
131 if (responsepos == responseend) return DNS_SOFT;
132
133 i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
134 if (i < 0) return DNS_SOFT;
135 responsepos += i;
136
137 i = responseend - responsepos;
138 if (i < 4 + 3 * 2) return DNS_SOFT;
139
140 rrtype = getshort(responsepos);
141 rrdlen = getshort(responsepos + 8);
142 responsepos += 10;
143
144 if (rrtype == wanttype)
145 {
146 if (rrdlen < 4)
147 return DNS_SOFT;
148 ip.d[0] = responsepos[0];
149 ip.d[1] = responsepos[1];
150 ip.d[2] = responsepos[2];
151 ip.d[3] = responsepos[3];
152 responsepos += rrdlen;
153 return 1;
154 }
155
156 responsepos += rrdlen;
157 return 0;
158} 98}
159 99
160static int findmx(wanttype) 100void dns_init(int flagsearch)
161int wanttype;
162{ 101{
163 unsigned short rrtype; 102 getdns_context_create(&context, 1);
164 unsigned short rrdlen; 103 getdns_context_set_resolution_type(context, GETDNS_RESOLUTION_STUB);
165 int i; 104 if (!flagsearch)
166 105 getdns_context_set_append_name(context, GETDNS_APPEND_NAME_NEVER);
167 if (numanswers <= 0) return 2; 106 else
168 --numanswers; 107 fprintf(stderr, "not supported!\n"); //FIXME
169 if (responsepos == responseend) return DNS_SOFT;
170
171 i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
172 if (i < 0) return DNS_SOFT;
173 responsepos += i;
174
175 i = responseend - responsepos;
176 if (i < 4 + 3 * 2) return DNS_SOFT;
177
178 rrtype = getshort(responsepos);
179 rrdlen = getshort(responsepos + 8);
180 responsepos += 10;
181
182 if (rrtype == wanttype)
183 {
184 if (rrdlen < 3)
185 return DNS_SOFT;
186 pref = (responsepos[0] << 8) + responsepos[1];
187 if (dn_expand(response.buf,responseend,responsepos + 2,name,MAXDNAME) < 0)
188 return DNS_SOFT;
189 responsepos += rrdlen;
190 return 1;
191 }
192
193 responsepos += rrdlen;
194 return 0;
195} 108}
196 109
197void dns_init(flagsearch) 110static int dns_cname_cb(getdns_dict *response, getdns_dict *rdata,
198int flagsearch; 111 void *userarg)
199{ 112{
200 res_init(); 113 stralloc *sa = userarg;
201 if (flagsearch) lookup = res_search; 114
115 getdns_bindata *bindata = NULL;
116 if (getdns_dict_get_bindata(rdata, "cname", &bindata)
117 != GETDNS_RETURN_GOOD)
118 return DNS_SOFT;
119
120 char *dname;
121 getdns_convert_dns_name_to_fqdn(bindata, &dname);
122 dname[strlen(dname) - 1] = '\0';
123 if (!stralloc_copys(sa, dname)) {
124 free(dname);
125 return DNS_MEM;
126 }
127 free(dname);
128 return 0;
202} 129}
203 130
204int dns_cname(sa) 131int dns_cname(stralloc *sa)
205stralloc *sa;
206{ 132{
207 int r; 133 int loop;
208 int loop; 134 for (loop = 0; loop < 10; ++loop)
209 for (loop = 0;loop < 10;++loop)
210 { 135 {
211 if (!sa->len) return loop; 136 if (!sa->len)
212 if (sa->s[sa->len - 1] == ']') return loop; 137 return loop;
213 if (sa->s[sa->len - 1] == '.') { --sa->len; continue; } 138 if (sa->s[sa->len - 1] == ']')
214 switch(resolve(sa,T_CNAME)) 139 return loop;
140 if (sa->s[sa->len - 1] == '.') {
141 --sa->len;
142 continue;
143 }
144
145 if (!stralloc_0(sa))
146 return DNS_MEM;
147 switch(getdns_resolve(sa->s, GETDNS_RRTYPE_CNAME, dns_cname_cb, sa))
215 { 148 {
216 case DNS_MEM: return DNS_MEM; 149 case DNS_MEM:
217 case DNS_SOFT: return DNS_SOFT; 150 return DNS_MEM;
218 case DNS_HARD: return loop; 151 case DNS_SOFT:
219 default: 152 return DNS_SOFT;
220 while ((r = findname(T_CNAME)) != 2) 153 case DNS_HARD:
221 { 154 case 0:
222 if (r == DNS_SOFT) return DNS_SOFT; 155 return loop;
223 if (r == 1)
224 {
225 if (!stralloc_copys(sa,name)) return DNS_MEM;
226 break;
227 }
228 }
229 if (r == 2) return loop;
230 } 156 }
231 } 157 }
232 return DNS_HARD; /* alias loop */ 158 return DNS_HARD; /* alias loop */
233} 159}
234 160
235#define FMT_IAA 40 161static int iaafmt(char *s, struct ip_address *ip)
236
237static int iaafmt(s,ip)
238char *s;
239struct ip_address *ip;
240{ 162{
241 unsigned int i; 163 unsigned int i, len = 0;
242 unsigned int len; 164 i = fmt_ulong(s, (unsigned long) ip->d[3]); len += i; if (s) s += i;
243 len = 0; 165 i = fmt_str(s, "."); len += i; if (s) s += i;
244 i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i; 166 i = fmt_ulong(s, (unsigned long) ip->d[2]); len += i; if (s) s += i;
245 i = fmt_str(s,"."); len += i; if (s) s += i; 167 i = fmt_str(s, "."); len += i; if (s) s += i;
246 i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i; 168 i = fmt_ulong(s, (unsigned long) ip->d[1]); len += i; if (s) s += i;
247 i = fmt_str(s,"."); len += i; if (s) s += i; 169 i = fmt_str(s, "."); len += i; if (s) s += i;
248 i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i; 170 i = fmt_ulong(s, (unsigned long) ip->d[0]); len += i; if (s) s += i;
249 i = fmt_str(s,"."); len += i; if (s) s += i; 171 i = fmt_str(s, ".in-addr.arpa."); len += i; if (s) s += i;
250 i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i; 172 return len;
251 i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i;
252 return len;
253} 173}
254 174
255int dns_ptr(sa,ip) 175static int dns_ptr_cb(getdns_dict *response, getdns_dict *rdata,
256stralloc *sa; 176 void *userarg)
257struct ip_address *ip;
258{ 177{
259 int r; 178 stralloc *sa = userarg;
260 179
261 if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM; 180 getdns_bindata *bindata = NULL;
262 sa->len = iaafmt(sa->s,ip); 181 if (getdns_dict_get_bindata(rdata, "rdata_raw", &bindata)
263 switch(resolve(sa,T_PTR)) 182 != GETDNS_RETURN_GOOD)
264 { 183 return DNS_SOFT;
265 case DNS_MEM: return DNS_MEM; 184
266 case DNS_SOFT: return DNS_SOFT; 185 char *dname;
267 case DNS_HARD: return DNS_HARD; 186 getdns_convert_dns_name_to_fqdn(bindata, &dname);
268 } 187 dname[strlen(dname) - 1] = '\0';
269 while ((r = findname(T_PTR)) != 2) 188 if (!stralloc_copys(sa, dname)) {
270 { 189 free(dname);
271 if (r == DNS_SOFT) return DNS_SOFT; 190 return DNS_MEM;
272 if (r == 1)
273 {
274 if (!stralloc_copys(sa,name)) return DNS_MEM;
275 return 0;
276 }
277 } 191 }
278 return DNS_HARD; 192 free(dname);
193 return 0;
194}
195
196int dns_ptr(stralloc *sa, struct ip_address *ip)
197{
198 if (!stralloc_ready(sa, iaafmt((char *)0, ip)))
199 return DNS_MEM;
200 sa->len = iaafmt(sa->s, ip);
201 if (!stralloc_0(sa))
202 return DNS_MEM;
203
204 int num = getdns_resolve(sa->s, GETDNS_RRTYPE_PTR, dns_ptr_cb, sa);
205 return (num < 0) ? num : 0;
279} 206}
280 207
281static int dns_ipplus(ia,sa,pref) 208struct dns_ipplus_user {
282ipalloc *ia; 209 ipalloc *ia;
283stralloc *sa; 210#ifdef IX_FQDN
284int pref; 211 char *fqdn;
212#endif
213 int pref;
214};
215
216static int dns_ipplus_cb(getdns_dict *response, getdns_dict *rdata,
217 void *userarg)
285{ 218{
286 int r; 219 struct dns_ipplus_user *u = userarg;
287 struct ip_mx ix = {0}; 220 struct ip_mx ix = {0};
221
222 getdns_bindata *bindata = NULL;
223 if (getdns_dict_get_bindata(rdata, "ipv4_address", &bindata)
224 != GETDNS_RETURN_GOOD)
225 return DNS_SOFT;
226
227 memcpy(ix.ip.d, bindata->data, 4);
228 ix.pref = u->pref;
229#ifdef IX_FQDN
230 ix.fqdn = u->fqdn;
231#endif
232 if (!ipalloc_append(u->ia, &ix))
233 return DNS_MEM;
234
235 return 0;
236}
288 237
289 if (!stralloc_copy(&glue,sa)) return DNS_MEM; 238static int dns_ipplus(ipalloc *ia, stralloc *sa, int pref)
290 if (!stralloc_0(&glue)) return DNS_MEM; 239{
291 if (glue.s[0]) { 240 struct ip_mx ix = {0};
292 if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)]) 241
242 if (!stralloc_copy(&glue, sa))
243 return DNS_MEM;
244 if (!stralloc_0(&glue))
245 return DNS_MEM;
246 if (glue.s[0]) {
247 if (!glue.s[ip_scan(glue.s, &ix.ip)] || !glue.s[ip_scanbracket(glue.s, &ix.ip)])
293 { 248 {
294 if (!ipalloc_append(ia,&ix)) return DNS_MEM; 249 if (!ipalloc_append(ia,&ix))
295 return 0; 250 return DNS_MEM;
251 return 0;
296 } 252 }
297 }
298
299 switch(resolve(sa,T_A))
300 {
301 case DNS_MEM: return DNS_MEM;
302 case DNS_SOFT: return DNS_SOFT;
303 case DNS_HARD: return DNS_HARD;
304 } 253 }
305 while ((r = findip(T_A)) != 2) 254
306 { 255 struct dns_ipplus_user u = {
307 ix.ip = ip; 256 .ia = ia,
308 ix.pref = pref;
309 if (r == DNS_SOFT) return DNS_SOFT;
310 if (r == 1) {
311#ifdef IX_FQDN 257#ifdef IX_FQDN
312 ix.fqdn = glue.s; 258 .fqdn = glue.s,
313#endif 259#endif
314 if (!ipalloc_append(ia,&ix)) return DNS_MEM; 260 .pref = pref,
315 } 261 };
316 } 262 int num = getdns_resolve(glue.s, GETDNS_RRTYPE_A, dns_ipplus_cb, &u);
317#ifdef IX_FQDN 263#ifdef IX_FQDN
318 glue.s = 0; 264 glue.s = 0;
319#endif 265#endif
320 return 0; 266 if (num == 0)
267 num = DNS_HARD;
268 return (num < 0) ? num : 0;
321} 269}
322 270
323int dns_ip(ia,sa) 271int dns_ip(ipalloc *ia, stralloc *sa)
324ipalloc *ia;
325stralloc *sa;
326{ 272{
327 if (!ipalloc_readyplus(ia,0)) return DNS_MEM; 273 if (!ipalloc_readyplus(ia, 0))
328 ia->len = 0; 274 return DNS_MEM;
329 return dns_ipplus(ia,sa,0); 275 ia->len = 0;
276 return dns_ipplus(ia, sa, 0);
330} 277}
331 278
332int dns_mxip(ia,sa,random) 279struct dns_mxip_user {
333ipalloc *ia; 280 unsigned num;
334stralloc *sa; 281 struct mx_user {
335unsigned long random; 282 stralloc sa;
283 unsigned short p;
284 } *mx;
285};
286
287static int dns_mxip_cb(getdns_dict *response, getdns_dict *rdata,
288 void *userarg)
336{ 289{
337 int r; 290 struct dns_mxip_user *mx = userarg;
338 struct mx { stralloc sa; unsigned short p; } *mx;
339 struct ip_mx ix = {0};
340 int nummx;
341 int i;
342 int j;
343 int flagsoft;
344
345 if (!ipalloc_readyplus(ia,0)) return DNS_MEM;
346 ia->len = 0;
347
348 if (!stralloc_copy(&glue,sa)) return DNS_MEM;
349 if (!stralloc_0(&glue)) return DNS_MEM;
350 if (glue.s[0]) {
351 if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
352 {
353 if (!ipalloc_append(ia,&ix)) return DNS_MEM;
354 return 0;
355 }
356 }
357 291
358 switch(resolve(sa,T_MX)) 292 getdns_bindata *bindata = NULL;
359 { 293 if (getdns_dict_get_bindata(rdata, "exchange", &bindata)
360 case DNS_MEM: return DNS_MEM; 294 != GETDNS_RETURN_GOOD)
361 case DNS_SOFT: return DNS_SOFT; 295 return DNS_SOFT;
362 case DNS_HARD: return dns_ip(ia,sa);
363 }
364 296
365 mx = (struct mx *) alloc(numanswers * sizeof(struct mx)); 297 char *dname;
366 if (!mx) return DNS_MEM; 298 getdns_convert_dns_name_to_fqdn(bindata, &dname);
367 nummx = 0; 299 dname[strlen(dname) - 1] = '\0';
368 300
369 while ((r = findmx(T_MX)) != 2) 301 uint32_t pref;
302 getdns_dict_get_int(rdata, "preference", &pref);
303
304 mx->mx[mx->num].p = pref;
305 mx->mx[mx->num].sa.s = 0;
306 if (!stralloc_copys(&mx->mx[mx->num].sa, dname))
370 { 307 {
371 if (r == DNS_SOFT) { alloc_free(mx); return DNS_SOFT; } 308 free(dname);
372 if (r == 1) 309 return DNS_MEM;
310 }
311 mx->num++;
312 free(dname);
313 return 0;
314}
315
316int dns_mxip(ipalloc *ia, stralloc *sa, unsigned long random)
317{
318 struct ip_mx ix = {0};
319
320 if (!ipalloc_readyplus(ia, 0))
321 return DNS_MEM;
322 ia->len = 0;
323
324 if (!stralloc_copy(&glue, sa))
325 return DNS_MEM;
326 if (!stralloc_0(&glue))
327 return DNS_MEM;
328 if (glue.s[0]) {
329 if (!glue.s[ip_scan(glue.s, &ix.ip)] || !glue.s[ip_scanbracket(glue.s, &ix.ip)])
373 { 330 {
374 mx[nummx].p = pref; 331 if (!ipalloc_append(ia,&ix))
375 mx[nummx].sa.s = 0; 332 return DNS_MEM;
376 if (!stralloc_copys(&mx[nummx].sa,name)) 333 return 0;
377 {
378 while (nummx > 0) alloc_free(mx[--nummx].sa.s);
379 alloc_free(mx); return DNS_MEM;
380 }
381 ++nummx;
382 } 334 }
383 } 335 }
384 336
385 if (!nummx) return dns_ip(ia,sa); /* e.g., CNAME -> A */ 337 getdns_dict *response = NULL;
338 size_t num_rr = 0;
339 int ret = getdns_resolve_query(glue.s, GETDNS_RRTYPE_MX, &response);
340 ret |= getdns_resolve_num(response, GETDNS_RRTYPE_MX, &num_rr);
341 if (ret != 0 || num_rr == 0) {
342 getdns_dict_destroy(response);
343 return (ret != 0) ? ret : dns_ip(ia, sa); /* e.g., CNAME -> A */
344 }
345
346 struct dns_mxip_user mx = {
347 .num = 0,
348 .mx = (struct mx_user*)alloc(num_rr * sizeof(struct mx_user)),
349 };
350 if (!mx.mx)
351 return DNS_MEM;
352 ret = getdns_resolve_loop(response, GETDNS_RRTYPE_MX, dns_mxip_cb, &mx);
353 if (ret < 0)
354 {
355 while (mx.num > 0)
356 alloc_free(mx.mx[--mx.num].sa.s);
357 alloc_free(mx.mx);
358 getdns_dict_destroy(response);
359 return ret;
360 }
361 getdns_dict_destroy(response);
386 362
387 flagsoft = 0; 363 int flagsoft = 0;
388 while (nummx > 0) 364 while (mx.num > 0)
389 { 365 {
390 unsigned long numsame; 366 int i, j;
367 unsigned long numsame = 1;
391 368
392 i = 0; 369 i = 0;
393 numsame = 1; 370 for (j = 1; j < mx.num; ++j) {
394 for (j = 1;j < nummx;++j) 371 if (mx.mx[j].p < mx.mx[i].p)
395 if (mx[j].p < mx[i].p)
396 { 372 {
397 i = j; 373 i = j;
398 numsame = 1; 374 numsame = 1;
399 } 375 }
400 else if (mx[j].p == mx[i].p) 376 else if (mx.mx[j].p == mx.mx[i].p)
401 { 377 {
402 ++numsame; 378 ++numsame;
403 random = random * 69069 + 1; 379 random = random * 69069 + 1;
404 if ((random / 2) < (2147483647 / numsame)) 380 if ((random / 2) < (2147483647 / numsame))
405 i = j; 381 i = j;
406 } 382 }
383 }
407 384
408 switch(dns_ipplus(ia,&mx[i].sa,mx[i].p)) 385 switch(dns_ipplus(ia, &mx.mx[i].sa, mx.mx[i].p))
409 { 386 {
410 case DNS_MEM: case DNS_SOFT: 387 case DNS_MEM:
411 flagsoft = 1; break; 388 case DNS_SOFT:
389 flagsoft = 1;
390 break;
412 } 391 }
413 392
414 alloc_free(mx[i].sa.s); 393 alloc_free(mx.mx[i].sa.s);
415 mx[i] = mx[--nummx]; 394 mx.mx[i] = mx.mx[--mx.num];
416 } 395 }
417 396
418 alloc_free(mx); 397 alloc_free(mx.mx);
419 return flagsoft; 398 return flagsoft;
420} 399}