]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/export/samples/sample.c
MFC 253983, 253984:
[FreeBSD/stable/9.git] / contrib / bind9 / lib / export / samples / sample.c
1 /*
2  * Copyright (C) 2009, 2012, 2013  Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /* $Id: sample.c,v 1.5 2009/09/29 15:06:07 fdupont Exp $ */
18
19 #include <config.h>
20
21 #include <sys/types.h>
22 #include <sys/socket.h>
23
24 #include <netinet/in.h>
25
26 #include <arpa/inet.h>
27
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <netdb.h>
33
34 #include <isc/base64.h>
35 #include <isc/buffer.h>
36 #include <isc/lib.h>
37 #include <isc/mem.h>
38 #include <isc/sockaddr.h>
39 #include <isc/util.h>
40
41 #include <dns/client.h>
42 #include <dns/fixedname.h>
43 #include <dns/keyvalues.h>
44 #include <dns/lib.h>
45 #include <dns/name.h>
46 #include <dns/rdata.h>
47 #include <dns/rdataset.h>
48 #include <dns/rdatastruct.h>
49 #include <dns/rdatatype.h>
50 #include <dns/result.h>
51 #include <dns/secalg.h>
52
53 #include <dst/dst.h>
54
55 static char *algname;
56
57 static isc_result_t
58 printdata(dns_rdataset_t *rdataset, dns_name_t *owner) {
59         isc_buffer_t target;
60         isc_result_t result;
61         isc_region_t r;
62         char t[4096];
63
64         if (!dns_rdataset_isassociated(rdataset)) {
65                 printf("[WARN: empty]\n");
66                 return (ISC_R_SUCCESS);
67         }
68
69         isc_buffer_init(&target, t, sizeof(t));
70
71         result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
72                                      &target);
73         if (result != ISC_R_SUCCESS)
74                 return (result);
75         isc_buffer_usedregion(&target, &r);
76         printf("%.*s", (int)r.length, (char *)r.base);
77
78         return (ISC_R_SUCCESS);
79 }
80
81 ISC_PLATFORM_NORETURN_PRE static void
82 usage(void) ISC_PLATFORM_NORETURN_POST;
83
84 static void
85 usage(void) {
86         fprintf(stderr, "sample [-t RRtype] "
87                 "[[-a algorithm] [-e] -k keyname -K keystring] "
88                 "[-s domain:serveraddr_for_domain ] "
89                 "server_address hostname\n");
90
91         exit(1);
92 }
93
94 static void
95 set_key(dns_client_t *client, char *keynamestr, char *keystr,
96         isc_boolean_t is_sep, isc_mem_t **mctxp)
97 {
98         isc_result_t result;
99         dns_fixedname_t fkeyname;
100         size_t namelen;
101         dns_name_t *keyname;
102         dns_rdata_dnskey_t keystruct;
103         unsigned char keydata[4096];
104         isc_buffer_t keydatabuf;
105         unsigned char rrdata[4096];
106         isc_buffer_t rrdatabuf;
107         isc_buffer_t b;
108         isc_textregion_t tr;
109         isc_region_t r;
110         dns_secalg_t alg;
111
112         result = isc_mem_create(0, 0, mctxp);
113         if (result != ISC_R_SUCCESS) {
114                 fprintf(stderr, "failed to crate mctx\n");
115                 exit(1);
116         }
117
118         if (algname != NULL) {
119                 tr.base = algname;
120                 tr.length = strlen(algname);
121                 result = dns_secalg_fromtext(&alg, &tr);
122                 if (result != ISC_R_SUCCESS) {
123                         fprintf(stderr, "failed to identify the algorithm\n");
124                         exit(1);
125                 }
126         } else
127                 alg = DNS_KEYALG_RSASHA1;
128
129         keystruct.common.rdclass = dns_rdataclass_in;
130         keystruct.common.rdtype = dns_rdatatype_dnskey;
131         keystruct.flags = DNS_KEYOWNER_ZONE; /* fixed */
132         if (is_sep)
133                 keystruct.flags |= DNS_KEYFLAG_KSK;
134         keystruct.protocol = DNS_KEYPROTO_DNSSEC; /* fixed */
135         keystruct.algorithm = alg;
136
137         isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
138         isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
139         result = isc_base64_decodestring(keystr, &keydatabuf);
140         if (result != ISC_R_SUCCESS) {
141                 fprintf(stderr, "base64 decode failed\n");
142                 exit(1);
143         }
144         isc_buffer_usedregion(&keydatabuf, &r);
145         keystruct.datalen = r.length;
146         keystruct.data = r.base;
147
148         result = dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
149                                       keystruct.common.rdtype,
150                                       &keystruct, &rrdatabuf);
151         if (result != ISC_R_SUCCESS) {
152                 fprintf(stderr, "failed to construct key rdata\n");
153                 exit(1);
154         }
155         namelen = strlen(keynamestr);
156         isc_buffer_init(&b, keynamestr, namelen);
157         isc_buffer_add(&b, namelen);
158         dns_fixedname_init(&fkeyname);
159         keyname = dns_fixedname_name(&fkeyname);
160         result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
161         if (result != ISC_R_SUCCESS) {
162                 fprintf(stderr, "failed to construct key name\n");
163                 exit(1);
164         }
165         result = dns_client_addtrustedkey(client, dns_rdataclass_in,
166                                           keyname, &rrdatabuf);
167         if (result != ISC_R_SUCCESS) {
168                 fprintf(stderr, "failed to add key for %s\n",
169                         keynamestr);
170                 exit(1);
171         }
172 }
173
174 static void
175 addserver(dns_client_t *client, const char *addrstr, const char *port,
176           const char *namespace)
177 {
178         struct addrinfo hints, *res;
179         int gai_error;
180         isc_sockaddr_t sa;
181         isc_sockaddrlist_t servers;
182         isc_result_t result;
183         size_t namelen;
184         isc_buffer_t b;
185         dns_fixedname_t fname;
186         dns_name_t *name = NULL;
187
188         memset(&hints, 0, sizeof(hints));
189         hints.ai_family = AF_UNSPEC;
190         hints.ai_socktype = SOCK_DGRAM;
191         hints.ai_protocol = IPPROTO_UDP;
192         hints.ai_flags = AI_NUMERICHOST;
193         gai_error = getaddrinfo(addrstr, port, &hints, &res);
194         if (gai_error != 0) {
195                 fprintf(stderr, "getaddrinfo failed: %s\n",
196                         gai_strerror(gai_error));
197                 exit(1);
198         }
199         INSIST(res->ai_addrlen <= sizeof(sa.type));
200         memcpy(&sa.type, res->ai_addr, res->ai_addrlen);
201         sa.length = res->ai_addrlen;
202         freeaddrinfo(res);
203         ISC_LINK_INIT(&sa, link);
204         ISC_LIST_INIT(servers);
205         ISC_LIST_APPEND(servers, &sa, link);
206
207         if (namespace != NULL) {
208                 namelen = strlen(namespace);
209                 isc_buffer_constinit(&b, namespace, namelen);
210                 isc_buffer_add(&b, namelen);
211                 dns_fixedname_init(&fname);
212                 name = dns_fixedname_name(&fname);
213                 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
214                 if (result != ISC_R_SUCCESS) {
215                         fprintf(stderr, "failed to convert qname: %d\n",
216                                 result);
217                         exit(1);
218                 }
219         }
220
221         result = dns_client_setservers(client, dns_rdataclass_in, name,
222                                        &servers);
223         if (result != ISC_R_SUCCESS) {
224                 fprintf(stderr, "set server failed: %d\n", result);
225                 exit(1);
226         }
227 }
228
229 int
230 main(int argc, char *argv[]) {
231         int ch;
232         isc_textregion_t tr;
233         char *altserver = NULL;
234         char *altserveraddr = NULL;
235         char *altservername = NULL;
236         dns_client_t *client = NULL;
237         char *keynamestr = NULL;
238         char *keystr = NULL;
239         isc_result_t result;
240         isc_buffer_t b;
241         dns_fixedname_t qname0;
242         size_t namelen;
243         dns_name_t *qname, *name;
244         dns_rdatatype_t type = dns_rdatatype_a;
245         dns_rdataset_t *rdataset;
246         dns_namelist_t namelist;
247         isc_mem_t *keymctx = NULL;
248         unsigned int clientopt, resopt;
249         isc_boolean_t is_sep = ISC_FALSE;
250         const char *port = "53";
251
252         while ((ch = getopt(argc, argv, "a:es:t:k:K:p:")) != -1) {
253                 switch (ch) {
254                 case 't':
255                         tr.base = optarg;
256                         tr.length = strlen(optarg);
257                         result = dns_rdatatype_fromtext(&type, &tr);
258                         if (result != ISC_R_SUCCESS) {
259                                 fprintf(stderr,
260                                         "invalid RRtype: %s\n", optarg);
261                                 exit(1);
262                         }
263                         break;
264                 case 'a':
265                         algname = optarg;
266                         break;
267                 case 'e':
268                         is_sep = ISC_TRUE;
269                         break;
270                 case 's':
271                         if (altserver != NULL) {
272                                 fprintf(stderr, "alternate server "
273                                         "already defined: %s\n",
274                                         altserver);
275                                 exit(1);
276                         }
277                         altserver = optarg;
278                         break;
279                 case 'k':
280                         keynamestr = optarg;
281                         break;
282                 case 'K':
283                         keystr = optarg;
284                         break;
285                 case 'p':
286                         port = optarg;
287                         break;
288                 default:
289                         usage();
290                 }
291         }
292
293         argc -= optind;
294         argv += optind;
295         if (argc < 2)
296                 usage();
297
298         if (altserver != NULL) {
299                 char *cp;
300
301                 cp = strchr(altserver, ':');
302                 if (cp == NULL) {
303                         fprintf(stderr, "invalid alternate server: %s\n",
304                                 altserver);
305                         exit(1);
306                 }
307                 *cp = '\0';
308                 altservername = altserver;
309                 altserveraddr = cp + 1;
310         }
311
312         isc_lib_register();
313         result = dns_lib_init();
314         if (result != ISC_R_SUCCESS) {
315                 fprintf(stderr, "dns_lib_init failed: %d\n", result);
316                 exit(1);
317         }
318
319         clientopt = 0;
320         result = dns_client_create(&client, clientopt);
321         if (result != ISC_R_SUCCESS) {
322                 fprintf(stderr, "dns_client_create failed: %d\n", result);
323                 exit(1);
324         }
325
326         /* Set the nameserver */
327         addserver(client, argv[0], port, NULL);
328
329         /* Set the alternate nameserver (when specified) */
330         if (altserver != NULL)
331                 addserver(client, altserveraddr, port, altservername);
332
333         /* Install DNSSEC key (if given) */
334         if (keynamestr != NULL) {
335                 if (keystr == NULL) {
336                         fprintf(stderr,
337                                 "key string is missing "
338                                 "while key name is provided\n");
339                         exit(1);
340                 }
341                 set_key(client, keynamestr, keystr, is_sep, &keymctx);
342         }
343
344         /* Construct qname */
345         namelen = strlen(argv[1]);
346         isc_buffer_init(&b, argv[1], namelen);
347         isc_buffer_add(&b, namelen);
348         dns_fixedname_init(&qname0);
349         qname = dns_fixedname_name(&qname0);
350         result = dns_name_fromtext(qname, &b, dns_rootname, 0, NULL);
351         if (result != ISC_R_SUCCESS)
352                 fprintf(stderr, "failed to convert qname: %d\n", result);
353
354         /* Perform resolution */
355         resopt = 0;
356         if (keynamestr == NULL)
357                 resopt |= DNS_CLIENTRESOPT_NODNSSEC;
358         ISC_LIST_INIT(namelist);
359         result = dns_client_resolve(client, qname, dns_rdataclass_in, type,
360                                     resopt, &namelist);
361         if (result != ISC_R_SUCCESS) {
362                 fprintf(stderr,
363                         "resolution failed: %s\n", dns_result_totext(result));
364         }
365         for (name = ISC_LIST_HEAD(namelist); name != NULL;
366              name = ISC_LIST_NEXT(name, link)) {
367                 for (rdataset = ISC_LIST_HEAD(name->list);
368                      rdataset != NULL;
369                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
370                         if (printdata(rdataset, name) != ISC_R_SUCCESS)
371                                 fprintf(stderr, "print data failed\n");
372                 }
373         }
374
375         dns_client_freeresanswer(client, &namelist);
376
377         /* Cleanup */
378         dns_client_destroy(&client);
379         if (keynamestr != NULL)
380                 isc_mem_destroy(&keymctx);
381         dns_lib_shutdown();
382
383         return (0);
384 }