1 /* $Cambridge: exim/src/src/lookups/dnsdb.c,v 1.2 2004/11/19 09:45:54 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[] = {
42 static int type_values[] = {
56 T_ZNS /* Private type for "zone nameservers" */
60 /*************************************************
62 *************************************************/
64 /* See local README for interface description. */
67 dnsdb_open(uschar *filename, uschar **errmsg)
69 filename = filename; /* Keep picky compilers happy */
70 errmsg = errmsg; /* Ditto */
71 return (void *)(-1); /* Any non-0 value */
76 /*************************************************
77 * Find entry point for dnsdb *
78 *************************************************/
80 /* See local README for interface description. */
83 dnsdb_find(void *handle, uschar *filename, uschar *keystring, int length,
84 uschar **result, uschar **errmsg, BOOL *do_cache)
90 uschar *orig_keystring = keystring;
91 uschar *equals = Ustrchr(keystring, '=');
94 /* Because we're the working in the search pool, we try to reclaim as much
95 store as possible later, so we preallocate the result here */
97 uschar *yield = store_get(size);
103 handle = handle; /* Keep picky compilers happy */
108 /* If the keystring contains an = this is preceded by a type name. */
113 int len = equals - keystring;
114 for (i = 0; i < sizeof(type_names)/sizeof(uschar *); i++)
116 if (len == Ustrlen(type_names[i]) &&
117 strncmpic(keystring, US type_names[i], len) == 0)
119 type = type_values[i];
123 if (i >= sizeof(type_names)/sizeof(uschar *))
125 *errmsg = US"unsupported DNS record type";
128 keystring += len + 1;
131 /* If the type is PTR, we have to construct the relevant magic lookup
132 key. This code is now in a separate function. */
136 dns_build_reverse(keystring, buffer);
140 DEBUG(D_lookup) debug_printf("dnsdb key: %s\n", keystring);
142 /* Initialize the resolver, in case this is the first time it is used
143 in this run. Then do the lookup and sort out the result. */
145 dns_init(FALSE, FALSE);
146 rc = dns_special_lookup(&dnsa, keystring, type, NULL);
148 if (rc == DNS_NOMATCH || rc == DNS_NODATA) return FAIL;
149 if (rc != DNS_SUCCEED) return DEFER;
151 /* If the lookup was a pseudo-type, change it to the correct type for searching
152 the returned records; then search for them. */
154 if (type == T_ZNS) type = T_NS;
155 for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
157 rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
159 if (rr->type != type) continue;
161 /* There may be several addresses from an A6 record. Put newlines between
162 them, just as for between several records. */
171 for (da = dns_address_from_rr(&dnsa, rr); da != NULL; da = da->next)
173 if (ptr != 0) yield = string_cat(yield, &size, &ptr, US"\n", 1);
174 yield = string_cat(yield, &size, &ptr, da->address, Ustrlen(da->address));
179 /* Other kinds of record just have one piece of data each. */
181 if (ptr != 0) yield = string_cat(yield, &size, &ptr, US"\n", 1);
185 yield = string_cat(yield, &size, &ptr, (uschar *)(rr->data+1),
188 else /* T_CNAME, T_MX, T_NS, T_PTR */
191 uschar *p = (uschar *)(rr->data);
195 GETSHORT(num, p); /* pointer is advanced */
196 sprintf(CS s, "%d ", num);
197 yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
199 else if (type == T_SRV)
201 int num, weight, port;
202 GETSHORT(num, p); /* pointer is advanced */
205 sprintf(CS s, "%d %d %d ", num, weight, port);
206 yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
208 rc = dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen, p,
209 (DN_EXPAND_ARG4_TYPE)(s), sizeof(s));
211 /* If an overlong response was received, the data will have been
212 truncated and dn_expand may fail. */
216 log_write(0, LOG_MAIN, "host name alias list truncated for %s",
220 else yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
225 store_reset(yield + ptr + 1); /* Reclaim unused */
231 /* End of lookups/dnsdb.c */