2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * lib/krb5/os/dnsglue.c
9 * Copyright 2004 by the Massachusetts Institute of Technology.
10 * All Rights Reserved.
12 * Export of this software from the United States of America may
13 * require a specific license from the United States Government.
14 * It is the responsibility of any person or organization contemplating
15 * export to obtain such a license before exporting.
17 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18 * distribute this software and its documentation for any purpose and
19 * without fee is hereby granted, provided that the above copyright
20 * notice appear in all copies and that both that copyright notice and
21 * this permission notice appear in supporting documentation, and that
22 * the name of M.I.T. not be used in advertising or publicity pertaining
23 * to distribution of the software without specific, written prior
24 * permission. Furthermore if you modify this software you must label
25 * your software as modified software and not distribute it in such a
26 * fashion that it might be confused with the original M.I.T. software.
27 * M.I.T. makes no representations about the suitability of
28 * this software for any purpose. It is provided "as is" without express
29 * or implied warranty.
33 #ifdef KRB5_DNS_LOOKUP
38 * Only use res_ninit() if there's also a res_ndestroy(), to avoid
39 * memory leaks (Linux & Solaris) and outright corruption (AIX 4.x,
40 * 5.x). While we're at it, make sure res_nsearch() is there too.
42 * In any case, it is probable that platforms having broken
43 * res_ninit() will have thread safety hacks for res_init() and _res.
45 #if HAVE_RES_NINIT && HAVE_RES_NDESTROY && HAVE_RES_NSEARCH
46 #define USE_RES_NINIT 1
52 struct krb5int_dns_state
{
63 unsigned short nanswers
;
67 #if !HAVE_NS_INITPARSE
68 static int initparse(struct krb5int_dns_state
*);
74 * Initialize an opaque handle. Do name lookup and initial parsing of
75 * reply, skipping question section. Prepare to iterate over answer
76 * section. Returns -1 on error, 0 on success.
79 krb5int_dns_init(struct krb5int_dns_state
**dsp
,
80 char *host
, int nclass
, int ntype
)
83 struct __res_state statbuf
;
85 struct krb5int_dns_state
*ds
;
87 size_t nextincr
, maxincr
;
90 *dsp
= ds
= malloc(sizeof(*ds
));
103 #if HAVE_NS_INITPARSE
108 memset(&statbuf
, 0, sizeof(statbuf
));
109 ret
= res_ninit(&statbuf
);
117 p
= (ds
->ansp
== NULL
)
118 ? malloc(nextincr
) : realloc(ds
->ansp
, nextincr
);
120 if (p
== NULL
&& ds
->ansp
!= NULL
) {
125 ds
->ansmax
= nextincr
;
128 len
= res_nsearch(&statbuf
, host
, ds
->nclass
, ds
->ntype
,
129 ds
->ansp
, ds
->ansmax
);
131 len
= res_search(host
, ds
->nclass
, ds
->ntype
,
132 ds
->ansp
, ds
->ansmax
);
138 while (nextincr
< len
)
140 if (len
< 0 || nextincr
> maxincr
) {
144 } while (len
> ds
->ansmax
);
147 #if HAVE_NS_INITPARSE
148 ret
= ns_initparse(ds
->ansp
, ds
->anslen
, &ds
->msg
);
159 res_ndestroy(&statbuf
);
162 if (ds
->ansp
!= NULL
) {
171 #if HAVE_NS_INITPARSE
173 * krb5int_dns_nextans - get next matching answer record
175 * Sets pp to NULL if no more records. Returns -1 on error, 0 on
179 krb5int_dns_nextans(struct krb5int_dns_state
*ds
,
180 const unsigned char **pp
, int *lenp
)
187 while (ds
->cur_ans
< ns_msg_count(ds
->msg
, ns_s_an
)) {
188 len
= ns_parserr(&ds
->msg
, ns_s_an
, ds
->cur_ans
, &rr
);
192 if (ds
->nclass
== ns_rr_class(rr
)
193 && ds
->ntype
== ns_rr_type(rr
)) {
194 *pp
= ns_rr_rdata(rr
);
195 *lenp
= ns_rr_rdlen(rr
);
204 * krb5int_dns_expand - wrapper for dn_expand()
206 int krb5int_dns_expand(struct krb5int_dns_state
*ds
,
207 const unsigned char *p
,
211 #if HAVE_NS_NAME_UNCOMPRESS
212 return ns_name_uncompress(ds
->ansp
,
213 (unsigned char *)ds
->ansp
+ ds
->anslen
,
214 p
, buf
, (size_t)len
);
216 return dn_expand(ds
->ansp
,
217 (unsigned char *)ds
->ansp
+ ds
->anslen
,
226 krb5int_dns_fini(struct krb5int_dns_state
*ds
)
235 * Compat routines for BIND 4
237 #if !HAVE_NS_INITPARSE
242 * Skip header and question section of reply. Set a pointer to the
243 * beginning of the answer section, and prepare to iterate over
247 initparse(struct krb5int_dns_state
*ds
)
251 unsigned short nqueries
, nanswers
;
253 #if !HAVE_DN_SKIPNAME
257 if (ds
->anslen
< sizeof(HEADER
))
260 hdr
= (HEADER
*)ds
->ansp
;
262 nqueries
= ntohs((unsigned short)hdr
->qdcount
);
263 nanswers
= ntohs((unsigned short)hdr
->ancount
);
267 * Skip query records.
271 len
= dn_skipname(p
, (unsigned char *)ds
->ansp
+ ds
->anslen
);
273 len
= dn_expand(ds
->ansp
, (unsigned char *)ds
->ansp
+ ds
->anslen
,
274 p
, host
, sizeof(host
));
276 if (len
< 0 || !INCR_OK(ds
->ansp
, ds
->anslen
, p
, len
+ 4))
281 ds
->nanswers
= nanswers
;
286 * krb5int_dns_nextans() - get next answer record
288 * Sets pp to NULL if no more records.
291 krb5int_dns_nextans(struct krb5int_dns_state
*ds
,
292 const unsigned char **pp
, int *lenp
)
296 unsigned short ntype
, nclass
, rdlen
;
297 #if !HAVE_DN_SKIPNAME
305 while (ds
->nanswers
--) {
307 len
= dn_skipname(p
, (unsigned char *)ds
->ansp
+ ds
->anslen
);
309 len
= dn_expand(ds
->ansp
, (unsigned char *)ds
->ansp
+ ds
->anslen
,
310 p
, host
, sizeof(host
));
312 if (len
< 0 || !INCR_OK(ds
->ansp
, ds
->anslen
, p
, len
))
315 SAFE_GETUINT16(ds
->ansp
, ds
->anslen
, p
, 2, ntype
, out
);
316 /* Also skip 4 bytes of TTL */
317 SAFE_GETUINT16(ds
->ansp
, ds
->anslen
, p
, 6, nclass
, out
);
318 SAFE_GETUINT16(ds
->ansp
, ds
->anslen
, p
, 2, rdlen
, out
);
320 if (!INCR_OK(ds
->ansp
, ds
->anslen
, p
, rdlen
))
322 /* Solaris Kerberos - resync */
327 if (nclass
== ds
->nclass
&& ntype
== ds
->ntype
) {
342 #endif /* KRB5_DNS_LOOKUP */