masqmail

annotate src/lookup.c @ 421:f37384470855

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