/contrib/bind9/lib/export/samples/sample-update.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 755 lines · 635 code · 69 blank · 51 comment · 183 complexity · e6ed2a2e4cfd0124f388a55807591af9 MD5 · raw file

  1. /*
  2. * Copyright (C) 2009, 2010 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. /* $Id: sample-update.c,v 1.10 2010/12/09 00:54:34 marka Exp $ */
  17. #include <config.h>
  18. #include <sys/types.h>
  19. #include <sys/socket.h>
  20. #include <netinet/in.h>
  21. #include <arpa/inet.h>
  22. #include <unistd.h>
  23. #include <ctype.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <netdb.h>
  28. #include <isc/buffer.h>
  29. #include <isc/lex.h>
  30. #include <isc/lib.h>
  31. #include <isc/mem.h>
  32. #include <isc/parseint.h>
  33. #include <isc/sockaddr.h>
  34. #include <isc/util.h>
  35. #include <dns/callbacks.h>
  36. #include <dns/client.h>
  37. #include <dns/fixedname.h>
  38. #include <dns/lib.h>
  39. #include <dns/name.h>
  40. #include <dns/rdata.h>
  41. #include <dns/rdataclass.h>
  42. #include <dns/rdatalist.h>
  43. #include <dns/rdataset.h>
  44. #include <dns/rdatastruct.h>
  45. #include <dns/rdatatype.h>
  46. #include <dns/result.h>
  47. #include <dns/secalg.h>
  48. #include <dns/tsec.h>
  49. #include <dst/dst.h>
  50. static dns_tsec_t *tsec = NULL;
  51. static const dns_rdataclass_t default_rdataclass = dns_rdataclass_in;
  52. static isc_bufferlist_t usedbuffers;
  53. static ISC_LIST(dns_rdatalist_t) usedrdatalists;
  54. static void setup_tsec(char *keyfile, isc_mem_t *mctx);
  55. static void update_addordelete(isc_mem_t *mctx, char *cmdline,
  56. isc_boolean_t isdelete, dns_name_t *name);
  57. static void evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name);
  58. ISC_PLATFORM_NORETURN_PRE static void
  59. usage(void) ISC_PLATFORM_NORETURN_POST;
  60. static void
  61. usage(void) {
  62. fprintf(stderr, "sample-update "
  63. "[-a auth_server] "
  64. "[-k keyfile] "
  65. "[-p prerequisite] "
  66. "[-r recursive_server] "
  67. "[-z zonename] "
  68. "(add|delete) \"name TTL RRtype RDATA\"\n");
  69. exit(1);
  70. }
  71. int
  72. main(int argc, char *argv[]) {
  73. int ch;
  74. struct addrinfo hints, *res;
  75. int gai_error;
  76. dns_client_t *client = NULL;
  77. char *zonenamestr = NULL;
  78. char *keyfilename = NULL;
  79. char *prereqstr = NULL;
  80. isc_sockaddrlist_t auth_servers;
  81. char *auth_server = NULL;
  82. char *recursive_server = NULL;
  83. isc_sockaddr_t sa_auth, sa_recursive;
  84. isc_sockaddrlist_t rec_servers;
  85. isc_result_t result;
  86. isc_boolean_t isdelete;
  87. isc_buffer_t b, *buf;
  88. dns_fixedname_t zname0, pname0, uname0;
  89. size_t namelen;
  90. dns_name_t *zname = NULL, *uname, *pname;
  91. dns_rdataset_t *rdataset;
  92. dns_rdatalist_t *rdatalist;
  93. dns_rdata_t *rdata;
  94. dns_namelist_t updatelist, prereqlist, *prereqlistp = NULL;
  95. isc_mem_t *umctx = NULL;
  96. while ((ch = getopt(argc, argv, "a:k:p:r:z:")) != -1) {
  97. switch (ch) {
  98. case 'k':
  99. keyfilename = optarg;
  100. break;
  101. case 'a':
  102. auth_server = optarg;
  103. break;
  104. case 'p':
  105. prereqstr = optarg;
  106. break;
  107. case 'r':
  108. recursive_server = optarg;
  109. break;
  110. case 'z':
  111. zonenamestr = optarg;
  112. break;
  113. default:
  114. usage();
  115. }
  116. }
  117. argc -= optind;
  118. argv += optind;
  119. if (argc < 2)
  120. usage();
  121. /* command line argument validation */
  122. if (strcmp(argv[0], "delete") == 0)
  123. isdelete = ISC_TRUE;
  124. else if (strcmp(argv[0], "add") == 0)
  125. isdelete = ISC_FALSE;
  126. else {
  127. fprintf(stderr, "invalid update command: %s\n", argv[0]);
  128. exit(1);
  129. }
  130. if (auth_server == NULL && recursive_server == NULL) {
  131. fprintf(stderr, "authoritative or recursive server "
  132. "must be specified\n");
  133. usage();
  134. }
  135. /* Initialization */
  136. ISC_LIST_INIT(usedbuffers);
  137. ISC_LIST_INIT(usedrdatalists);
  138. ISC_LIST_INIT(prereqlist);
  139. ISC_LIST_INIT(auth_servers);
  140. isc_lib_register();
  141. result = dns_lib_init();
  142. if (result != ISC_R_SUCCESS) {
  143. fprintf(stderr, "dns_lib_init failed: %d\n", result);
  144. exit(1);
  145. }
  146. result = isc_mem_create(0, 0, &umctx);
  147. if (result != ISC_R_SUCCESS) {
  148. fprintf(stderr, "failed to crate mctx\n");
  149. exit(1);
  150. }
  151. result = dns_client_create(&client, 0);
  152. if (result != ISC_R_SUCCESS) {
  153. fprintf(stderr, "dns_client_create failed: %d\n", result);
  154. exit(1);
  155. }
  156. /* Set the authoritative server */
  157. if (auth_server != NULL) {
  158. memset(&hints, 0, sizeof(hints));
  159. hints.ai_family = AF_UNSPEC;
  160. hints.ai_socktype = SOCK_DGRAM;
  161. hints.ai_protocol = IPPROTO_UDP;
  162. hints.ai_flags = AI_NUMERICHOST;
  163. gai_error = getaddrinfo(auth_server, "53", &hints, &res);
  164. if (gai_error != 0) {
  165. fprintf(stderr, "getaddrinfo failed: %s\n",
  166. gai_strerror(gai_error));
  167. exit(1);
  168. }
  169. INSIST(res->ai_addrlen <= sizeof(sa_auth.type));
  170. memcpy(&sa_auth.type, res->ai_addr, res->ai_addrlen);
  171. freeaddrinfo(res);
  172. sa_auth.length = res->ai_addrlen;
  173. ISC_LINK_INIT(&sa_auth, link);
  174. ISC_LIST_APPEND(auth_servers, &sa_auth, link);
  175. }
  176. /* Set the recursive server */
  177. if (recursive_server != NULL) {
  178. memset(&hints, 0, sizeof(hints));
  179. hints.ai_family = AF_UNSPEC;
  180. hints.ai_socktype = SOCK_DGRAM;
  181. hints.ai_protocol = IPPROTO_UDP;
  182. hints.ai_flags = AI_NUMERICHOST;
  183. gai_error = getaddrinfo(recursive_server, "53", &hints, &res);
  184. if (gai_error != 0) {
  185. fprintf(stderr, "getaddrinfo failed: %s\n",
  186. gai_strerror(gai_error));
  187. exit(1);
  188. }
  189. INSIST(res->ai_addrlen <= sizeof(sa_recursive.type));
  190. memcpy(&sa_recursive.type, res->ai_addr, res->ai_addrlen);
  191. freeaddrinfo(res);
  192. sa_recursive.length = res->ai_addrlen;
  193. ISC_LINK_INIT(&sa_recursive, link);
  194. ISC_LIST_INIT(rec_servers);
  195. ISC_LIST_APPEND(rec_servers, &sa_recursive, link);
  196. result = dns_client_setservers(client, dns_rdataclass_in,
  197. NULL, &rec_servers);
  198. if (result != ISC_R_SUCCESS) {
  199. fprintf(stderr, "set server failed: %d\n", result);
  200. exit(1);
  201. }
  202. }
  203. /* Construct zone name */
  204. zname = NULL;
  205. if (zonenamestr != NULL) {
  206. namelen = strlen(zonenamestr);
  207. isc_buffer_init(&b, zonenamestr, namelen);
  208. isc_buffer_add(&b, namelen);
  209. dns_fixedname_init(&zname0);
  210. zname = dns_fixedname_name(&zname0);
  211. result = dns_name_fromtext(zname, &b, dns_rootname, 0, NULL);
  212. if (result != ISC_R_SUCCESS)
  213. fprintf(stderr, "failed to convert zone name: %d\n",
  214. result);
  215. }
  216. /* Construct prerequisite name (if given) */
  217. if (prereqstr != NULL) {
  218. dns_fixedname_init(&pname0);
  219. pname = dns_fixedname_name(&pname0);
  220. evaluate_prereq(umctx, prereqstr, pname);
  221. ISC_LIST_APPEND(prereqlist, pname, link);
  222. prereqlistp = &prereqlist;
  223. }
  224. /* Construct update name */
  225. ISC_LIST_INIT(updatelist);
  226. dns_fixedname_init(&uname0);
  227. uname = dns_fixedname_name(&uname0);
  228. update_addordelete(umctx, argv[1], isdelete, uname);
  229. ISC_LIST_APPEND(updatelist, uname, link);
  230. /* Set up TSIG/SIG(0) key (if given) */
  231. if (keyfilename != NULL)
  232. setup_tsec(keyfilename, umctx);
  233. /* Perform update */
  234. result = dns_client_update(client,
  235. default_rdataclass, /* XXX: fixed */
  236. zname, prereqlistp, &updatelist,
  237. (auth_server == NULL) ? NULL :
  238. &auth_servers, tsec, 0);
  239. if (result != ISC_R_SUCCESS) {
  240. fprintf(stderr,
  241. "update failed: %s\n", dns_result_totext(result));
  242. } else
  243. fprintf(stderr, "update succeeded\n");
  244. /* Cleanup */
  245. while ((pname = ISC_LIST_HEAD(prereqlist)) != NULL) {
  246. while ((rdataset = ISC_LIST_HEAD(pname->list)) != NULL) {
  247. ISC_LIST_UNLINK(pname->list, rdataset, link);
  248. dns_rdataset_disassociate(rdataset);
  249. isc_mem_put(umctx, rdataset, sizeof(*rdataset));
  250. }
  251. ISC_LIST_UNLINK(prereqlist, pname, link);
  252. }
  253. while ((uname = ISC_LIST_HEAD(updatelist)) != NULL) {
  254. while ((rdataset = ISC_LIST_HEAD(uname->list)) != NULL) {
  255. ISC_LIST_UNLINK(uname->list, rdataset, link);
  256. dns_rdataset_disassociate(rdataset);
  257. isc_mem_put(umctx, rdataset, sizeof(*rdataset));
  258. }
  259. ISC_LIST_UNLINK(updatelist, uname, link);
  260. }
  261. while ((rdatalist = ISC_LIST_HEAD(usedrdatalists)) != NULL) {
  262. while ((rdata = ISC_LIST_HEAD(rdatalist->rdata)) != NULL) {
  263. ISC_LIST_UNLINK(rdatalist->rdata, rdata, link);
  264. isc_mem_put(umctx, rdata, sizeof(*rdata));
  265. }
  266. ISC_LIST_UNLINK(usedrdatalists, rdatalist, link);
  267. isc_mem_put(umctx, rdatalist, sizeof(*rdatalist));
  268. }
  269. while ((buf = ISC_LIST_HEAD(usedbuffers)) != NULL) {
  270. ISC_LIST_UNLINK(usedbuffers, buf, link);
  271. isc_buffer_free(&buf);
  272. }
  273. if (tsec != NULL)
  274. dns_tsec_destroy(&tsec);
  275. isc_mem_destroy(&umctx);
  276. dns_client_destroy(&client);
  277. dns_lib_shutdown();
  278. exit(0);
  279. }
  280. /*
  281. * Subroutines borrowed from nsupdate.c
  282. */
  283. #define MAXWIRE (64 * 1024)
  284. #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
  285. static char *
  286. nsu_strsep(char **stringp, const char *delim) {
  287. char *string = *stringp;
  288. char *s;
  289. const char *d;
  290. char sc, dc;
  291. if (string == NULL)
  292. return (NULL);
  293. for (; *string != '\0'; string++) {
  294. sc = *string;
  295. for (d = delim; (dc = *d) != '\0'; d++) {
  296. if (sc == dc)
  297. break;
  298. }
  299. if (dc == 0)
  300. break;
  301. }
  302. for (s = string; *s != '\0'; s++) {
  303. sc = *s;
  304. for (d = delim; (dc = *d) != '\0'; d++) {
  305. if (sc == dc) {
  306. *s++ = '\0';
  307. *stringp = s;
  308. return (string);
  309. }
  310. }
  311. }
  312. *stringp = NULL;
  313. return (string);
  314. }
  315. static void
  316. fatal(const char *format, ...) {
  317. va_list args;
  318. va_start(args, format);
  319. vfprintf(stderr, format, args);
  320. va_end(args);
  321. fprintf(stderr, "\n");
  322. exit(1);
  323. }
  324. static inline void
  325. check_result(isc_result_t result, const char *msg) {
  326. if (result != ISC_R_SUCCESS)
  327. fatal("%s: %s", msg, isc_result_totext(result));
  328. }
  329. static void
  330. parse_name(char **cmdlinep, dns_name_t *name) {
  331. isc_result_t result;
  332. char *word;
  333. isc_buffer_t source;
  334. word = nsu_strsep(cmdlinep, " \t\r\n");
  335. if (*word == 0) {
  336. fprintf(stderr, "could not read owner name\n");
  337. exit(1);
  338. }
  339. isc_buffer_init(&source, word, strlen(word));
  340. isc_buffer_add(&source, strlen(word));
  341. result = dns_name_fromtext(name, &source, dns_rootname, 0, NULL);
  342. check_result(result, "dns_name_fromtext");
  343. isc_buffer_invalidate(&source);
  344. }
  345. static void
  346. parse_rdata(isc_mem_t *mctx, char **cmdlinep, dns_rdataclass_t rdataclass,
  347. dns_rdatatype_t rdatatype, dns_rdata_t *rdata)
  348. {
  349. char *cmdline = *cmdlinep;
  350. isc_buffer_t source, *buf = NULL, *newbuf = NULL;
  351. isc_region_t r;
  352. isc_lex_t *lex = NULL;
  353. dns_rdatacallbacks_t callbacks;
  354. isc_result_t result;
  355. while (cmdline != NULL && *cmdline != 0 &&
  356. isspace((unsigned char)*cmdline))
  357. cmdline++;
  358. if (cmdline != NULL && *cmdline != 0) {
  359. dns_rdatacallbacks_init(&callbacks);
  360. result = isc_lex_create(mctx, strlen(cmdline), &lex);
  361. check_result(result, "isc_lex_create");
  362. isc_buffer_init(&source, cmdline, strlen(cmdline));
  363. isc_buffer_add(&source, strlen(cmdline));
  364. result = isc_lex_openbuffer(lex, &source);
  365. check_result(result, "isc_lex_openbuffer");
  366. result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
  367. check_result(result, "isc_buffer_allocate");
  368. result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex,
  369. dns_rootname, 0, mctx, buf,
  370. &callbacks);
  371. isc_lex_destroy(&lex);
  372. if (result == ISC_R_SUCCESS) {
  373. isc_buffer_usedregion(buf, &r);
  374. result = isc_buffer_allocate(mctx, &newbuf, r.length);
  375. check_result(result, "isc_buffer_allocate");
  376. isc_buffer_putmem(newbuf, r.base, r.length);
  377. isc_buffer_usedregion(newbuf, &r);
  378. dns_rdata_reset(rdata);
  379. dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
  380. isc_buffer_free(&buf);
  381. ISC_LIST_APPEND(usedbuffers, newbuf, link);
  382. } else {
  383. fprintf(stderr, "invalid rdata format: %s\n",
  384. isc_result_totext(result));
  385. isc_buffer_free(&buf);
  386. exit(1);
  387. }
  388. } else {
  389. rdata->flags = DNS_RDATA_UPDATE;
  390. }
  391. *cmdlinep = cmdline;
  392. }
  393. static void
  394. update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete,
  395. dns_name_t *name)
  396. {
  397. isc_result_t result;
  398. isc_uint32_t ttl;
  399. char *word;
  400. dns_rdataclass_t rdataclass;
  401. dns_rdatatype_t rdatatype;
  402. dns_rdata_t *rdata = NULL;
  403. dns_rdatalist_t *rdatalist = NULL;
  404. dns_rdataset_t *rdataset = NULL;
  405. isc_textregion_t region;
  406. /*
  407. * Read the owner name.
  408. */
  409. parse_name(&cmdline, name);
  410. rdata = isc_mem_get(mctx, sizeof(*rdata));
  411. if (rdata == NULL) {
  412. fprintf(stderr, "memory allocation for rdata failed\n");
  413. exit(1);
  414. }
  415. dns_rdata_init(rdata);
  416. /*
  417. * If this is an add, read the TTL and verify that it's in range.
  418. * If it's a delete, ignore a TTL if present (for compatibility).
  419. */
  420. word = nsu_strsep(&cmdline, " \t\r\n");
  421. if (word == NULL || *word == 0) {
  422. if (!isdelete) {
  423. fprintf(stderr, "could not read owner ttl\n");
  424. exit(1);
  425. }
  426. else {
  427. ttl = 0;
  428. rdataclass = dns_rdataclass_any;
  429. rdatatype = dns_rdatatype_any;
  430. rdata->flags = DNS_RDATA_UPDATE;
  431. goto doneparsing;
  432. }
  433. }
  434. result = isc_parse_uint32(&ttl, word, 10);
  435. if (result != ISC_R_SUCCESS) {
  436. if (isdelete) {
  437. ttl = 0;
  438. goto parseclass;
  439. } else {
  440. fprintf(stderr, "ttl '%s': %s\n", word,
  441. isc_result_totext(result));
  442. exit(1);
  443. }
  444. }
  445. if (isdelete)
  446. ttl = 0;
  447. else if (ttl > TTL_MAX) {
  448. fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
  449. word, TTL_MAX);
  450. exit(1);
  451. }
  452. /*
  453. * Read the class or type.
  454. */
  455. word = nsu_strsep(&cmdline, " \t\r\n");
  456. parseclass:
  457. if (word == NULL || *word == 0) {
  458. if (isdelete) {
  459. rdataclass = dns_rdataclass_any;
  460. rdatatype = dns_rdatatype_any;
  461. rdata->flags = DNS_RDATA_UPDATE;
  462. goto doneparsing;
  463. } else {
  464. fprintf(stderr, "could not read class or type\n");
  465. exit(1);
  466. }
  467. }
  468. region.base = word;
  469. region.length = strlen(word);
  470. result = dns_rdataclass_fromtext(&rdataclass, &region);
  471. if (result == ISC_R_SUCCESS) {
  472. /*
  473. * Now read the type.
  474. */
  475. word = nsu_strsep(&cmdline, " \t\r\n");
  476. if (word == NULL || *word == 0) {
  477. if (isdelete) {
  478. rdataclass = dns_rdataclass_any;
  479. rdatatype = dns_rdatatype_any;
  480. rdata->flags = DNS_RDATA_UPDATE;
  481. goto doneparsing;
  482. } else {
  483. fprintf(stderr, "could not read type\n");
  484. exit(1);
  485. }
  486. }
  487. region.base = word;
  488. region.length = strlen(word);
  489. result = dns_rdatatype_fromtext(&rdatatype, &region);
  490. if (result != ISC_R_SUCCESS) {
  491. fprintf(stderr, "'%s' is not a valid type: %s\n",
  492. word, isc_result_totext(result));
  493. exit(1);
  494. }
  495. } else {
  496. rdataclass = default_rdataclass;
  497. result = dns_rdatatype_fromtext(&rdatatype, &region);
  498. if (result != ISC_R_SUCCESS) {
  499. fprintf(stderr, "'%s' is not a valid class or type: "
  500. "%s\n", word, isc_result_totext(result));
  501. exit(1);
  502. }
  503. }
  504. parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);
  505. if (isdelete) {
  506. if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
  507. rdataclass = dns_rdataclass_any;
  508. else
  509. rdataclass = dns_rdataclass_none;
  510. } else {
  511. if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
  512. fprintf(stderr, "could not read rdata\n");
  513. exit(1);
  514. }
  515. }
  516. doneparsing:
  517. rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
  518. if (rdatalist == NULL) {
  519. fprintf(stderr, "memory allocation for rdatalist failed\n");
  520. exit(1);
  521. }
  522. dns_rdatalist_init(rdatalist);
  523. rdatalist->type = rdatatype;
  524. rdatalist->rdclass = rdataclass;
  525. rdatalist->covers = rdatatype;
  526. rdatalist->ttl = (dns_ttl_t)ttl;
  527. ISC_LIST_INIT(rdatalist->rdata);
  528. ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  529. ISC_LIST_APPEND(usedrdatalists, rdatalist, link);
  530. rdataset = isc_mem_get(mctx, sizeof(*rdataset));
  531. if (rdataset == NULL) {
  532. fprintf(stderr, "memory allocation for rdataset failed\n");
  533. exit(1);
  534. }
  535. dns_rdataset_init(rdataset);
  536. dns_rdatalist_tordataset(rdatalist, rdataset);
  537. ISC_LIST_INIT(name->list);
  538. ISC_LIST_APPEND(name->list, rdataset, link);
  539. }
  540. static void
  541. make_prereq(isc_mem_t *mctx, char *cmdline, isc_boolean_t ispositive,
  542. isc_boolean_t isrrset, dns_name_t *name)
  543. {
  544. isc_result_t result;
  545. char *word;
  546. isc_textregion_t region;
  547. dns_rdataset_t *rdataset = NULL;
  548. dns_rdatalist_t *rdatalist = NULL;
  549. dns_rdataclass_t rdataclass;
  550. dns_rdatatype_t rdatatype;
  551. dns_rdata_t *rdata = NULL;
  552. /*
  553. * Read the owner name
  554. */
  555. parse_name(&cmdline, name);
  556. /*
  557. * If this is an rrset prereq, read the class or type.
  558. */
  559. if (isrrset) {
  560. word = nsu_strsep(&cmdline, " \t\r\n");
  561. if (word == NULL || *word == 0) {
  562. fprintf(stderr, "could not read class or type\n");
  563. exit(1);
  564. }
  565. region.base = word;
  566. region.length = strlen(word);
  567. result = dns_rdataclass_fromtext(&rdataclass, &region);
  568. if (result == ISC_R_SUCCESS) {
  569. /*
  570. * Now read the type.
  571. */
  572. word = nsu_strsep(&cmdline, " \t\r\n");
  573. if (word == NULL || *word == 0) {
  574. fprintf(stderr, "could not read type\n");
  575. exit(1);
  576. }
  577. region.base = word;
  578. region.length = strlen(word);
  579. result = dns_rdatatype_fromtext(&rdatatype, &region);
  580. if (result != ISC_R_SUCCESS) {
  581. fprintf(stderr, "invalid type: %s\n", word);
  582. exit(1);
  583. }
  584. } else {
  585. rdataclass = default_rdataclass;
  586. result = dns_rdatatype_fromtext(&rdatatype, &region);
  587. if (result != ISC_R_SUCCESS) {
  588. fprintf(stderr, "invalid type: %s\n", word);
  589. exit(1);
  590. }
  591. }
  592. } else
  593. rdatatype = dns_rdatatype_any;
  594. rdata = isc_mem_get(mctx, sizeof(*rdata));
  595. if (rdata == NULL) {
  596. fprintf(stderr, "memory allocation for rdata failed\n");
  597. exit(1);
  598. }
  599. dns_rdata_init(rdata);
  600. if (isrrset && ispositive)
  601. parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);
  602. else
  603. rdata->flags = DNS_RDATA_UPDATE;
  604. rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
  605. if (rdatalist == NULL) {
  606. fprintf(stderr, "memory allocation for rdatalist failed\n");
  607. exit(1);
  608. }
  609. dns_rdatalist_init(rdatalist);
  610. rdatalist->type = rdatatype;
  611. if (ispositive) {
  612. if (isrrset && rdata->data != NULL)
  613. rdatalist->rdclass = rdataclass;
  614. else
  615. rdatalist->rdclass = dns_rdataclass_any;
  616. } else
  617. rdatalist->rdclass = dns_rdataclass_none;
  618. rdatalist->covers = 0;
  619. rdatalist->ttl = 0;
  620. rdata->rdclass = rdatalist->rdclass;
  621. rdata->type = rdatatype;
  622. ISC_LIST_INIT(rdatalist->rdata);
  623. ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  624. ISC_LIST_APPEND(usedrdatalists, rdatalist, link);
  625. rdataset = isc_mem_get(mctx, sizeof(*rdataset));
  626. if (rdataset == NULL) {
  627. fprintf(stderr, "memory allocation for rdataset failed\n");
  628. exit(1);
  629. }
  630. dns_rdataset_init(rdataset);
  631. dns_rdatalist_tordataset(rdatalist, rdataset);
  632. ISC_LIST_INIT(name->list);
  633. ISC_LIST_APPEND(name->list, rdataset, link);
  634. }
  635. static void
  636. evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name) {
  637. char *word;
  638. isc_boolean_t ispositive, isrrset;
  639. word = nsu_strsep(&cmdline, " \t\r\n");
  640. if (word == NULL || *word == 0) {
  641. fprintf(stderr, "could not read operation code\n");
  642. exit(1);
  643. }
  644. if (strcasecmp(word, "nxdomain") == 0) {
  645. ispositive = ISC_FALSE;
  646. isrrset = ISC_FALSE;
  647. } else if (strcasecmp(word, "yxdomain") == 0) {
  648. ispositive = ISC_TRUE;
  649. isrrset = ISC_FALSE;
  650. } else if (strcasecmp(word, "nxrrset") == 0) {
  651. ispositive = ISC_FALSE;
  652. isrrset = ISC_TRUE;
  653. } else if (strcasecmp(word, "yxrrset") == 0) {
  654. ispositive = ISC_TRUE;
  655. isrrset = ISC_TRUE;
  656. } else {
  657. fprintf(stderr, "incorrect operation code: %s\n", word);
  658. exit(1);
  659. }
  660. make_prereq(mctx, cmdline, ispositive, isrrset, name);
  661. }
  662. static void
  663. setup_tsec(char *keyfile, isc_mem_t *mctx) {
  664. dst_key_t *dstkey = NULL;
  665. isc_result_t result;
  666. dns_tsectype_t tsectype;
  667. result = dst_key_fromnamedfile(keyfile, NULL,
  668. DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
  669. &dstkey);
  670. if (result != ISC_R_SUCCESS) {
  671. fprintf(stderr, "could not read key from %s: %s\n",
  672. keyfile, isc_result_totext(result));
  673. exit(1);
  674. }
  675. if (dst_key_alg(dstkey) == DST_ALG_HMACMD5)
  676. tsectype = dns_tsectype_tsig;
  677. else
  678. tsectype = dns_tsectype_sig0;
  679. result = dns_tsec_create(mctx, tsectype, dstkey, &tsec);
  680. dst_key_free(&dstkey);
  681. if (result != ISC_R_SUCCESS) {
  682. fprintf(stderr, "could not create tsec: %s\n",
  683. isc_result_totext(result));
  684. exit(1);
  685. }
  686. }