1 /* $NetBSD: resolve.c,v 1.1.1.4 2014/12/10 03:34:46 christos Exp $ */
4 * Copyright (C) 2009, 2012-2014 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
22 #include <sys/types.h>
23 #include <sys/socket.h>
25 #include <netinet/in.h>
27 #include <arpa/inet.h>
37 #include <isc/base64.h>
38 #include <isc/buffer.h>
39 #include <isc/commandline.h>
42 #include <isc/sockaddr.h>
46 #include <isc/socket.h>
47 #include <isc/timer.h>
49 #include <irs/resconf.h>
50 #include <irs/netdb.h>
52 #include <dns/client.h>
53 #include <dns/fixedname.h>
54 #include <dns/keyvalues.h>
57 #include <dns/rdata.h>
58 #include <dns/rdataset.h>
59 #include <dns/rdatastruct.h>
60 #include <dns/rdatatype.h>
61 #include <dns/result.h>
62 #include <dns/secalg.h>
69 printdata(dns_rdataset_t
*rdataset
, dns_name_t
*owner
) {
75 if (!dns_rdataset_isassociated(rdataset
)) {
76 printf("[WARN: empty]\n");
77 return (ISC_R_SUCCESS
);
80 isc_buffer_init(&target
, t
, sizeof(t
));
82 result
= dns_rdataset_totext(rdataset
, owner
, ISC_FALSE
, ISC_FALSE
,
84 if (result
!= ISC_R_SUCCESS
)
86 isc_buffer_usedregion(&target
, &r
);
87 printf("%.*s", (int)r
.length
, (char *)r
.base
);
89 return (ISC_R_SUCCESS
);
92 ISC_PLATFORM_NORETURN_PRE
static void
93 usage(void) ISC_PLATFORM_NORETURN_POST
;
97 fprintf(stderr
, "resolve [-t RRtype] "
98 "[[-a algorithm] [-e] -k keyname -K keystring] "
99 "[-S domain:serveraddr_for_domain ] [-s server_address]"
100 "[-b address[#port]] hostname\n");
106 set_key(dns_client_t
*client
, char *keynamestr
, char *keystr
,
107 isc_boolean_t is_sep
, isc_mem_t
**mctxp
)
110 dns_fixedname_t fkeyname
;
111 unsigned int namelen
;
113 dns_rdata_dnskey_t keystruct
;
114 unsigned char keydata
[4096];
115 isc_buffer_t keydatabuf
;
116 unsigned char rrdata
[4096];
117 isc_buffer_t rrdatabuf
;
123 result
= isc_mem_create(0, 0, mctxp
);
124 if (result
!= ISC_R_SUCCESS
) {
125 fprintf(stderr
, "failed to create mctx\n");
129 if (algname
!= NULL
) {
131 tr
.length
= strlen(algname
);
132 result
= dns_secalg_fromtext(&alg
, &tr
);
133 if (result
!= ISC_R_SUCCESS
) {
134 fprintf(stderr
, "failed to identify the algorithm\n");
138 alg
= DNS_KEYALG_RSASHA1
;
140 keystruct
.common
.rdclass
= dns_rdataclass_in
;
141 keystruct
.common
.rdtype
= dns_rdatatype_dnskey
;
142 keystruct
.flags
= DNS_KEYOWNER_ZONE
; /* fixed */
144 keystruct
.flags
|= DNS_KEYFLAG_KSK
;
145 keystruct
.protocol
= DNS_KEYPROTO_DNSSEC
; /* fixed */
146 keystruct
.algorithm
= alg
;
148 isc_buffer_init(&keydatabuf
, keydata
, sizeof(keydata
));
149 isc_buffer_init(&rrdatabuf
, rrdata
, sizeof(rrdata
));
150 result
= isc_base64_decodestring(keystr
, &keydatabuf
);
151 if (result
!= ISC_R_SUCCESS
) {
152 fprintf(stderr
, "base64 decode failed\n");
155 isc_buffer_usedregion(&keydatabuf
, &r
);
156 keystruct
.datalen
= r
.length
;
157 keystruct
.data
= r
.base
;
159 result
= dns_rdata_fromstruct(NULL
, keystruct
.common
.rdclass
,
160 keystruct
.common
.rdtype
,
161 &keystruct
, &rrdatabuf
);
162 if (result
!= ISC_R_SUCCESS
) {
163 fprintf(stderr
, "failed to construct key rdata\n");
166 namelen
= strlen(keynamestr
);
167 isc_buffer_init(&b
, keynamestr
, namelen
);
168 isc_buffer_add(&b
, namelen
);
169 dns_fixedname_init(&fkeyname
);
170 keyname
= dns_fixedname_name(&fkeyname
);
171 result
= dns_name_fromtext(keyname
, &b
, dns_rootname
, 0, NULL
);
172 if (result
!= ISC_R_SUCCESS
) {
173 fprintf(stderr
, "failed to construct key name\n");
176 result
= dns_client_addtrustedkey(client
, dns_rdataclass_in
,
177 keyname
, &rrdatabuf
);
178 if (result
!= ISC_R_SUCCESS
) {
179 fprintf(stderr
, "failed to add key for %s\n",
186 addserver(dns_client_t
*client
, const char *addrstr
, const char *port
,
187 const char *namespace)
189 struct addrinfo hints
, *res
;
192 isc_sockaddrlist_t servers
;
194 unsigned int namelen
;
196 dns_fixedname_t fname
;
197 dns_name_t
*name
= NULL
;
199 memset(&hints
, 0, sizeof(hints
));
200 hints
.ai_family
= AF_UNSPEC
;
201 hints
.ai_socktype
= SOCK_DGRAM
;
202 hints
.ai_protocol
= IPPROTO_UDP
;
203 hints
.ai_flags
= AI_NUMERICHOST
;
204 gai_error
= getaddrinfo(addrstr
, port
, &hints
, &res
);
205 if (gai_error
!= 0) {
206 fprintf(stderr
, "getaddrinfo failed: %s\n",
207 gai_strerror(gai_error
));
210 INSIST(res
->ai_addrlen
<= sizeof(sa
.type
));
211 memmove(&sa
.type
, res
->ai_addr
, res
->ai_addrlen
);
212 sa
.length
= (unsigned int)res
->ai_addrlen
;
214 ISC_LINK_INIT(&sa
, link
);
215 ISC_LIST_INIT(servers
);
216 ISC_LIST_APPEND(servers
, &sa
, link
);
218 if (namespace != NULL
) {
219 namelen
= strlen(namespace);
220 isc_buffer_constinit(&b
, namespace, namelen
);
221 isc_buffer_add(&b
, namelen
);
222 dns_fixedname_init(&fname
);
223 name
= dns_fixedname_name(&fname
);
224 result
= dns_name_fromtext(name
, &b
, dns_rootname
, 0, NULL
);
225 if (result
!= ISC_R_SUCCESS
) {
226 fprintf(stderr
, "failed to convert qname: %d\n",
232 result
= dns_client_setservers(client
, dns_rdataclass_in
, name
,
234 if (result
!= ISC_R_SUCCESS
) {
235 fprintf(stderr
, "set server failed: %d\n", result
);
241 main(int argc
, char *argv
[]) {
245 char *altserver
= NULL
;
246 char *altserveraddr
= NULL
;
247 char *altservername
= NULL
;
248 dns_client_t
*client
= NULL
;
249 char *keynamestr
= NULL
;
253 dns_fixedname_t qname0
;
254 unsigned int namelen
;
255 dns_name_t
*qname
, *name
;
256 dns_rdatatype_t type
= dns_rdatatype_a
;
257 dns_rdataset_t
*rdataset
;
258 dns_namelist_t namelist
;
259 isc_mem_t
*keymctx
= NULL
;
260 unsigned int clientopt
, resopt
;
261 isc_boolean_t is_sep
= ISC_FALSE
;
262 const char *port
= "53";
263 isc_mem_t
*mctx
= NULL
;
264 isc_appctx_t
*actx
= NULL
;
265 isc_taskmgr_t
*taskmgr
= NULL
;
266 isc_socketmgr_t
*socketmgr
= NULL
;
267 isc_timermgr_t
*timermgr
= NULL
;
270 isc_sockaddr_t a4
, a6
;
271 isc_sockaddr_t
*addr4
= NULL
, *addr6
= NULL
;
273 while ((ch
= isc_commandline_parse(argc
, argv
,
274 "a:b:es:t:k:K:p:S:")) != -1) {
277 tr
.base
= isc_commandline_argument
;
278 tr
.length
= strlen(isc_commandline_argument
);
279 result
= dns_rdatatype_fromtext(&type
, &tr
);
280 if (result
!= ISC_R_SUCCESS
) {
282 "invalid RRtype: %s\n",
283 isc_commandline_argument
);
288 algname
= isc_commandline_argument
;
291 if (inet_pton(AF_INET
,
292 isc_commandline_argument
, &in4
) == 1) {
294 fprintf(stderr
, "only one local "
295 "address per family "
296 "can be specified\n");
299 isc_sockaddr_fromin(&a4
, &in4
, 0);
301 } else if (inet_pton(AF_INET6
,
302 isc_commandline_argument
,
305 fprintf(stderr
, "only one local "
306 "address per family "
307 "can be specified\n");
310 isc_sockaddr_fromin6(&a6
, &in6
, 0);
313 fprintf(stderr
, "invalid address %s\n",
314 isc_commandline_argument
);
322 if (altserver
!= NULL
) {
323 fprintf(stderr
, "alternate server "
324 "already defined: %s\n",
328 altserver
= isc_commandline_argument
;
331 if (server
!= NULL
) {
332 fprintf(stderr
, "server "
333 "already defined: %s\n",
337 server
= isc_commandline_argument
;
340 keynamestr
= isc_commandline_argument
;
343 keystr
= isc_commandline_argument
;
346 port
= isc_commandline_argument
;
353 argc
-= isc_commandline_index
;
354 argv
+= isc_commandline_index
;
358 if (altserver
!= NULL
) {
361 cp
= strchr(altserver
, ':');
363 fprintf(stderr
, "invalid alternate server: %s\n",
368 altservername
= altserver
;
369 altserveraddr
= cp
+ 1;
373 result
= dns_lib_init();
374 if (result
!= ISC_R_SUCCESS
) {
375 fprintf(stderr
, "dns_lib_init failed: %d\n", result
);
379 result
= isc_mem_create(0, 0, &mctx
);
380 if (result
!= ISC_R_SUCCESS
) {
381 fprintf(stderr
, "failed to crate mctx\n");
385 result
= isc_appctx_create(mctx
, &actx
);
386 if (result
!= ISC_R_SUCCESS
)
388 result
= isc_app_ctxstart(actx
);
389 if (result
!= ISC_R_SUCCESS
)
391 result
= isc_taskmgr_createinctx(mctx
, actx
, 1, 0, &taskmgr
);
392 if (result
!= ISC_R_SUCCESS
)
394 result
= isc_socketmgr_createinctx(mctx
, actx
, &socketmgr
);
395 if (result
!= ISC_R_SUCCESS
)
397 result
= isc_timermgr_createinctx(mctx
, actx
, &timermgr
);
398 if (result
!= ISC_R_SUCCESS
)
402 result
= dns_client_createx2(mctx
, actx
, taskmgr
, socketmgr
, timermgr
,
403 clientopt
, &client
, addr4
, addr6
);
404 if (result
!= ISC_R_SUCCESS
) {
405 fprintf(stderr
, "dns_client_create failed: %d, %s\n", result
,
406 isc_result_totext(result
));
410 /* Set the nameserver */
411 if (server
== NULL
) {
412 irs_resconf_t
*resconf
= NULL
;
413 isc_sockaddrlist_t
*nameservers
;
415 result
= irs_resconf_load(mctx
, "/etc/resolv.conf", &resconf
);
416 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_FILENOTFOUND
) {
417 fprintf(stderr
, "irs_resconf_load failed: %d\n",
421 nameservers
= irs_resconf_getnameservers(resconf
);
422 result
= dns_client_setservers(client
, dns_rdataclass_in
,
424 if (result
!= ISC_R_SUCCESS
) {
425 irs_resconf_destroy(&resconf
);
426 fprintf(stderr
, "dns_client_setservers failed: %d\n",
430 irs_resconf_destroy(&resconf
);
432 addserver(client
, server
, port
, NULL
);
435 /* Set the alternate nameserver (when specified) */
436 if (altserver
!= NULL
)
437 addserver(client
, altserveraddr
, port
, altservername
);
439 /* Install DNSSEC key (if given) */
440 if (keynamestr
!= NULL
) {
441 if (keystr
== NULL
) {
443 "key string is missing "
444 "while key name is provided\n");
447 set_key(client
, keynamestr
, keystr
, is_sep
, &keymctx
);
450 /* Construct qname */
451 namelen
= strlen(argv
[0]);
452 isc_buffer_init(&b
, argv
[0], namelen
);
453 isc_buffer_add(&b
, namelen
);
454 dns_fixedname_init(&qname0
);
455 qname
= dns_fixedname_name(&qname0
);
456 result
= dns_name_fromtext(qname
, &b
, dns_rootname
, 0, NULL
);
457 if (result
!= ISC_R_SUCCESS
)
458 fprintf(stderr
, "failed to convert qname: %d\n", result
);
460 /* Perform resolution */
461 resopt
= DNS_CLIENTRESOPT_ALLOWRUN
;
462 if (keynamestr
== NULL
)
463 resopt
|= DNS_CLIENTRESOPT_NODNSSEC
;
464 ISC_LIST_INIT(namelist
);
465 result
= dns_client_resolve(client
, qname
, dns_rdataclass_in
, type
,
467 if (result
!= ISC_R_SUCCESS
) {
469 "resolution failed: %s\n", dns_result_totext(result
));
471 for (name
= ISC_LIST_HEAD(namelist
); name
!= NULL
;
472 name
= ISC_LIST_NEXT(name
, link
)) {
473 for (rdataset
= ISC_LIST_HEAD(name
->list
);
475 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
476 if (printdata(rdataset
, name
) != ISC_R_SUCCESS
)
477 fprintf(stderr
, "print data failed\n");
481 dns_client_freeresanswer(client
, &namelist
);
485 dns_client_destroy(&client
);
488 isc_taskmgr_destroy(&taskmgr
);
489 if (timermgr
!= NULL
)
490 isc_timermgr_destroy(&timermgr
);
491 if (socketmgr
!= NULL
)
492 isc_socketmgr_destroy(&socketmgr
);
494 isc_appctx_destroy(&actx
);
495 isc_mem_detach(&mctx
);
497 if (keynamestr
!= NULL
)
498 isc_mem_destroy(&keymctx
);