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 */