Mercurial > masqmail
comparison src/lookup.c @ 10:26e34ae9a3e3
changed indention and line wrapping to a more consistent style
author | meillo@marmaro.de |
---|---|
date | Mon, 27 Oct 2008 16:23:10 +0100 |
parents | 08114f7dcc23 |
children | f671821d8222 |
comparison
equal
deleted
inserted
replaced
9:31cc8a89cb74 | 10:26e34ae9a3e3 |
---|---|
2 * | 2 * |
3 * This program is free software; you can redistribute it and/or modify | 3 * This program is free software; you can redistribute it and/or modify |
4 * it under the terms of the GNU General Public License as published by | 4 * it under the terms of the GNU General Public License as published by |
5 * the Free Software Foundation; either version 2 of the License, or | 5 * the Free Software Foundation; either version 2 of the License, or |
6 * (at your option) any later version. | 6 * (at your option) any later version. |
7 * | 7 * |
8 * This program is distributed in the hope that it will be useful, | 8 * This program is distributed in the hope that it will be useful, |
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 * GNU General Public License for more details. | 11 * GNU General Public License for more details. |
12 * | 12 * |
31 #endif | 31 #endif |
32 | 32 |
33 #ifdef ENABLE_RESOLVER | 33 #ifdef ENABLE_RESOLVER |
34 | 34 |
35 static union { | 35 static union { |
36 HEADER hdr; | 36 HEADER hdr; |
37 unsigned char buf[PACKETSZ]; | 37 unsigned char buf[PACKETSZ]; |
38 } response; | 38 } response; |
39 static unsigned char *resp_end; | 39 static unsigned char *resp_end; |
40 static unsigned char *resp_pos; | 40 static unsigned char *resp_pos; |
41 | 41 |
42 static int num_answers; | 42 static int num_answers; |
43 static char name[MAX_DNSNAME]; | 43 static char name[MAX_DNSNAME]; |
44 | 44 |
45 unsigned short rr_type; | 45 unsigned short rr_type; |
46 unsigned short rr_dlen; | 46 unsigned short rr_dlen; |
47 | 47 |
48 static | 48 static unsigned short |
49 unsigned short getshort(unsigned char *c) | 49 getshort(unsigned char *c) |
50 { | 50 { |
51 unsigned short u; | 51 unsigned short u; |
52 u = c[0]; | 52 u = c[0]; |
53 return (u << 8) + c[1]; | 53 return (u << 8) + c[1]; |
54 } | 54 } |
55 | 55 |
56 static | 56 static int |
57 int dns_resolve(char *domain, int type, gboolean do_search) | 57 dns_resolve(char *domain, int type, gboolean do_search) |
58 { | 58 { |
59 int n; | 59 int n; |
60 int i; | 60 int i; |
61 | 61 |
62 int resp_len; | 62 int resp_len; |
63 /*errno = 0;*/ | 63 /*errno = 0; */ |
64 | 64 |
65 /* | 65 /* |
66 if (!stralloc_copy(&glue,domain)) return DNS_MEM; | 66 if (!stralloc_copy(&glue,domain)) return DNS_MEM; |
67 if (!stralloc_0(&glue)) return DNS_MEM; | 67 if (!stralloc_0(&glue)) return DNS_MEM; |
68 */ | 68 */ |
69 | 69 |
70 // resp_len = res_query(domain, C_IN, type, response.buf, sizeof(response)); | 70 // resp_len = res_query(domain, C_IN, type, response.buf, sizeof(response)); |
71 DEBUG(5) debugf("DNS: before res_search()\n"); | 71 DEBUG(5) debugf("DNS: before res_search()\n"); |
72 if(do_search) | 72 if (do_search) |
73 resp_len = res_search(domain, C_IN, type, response.buf, sizeof(response)); | 73 resp_len = res_search(domain, C_IN, type, response.buf, sizeof(response)); |
74 else | 74 else |
75 resp_len = res_query(domain, C_IN, type, response.buf, sizeof(response)); | 75 resp_len = res_query(domain, C_IN, type, response.buf, sizeof(response)); |
76 DEBUG(5) debugf("DBG: after res_search()\n"); | 76 DEBUG(5) debugf("DBG: after res_search()\n"); |
77 | 77 |
78 if (resp_len <= 0){ | 78 if (resp_len <= 0) { |
79 /* | 79 /* |
80 if (errno == ECONNREFUSED) return DNS_SOFT; | 80 if (errno == ECONNREFUSED) return DNS_SOFT; |
81 if (h_errno == TRY_AGAIN) return DNS_SOFT; | 81 if (h_errno == TRY_AGAIN) return DNS_SOFT; |
82 return DNS_HARD; | 82 return DNS_HARD; |
83 */ | 83 */ |
84 return -1; | 84 return -1; |
85 } | 85 } |
86 if (resp_len >= sizeof(response)) | 86 if (resp_len >= sizeof(response)) |
87 resp_len = sizeof(response); | 87 resp_len = sizeof(response); |
88 | 88 |
89 resp_end = response.buf + resp_len; | 89 resp_end = response.buf + resp_len; |
90 resp_pos = response.buf + sizeof(HEADER); | 90 resp_pos = response.buf + sizeof(HEADER); |
91 n = ntohs(response.hdr.qdcount); | 91 n = ntohs(response.hdr.qdcount); |
92 | 92 |
93 while (n-- > 0){ | 93 while (n-- > 0) { |
94 i = dn_expand(response.buf, resp_end, resp_pos, name, MAX_DNSNAME); | 94 i = dn_expand(response.buf, resp_end, resp_pos, name, MAX_DNSNAME); |
95 if (i < 0) | 95 if (i < 0) |
96 return -1; | |
97 DEBUG(5) debugf("DBG: resolve name = %s\n", name); | |
98 resp_pos += i; | |
99 i = resp_end - resp_pos; | |
100 if (i < QFIXEDSZ) | |
101 return -1; | |
102 resp_pos += QFIXEDSZ; | |
103 } | |
104 num_answers = ntohs(response.hdr.ancount); | |
105 | |
106 return 0; | |
107 } | |
108 | |
109 static int | |
110 dns_next() | |
111 { | |
112 int i; | |
113 | |
114 if (num_answers <= 0) | |
115 return 2; | |
116 num_answers--; | |
117 | |
118 if (resp_pos == resp_end) | |
119 return -1; /* soft */ | |
120 | |
121 i = dn_expand(response.buf, resp_end, resp_pos, name, 256); | |
122 if (i < 0) | |
123 return -1; /* soft */ | |
124 resp_pos += i; | |
125 | |
126 i = resp_end - resp_pos; | |
127 if (i < 4 + 3 * 2) | |
128 return -1; /* soft */ | |
129 | |
130 rr_type = getshort(resp_pos); | |
131 rr_dlen = getshort(resp_pos + 8); | |
132 resp_pos += 10; | |
133 | |
134 return 0; | |
135 } | |
136 | |
137 static int | |
138 dns_getip(guint32 * ip) | |
139 { | |
140 int ret; | |
141 | |
142 if ((ret = dns_next())) | |
143 return ret; | |
144 | |
145 if (rr_type == T_A) { | |
146 if (rr_dlen < 4) | |
147 return -1; /* soft */ | |
148 *ip = *(guint32 *) (resp_pos); | |
149 DEBUG(5) debugf("DNS: dns_getip(): ip = %s\n", inet_ntoa(*(struct in_addr *) ip)); | |
150 resp_pos += rr_dlen; | |
151 | |
152 return 1; | |
153 } | |
154 resp_pos += rr_dlen; | |
155 return 0; | |
156 } | |
157 | |
158 static int | |
159 dns_getmx(int *pref) | |
160 { | |
161 int ret; | |
162 | |
163 if ((ret = dns_next())) | |
164 return ret; | |
165 | |
166 if (rr_type == T_MX) { | |
167 if (rr_dlen < 3) | |
168 return -1; /* soft */ | |
169 | |
170 *pref = (resp_pos[0] << 8) + resp_pos[1]; | |
171 if (dn_expand(response.buf, resp_end, resp_pos + 2, name, MAX_DNSNAME) < 0) | |
172 return -1; | |
173 | |
174 resp_pos += rr_dlen; | |
175 | |
176 return 1; | |
177 } | |
178 resp_pos += rr_dlen; | |
179 return 0; | |
180 } | |
181 | |
182 /* | |
183 static int | |
184 dns_getname(int type) | |
185 { | |
186 int ret; | |
187 | |
188 if((ret = dns_next())) return ret; | |
189 | |
190 if (rr_type == type){ | |
191 if (dn_expand(response.buf, resp_end, resp_pos, name, MAX_DNSNAME) < 0) | |
96 return -1; | 192 return -1; |
97 DEBUG(5) debugf("DBG: resolve name = %s\n", name); | 193 |
98 resp_pos += i; | |
99 i = resp_end - resp_pos; | |
100 if (i < QFIXEDSZ) | |
101 return -1; | |
102 resp_pos += QFIXEDSZ; | |
103 } | |
104 num_answers = ntohs(response.hdr.ancount); | |
105 | |
106 return 0; | |
107 } | |
108 | |
109 static int dns_next() | |
110 { | |
111 int i; | |
112 | |
113 if (num_answers <= 0) return 2; | |
114 num_answers--; | |
115 | |
116 if (resp_pos == resp_end) | |
117 return -1 /* soft */; | |
118 | |
119 i = dn_expand(response.buf, resp_end, resp_pos, name, 256); | |
120 if (i < 0) | |
121 return -1; /* soft */ | |
122 resp_pos += i; | |
123 | |
124 i = resp_end - resp_pos; | |
125 if (i < 4 + 3 * 2) | |
126 return -1; /* soft */ | |
127 | |
128 rr_type = getshort(resp_pos); | |
129 rr_dlen = getshort(resp_pos + 8); | |
130 resp_pos += 10; | |
131 | |
132 return 0; | |
133 } | |
134 | |
135 static | |
136 int dns_getip(guint32 *ip) | |
137 { | |
138 int ret; | |
139 | |
140 if((ret = dns_next())) return ret; | |
141 | |
142 if (rr_type == T_A){ | |
143 if (rr_dlen < 4) | |
144 return -1; /* soft */ | |
145 *ip = *(guint32 *)(resp_pos); | |
146 DEBUG(5) debugf("DNS: dns_getip(): ip = %s\n", inet_ntoa(*(struct in_addr*)ip)); | |
147 resp_pos += rr_dlen; | 194 resp_pos += rr_dlen; |
148 | 195 |
149 return 1; | 196 return 1; |
150 } | 197 } |
151 resp_pos += rr_dlen; | 198 resp_pos += rr_dlen; |
152 return 0; | 199 return 0; |
153 } | 200 } |
154 | |
155 static | |
156 int dns_getmx(int *pref) | |
157 { | |
158 int ret; | |
159 | |
160 if((ret = dns_next())) return ret; | |
161 | |
162 if (rr_type == T_MX){ | |
163 if (rr_dlen < 3) | |
164 return -1; /* soft */ | |
165 | |
166 *pref = (resp_pos[0] << 8) + resp_pos[1]; | |
167 if (dn_expand(response.buf, resp_end, resp_pos + 2, name, MAX_DNSNAME) < 0) | |
168 return -1; | |
169 | |
170 resp_pos += rr_dlen; | |
171 | |
172 return 1; | |
173 } | |
174 resp_pos += rr_dlen; | |
175 return 0; | |
176 } | |
177 | |
178 /* | |
179 static | |
180 int dns_getname(int type) | |
181 { | |
182 int ret; | |
183 | |
184 if((ret = dns_next())) return ret; | |
185 | |
186 if (rr_type == type){ | |
187 if (dn_expand(response.buf, resp_end, resp_pos, name, MAX_DNSNAME) < 0) | |
188 return -1; | |
189 | |
190 resp_pos += rr_dlen; | |
191 | |
192 return 1; | |
193 } | |
194 resp_pos += rr_dlen; | |
195 return 0; | |
196 } | |
197 */ | 201 */ |
198 | 202 |
199 static | 203 static int |
200 int dns_look_ip(gchar *domain, guint32 *ip) | 204 dns_look_ip(gchar * domain, guint32 * ip) |
201 { | 205 { |
202 gchar *n = domain; | 206 gchar *n = domain; |
203 | 207 |
204 while(TRUE){ | 208 while (TRUE) { |
205 if(dns_resolve(n, T_A, FALSE) == 0){ | 209 if (dns_resolve(n, T_A, FALSE) == 0) { |
206 dns_next(); | 210 dns_next(); |
207 if(rr_type == T_A){ | 211 if (rr_type == T_A) { |
208 if (rr_dlen < 4) | 212 if (rr_dlen < 4) |
209 return -1; /* soft */ | 213 return -1; /* soft */ |
210 *ip = *(guint32 *)(resp_pos); | 214 *ip = *(guint32 *) (resp_pos); |
211 | 215 |
212 DEBUG(5) debugf("DNS: dns_look_ip(): ip = %s\n", | 216 DEBUG(5) debugf("DNS: dns_look_ip(): ip = %s\n", inet_ntoa(*(struct in_addr *) ip)); |
213 inet_ntoa(*(struct in_addr*)ip)); | 217 |
214 | 218 resp_pos += rr_dlen; |
215 resp_pos += rr_dlen; | 219 return 0; |
216 return 0; | 220 } else if (rr_type == T_CNAME) { |
217 }else if(rr_type == T_CNAME){ | 221 if (dn_expand(response.buf, resp_end, resp_pos, name, MAX_DNSNAME) < 0) |
218 if (dn_expand(response.buf, resp_end, resp_pos, name, MAX_DNSNAME) < 0) | 222 return -1; |
219 return -1; | 223 |
220 | 224 DEBUG(5) debugf("DNS: (CNAME) dns_look_ip(): name = %s\n", name); |
221 DEBUG(5) debugf("DNS: (CNAME) dns_look_ip(): name = %s\n", name); | 225 |
222 | 226 resp_pos += rr_dlen; |
223 resp_pos += rr_dlen; | 227 n = name; |
224 n = name; | 228 } else |
225 }else | 229 return -1; |
226 return -1; | 230 } else |
227 }else | 231 return -1; |
228 return -1; | 232 } |
229 } | 233 } |
230 } | 234 |
231 | 235 GList* |
232 GList *resolve_dns_a(GList *list, gchar *domain) | 236 resolve_dns_a(GList * list, gchar * domain) |
233 { | 237 { |
234 int ret; | 238 int ret; |
235 | 239 |
236 DEBUG(5) debugf("DNS: resolve_dns_a entered\n"); | 240 DEBUG(5) debugf("DNS: resolve_dns_a entered\n"); |
237 | 241 |
238 if(dns_resolve(domain, T_A, TRUE) == 0){ | 242 if (dns_resolve(domain, T_A, TRUE) == 0) { |
239 mxip_addr mxip; | 243 mxip_addr mxip; |
240 while((ret = dns_getip(&(mxip.ip))) != 2){ | 244 while ((ret = dns_getip(&(mxip.ip))) != 2) { |
241 if(ret == 1){ | 245 if (ret == 1) { |
242 mxip.name = g_strdup(name); | 246 mxip.name = g_strdup(name); |
243 mxip.pref = 0; | 247 mxip.pref = 0; |
244 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip))); | 248 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip))); |
245 } | 249 } |
246 } | 250 } |
247 } | 251 } |
248 return list; | 252 return list; |
249 } | 253 } |
250 | 254 |
251 static | 255 static gint |
252 gint _mx_sort_func(gconstpointer aa, gconstpointer bb) | 256 _mx_sort_func(gconstpointer aa, gconstpointer bb) |
253 { | 257 { |
254 const mxip_addr *a = (mxip_addr *)aa; | 258 const mxip_addr *a = (mxip_addr *) aa; |
255 const mxip_addr *b = (mxip_addr *)bb; | 259 const mxip_addr *b = (mxip_addr *) bb; |
256 | 260 |
257 if(a->pref == b->pref) | 261 if (a->pref == b->pref) |
258 return a->ip - b->ip; | 262 return a->ip - b->ip; |
259 else | 263 else |
260 return a->pref - b->pref; | 264 return a->pref - b->pref; |
261 } | 265 } |
262 | 266 |
263 GList *resolve_dns_mx(GList *list, gchar *domain) | 267 GList* |
264 { | 268 resolve_dns_mx(GList * list, gchar * domain) |
265 GList *node; | 269 { |
266 int ret; | 270 GList *node; |
267 int cnt = 0; | 271 int ret; |
268 | 272 int cnt = 0; |
269 DEBUG(5) debugf("DNS: resolve_dns_mx entered\n"); | 273 |
270 | 274 DEBUG(5) debugf("DNS: resolve_dns_mx entered\n"); |
271 if(dns_resolve(domain, T_MX, TRUE) == 0){ | 275 |
272 GList *node_next; | 276 if (dns_resolve(domain, T_MX, TRUE) == 0) { |
273 mxip_addr mxip; | 277 GList *node_next; |
274 while((ret = dns_getmx(&(mxip.pref))) != 2){ | 278 mxip_addr mxip; |
275 if(ret == 1){ | 279 while ((ret = dns_getmx(&(mxip.pref))) != 2) { |
276 mxip.name = g_strdup(name); | 280 if (ret == 1) { |
277 mxip.ip = rand(); | 281 mxip.name = g_strdup(name); |
278 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip))); | 282 mxip.ip = rand(); |
279 cnt++; | 283 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip))); |
280 } | 284 cnt++; |
281 } | 285 } |
282 | 286 } |
283 DEBUG(5) debugf("DNS: found %d mx records\n", cnt); | 287 |
284 | 288 DEBUG(5) debugf("DNS: found %d mx records\n", cnt); |
285 /* to randomize sequences with equal pref values, | 289 |
286 we temporarily 'misused' the ip field and | 290 /* to randomize sequences with equal pref values, |
287 put a random number in it as a secondary sort key. | 291 we temporarily 'misused' the ip field and |
288 */ | 292 put a random number in it as a secondary sort key. |
289 list = g_list_sort(list, _mx_sort_func); | 293 */ |
290 | 294 list = g_list_sort(list, _mx_sort_func); |
291 /* CNAME resolving has to be added as well. */ | 295 |
292 | 296 /* CNAME resolving has to be added as well. */ |
293 for(node = g_list_first(list); | 297 |
294 node != NULL; | 298 for (node = g_list_first(list); node != NULL; node = node_next) { |
295 node = node_next){ | 299 |
296 | 300 mxip_addr *p_mxip = (mxip_addr *) (node->data); |
297 mxip_addr *p_mxip = (mxip_addr *)(node->data); | 301 node_next = g_list_next(node); |
298 node_next = g_list_next(node); | 302 |
299 | 303 if (dns_look_ip(p_mxip->name, &(p_mxip->ip)) != 0) { |
300 if(dns_look_ip(p_mxip->name, &(p_mxip->ip)) != 0){ | 304 DEBUG(1) debugf("DNS: could not resolve target of mx %s\n", p_mxip->name); |
301 DEBUG(1) debugf("DNS: could not resolve target of mx %s\n", p_mxip->name); | 305 list = g_list_remove_link(list, node); |
302 list = g_list_remove_link(list, node); | 306 g_free(node->data); |
303 g_free(node->data); | 307 g_list_free_1(node); |
304 g_list_free_1(node); | 308 } |
305 } | 309 } |
306 } | 310 } |
307 } | 311 return list; |
308 return list; | |
309 } | 312 } |
310 | 313 |
311 #endif | 314 #endif |
312 | 315 |
313 /* now something completely different... */ | 316 /* now something completely different... */ |
314 | 317 |
315 GList *resolve_byname(GList *list, gchar *domain) | 318 GList* |
316 { | 319 resolve_byname(GList * list, gchar * domain) |
317 struct hostent *hent; | 320 { |
318 | 321 struct hostent *hent; |
319 DEBUG(5) debugf("DNS: resolve_byname entered\n"); | 322 |
320 | 323 DEBUG(5) debugf("DNS: resolve_byname entered\n"); |
321 if((hent = gethostbyname(domain))){ | 324 |
322 char *haddr; | 325 if ((hent = gethostbyname(domain))) { |
323 int i = 0; | 326 char *haddr; |
324 while((haddr = hent->h_addr_list[i++])){ | 327 int i = 0; |
325 mxip_addr mxip; | 328 while ((haddr = hent->h_addr_list[i++])) { |
326 mxip.ip = *(guint32 *)(haddr); | 329 mxip_addr mxip; |
327 mxip.pref = 0; | 330 mxip.ip = *(guint32 *) (haddr); |
328 mxip.name = g_strdup(hent->h_name); | 331 mxip.pref = 0; |
329 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip))); | 332 mxip.name = g_strdup(hent->h_name); |
330 } | 333 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip))); |
331 } | 334 } |
332 return list; | 335 } |
336 return list; | |
333 } | 337 } |
334 | 338 |
335 #ifdef RESOLV_TEST | 339 #ifdef RESOLV_TEST |
336 int main(int argc, char *argv[]) | 340 int |
337 { | 341 main(int argc, char *argv[]) |
338 GList *addr_list = NULL, *node; | 342 { |
339 | 343 GList *addr_list = NULL, *node; |
340 g_print("starting res_init()\n"); | 344 |
341 | 345 g_print("starting res_init()\n"); |
342 g_print("retrans = %d, retry = %d\n", _res.retrans, _res.retry); | 346 |
343 | 347 g_print("retrans = %d, retry = %d\n", _res.retrans, _res.retry); |
344 if(res_init() == 0){ | 348 |
345 | 349 if (res_init() == 0) { |
346 addr_list = resolve_dns_a(NULL, argv[1]); | 350 |
347 g_print("A:\n"); | 351 addr_list = resolve_dns_a(NULL, argv[1]); |
348 | 352 g_print("A:\n"); |
349 foreach(addr_list, node){ | 353 |
350 mxip_addr *p_mxip = (mxip_addr *)(node->data); | 354 foreach(addr_list, node) { |
351 | 355 mxip_addr *p_mxip = (mxip_addr *) (node->data); |
352 printf("name = %s\n IP = %s\n", | 356 |
353 p_mxip->name, | 357 printf("name = %s\n IP = %s\n", p_mxip->name, inet_ntoa(*(struct in_addr *) &(p_mxip->ip))); |
354 inet_ntoa(*(struct in_addr *)&(p_mxip->ip))); | 358 } |
355 } | 359 addr_list = resolve_dns_mx(NULL, argv[1]); |
356 addr_list = resolve_dns_mx(NULL, argv[1]); | 360 g_print("MX:\n"); |
357 g_print("MX:\n"); | 361 |
358 | 362 foreach(addr_list, node) { |
359 foreach(addr_list, node){ | 363 mxip_addr *p_mxip = (mxip_addr *) (node->data); |
360 mxip_addr *p_mxip = (mxip_addr *)(node->data); | 364 |
361 | 365 printf("name = %s\n IP = %s pref = %d\n", p_mxip->name, inet_ntoa(*(struct in_addr *) &(p_mxip->ip)), p_mxip->pref); |
362 printf("name = %s\n IP = %s pref = %d\n", | 366 } |
363 p_mxip->name, | 367 { |
364 inet_ntoa(*(struct in_addr *)&(p_mxip->ip)), | 368 guint32 ip; |
365 p_mxip->pref); | 369 dns_look_ip(argv[1], &ip); |
366 } | 370 printf("dns_look_ip: %s\n", inet_ntoa(*((struct in_addr *) (&ip)))); |
367 { | 371 } |
368 guint32 ip; | 372 } else |
369 dns_look_ip(argv[1], &ip); | 373 printf("res_init() failed.\n"); |
370 printf("dns_look_ip: %s\n", inet_ntoa(*((struct in_addr *)(&ip)))); | 374 |
371 } | |
372 }else | |
373 printf("res_init() failed.\n"); | |
374 | |
375 } | 375 } |
376 #endif | 376 #endif |