2 * lib/krb5/os/dnsglue.c
4 * Copyright 2004 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
27 #ifdef KRB5_DNS_LOOKUP
34 struct krb5int_dns_state {
45 unsigned short nanswers;
49 #if !HAVE_NS_INITPARSE
50 static int initparse(struct krb5int_dns_state *);
56 * Initialize an opaue handl. Do name lookup and initial parsing of
57 * reply, skipping question section. Prepare to iterate over answer
58 * section. Returns -1 on error, 0 on success.
61 krb5int_dns_init(struct krb5int_dns_state **dsp,
62 char *host, int nclass, int ntype)
65 struct __res_state statbuf;
67 struct krb5int_dns_state *ds;
69 size_t nextincr, maxincr;
72 *dsp = ds = malloc(sizeof(*ds));
89 len = res_ninit(&statbuf);
95 p = (ds->ansp == NULL)
96 ? malloc(nextincr) : realloc(ds->ansp, nextincr);
98 if (p == NULL && ds->ansp != NULL) {
103 ds->ansmax = nextincr;
106 len = res_nsearch(&statbuf, host, ds->nclass, ds->ntype,
107 ds->ansp, ds->ansmax);
109 len = res_search(host, ds->nclass, ds->ntype,
110 ds->ansp, ds->ansmax);
114 while (nextincr < len)
116 if (len < 0 || nextincr > maxincr) {
120 } while (len > ds->ansmax);
123 #if HAVE_NS_INITPARSE
124 len = ns_initparse(ds->ansp, ds->anslen, &ds->msg);
136 #if HAVE_NS_INITPARSE
138 * krb5int_dns_nextans - get next matching answer record
140 * Sets pp to NULL if no more records. Returns -1 on error, 0 on
144 krb5int_dns_nextans(struct krb5int_dns_state *ds,
145 const unsigned char **pp, int *lenp)
152 while (ds->cur_ans < ns_msg_count(ds->msg, ns_s_an)) {
153 len = ns_parserr(&ds->msg, ns_s_an, ds->cur_ans, &rr);
157 if (ds->nclass == ns_rr_class(rr)
158 && ds->ntype == ns_rr_type(rr)) {
159 *pp = ns_rr_rdata(rr);
160 *lenp = ns_rr_rdlen(rr);
169 * krb5int_dns_expand - wrapper for dn_expand()
171 int krb5int_dns_expand(struct krb5int_dns_state *ds,
172 const unsigned char *p,
176 #if HAVE_NS_NAME_UNCOMPRESS
177 return ns_name_uncompress(ds->ansp,
178 (unsigned char *)ds->ansp + ds->anslen,
179 p, buf, (size_t)len);
181 return dn_expand(ds->ansp,
182 (unsigned char *)ds->ansp + ds->anslen,
191 krb5int_dns_fini(struct krb5int_dns_state *ds)
193 if (ds->ansp != NULL)
200 * Compat routines for BIND 4
202 #if !HAVE_NS_INITPARSE
207 * Skip header and question section of reply. Set a pointer to the
208 * beginning of the answer section, and prepare to iterate over
212 initparse(struct krb5int_dns_state *ds)
216 unsigned short nqueries, nanswers;
218 #if !HAVE_DN_SKIPNAME
222 if (ds->anslen < sizeof(HEADER))
225 hdr = (HEADER *)ds->ansp;
227 nqueries = ntohs((unsigned short)hdr->qdcount);
228 nanswers = ntohs((unsigned short)hdr->ancount);
232 * Skip query records.
236 len = dn_skipname(p, (unsigned char *)ds->ansp + ds->anslen);
238 len = dn_expand(ds->ansp, (unsigned char *)ds->ansp + ds->anslen,
239 p, host, sizeof(host));
241 if (len < 0 || !INCR_OK(ds->ansp, ds->anslen, p, len))
246 ds->nanswers = nanswers;
251 * krb5int_dns_nextans() - get next answer record
253 * Sets pp to NULL if no more records.
256 krb5int_dns_nextans(struct krb5int_dns_state *ds,
257 const unsigned char **pp, int *lenp)
261 unsigned short ntype, nclass, rdlen;
262 #if !HAVE_DN_SKIPNAME
270 while (ds->nanswers--) {
272 len = dn_skipname(ds->ansp, (unsigned char *)ds->ansp + ds->anslen);
274 len = dn_expand(ds->ansp, (unsigned char *)ds->ansp + ds->anslen,
275 p, host, sizeof(host));
277 if (len < 0 || !INCR_OK(ds->ansp, ds->anslen, p, len))
279 SAFE_GETUINT16(ds->ansp, ds->anslen, p, 2, ntype, out);
280 /* Also skip 4 bytes of TTL */
281 SAFE_GETUINT16(ds->ansp, ds->anslen, p, 6, nclass, out);
282 SAFE_GETUINT16(ds->ansp, ds->anslen, p, 2, rdlen, out);
284 if (!INCR_OK(ds->ansp, ds->anslen, p, rdlen))
288 if (nclass == ds->nclass && ntype == ds->ntype) {
302 #endif /* KRB5_DNS_LOOKUP */