1 /* $Cambridge: exim/src/src/lookups/dnsdb.c,v 1.1 2004/10/07 13:10:01 ph10 Exp $ */
3 /*************************************************
4 * Exim - an Internet mail transport agent *
5 *************************************************/
7 /* Copyright (c) University of Cambridge 1995 - 2004 */
8 /* See the file NOTICE for conditions of use and distribution. */
11 #include "lf_functions.h"
16 /* Ancient systems (e.g. SunOS4) don't appear to have T_TXT defined in their
23 /* Table of recognized DNS record types and their integer values. */
25 static char *type_names[] = {
40 static int type_values[] = {
56 /*************************************************
58 *************************************************/
60 /* See local README for interface description. */
63 dnsdb_open(uschar *filename, uschar **errmsg)
65 filename = filename; /* Keep picky compilers happy */
66 errmsg = errmsg; /* Ditto */
67 return (void *)(-1); /* Any non-0 value */
72 /*************************************************
73 * Find entry point for dnsdb *
74 *************************************************/
76 /* See local README for interface description. */
79 dnsdb_find(void *handle, uschar *filename, uschar *keystring, int length,
80 uschar **result, uschar **errmsg, BOOL *do_cache)
86 uschar *orig_keystring = keystring;
87 uschar *equals = Ustrchr(keystring, '=');
90 /* Because we're the working in the search pool, we try to reclaim as much
91 store as possible later, so we preallocate the result here */
93 uschar *yield = store_get(size);
99 handle = handle; /* Keep picky compilers happy */
104 /* If the keystring contains an = this is preceded by a type name. */
109 int len = equals - keystring;
110 for (i = 0; i < sizeof(type_names)/sizeof(uschar *); i++)
112 if (len == Ustrlen(type_names[i]) &&
113 strncmpic(keystring, US type_names[i], len) == 0)
115 type = type_values[i];
119 if (i >= sizeof(type_names)/sizeof(uschar *))
121 *errmsg = US"unsupported DNS record type";
124 keystring += len + 1;
127 /* If the type is PTR, we have to construct the relevant magic lookup
128 key. This code is now in a separate function. */
132 dns_build_reverse(keystring, buffer);
136 DEBUG(D_lookup) debug_printf("dnsdb key: %s\n", keystring);
138 /* Initialize the resolver, in case this is the first time it is used
139 in this run. Then do the lookup and sort out the result. */
141 dns_init(FALSE, FALSE);
142 rc = dns_lookup(&dnsa, keystring, type, NULL);
144 if (rc == DNS_NOMATCH || rc == DNS_NODATA) return FAIL;
145 if (rc != DNS_SUCCEED) return DEFER;
147 for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
149 rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
151 if (rr->type != type) continue;
153 /* There may be several addresses from an A6 record. Put newlines between
154 them, just as for between several records. */
163 for (da = dns_address_from_rr(&dnsa, rr); da != NULL; da = da->next)
165 if (ptr != 0) yield = string_cat(yield, &size, &ptr, US"\n", 1);
166 yield = string_cat(yield, &size, &ptr, da->address, Ustrlen(da->address));
171 /* Other kinds of record just have one piece of data each. */
173 if (ptr != 0) yield = string_cat(yield, &size, &ptr, US"\n", 1);
177 yield = string_cat(yield, &size, &ptr, (uschar *)(rr->data+1),
180 else /* T_CNAME, T_MX, T_NS, T_PTR */
183 uschar *p = (uschar *)(rr->data);
187 GETSHORT(num, p); /* pointer is advanced */
188 sprintf(CS s, "%d ", num);
189 yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
191 else if (type == T_SRV)
193 int num, weight, port;
194 GETSHORT(num, p); /* pointer is advanced */
197 sprintf(CS s, "%d %d %d ", num, weight, port);
198 yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
200 rc = dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen, p,
201 (DN_EXPAND_ARG4_TYPE)(s), sizeof(s));
203 /* If an overlong response was received, the data will have been
204 truncated and dn_expand may fail. */
208 log_write(0, LOG_MAIN, "host name alias list truncated for %s",
212 else yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
217 store_reset(yield + ptr + 1); /* Reclaim unused */
223 /* End of lookups/dnsdb.c */