masqmail

view src/lookup.c @ 378:5781ba87df95

Removed ident. This had been discussed on the mailing list in Oct 2011. Ident is hardly useful in typical setups for masqmail. Probably Oliver had used it in his setup; that would make sense. Now, I know of nobody who needs it.
author markus schnalke <meillo@marmaro.de>
date Sat, 14 Jan 2012 21:36:58 +0100
parents 41958685480d
children
line source
1 /*
2 ** MasqMail
3 ** Copyright (C) Oliver Kurth
4 ** Copyright (C) markus schnalke <meillo@marmaro.de>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
21 #include <sys/types.h>
22 #include <netinet/in.h>
23 #include <arpa/nameser.h>
24 #include <resolv.h>
26 #include "masqmail.h"
29 #ifdef ENABLE_RESOLVER
31 static union {
32 HEADER hdr;
33 unsigned char buf[PACKETSZ];
34 } response;
35 static unsigned char *resp_end;
36 static unsigned char *resp_pos;
38 static int num_answers;
39 static char name[MAX_DNSNAME];
41 unsigned short rr_type;
42 unsigned short rr_dlen;
44 static unsigned short
45 getshort(unsigned char *c)
46 {
47 unsigned short u;
48 u = c[0];
49 return (u << 8) + c[1];
50 }
52 static int
53 dns_resolve(char *domain, int type, gboolean do_search)
54 {
55 int n;
56 int i;
57 int resp_len;
59 DEBUG(5) debugf("DNS: before res_search()\n");
60 if (do_search)
61 resp_len = res_search(domain, C_IN, type, response.buf, sizeof(response));
62 else
63 resp_len = res_query(domain, C_IN, type, response.buf, sizeof(response));
64 DEBUG(5) debugf("DBG: after res_search()\n");
66 if (resp_len <= 0) {
67 /*
68 ** if (errno == ECONNREFUSED) return DNS_SOFT;
69 ** if (h_errno == TRY_AGAIN) return DNS_SOFT;
70 ** return DNS_HARD;
71 */
72 return -1;
73 }
74 if (resp_len >= sizeof(response))
75 resp_len = sizeof(response);
77 resp_end = response.buf + resp_len;
78 resp_pos = response.buf + sizeof(HEADER);
79 n = ntohs(response.hdr.qdcount);
81 while (n-- > 0) {
82 i = dn_expand(response.buf, resp_end, resp_pos, name, MAX_DNSNAME);
83 if (i < 0)
84 return -1;
85 DEBUG(5) debugf("DBG: resolve name = %s\n", name);
86 resp_pos += i;
87 i = resp_end - resp_pos;
88 if (i < QFIXEDSZ)
89 return -1;
90 resp_pos += QFIXEDSZ;
91 }
92 num_answers = ntohs(response.hdr.ancount);
94 return 0;
95 }
97 static int
98 dns_next()
99 {
100 int i;
102 if (num_answers <= 0)
103 return 2;
104 num_answers--;
106 if (resp_pos == resp_end)
107 return -1; /* soft */
109 i = dn_expand(response.buf, resp_end, resp_pos, name, 256);
110 if (i < 0)
111 return -1; /* soft */
112 resp_pos += i;
114 i = resp_end - resp_pos;
115 if (i < 4 + 3 * 2)
116 return -1; /* soft */
118 rr_type = getshort(resp_pos);
119 rr_dlen = getshort(resp_pos + 8);
120 resp_pos += 10;
122 return 0;
123 }
125 static int
126 dns_getip(guint32 *ip)
127 {
128 int ret;
130 if ((ret = dns_next()))
131 return ret;
133 if (rr_type == T_A) {
134 if (rr_dlen < 4)
135 return -1; /* soft */
136 *ip = *(guint32 *) (resp_pos);
137 DEBUG(5) debugf("DNS: dns_getip(): ip = %s\n", inet_ntoa(*(struct in_addr *) ip));
138 resp_pos += rr_dlen;
140 return 1;
141 }
142 resp_pos += rr_dlen;
143 return 0;
144 }
146 static int
147 dns_getmx(int *pref)
148 {
149 int ret;
151 if ((ret = dns_next()))
152 return ret;
154 if (rr_type == T_MX) {
155 if (rr_dlen < 3)
156 return -1; /* soft */
158 *pref = (resp_pos[0] << 8) + resp_pos[1];
159 if (dn_expand(response.buf, resp_end, resp_pos + 2, name, MAX_DNSNAME) < 0)
160 return -1;
162 resp_pos += rr_dlen;
164 return 1;
165 }
166 resp_pos += rr_dlen;
167 return 0;
168 }
170 int
171 dns_look_ip(gchar *domain, guint32 *ip)
172 {
173 gchar *n = domain;
175 while (TRUE) {
176 if (dns_resolve(n, T_A, FALSE) != 0) {
177 return -1;
178 }
180 dns_next();
181 if (rr_type == T_A) {
182 if (rr_dlen < 4) {
183 return -1; /* soft */
184 }
185 *ip = *(guint32 *) (resp_pos);
187 DEBUG(5) debugf("DNS: dns_look_ip(): ip = %s\n", inet_ntoa(*(struct in_addr *) ip));
189 resp_pos += rr_dlen;
190 return 0;
191 } else if (rr_type == T_CNAME) {
192 if (dn_expand(response.buf, resp_end, resp_pos, name, MAX_DNSNAME) < 0) {
193 return -1;
194 }
196 DEBUG(5) debugf("DNS: (CNAME) dns_look_ip(): name = %s\n", name);
198 resp_pos += rr_dlen;
199 n = name;
200 } else {
201 return -1;
202 }
203 }
204 }
206 GList*
207 resolve_dns_a(GList *list, gchar *domain)
208 {
209 int ret;
211 DEBUG(5) debugf("DNS: resolve_dns_a entered\n");
213 if (dns_resolve(domain, T_A, TRUE) == 0) {
214 mxip_addr mxip;
215 while ((ret = dns_getip(&(mxip.ip))) != 2) {
216 if (ret == 1) {
217 mxip.name = g_strdup(name);
218 mxip.pref = 0;
219 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip)));
220 }
221 }
222 }
223 return list;
224 }
226 static gint
227 _mx_sort_func(gconstpointer aa, gconstpointer bb)
228 {
229 const mxip_addr *a = (mxip_addr *) aa;
230 const mxip_addr *b = (mxip_addr *) bb;
232 if (a->pref == b->pref)
233 return a->ip - b->ip;
234 else
235 return a->pref - b->pref;
236 }
238 GList*
239 resolve_dns_mx(GList *list, gchar *domain)
240 {
241 GList *node;
242 int ret;
243 int cnt = 0;
245 DEBUG(5) debugf("DNS: resolve_dns_mx entered\n");
247 if (dns_resolve(domain, T_MX, TRUE) == 0) {
248 GList *node_next;
249 mxip_addr mxip;
250 while ((ret = dns_getmx(&(mxip.pref))) != 2) {
251 if (ret == 1) {
252 mxip.name = g_strdup(name);
253 mxip.ip = rand();
254 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip)));
255 cnt++;
256 }
257 }
259 DEBUG(5) debugf("DNS: found %d mx records\n", cnt);
261 /*
262 ** to randomize sequences with equal pref values,
263 ** we temporarily 'misused' the ip field and
264 ** put a random number in it as a secondary sort key.
265 */
266 list = g_list_sort(list, _mx_sort_func);
268 /* CNAME resolving has to be added as well. */
270 for (node = g_list_first(list); node != NULL; node = node_next) {
272 mxip_addr *p_mxip = (mxip_addr *) (node->data);
273 node_next = g_list_next(node);
275 if (dns_look_ip(p_mxip->name, &(p_mxip->ip)) != 0) {
276 DEBUG(1) debugf("DNS: could not resolve target of mx %s\n", p_mxip->name);
277 list = g_list_remove_link(list, node);
278 g_free(node->data);
279 g_list_free_1(node);
280 }
281 }
282 }
283 return list;
284 }
286 #endif
288 /* now something completely different... */
290 GList*
291 resolve_byname(GList *list, gchar *domain)
292 {
293 struct hostent *hent;
295 DEBUG(5) debugf("DNS: resolve_byname entered\n");
297 if ((hent = gethostbyname(domain))) {
298 char *haddr;
299 int i = 0;
300 while ((haddr = hent->h_addr_list[i++])) {
301 mxip_addr mxip;
302 mxip.ip = *(guint32 *) (haddr);
303 mxip.pref = 0;
304 mxip.name = g_strdup(hent->h_name);
305 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip)));
306 }
307 }
308 return list;
309 }