]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/export/samples/sample.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / export / samples / sample.c
1 /*
2  * Copyright (C) 2009  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 *namespace) {
176         struct addrinfo hints, *res;
177         int gai_error;
178         isc_sockaddr_t sa;
179         isc_sockaddrlist_t servers;
180         isc_result_t result;
181         size_t namelen;
182         isc_buffer_t b;
183         dns_fixedname_t fname;
184         dns_name_t *name = NULL;
185
186         memset(&hints, 0, sizeof(hints));
187         hints.ai_family = AF_UNSPEC;
188         hints.ai_socktype = SOCK_DGRAM;
189         hints.ai_protocol = IPPROTO_UDP;
190         hints.ai_flags = AI_NUMERICHOST;
191         gai_error = getaddrinfo(addrstr, "53", &hints, &res);
192         if (gai_error != 0) {
193                 fprintf(stderr, "getaddrinfo failed: %s\n",
194                         gai_strerror(gai_error));
195                 exit(1);
196         }
197         INSIST(res->ai_addrlen <= sizeof(sa.type));
198         memcpy(&sa.type, res->ai_addr, res->ai_addrlen);
199         freeaddrinfo(res);
200         sa.length = res->ai_addrlen;
201         ISC_LINK_INIT(&sa, link);
202         ISC_LIST_INIT(servers);
203         ISC_LIST_APPEND(servers, &sa, link);
204
205         if (namespace != NULL) {
206                 namelen = strlen(namespace);
207                 isc_buffer_init(&b, namespace, namelen);
208                 isc_buffer_add(&b, namelen);
209                 dns_fixedname_init(&fname);
210                 name = dns_fixedname_name(&fname);
211                 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
212                 if (result != ISC_R_SUCCESS) {
213                         fprintf(stderr, "failed to convert qname: %d\n",
214                                 result);
215                         exit(1);
216                 }
217         }
218
219         result = dns_client_setservers(client, dns_rdataclass_in, name,
220                                        &servers);
221         if (result != ISC_R_SUCCESS) {
222                 fprintf(stderr, "set server failed: %d\n", result);
223                 exit(1);
224         }
225 }
226
227 int
228 main(int argc, char *argv[]) {
229         int ch;
230         isc_textregion_t tr;
231         char *altserver = NULL;
232         char *altserveraddr = NULL;
233         char *altservername = NULL;
234         dns_client_t *client = NULL;
235         char *keynamestr = NULL;
236         char *keystr = NULL;
237         isc_result_t result;
238         isc_buffer_t b;
239         dns_fixedname_t qname0;
240         size_t namelen;
241         dns_name_t *qname, *name;
242         dns_rdatatype_t type = dns_rdatatype_a;
243         dns_rdataset_t *rdataset;
244         dns_namelist_t namelist;
245         isc_mem_t *keymctx = NULL;
246         unsigned int clientopt, resopt;
247         isc_boolean_t is_sep = ISC_FALSE;
248
249         while ((ch = getopt(argc, argv, "a:es:t:k:K:")) != -1) {
250                 switch (ch) {
251                 case 't':
252                         tr.base = optarg;
253                         tr.length = strlen(optarg);
254                         result = dns_rdatatype_fromtext(&type, &tr);
255                         if (result != ISC_R_SUCCESS) {
256                                 fprintf(stderr,
257                                         "invalid RRtype: %s\n", optarg);
258                                 exit(1);
259                         }
260                         break;
261                 case 'a':
262                         algname = optarg;
263                         break;
264                 case 'e':
265                         is_sep = ISC_TRUE;
266                         break;
267                 case 's':
268                         if (altserver != NULL) {
269                                 fprintf(stderr, "alternate server "
270                                         "already defined: %s\n",
271                                         altserver);
272                                 exit(1);
273                         }
274                         altserver = optarg;
275                         break;
276                 case 'k':
277                         keynamestr = optarg;
278                         break;
279                 case 'K':
280                         keystr = optarg;
281                         break;
282                 default:
283                         usage();
284                 }
285         }
286
287         argc -= optind;
288         argv += optind;
289         if (argc < 2)
290                 usage();
291
292         if (altserver != NULL) {
293                 char *cp;
294
295                 cp = strchr(altserver, ':');
296                 if (cp == NULL) {
297                         fprintf(stderr, "invalid alternate server: %s\n",
298                                 altserver);
299                         exit(1);
300                 }
301                 *cp = '\0';
302                 altservername = altserver;
303                 altserveraddr = cp + 1;
304         }
305
306         isc_lib_register();
307         result = dns_lib_init();
308         if (result != ISC_R_SUCCESS) {
309                 fprintf(stderr, "dns_lib_init failed: %d\n", result);
310                 exit(1);
311         }
312
313         clientopt = 0;
314         result = dns_client_create(&client, clientopt);
315         if (result != ISC_R_SUCCESS) {
316                 fprintf(stderr, "dns_client_create failed: %d\n", result);
317                 exit(1);
318         }
319
320         /* Set the nameserver */
321         addserver(client, argv[0], NULL);
322
323         /* Set the alternate nameserver (when specified) */
324         if (altserver != NULL)
325                 addserver(client, altserveraddr, altservername);
326
327         /* Install DNSSEC key (if given) */
328         if (keynamestr != NULL) {
329                 if (keystr == NULL) {
330                         fprintf(stderr,
331                                 "key string is missing "
332                                 "while key name is provided\n");
333                         exit(1);
334                 }
335                 set_key(client, keynamestr, keystr, is_sep, &keymctx);
336         }
337
338         /* Construct qname */
339         namelen = strlen(argv[1]);
340         isc_buffer_init(&b, argv[1], namelen);
341         isc_buffer_add(&b, namelen);
342         dns_fixedname_init(&qname0);
343         qname = dns_fixedname_name(&qname0);
344         result = dns_name_fromtext(qname, &b, dns_rootname, 0, NULL);
345         if (result != ISC_R_SUCCESS)
346                 fprintf(stderr, "failed to convert qname: %d\n", result);
347
348         /* Perform resolution */
349         resopt = 0;
350         if (keynamestr == NULL)
351                 resopt |= DNS_CLIENTRESOPT_NODNSSEC;
352         ISC_LIST_INIT(namelist);
353         result = dns_client_resolve(client, qname, dns_rdataclass_in, type,
354                                     resopt, &namelist);
355         if (result != ISC_R_SUCCESS) {
356                 fprintf(stderr,
357                         "resolution failed: %s\n", dns_result_totext(result));
358         }
359         for (name = ISC_LIST_HEAD(namelist); name != NULL;
360              name = ISC_LIST_NEXT(name, link)) {
361                 for (rdataset = ISC_LIST_HEAD(name->list);
362                      rdataset != NULL;
363                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
364                         if (printdata(rdataset, name) != ISC_R_SUCCESS)
365                                 fprintf(stderr, "print data failed\n");
366                 }
367         }
368
369         dns_client_freeresanswer(client, &namelist);
370
371         /* Cleanup */
372         dns_client_destroy(&client);
373         if (keynamestr != NULL)
374                 isc_mem_destroy(&keymctx);
375         dns_lib_shutdown();
376
377         exit(0);
378 }