/contrib/bind9/bin/nsupdate/nsupdate.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 2973 lines · 2505 code · 387 blank · 81 comment · 696 complexity · 35b41d505eb59fa22cae3444d19c68b1 MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2000-2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* $Id: nsupdate.c,v 1.193.12.4 2011/11/03 04:30:09 each Exp $ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <ctype.h>
  21. #include <errno.h>
  22. #include <limits.h>
  23. #include <stdlib.h>
  24. #include <unistd.h>
  25. #include <isc/app.h>
  26. #include <isc/base64.h>
  27. #include <isc/buffer.h>
  28. #include <isc/commandline.h>
  29. #include <isc/entropy.h>
  30. #include <isc/event.h>
  31. #include <isc/file.h>
  32. #include <isc/hash.h>
  33. #include <isc/lex.h>
  34. #include <isc/log.h>
  35. #include <isc/mem.h>
  36. #include <isc/parseint.h>
  37. #include <isc/print.h>
  38. #include <isc/random.h>
  39. #include <isc/region.h>
  40. #include <isc/sockaddr.h>
  41. #include <isc/socket.h>
  42. #include <isc/stdio.h>
  43. #include <isc/string.h>
  44. #include <isc/task.h>
  45. #include <isc/timer.h>
  46. #include <isc/types.h>
  47. #include <isc/util.h>
  48. #include <isccfg/namedconf.h>
  49. #include <dns/callbacks.h>
  50. #include <dns/dispatch.h>
  51. #include <dns/dnssec.h>
  52. #include <dns/events.h>
  53. #include <dns/fixedname.h>
  54. #include <dns/log.h>
  55. #include <dns/masterdump.h>
  56. #include <dns/message.h>
  57. #include <dns/name.h>
  58. #include <dns/rcode.h>
  59. #include <dns/rdata.h>
  60. #include <dns/rdataclass.h>
  61. #include <dns/rdatalist.h>
  62. #include <dns/rdataset.h>
  63. #include <dns/rdatastruct.h>
  64. #include <dns/rdatatype.h>
  65. #include <dns/request.h>
  66. #include <dns/result.h>
  67. #include <dns/tkey.h>
  68. #include <dns/tsig.h>
  69. #include <dst/dst.h>
  70. #include <lwres/lwres.h>
  71. #include <lwres/net.h>
  72. #ifdef GSSAPI
  73. #include <dst/gssapi.h>
  74. #include ISC_PLATFORM_KRB5HEADER
  75. #endif
  76. #include <bind9/getaddresses.h>
  77. #ifdef HAVE_ADDRINFO
  78. #ifdef HAVE_GETADDRINFO
  79. #ifdef HAVE_GAISTRERROR
  80. #define USE_GETADDRINFO
  81. #endif
  82. #endif
  83. #endif
  84. #ifndef USE_GETADDRINFO
  85. #ifndef ISC_PLATFORM_NONSTDHERRNO
  86. extern int h_errno;
  87. #endif
  88. #endif
  89. #define MAXCMD (4 * 1024)
  90. #define MAXWIRE (64 * 1024)
  91. #define PACKETSIZE ((64 * 1024) - 1)
  92. #define INITTEXT (2 * 1024)
  93. #define MAXTEXT (128 * 1024)
  94. #define FIND_TIMEOUT 5
  95. #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
  96. #define DNSDEFAULTPORT 53
  97. static isc_uint16_t dnsport = DNSDEFAULTPORT;
  98. #ifndef RESOLV_CONF
  99. #define RESOLV_CONF "/etc/resolv.conf"
  100. #endif
  101. static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
  102. static isc_boolean_t memdebugging = ISC_FALSE;
  103. static isc_boolean_t have_ipv4 = ISC_FALSE;
  104. static isc_boolean_t have_ipv6 = ISC_FALSE;
  105. static isc_boolean_t is_dst_up = ISC_FALSE;
  106. static isc_boolean_t usevc = ISC_FALSE;
  107. static isc_boolean_t usegsstsig = ISC_FALSE;
  108. static isc_boolean_t use_win2k_gsstsig = ISC_FALSE;
  109. static isc_boolean_t tried_other_gsstsig = ISC_FALSE;
  110. static isc_boolean_t local_only = ISC_FALSE;
  111. static isc_taskmgr_t *taskmgr = NULL;
  112. static isc_task_t *global_task = NULL;
  113. static isc_event_t *global_event = NULL;
  114. static isc_log_t *lctx = NULL;
  115. static isc_mem_t *mctx = NULL;
  116. static dns_dispatchmgr_t *dispatchmgr = NULL;
  117. static dns_requestmgr_t *requestmgr = NULL;
  118. static isc_socketmgr_t *socketmgr = NULL;
  119. static isc_timermgr_t *timermgr = NULL;
  120. static dns_dispatch_t *dispatchv4 = NULL;
  121. static dns_dispatch_t *dispatchv6 = NULL;
  122. static dns_message_t *updatemsg = NULL;
  123. static dns_fixedname_t fuserzone;
  124. static dns_name_t *userzone = NULL;
  125. static dns_name_t *zonename = NULL;
  126. static dns_name_t tmpzonename;
  127. static dns_name_t restart_master;
  128. static dns_tsig_keyring_t *gssring = NULL;
  129. static dns_tsigkey_t *tsigkey = NULL;
  130. static dst_key_t *sig0key = NULL;
  131. static lwres_context_t *lwctx = NULL;
  132. static lwres_conf_t *lwconf;
  133. static isc_sockaddr_t *servers;
  134. static int ns_inuse = 0;
  135. static int ns_total = 0;
  136. static isc_sockaddr_t *userserver = NULL;
  137. static isc_sockaddr_t *localaddr = NULL;
  138. static isc_sockaddr_t *serveraddr = NULL;
  139. static isc_sockaddr_t tempaddr;
  140. static const char *keyfile = NULL;
  141. static char *keystr = NULL;
  142. static isc_entropy_t *entropy = NULL;
  143. static isc_boolean_t shuttingdown = ISC_FALSE;
  144. static FILE *input;
  145. static isc_boolean_t interactive = ISC_TRUE;
  146. static isc_boolean_t seenerror = ISC_FALSE;
  147. static const dns_master_style_t *style;
  148. static int requests = 0;
  149. static unsigned int logdebuglevel = 0;
  150. static unsigned int timeout = 300;
  151. static unsigned int udp_timeout = 3;
  152. static unsigned int udp_retries = 3;
  153. static dns_rdataclass_t defaultclass = dns_rdataclass_in;
  154. static dns_rdataclass_t zoneclass = dns_rdataclass_none;
  155. static dns_message_t *answer = NULL;
  156. static isc_uint32_t default_ttl = 0;
  157. static isc_boolean_t default_ttl_set = ISC_FALSE;
  158. typedef struct nsu_requestinfo {
  159. dns_message_t *msg;
  160. isc_sockaddr_t *addr;
  161. } nsu_requestinfo_t;
  162. static void
  163. sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
  164. dns_message_t *msg, dns_request_t **request);
  165. ISC_PLATFORM_NORETURN_PRE static void
  166. fatal(const char *format, ...)
  167. ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
  168. static void
  169. debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
  170. static void
  171. ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
  172. #ifdef GSSAPI
  173. static dns_fixedname_t fkname;
  174. static isc_sockaddr_t *kserver = NULL;
  175. static char *realm = NULL;
  176. static char servicename[DNS_NAME_FORMATSIZE];
  177. static dns_name_t *keyname;
  178. typedef struct nsu_gssinfo {
  179. dns_message_t *msg;
  180. isc_sockaddr_t *addr;
  181. gss_ctx_id_t context;
  182. } nsu_gssinfo_t;
  183. static void
  184. start_gssrequest(dns_name_t *master);
  185. static void
  186. send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
  187. dns_message_t *msg, dns_request_t **request,
  188. gss_ctx_id_t context);
  189. static void
  190. recvgss(isc_task_t *task, isc_event_t *event);
  191. #endif /* GSSAPI */
  192. static void
  193. error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
  194. #define STATUS_MORE (isc_uint16_t)0
  195. #define STATUS_SEND (isc_uint16_t)1
  196. #define STATUS_QUIT (isc_uint16_t)2
  197. #define STATUS_SYNTAX (isc_uint16_t)3
  198. typedef struct entropysource entropysource_t;
  199. struct entropysource {
  200. isc_entropysource_t *source;
  201. isc_mem_t *mctx;
  202. ISC_LINK(entropysource_t) link;
  203. };
  204. static ISC_LIST(entropysource_t) sources;
  205. static void
  206. setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx)
  207. {
  208. isc_result_t result;
  209. isc_entropysource_t *source = NULL;
  210. entropysource_t *elt;
  211. int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
  212. REQUIRE(ectx != NULL);
  213. if (*ectx == NULL) {
  214. result = isc_entropy_create(mctx, ectx);
  215. if (result != ISC_R_SUCCESS)
  216. fatal("could not create entropy object");
  217. ISC_LIST_INIT(sources);
  218. }
  219. if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
  220. usekeyboard = ISC_ENTROPY_KEYBOARDYES;
  221. randomfile = NULL;
  222. }
  223. result = isc_entropy_usebestsource(*ectx, &source, randomfile,
  224. usekeyboard);
  225. if (result != ISC_R_SUCCESS)
  226. fatal("could not initialize entropy source: %s",
  227. isc_result_totext(result));
  228. if (source != NULL) {
  229. elt = isc_mem_get(mctx, sizeof(*elt));
  230. if (elt == NULL)
  231. fatal("out of memory");
  232. elt->source = source;
  233. elt->mctx = mctx;
  234. ISC_LINK_INIT(elt, link);
  235. ISC_LIST_APPEND(sources, elt, link);
  236. }
  237. }
  238. static void
  239. cleanup_entropy(isc_entropy_t **ectx) {
  240. entropysource_t *source;
  241. while (!ISC_LIST_EMPTY(sources)) {
  242. source = ISC_LIST_HEAD(sources);
  243. ISC_LIST_UNLINK(sources, source, link);
  244. isc_entropy_destroysource(&source->source);
  245. isc_mem_put(source->mctx, source, sizeof(*source));
  246. }
  247. isc_entropy_detach(ectx);
  248. }
  249. static dns_rdataclass_t
  250. getzoneclass(void) {
  251. if (zoneclass == dns_rdataclass_none)
  252. zoneclass = defaultclass;
  253. return (zoneclass);
  254. }
  255. static isc_boolean_t
  256. setzoneclass(dns_rdataclass_t rdclass) {
  257. if (zoneclass == dns_rdataclass_none ||
  258. rdclass == dns_rdataclass_none)
  259. zoneclass = rdclass;
  260. if (zoneclass != rdclass)
  261. return (ISC_FALSE);
  262. return (ISC_TRUE);
  263. }
  264. static void
  265. fatal(const char *format, ...) {
  266. va_list args;
  267. va_start(args, format);
  268. vfprintf(stderr, format, args);
  269. va_end(args);
  270. fprintf(stderr, "\n");
  271. exit(1);
  272. }
  273. static void
  274. error(const char *format, ...) {
  275. va_list args;
  276. va_start(args, format);
  277. vfprintf(stderr, format, args);
  278. va_end(args);
  279. fprintf(stderr, "\n");
  280. }
  281. static void
  282. debug(const char *format, ...) {
  283. va_list args;
  284. if (debugging) {
  285. va_start(args, format);
  286. vfprintf(stderr, format, args);
  287. va_end(args);
  288. fprintf(stderr, "\n");
  289. }
  290. }
  291. static void
  292. ddebug(const char *format, ...) {
  293. va_list args;
  294. if (ddebugging) {
  295. va_start(args, format);
  296. vfprintf(stderr, format, args);
  297. va_end(args);
  298. fprintf(stderr, "\n");
  299. }
  300. }
  301. static inline void
  302. check_result(isc_result_t result, const char *msg) {
  303. if (result != ISC_R_SUCCESS)
  304. fatal("%s: %s", msg, isc_result_totext(result));
  305. }
  306. static void *
  307. mem_alloc(void *arg, size_t size) {
  308. return (isc_mem_get(arg, size));
  309. }
  310. static void
  311. mem_free(void *arg, void *mem, size_t size) {
  312. isc_mem_put(arg, mem, size);
  313. }
  314. static char *
  315. nsu_strsep(char **stringp, const char *delim) {
  316. char *string = *stringp;
  317. char *s;
  318. const char *d;
  319. char sc, dc;
  320. if (string == NULL)
  321. return (NULL);
  322. for (; *string != '\0'; string++) {
  323. sc = *string;
  324. for (d = delim; (dc = *d) != '\0'; d++) {
  325. if (sc == dc)
  326. break;
  327. }
  328. if (dc == 0)
  329. break;
  330. }
  331. for (s = string; *s != '\0'; s++) {
  332. sc = *s;
  333. for (d = delim; (dc = *d) != '\0'; d++) {
  334. if (sc == dc) {
  335. *s++ = '\0';
  336. *stringp = s;
  337. return (string);
  338. }
  339. }
  340. }
  341. *stringp = NULL;
  342. return (string);
  343. }
  344. static void
  345. reset_system(void) {
  346. isc_result_t result;
  347. ddebug("reset_system()");
  348. /* If the update message is still around, destroy it */
  349. if (updatemsg != NULL)
  350. dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
  351. else {
  352. result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
  353. &updatemsg);
  354. check_result(result, "dns_message_create");
  355. }
  356. updatemsg->opcode = dns_opcode_update;
  357. if (usegsstsig) {
  358. if (tsigkey != NULL)
  359. dns_tsigkey_detach(&tsigkey);
  360. if (gssring != NULL)
  361. dns_tsigkeyring_detach(&gssring);
  362. tried_other_gsstsig = ISC_FALSE;
  363. }
  364. }
  365. static isc_uint16_t
  366. parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
  367. isc_uint16_t digestbits = 0;
  368. isc_result_t result;
  369. char buf[20];
  370. REQUIRE(hmac != NULL && *hmac == NULL);
  371. REQUIRE(hmacstr != NULL);
  372. if (len >= sizeof(buf))
  373. fatal("unknown key type '%.*s'", (int)(len), hmacstr);
  374. strncpy(buf, hmacstr, len);
  375. buf[len] = 0;
  376. if (strcasecmp(buf, "hmac-md5") == 0) {
  377. *hmac = DNS_TSIG_HMACMD5_NAME;
  378. } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
  379. *hmac = DNS_TSIG_HMACMD5_NAME;
  380. result = isc_parse_uint16(&digestbits, &buf[9], 10);
  381. if (result != ISC_R_SUCCESS || digestbits > 128)
  382. fatal("digest-bits out of range [0..128]");
  383. digestbits = (digestbits +7) & ~0x7U;
  384. } else if (strcasecmp(buf, "hmac-sha1") == 0) {
  385. *hmac = DNS_TSIG_HMACSHA1_NAME;
  386. } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
  387. *hmac = DNS_TSIG_HMACSHA1_NAME;
  388. result = isc_parse_uint16(&digestbits, &buf[10], 10);
  389. if (result != ISC_R_SUCCESS || digestbits > 160)
  390. fatal("digest-bits out of range [0..160]");
  391. digestbits = (digestbits +7) & ~0x7U;
  392. } else if (strcasecmp(buf, "hmac-sha224") == 0) {
  393. *hmac = DNS_TSIG_HMACSHA224_NAME;
  394. } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
  395. *hmac = DNS_TSIG_HMACSHA224_NAME;
  396. result = isc_parse_uint16(&digestbits, &buf[12], 10);
  397. if (result != ISC_R_SUCCESS || digestbits > 224)
  398. fatal("digest-bits out of range [0..224]");
  399. digestbits = (digestbits +7) & ~0x7U;
  400. } else if (strcasecmp(buf, "hmac-sha256") == 0) {
  401. *hmac = DNS_TSIG_HMACSHA256_NAME;
  402. } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
  403. *hmac = DNS_TSIG_HMACSHA256_NAME;
  404. result = isc_parse_uint16(&digestbits, &buf[12], 10);
  405. if (result != ISC_R_SUCCESS || digestbits > 256)
  406. fatal("digest-bits out of range [0..256]");
  407. digestbits = (digestbits +7) & ~0x7U;
  408. } else if (strcasecmp(buf, "hmac-sha384") == 0) {
  409. *hmac = DNS_TSIG_HMACSHA384_NAME;
  410. } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
  411. *hmac = DNS_TSIG_HMACSHA384_NAME;
  412. result = isc_parse_uint16(&digestbits, &buf[12], 10);
  413. if (result != ISC_R_SUCCESS || digestbits > 384)
  414. fatal("digest-bits out of range [0..384]");
  415. digestbits = (digestbits +7) & ~0x7U;
  416. } else if (strcasecmp(buf, "hmac-sha512") == 0) {
  417. *hmac = DNS_TSIG_HMACSHA512_NAME;
  418. } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
  419. *hmac = DNS_TSIG_HMACSHA512_NAME;
  420. result = isc_parse_uint16(&digestbits, &buf[12], 10);
  421. if (result != ISC_R_SUCCESS || digestbits > 512)
  422. fatal("digest-bits out of range [0..512]");
  423. digestbits = (digestbits +7) & ~0x7U;
  424. } else
  425. fatal("unknown key type '%s'", buf);
  426. return (digestbits);
  427. }
  428. static int
  429. basenamelen(const char *file) {
  430. int len = strlen(file);
  431. if (len > 1 && file[len - 1] == '.')
  432. len -= 1;
  433. else if (len > 8 && strcmp(file + len - 8, ".private") == 0)
  434. len -= 8;
  435. else if (len > 4 && strcmp(file + len - 4, ".key") == 0)
  436. len -= 4;
  437. return (len);
  438. }
  439. static void
  440. setup_keystr(void) {
  441. unsigned char *secret = NULL;
  442. int secretlen;
  443. isc_buffer_t secretbuf;
  444. isc_result_t result;
  445. isc_buffer_t keynamesrc;
  446. char *secretstr;
  447. char *s, *n;
  448. dns_fixedname_t fkeyname;
  449. dns_name_t *keyname;
  450. char *name;
  451. dns_name_t *hmacname = NULL;
  452. isc_uint16_t digestbits = 0;
  453. dns_fixedname_init(&fkeyname);
  454. keyname = dns_fixedname_name(&fkeyname);
  455. debug("Creating key...");
  456. s = strchr(keystr, ':');
  457. if (s == NULL || s == keystr || s[1] == 0)
  458. fatal("key option must specify [hmac:]keyname:secret");
  459. secretstr = s + 1;
  460. n = strchr(secretstr, ':');
  461. if (n != NULL) {
  462. if (n == secretstr || n[1] == 0)
  463. fatal("key option must specify [hmac:]keyname:secret");
  464. name = secretstr;
  465. secretstr = n + 1;
  466. digestbits = parse_hmac(&hmacname, keystr, s - keystr);
  467. } else {
  468. hmacname = DNS_TSIG_HMACMD5_NAME;
  469. name = keystr;
  470. n = s;
  471. }
  472. isc_buffer_init(&keynamesrc, name, n - name);
  473. isc_buffer_add(&keynamesrc, n - name);
  474. debug("namefromtext");
  475. result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, 0, NULL);
  476. check_result(result, "dns_name_fromtext");
  477. secretlen = strlen(secretstr) * 3 / 4;
  478. secret = isc_mem_allocate(mctx, secretlen);
  479. if (secret == NULL)
  480. fatal("out of memory");
  481. isc_buffer_init(&secretbuf, secret, secretlen);
  482. result = isc_base64_decodestring(secretstr, &secretbuf);
  483. if (result != ISC_R_SUCCESS) {
  484. fprintf(stderr, "could not create key from %s: %s\n",
  485. keystr, isc_result_totext(result));
  486. goto failure;
  487. }
  488. secretlen = isc_buffer_usedlength(&secretbuf);
  489. debug("keycreate");
  490. result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
  491. ISC_FALSE, NULL, 0, 0, mctx, NULL,
  492. &tsigkey);
  493. if (result != ISC_R_SUCCESS)
  494. fprintf(stderr, "could not create key from %s: %s\n",
  495. keystr, dns_result_totext(result));
  496. else
  497. dst_key_setbits(tsigkey->key, digestbits);
  498. failure:
  499. if (secret != NULL)
  500. isc_mem_free(mctx, secret);
  501. }
  502. /*
  503. * Get a key from a named.conf format keyfile
  504. */
  505. static isc_result_t
  506. read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) {
  507. cfg_parser_t *pctx = NULL;
  508. cfg_obj_t *sessionkey = NULL;
  509. const cfg_obj_t *key = NULL;
  510. const cfg_obj_t *secretobj = NULL;
  511. const cfg_obj_t *algorithmobj = NULL;
  512. const char *keyname;
  513. const char *secretstr;
  514. const char *algorithm;
  515. isc_result_t result;
  516. int len;
  517. if (! isc_file_exists(keyfile))
  518. return (ISC_R_FILENOTFOUND);
  519. result = cfg_parser_create(mctx, lctx, &pctx);
  520. if (result != ISC_R_SUCCESS)
  521. goto cleanup;
  522. result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
  523. &sessionkey);
  524. if (result != ISC_R_SUCCESS)
  525. goto cleanup;
  526. result = cfg_map_get(sessionkey, "key", &key);
  527. if (result != ISC_R_SUCCESS)
  528. goto cleanup;
  529. (void) cfg_map_get(key, "secret", &secretobj);
  530. (void) cfg_map_get(key, "algorithm", &algorithmobj);
  531. if (secretobj == NULL || algorithmobj == NULL)
  532. fatal("key must have algorithm and secret");
  533. keyname = cfg_obj_asstring(cfg_map_getname(key));
  534. secretstr = cfg_obj_asstring(secretobj);
  535. algorithm = cfg_obj_asstring(algorithmobj);
  536. len = strlen(algorithm) + strlen(keyname) + strlen(secretstr) + 3;
  537. keystr = isc_mem_allocate(mctx, len);
  538. snprintf(keystr, len, "%s:%s:%s", algorithm, keyname, secretstr);
  539. setup_keystr();
  540. cleanup:
  541. if (pctx != NULL) {
  542. if (sessionkey != NULL)
  543. cfg_obj_destroy(pctx, &sessionkey);
  544. cfg_parser_destroy(&pctx);
  545. }
  546. if (keystr != NULL)
  547. isc_mem_free(mctx, keystr);
  548. return (result);
  549. }
  550. static void
  551. setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
  552. dst_key_t *dstkey = NULL;
  553. isc_result_t result;
  554. dns_name_t *hmacname = NULL;
  555. debug("Creating key...");
  556. if (sig0key != NULL)
  557. dst_key_free(&sig0key);
  558. /* Try reading the key from a K* pair */
  559. result = dst_key_fromnamedfile(keyfile, NULL,
  560. DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
  561. &dstkey);
  562. /* If that didn't work, try reading it as a session.key keyfile */
  563. if (result != ISC_R_SUCCESS) {
  564. result = read_sessionkey(mctx, lctx);
  565. if (result == ISC_R_SUCCESS)
  566. return;
  567. }
  568. if (result != ISC_R_SUCCESS) {
  569. fprintf(stderr, "could not read key from %.*s.{private,key}: "
  570. "%s\n", basenamelen(keyfile), keyfile,
  571. isc_result_totext(result));
  572. return;
  573. }
  574. switch (dst_key_alg(dstkey)) {
  575. case DST_ALG_HMACMD5:
  576. hmacname = DNS_TSIG_HMACMD5_NAME;
  577. break;
  578. case DST_ALG_HMACSHA1:
  579. hmacname = DNS_TSIG_HMACSHA1_NAME;
  580. break;
  581. case DST_ALG_HMACSHA224:
  582. hmacname = DNS_TSIG_HMACSHA224_NAME;
  583. break;
  584. case DST_ALG_HMACSHA256:
  585. hmacname = DNS_TSIG_HMACSHA256_NAME;
  586. break;
  587. case DST_ALG_HMACSHA384:
  588. hmacname = DNS_TSIG_HMACSHA384_NAME;
  589. break;
  590. case DST_ALG_HMACSHA512:
  591. hmacname = DNS_TSIG_HMACSHA512_NAME;
  592. break;
  593. }
  594. if (hmacname != NULL) {
  595. result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
  596. hmacname, dstkey, ISC_FALSE,
  597. NULL, 0, 0, mctx, NULL,
  598. &tsigkey);
  599. dst_key_free(&dstkey);
  600. if (result != ISC_R_SUCCESS) {
  601. fprintf(stderr, "could not create key from %s: %s\n",
  602. keyfile, isc_result_totext(result));
  603. return;
  604. }
  605. } else {
  606. dst_key_attach(dstkey, &sig0key);
  607. dst_key_free(&dstkey);
  608. }
  609. }
  610. static void
  611. doshutdown(void) {
  612. isc_task_detach(&global_task);
  613. if (userserver != NULL)
  614. isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
  615. if (localaddr != NULL)
  616. isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
  617. if (tsigkey != NULL) {
  618. ddebug("Freeing TSIG key");
  619. dns_tsigkey_detach(&tsigkey);
  620. }
  621. if (sig0key != NULL) {
  622. ddebug("Freeing SIG(0) key");
  623. dst_key_free(&sig0key);
  624. }
  625. if (updatemsg != NULL)
  626. dns_message_destroy(&updatemsg);
  627. if (is_dst_up) {
  628. ddebug("Destroy DST lib");
  629. dst_lib_destroy();
  630. is_dst_up = ISC_FALSE;
  631. }
  632. cleanup_entropy(&entropy);
  633. lwres_conf_clear(lwctx);
  634. lwres_context_destroy(&lwctx);
  635. isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
  636. ddebug("Destroying request manager");
  637. dns_requestmgr_detach(&requestmgr);
  638. ddebug("Freeing the dispatchers");
  639. if (have_ipv4)
  640. dns_dispatch_detach(&dispatchv4);
  641. if (have_ipv6)
  642. dns_dispatch_detach(&dispatchv6);
  643. ddebug("Shutting down dispatch manager");
  644. dns_dispatchmgr_destroy(&dispatchmgr);
  645. }
  646. static void
  647. maybeshutdown(void) {
  648. ddebug("Shutting down request manager");
  649. dns_requestmgr_shutdown(requestmgr);
  650. if (requests != 0)
  651. return;
  652. doshutdown();
  653. }
  654. static void
  655. shutdown_program(isc_task_t *task, isc_event_t *event) {
  656. REQUIRE(task == global_task);
  657. UNUSED(task);
  658. ddebug("shutdown_program()");
  659. isc_event_free(&event);
  660. shuttingdown = ISC_TRUE;
  661. maybeshutdown();
  662. }
  663. static void
  664. setup_system(void) {
  665. isc_result_t result;
  666. isc_sockaddr_t bind_any, bind_any6;
  667. lwres_result_t lwresult;
  668. unsigned int attrs, attrmask;
  669. int i;
  670. isc_logconfig_t *logconfig = NULL;
  671. ddebug("setup_system()");
  672. dns_result_register();
  673. result = isc_net_probeipv4();
  674. if (result == ISC_R_SUCCESS)
  675. have_ipv4 = ISC_TRUE;
  676. result = isc_net_probeipv6();
  677. if (result == ISC_R_SUCCESS)
  678. have_ipv6 = ISC_TRUE;
  679. if (!have_ipv4 && !have_ipv6)
  680. fatal("could not find either IPv4 or IPv6");
  681. result = isc_log_create(mctx, &lctx, &logconfig);
  682. check_result(result, "isc_log_create");
  683. isc_log_setcontext(lctx);
  684. dns_log_init(lctx);
  685. dns_log_setcontext(lctx);
  686. result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
  687. check_result(result, "isc_log_usechannel");
  688. isc_log_setdebuglevel(lctx, logdebuglevel);
  689. lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
  690. if (lwresult != LWRES_R_SUCCESS)
  691. fatal("lwres_context_create failed");
  692. (void)lwres_conf_parse(lwctx, RESOLV_CONF);
  693. lwconf = lwres_conf_get(lwctx);
  694. ns_total = lwconf->nsnext;
  695. if (ns_total <= 0) {
  696. /* No name servers in resolv.conf; default to loopback. */
  697. struct in_addr localhost;
  698. ns_total = 1;
  699. servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
  700. if (servers == NULL)
  701. fatal("out of memory");
  702. localhost.s_addr = htonl(INADDR_LOOPBACK);
  703. isc_sockaddr_fromin(&servers[0], &localhost, dnsport);
  704. } else {
  705. servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
  706. if (servers == NULL)
  707. fatal("out of memory");
  708. for (i = 0; i < ns_total; i++) {
  709. if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) {
  710. struct in_addr in4;
  711. memcpy(&in4, lwconf->nameservers[i].address, 4);
  712. isc_sockaddr_fromin(&servers[i], &in4, dnsport);
  713. } else {
  714. struct in6_addr in6;
  715. memcpy(&in6, lwconf->nameservers[i].address, 16);
  716. isc_sockaddr_fromin6(&servers[i], &in6,
  717. dnsport);
  718. }
  719. }
  720. }
  721. setup_entropy(mctx, NULL, &entropy);
  722. result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE);
  723. check_result(result, "isc_hash_create");
  724. isc_hash_init();
  725. result = dns_dispatchmgr_create(mctx, entropy, &dispatchmgr);
  726. check_result(result, "dns_dispatchmgr_create");
  727. result = isc_socketmgr_create(mctx, &socketmgr);
  728. check_result(result, "dns_socketmgr_create");
  729. result = isc_timermgr_create(mctx, &timermgr);
  730. check_result(result, "dns_timermgr_create");
  731. result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
  732. check_result(result, "isc_taskmgr_create");
  733. result = isc_task_create(taskmgr, 0, &global_task);
  734. check_result(result, "isc_task_create");
  735. result = isc_task_onshutdown(global_task, shutdown_program, NULL);
  736. check_result(result, "isc_task_onshutdown");
  737. result = dst_lib_init(mctx, entropy, 0);
  738. check_result(result, "dst_lib_init");
  739. is_dst_up = ISC_TRUE;
  740. attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
  741. attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
  742. if (have_ipv6) {
  743. attrs = DNS_DISPATCHATTR_UDP;
  744. attrs |= DNS_DISPATCHATTR_MAKEQUERY;
  745. attrs |= DNS_DISPATCHATTR_IPV6;
  746. isc_sockaddr_any6(&bind_any6);
  747. result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
  748. &bind_any6, PACKETSIZE,
  749. 4, 2, 3, 5,
  750. attrs, attrmask, &dispatchv6);
  751. check_result(result, "dns_dispatch_getudp (v6)");
  752. }
  753. if (have_ipv4) {
  754. attrs = DNS_DISPATCHATTR_UDP;
  755. attrs |= DNS_DISPATCHATTR_MAKEQUERY;
  756. attrs |= DNS_DISPATCHATTR_IPV4;
  757. isc_sockaddr_any(&bind_any);
  758. result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
  759. &bind_any, PACKETSIZE,
  760. 4, 2, 3, 5,
  761. attrs, attrmask, &dispatchv4);
  762. check_result(result, "dns_dispatch_getudp (v4)");
  763. }
  764. result = dns_requestmgr_create(mctx, timermgr,
  765. socketmgr, taskmgr, dispatchmgr,
  766. dispatchv4, dispatchv6, &requestmgr);
  767. check_result(result, "dns_requestmgr_create");
  768. if (keystr != NULL)
  769. setup_keystr();
  770. else if (local_only) {
  771. result = read_sessionkey(mctx, lctx);
  772. if (result != ISC_R_SUCCESS)
  773. fatal("can't read key from %s: %s\n",
  774. keyfile, isc_result_totext(result));
  775. } else if (keyfile != NULL)
  776. setup_keyfile(mctx, lctx);
  777. }
  778. static void
  779. get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
  780. int count;
  781. isc_result_t result;
  782. isc_app_block();
  783. result = bind9_getaddresses(host, port, sockaddr, 1, &count);
  784. isc_app_unblock();
  785. if (result != ISC_R_SUCCESS)
  786. fatal("couldn't get address for '%s': %s",
  787. host, isc_result_totext(result));
  788. INSIST(count == 1);
  789. }
  790. #define PARSE_ARGS_FMT "dDML:y:ghlovk:p:rR::t:u:"
  791. static void
  792. pre_parse_args(int argc, char **argv) {
  793. int ch;
  794. while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
  795. switch (ch) {
  796. case 'M': /* was -dm */
  797. debugging = ISC_TRUE;
  798. ddebugging = ISC_TRUE;
  799. memdebugging = ISC_TRUE;
  800. isc_mem_debugging = ISC_MEM_DEBUGTRACE |
  801. ISC_MEM_DEBUGRECORD;
  802. break;
  803. case '?':
  804. case 'h':
  805. if (isc_commandline_option != '?')
  806. fprintf(stderr, "%s: invalid argument -%c\n",
  807. argv[0], isc_commandline_option);
  808. fprintf(stderr, "usage: nsupdate [-dD] [-L level] [-l]"
  809. "[-g | -o | -y keyname:secret | -k keyfile] "
  810. "[-v] [filename]\n");
  811. exit(1);
  812. default:
  813. break;
  814. }
  815. }
  816. isc_commandline_reset = ISC_TRUE;
  817. isc_commandline_index = 1;
  818. }
  819. static void
  820. parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
  821. int ch;
  822. isc_uint32_t i;
  823. isc_result_t result;
  824. debug("parse_args");
  825. while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
  826. switch (ch) {
  827. case 'd':
  828. debugging = ISC_TRUE;
  829. break;
  830. case 'D': /* was -dd */
  831. debugging = ISC_TRUE;
  832. ddebugging = ISC_TRUE;
  833. break;
  834. case 'M':
  835. break;
  836. case 'l':
  837. local_only = ISC_TRUE;
  838. break;
  839. case 'L':
  840. result = isc_parse_uint32(&i, isc_commandline_argument,
  841. 10);
  842. if (result != ISC_R_SUCCESS) {
  843. fprintf(stderr, "bad library debug value "
  844. "'%s'\n", isc_commandline_argument);
  845. exit(1);
  846. }
  847. logdebuglevel = i;
  848. break;
  849. case 'y':
  850. keystr = isc_commandline_argument;
  851. break;
  852. case 'v':
  853. usevc = ISC_TRUE;
  854. break;
  855. case 'k':
  856. keyfile = isc_commandline_argument;
  857. break;
  858. case 'g':
  859. usegsstsig = ISC_TRUE;
  860. use_win2k_gsstsig = ISC_FALSE;
  861. break;
  862. case 'o':
  863. usegsstsig = ISC_TRUE;
  864. use_win2k_gsstsig = ISC_TRUE;
  865. break;
  866. case 'p':
  867. result = isc_parse_uint16(&dnsport,
  868. isc_commandline_argument, 10);
  869. if (result != ISC_R_SUCCESS) {
  870. fprintf(stderr, "bad port number "
  871. "'%s'\n", isc_commandline_argument);
  872. exit(1);
  873. }
  874. break;
  875. case 't':
  876. result = isc_parse_uint32(&timeout,
  877. isc_commandline_argument, 10);
  878. if (result != ISC_R_SUCCESS) {
  879. fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
  880. exit(1);
  881. }
  882. if (timeout == 0)
  883. timeout = UINT_MAX;
  884. break;
  885. case 'u':
  886. result = isc_parse_uint32(&udp_timeout,
  887. isc_commandline_argument, 10);
  888. if (result != ISC_R_SUCCESS) {
  889. fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
  890. exit(1);
  891. }
  892. if (udp_timeout == 0)
  893. udp_timeout = UINT_MAX;
  894. break;
  895. case 'r':
  896. result = isc_parse_uint32(&udp_retries,
  897. isc_commandline_argument, 10);
  898. if (result != ISC_R_SUCCESS) {
  899. fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
  900. exit(1);
  901. }
  902. break;
  903. case 'R':
  904. setup_entropy(mctx, isc_commandline_argument, ectx);
  905. break;
  906. default:
  907. fprintf(stderr, "%s: unhandled option: %c\n",
  908. argv[0], isc_commandline_option);
  909. exit(1);
  910. }
  911. }
  912. if (keyfile != NULL && keystr != NULL) {
  913. fprintf(stderr, "%s: cannot specify both -k and -y\n",
  914. argv[0]);
  915. exit(1);
  916. }
  917. if (local_only) {
  918. struct in_addr localhost;
  919. if (keyfile == NULL)
  920. keyfile = SESSION_KEYFILE;
  921. if (userserver == NULL) {
  922. userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
  923. if (userserver == NULL)
  924. fatal("out of memory");
  925. }
  926. localhost.s_addr = htonl(INADDR_LOOPBACK);
  927. isc_sockaddr_fromin(userserver, &localhost, dnsport);
  928. }
  929. #ifdef GSSAPI
  930. if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
  931. fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
  932. argv[0]);
  933. exit(1);
  934. }
  935. #else
  936. if (usegsstsig) {
  937. fprintf(stderr, "%s: cannot specify -g or -o, " \
  938. "program not linked with GSS API Library\n",
  939. argv[0]);
  940. exit(1);
  941. }
  942. #endif
  943. if (argv[isc_commandline_index] != NULL) {
  944. if (strcmp(argv[isc_commandline_index], "-") == 0) {
  945. input = stdin;
  946. } else {
  947. result = isc_stdio_open(argv[isc_commandline_index],
  948. "r", &input);
  949. if (result != ISC_R_SUCCESS) {
  950. fprintf(stderr, "could not open '%s': %s\n",
  951. argv[isc_commandline_index],
  952. isc_result_totext(result));
  953. exit(1);
  954. }
  955. }
  956. interactive = ISC_FALSE;
  957. }
  958. }
  959. static isc_uint16_t
  960. parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
  961. isc_result_t result;
  962. char *word;
  963. isc_buffer_t *namebuf = NULL;
  964. isc_buffer_t source;
  965. word = nsu_strsep(cmdlinep, " \t\r\n");
  966. if (*word == 0) {
  967. fprintf(stderr, "could not read owner name\n");
  968. return (STATUS_SYNTAX);
  969. }
  970. result = dns_message_gettempname(msg, namep);
  971. check_result(result, "dns_message_gettempname");
  972. result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
  973. check_result(result, "isc_buffer_allocate");
  974. dns_name_init(*namep, NULL);
  975. dns_name_setbuffer(*namep, namebuf);
  976. dns_message_takebuffer(msg, &namebuf);
  977. isc_buffer_init(&source, word, strlen(word));
  978. isc_buffer_add(&source, strlen(word));
  979. result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL);
  980. check_result(result, "dns_name_fromtext");
  981. isc_buffer_invalidate(&source);
  982. return (STATUS_MORE);
  983. }
  984. static isc_uint16_t
  985. parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
  986. dns_rdatatype_t rdatatype, dns_message_t *msg,
  987. dns_rdata_t *rdata)
  988. {
  989. char *cmdline = *cmdlinep;
  990. isc_buffer_t source, *buf = NULL, *newbuf = NULL;
  991. isc_region_t r;
  992. isc_lex_t *lex = NULL;
  993. dns_rdatacallbacks_t callbacks;
  994. isc_result_t result;
  995. while (*cmdline != 0 && isspace((unsigned char)*cmdline))
  996. cmdline++;
  997. if (*cmdline != 0) {
  998. dns_rdatacallbacks_init(&callbacks);
  999. result = isc_lex_create(mctx, strlen(cmdline), &lex);
  1000. check_result(result, "isc_lex_create");
  1001. isc_buffer_init(&source, cmdline, strlen(cmdline));
  1002. isc_buffer_add(&source, strlen(cmdline));
  1003. result = isc_lex_openbuffer(lex, &source);
  1004. check_result(result, "isc_lex_openbuffer");
  1005. result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
  1006. check_result(result, "isc_buffer_allocate");
  1007. result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
  1008. dns_rootname, 0, mctx, buf,
  1009. &callbacks);
  1010. isc_lex_destroy(&lex);
  1011. if (result == ISC_R_SUCCESS) {
  1012. isc_buffer_usedregion(buf, &r);
  1013. result = isc_buffer_allocate(mctx, &newbuf, r.length);
  1014. check_result(result, "isc_buffer_allocate");
  1015. isc_buffer_putmem(newbuf, r.base, r.length);
  1016. isc_buffer_usedregion(newbuf, &r);
  1017. dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
  1018. isc_buffer_free(&buf);
  1019. dns_message_takebuffer(msg, &newbuf);
  1020. } else {
  1021. fprintf(stderr, "invalid rdata format: %s\n",
  1022. isc_result_totext(result));
  1023. isc_buffer_free(&buf);
  1024. return (STATUS_SYNTAX);
  1025. }
  1026. } else {
  1027. rdata->flags = DNS_RDATA_UPDATE;
  1028. }
  1029. *cmdlinep = cmdline;
  1030. return (STATUS_MORE);
  1031. }
  1032. static isc_uint16_t
  1033. make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
  1034. isc_result_t result;
  1035. char *word;
  1036. dns_name_t *name = NULL;
  1037. isc_textregion_t region;
  1038. dns_rdataset_t *rdataset = NULL;
  1039. dns_rdatalist_t *rdatalist = NULL;
  1040. dns_rdataclass_t rdataclass;
  1041. dns_rdatatype_t rdatatype;
  1042. dns_rdata_t *rdata = NULL;
  1043. isc_uint16_t retval;
  1044. ddebug("make_prereq()");
  1045. /*
  1046. * Read the owner name
  1047. */
  1048. retval = parse_name(&cmdline, updatemsg, &name);
  1049. if (retval != STATUS_MORE)
  1050. return (retval);
  1051. /*
  1052. * If this is an rrset prereq, read the class or type.
  1053. */
  1054. if (isrrset) {
  1055. word = nsu_strsep(&cmdline, " \t\r\n");
  1056. if (*word == 0) {
  1057. fprintf(stderr, "could not read class or type\n");
  1058. goto failure;
  1059. }
  1060. region.base = word;
  1061. region.length = strlen(word);
  1062. result = dns_rdataclass_fromtext(&rdataclass, &region);
  1063. if (result == ISC_R_SUCCESS) {
  1064. if (!setzoneclass(rdataclass)) {
  1065. fprintf(stderr, "class mismatch: %s\n", word);
  1066. goto failure;
  1067. }
  1068. /*
  1069. * Now read the type.
  1070. */
  1071. word = nsu_strsep(&cmdline, " \t\r\n");
  1072. if (*word == 0) {
  1073. fprintf(stderr, "could not read type\n");
  1074. goto failure;
  1075. }
  1076. region.base = word;
  1077. region.length = strlen(word);
  1078. result = dns_rdatatype_fromtext(&rdatatype, &region);
  1079. if (result != ISC_R_SUCCESS) {
  1080. fprintf(stderr, "invalid type: %s\n", word);
  1081. goto failure;
  1082. }
  1083. } else {
  1084. rdataclass = getzoneclass();
  1085. result = dns_rdatatype_fromtext(&rdatatype, &region);
  1086. if (result != ISC_R_SUCCESS) {
  1087. fprintf(stderr, "invalid type: %s\n", word);
  1088. goto failure;
  1089. }
  1090. }
  1091. } else
  1092. rdatatype = dns_rdatatype_any;
  1093. result = dns_message_gettemprdata(updatemsg, &rdata);
  1094. check_result(result, "dns_message_gettemprdata");
  1095. dns_rdata_init(rdata);
  1096. if (isrrset && ispositive) {
  1097. retval = parse_rdata(&cmdline, rdataclass, rdatatype,
  1098. updatemsg, rdata);
  1099. if (retval != STATUS_MORE)
  1100. goto failure;
  1101. } else
  1102. rdata->flags = DNS_RDATA_UPDATE;
  1103. result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
  1104. check_result(result, "dns_message_gettemprdatalist");
  1105. result = dns_message_gettemprdataset(updatemsg, &rdataset);
  1106. check_result(result, "dns_message_gettemprdataset");
  1107. dns_rdatalist_init(rdatalist);
  1108. rdatalist->type = rdatatype;
  1109. if (ispositive) {
  1110. if (isrrset && rdata->data != NULL)
  1111. rdatalist->rdclass = rdataclass;
  1112. else
  1113. rdatalist->rdclass = dns_rdataclass_any;
  1114. } else
  1115. rdatalist->rdclass = dns_rdataclass_none;
  1116. rdatalist->covers = 0;
  1117. rdatalist->ttl = 0;
  1118. rdata->rdclass = rdatalist->rdclass;
  1119. rdata->type = rdatatype;
  1120. ISC_LIST_INIT(rdatalist->rdata);
  1121. ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  1122. dns_rdataset_init(rdataset);
  1123. dns_rdatalist_tordataset(rdatalist, rdataset);
  1124. ISC_LIST_INIT(name->list);
  1125. ISC_LIST_APPEND(name->list, rdataset, link);
  1126. dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
  1127. return (STATUS_MORE);
  1128. failure:
  1129. if (name != NULL)
  1130. dns_message_puttempname(updatemsg, &name);
  1131. return (STATUS_SYNTAX);
  1132. }
  1133. static isc_uint16_t
  1134. evaluate_prereq(char *cmdline) {
  1135. char *word;
  1136. isc_boolean_t ispositive, isrrset;
  1137. ddebug("evaluate_prereq()");
  1138. word = nsu_strsep(&cmdline, " \t\r\n");
  1139. if (*word == 0) {
  1140. fprintf(stderr, "could not read operation code\n");
  1141. return (STATUS_SYNTAX);
  1142. }
  1143. if (strcasecmp(word, "nxdomain") == 0) {
  1144. ispositive = ISC_FALSE;
  1145. isrrset = ISC_FALSE;
  1146. } else if (strcasecmp(word, "yxdomain") == 0) {
  1147. ispositive = ISC_TRUE;
  1148. isrrset = ISC_FALSE;
  1149. } else if (strcasecmp(word, "nxrrset") == 0) {
  1150. ispositive = ISC_FALSE;
  1151. isrrset = ISC_TRUE;
  1152. } else if (strcasecmp(word, "yxrrset") == 0) {
  1153. ispositive = ISC_TRUE;
  1154. isrrset = ISC_TRUE;
  1155. } else {
  1156. fprintf(stderr, "incorrect operation code: %s\n", word);
  1157. return (STATUS_SYNTAX);
  1158. }
  1159. return (make_prereq(cmdline, ispositive, isrrset));
  1160. }
  1161. static isc_uint16_t
  1162. evaluate_server(char *cmdline) {
  1163. char *word, *server;
  1164. long port;
  1165. if (local_only) {
  1166. fprintf(stderr, "cannot reset server in localhost-only mode\n");
  1167. return (STATUS_SYNTAX);
  1168. }
  1169. word = nsu_strsep(&cmdline, " \t\r\n");
  1170. if (*word == 0) {
  1171. fprintf(stderr, "could not read server name\n");
  1172. return (STATUS_SYNTAX);
  1173. }
  1174. server = word;
  1175. word = nsu_strsep(&cmdline, " \t\r\n");
  1176. if (*word == 0)
  1177. port = dnsport;
  1178. else {
  1179. char *endp;
  1180. port = strtol(word, &endp, 10);
  1181. if (*endp != 0) {
  1182. fprintf(stderr, "port '%s' is not numeric\n", word);
  1183. return (STATUS_SYNTAX);
  1184. } else if (port < 1 || port > 65535) {
  1185. fprintf(stderr, "port '%s' is out of range "
  1186. "(1 to 65535)\n", word);
  1187. return (STATUS_SYNTAX);
  1188. }
  1189. }
  1190. if (userserver == NULL) {
  1191. userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
  1192. if (userserver == NULL)
  1193. fatal("out of memory");
  1194. }
  1195. get_address(server, (in_port_t)port, userserver);
  1196. return (STATUS_MORE);
  1197. }
  1198. static isc_uint16_t
  1199. evaluate_local(char *cmdline) {
  1200. char *word, *local;
  1201. long port;
  1202. struct in_addr in4;
  1203. struct in6_addr in6;
  1204. word = nsu_strsep(&cmdline, " \t\r\n");
  1205. if (*word == 0) {
  1206. fprintf(stderr, "could not read server name\n");
  1207. return (STATUS_SYNTAX);
  1208. }
  1209. local = word;
  1210. word = nsu_strsep(&cmdline, " \t\r\n");
  1211. if (*word == 0)
  1212. port = 0;
  1213. else {
  1214. char *endp;
  1215. port = strtol(word, &endp, 10);
  1216. if (*endp != 0) {
  1217. fprintf(stderr, "port '%s' is not numeric\n", word);
  1218. return (STATUS_SYNTAX);
  1219. } else if (port < 1 || port > 65535) {
  1220. fprintf(stderr, "port '%s' is out of range "
  1221. "(1 to 65535)\n", word);
  1222. return (STATUS_SYNTAX);
  1223. }
  1224. }
  1225. if (localaddr == NULL) {
  1226. localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
  1227. if (localaddr == NULL)
  1228. fatal("out of memory");
  1229. }
  1230. if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
  1231. isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
  1232. else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
  1233. isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
  1234. else {
  1235. fprintf(stderr, "invalid address %s", local);
  1236. return (STATUS_SYNTAX);
  1237. }
  1238. return (STATUS_MORE);
  1239. }
  1240. static isc_uint16_t
  1241. evaluate_key(char *cmdline) {
  1242. char *namestr;
  1243. char *secretstr;
  1244. isc_buffer_t b;
  1245. isc_result_t result;
  1246. dns_fixedname_t fkeyname;
  1247. dns_name_t *keyname;
  1248. int secretlen;
  1249. unsigned char *secret = NULL;
  1250. isc_buffer_t secretbuf;
  1251. dns_name_t *hmacname = NULL;
  1252. isc_uint16_t digestbits = 0;
  1253. char *n;
  1254. namestr = nsu_strsep(&cmdline, " \t\r\n");
  1255. if (*namestr == 0) {
  1256. fprintf(stderr, "could not read key name\n");
  1257. return (STATUS_SYNTAX);
  1258. }
  1259. dns_fixedname_init(&fkeyname);
  1260. keyname = dns_fixedname_name(&fkeyname);
  1261. n = strchr(namestr, ':');
  1262. if (n != NULL) {
  1263. digestbits = parse_hmac(&hmacname, namestr, n - namestr);
  1264. namestr = n + 1;
  1265. } else
  1266. hmacname = DNS_TSIG_HMACMD5_NAME;
  1267. isc_buffer_init(&b, namestr, strlen(namestr));
  1268. isc_buffer_add(&b, strlen(namestr));
  1269. result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
  1270. if (result != ISC_R_SUCCESS) {
  1271. fprintf(stderr, "could not parse key name\n");
  1272. return (STATUS_SYNTAX);
  1273. }
  1274. secretstr = nsu_strsep(&cmdline, "\r\n");
  1275. if (*secretstr == 0) {
  1276. fprintf(stderr, "could not read key secret\n");
  1277. return (STATUS_SYNTAX);
  1278. }
  1279. secretlen = strlen(secretstr) * 3 / 4;
  1280. secret = isc_mem_allocate(mctx, secretlen);
  1281. if (secret == NULL)
  1282. fatal("out of memory");
  1283. isc_buffer_init(&secretbuf, secret, secretlen);
  1284. result = isc_base64_decodestring(secretstr, &secretbuf);
  1285. if (result != ISC_R_SUCCESS) {
  1286. fprintf(stderr, "could not create key from %s: %s\n",
  1287. secretstr, isc_result_totext(result));
  1288. isc_mem_free(mctx, secret);
  1289. return (STATUS_SYNTAX);
  1290. }
  1291. secretlen = isc_buffer_usedlength(&secretbuf);
  1292. if (tsigkey != NULL)
  1293. dns_tsigkey_detach(&tsigkey);
  1294. result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
  1295. ISC_FALSE, NULL, 0, 0, mctx, NULL,
  1296. &tsigkey);
  1297. isc_mem_free(mctx, secret);
  1298. if (result != ISC_R_SUCCESS) {
  1299. fprintf(stderr, "could not create key from %s %s: %s\n",
  1300. namestr, secretstr, dns_result_totext(result));
  1301. return (STATUS_SYNTAX);
  1302. }
  1303. dst_key_setbits(tsigkey->key, digestbits);
  1304. return (STATUS_MORE);
  1305. }
  1306. static isc_uint16_t
  1307. evaluate_zone(char *cmdline) {
  1308. char *word;
  1309. isc_buffer_t b;
  1310. isc_result_t result;
  1311. word = nsu_strsep(&cmdline, " \t\r\n");
  1312. if (*word == 0) {
  1313. fprintf(stderr, "could not read zone name\n");
  1314. return (STATUS_SYNTAX);
  1315. }
  1316. dns_fixedname_init(&fuserzone);
  1317. userzone = dns_fixedname_name(&fuserzone);
  1318. isc_buffer_init(&b, word, strlen(word));
  1319. isc_buffer_add(&b, strlen(word));
  1320. result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL);
  1321. if (result != ISC_R_SUCCESS) {
  1322. userzone = NULL; /* Lest it point to an invalid name */
  1323. fprintf(stderr, "could not parse zone name\n");
  1324. return (STATUS_SYNTAX);
  1325. }
  1326. return (STATUS_MORE);
  1327. }
  1328. static isc_uint16_t
  1329. evaluate_realm(char *cmdline) {
  1330. #ifdef GSSAPI
  1331. char *word;
  1332. char buf[1024];
  1333. word = nsu_strsep(&cmdline, " \t\r\n");
  1334. if (*word == 0) {
  1335. if (realm != NULL)
  1336. isc_mem_free(mctx, realm);
  1337. realm = NULL;
  1338. return (STATUS_MORE);
  1339. }
  1340. snprintf(buf, sizeof(buf), "@%s", word);
  1341. realm = isc_mem_strdup(mctx, buf);
  1342. if (realm == NULL)
  1343. fatal("out of memory");
  1344. return (STATUS_MORE);
  1345. #else
  1346. UNUSED(cmdline);
  1347. return (STATUS_SYNTAX);
  1348. #endif
  1349. }
  1350. static isc_uint16_t
  1351. evaluate_ttl(char *cmdline) {
  1352. char *word;
  1353. isc_result_t result;
  1354. isc_uint32_t ttl;
  1355. word = nsu_strsep(&cmdline, " \t\r\n");
  1356. if (*word == 0) {
  1357. fprintf(stderr, "could not ttl\n");
  1358. return (STATUS_SYNTAX);
  1359. }
  1360. if (!strcasecmp(word, "none")) {
  1361. default_ttl = 0;
  1362. default_ttl_set = ISC_FALSE;
  1363. return (STATUS_MORE);
  1364. }
  1365. result = isc_parse_uint32(&ttl, word, 10);
  1366. if (result != ISC_R_SUCCESS)
  1367. return (STATUS_SYNTAX);
  1368. if (ttl > TTL_MAX) {
  1369. fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
  1370. word, TTL_MAX);
  1371. return (STATUS_SYNTAX);
  1372. }
  1373. default_ttl = ttl;
  1374. default_ttl_set = ISC_TRUE;
  1375. return (STATUS_MORE);
  1376. }
  1377. static isc_uint16_t
  1378. evaluate_class(char *cmdline) {
  1379. char *word;
  1380. isc_textregion_t r;
  1381. isc_result_t result;
  1382. dns_rdataclass_t rdclass;
  1383. word = nsu_strsep(&cmdline, " \t\r\n");
  1384. if (*word == 0) {
  1385. fprintf(stderr, "could not read class name\n");
  1386. return (STATUS_SYNTAX);
  1387. }
  1388. r.base = word;
  1389. r.length = strlen(word);
  1390. result = dns_rdataclass_fromtext(&rdclass, &r);
  1391. if (result != ISC_R_SUCCESS) {
  1392. fprintf(stderr, "could not parse class name: %s\n", word);
  1393. return (STATUS_SYNTAX);
  1394. }
  1395. switch (rdclass) {
  1396. case dns_rdataclass_none:
  1397. case dns_rdataclass_any:
  1398. case dns_rdataclass_reserved0:
  1399. fprintf(stderr, "bad default class: %s\n", word);
  1400. return (STATUS_SYNTAX);
  1401. default:
  1402. defaultclass = rdclass;
  1403. }
  1404. return (STATUS_MORE);
  1405. }
  1406. static isc_uint16_t
  1407. update_addordelete(char *cmdline, isc_boolean_t isdelete) {
  1408. isc_result_t result;
  1409. dns_name_t *name = NULL;
  1410. isc_uint32_t ttl;
  1411. char *word;
  1412. dns_rdataclass_t rdataclass;
  1413. dns_rdatatype_t rdatatype;
  1414. dns_rdata_t *rdata = NULL;
  1415. dns_rdatalist_t *rdatalist = NULL;
  1416. dns_rdataset_t *rdataset = NULL;
  1417. isc_textregion_t region;
  1418. isc_uint16_t retval;
  1419. ddebug("update_addordelete()");
  1420. /*
  1421. * Read the owner name.
  1422. */
  1423. retval = parse_name(&cmdline, updatemsg, &name);
  1424. if (retval != STATUS_MORE)
  1425. return (retval);
  1426. result = dns_message_gettemprdata(updatemsg, &rdata);
  1427. check_result(result, "dns_message_gettemprdata");
  1428. dns_rdata_init(rdata);
  1429. /*
  1430. * If this is an add, read the TTL and verify that it's in range.
  1431. * If it's a delete, ignore a TTL if present (for compatibility).
  1432. */
  1433. word = nsu_strsep(&cmdline, " \t\r\n");
  1434. if (*word == 0) {
  1435. if (!isdelete) {
  1436. fprintf(stderr, "could not read owner ttl\n");
  1437. goto failure;
  1438. }
  1439. else {
  1440. ttl = 0;
  1441. rdataclass = dns_rdataclass_any;
  1442. rdatatype = dns_rdatatype_any;
  1443. rdata->flags = DNS_RDATA_UPDATE;
  1444. goto doneparsing;
  1445. }
  1446. }
  1447. result = isc_parse_uint32(&ttl, word, 10);
  1448. if (result != ISC_R_SUCCESS) {
  1449. if (isdelete) {
  1450. ttl = 0;
  1451. goto parseclass;
  1452. } else if (default_ttl_set) {
  1453. ttl = default_ttl;
  1454. goto parseclass;
  1455. } else {
  1456. fprintf(stderr, "ttl '%s': %s\n", word,
  1457. isc_result_totext(result));
  1458. goto failure;
  1459. }
  1460. }
  1461. if (isdelete)
  1462. ttl = 0;
  1463. else if (ttl > TTL_MAX) {
  1464. fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
  1465. word, TTL_MAX);
  1466. goto failure;
  1467. }
  1468. /*
  1469. * Read the class or type.
  1470. */
  1471. word = nsu_strsep(&cmdline, " \t\r\n");
  1472. parseclass:
  1473. if (*word == 0) {
  1474. if (isdelete) {
  1475. rdataclass = dns_rdataclass_any;
  1476. rdatatype = dns_rdatatype_any;
  1477. rdata->flags = DNS_RDATA_UPDATE;
  1478. goto doneparsing;
  1479. } else {
  1480. fprintf(stderr, "could not read class or type\n");
  1481. goto failure;
  1482. }
  1483. }
  1484. region.base = word;
  1485. region.length = strlen(word);
  1486. rdataclass = dns_rdataclass_any;
  1487. result = dns_rdataclass_fromtext(&rdataclass, &region);
  1488. if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
  1489. if (!setzoneclass(rdataclass)) {
  1490. fprintf(stderr, "class mismatch: %s\n", word);
  1491. goto failure;
  1492. }
  1493. /*
  1494. * Now read the type.
  1495. */
  1496. word = nsu_strsep(&cmdline, " \t\r\n");
  1497. if (*word == 0) {
  1498. if (isdelete) {
  1499. rdataclass = dns_rdataclass_any;
  1500. rdatatype = dns_rdatatype_any;
  1501. rdata->flags = DNS_RDATA_UPDATE;
  1502. goto doneparsing;
  1503. } else {
  1504. fprintf(stderr, "could not read type\n");
  1505. goto failure;
  1506. }
  1507. }
  1508. region.base = word;
  1509. region.length = strlen(word);
  1510. result = dns_rdatatype_fromtext(&rdatatype, &region);
  1511. if (result != ISC_R_SUCCESS) {
  1512. fprintf(stderr, "'%s' is not a valid type: %s\n",
  1513. word, isc_result_totext(result));
  1514. goto failure;
  1515. }
  1516. } else {
  1517. rdataclass = getzoneclass();
  1518. result = dns_rdatatype_fromtext(&rdatatype, &region);
  1519. if (result != ISC_R_SUCCESS) {
  1520. fprintf(stderr, "'%s' is not a valid class or type: "
  1521. "%s\n", word, isc_result_totext(result));
  1522. goto failure;
  1523. }
  1524. }
  1525. retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
  1526. rdata);
  1527. if (retval != STATUS_MORE)
  1528. goto failure;
  1529. if (isdelete) {
  1530. if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
  1531. rdataclass = dns_rdataclass_any;
  1532. else
  1533. rdataclass = dns_rdataclass_none;
  1534. } else {
  1535. if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
  1536. fprintf(stderr, "could not read rdata\n");
  1537. goto failure;
  1538. }
  1539. }
  1540. doneparsing:
  1541. result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
  1542. check_result(result, "dns_message_gettemprdatalist");
  1543. result = dns_message_gettemprdataset(updatemsg, &rdataset);
  1544. check_result(result, "dns_message_gettemprdataset");
  1545. dns_rdatalist_init(rdatalist);
  1546. rdatalist->type = rdatatype;
  1547. rdatalist->rdclass = rdataclass;
  1548. rdatalist->covers = rdatatype;
  1549. rdatalist->ttl = (dns_ttl_t)ttl;
  1550. ISC_LIST_INIT(rdatalist->rdata);
  1551. ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  1552. dns_rdataset_init(rdataset);
  1553. dns_rdatalist_tordataset(rdatalist, rdataset);
  1554. ISC_LIST_INIT(name->list);
  1555. ISC_LIST_APPEND(name->list, rdataset, link);
  1556. dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
  1557. return (STATUS_MORE);
  1558. failure:
  1559. if (name != NULL)
  1560. dns_message_puttempname(updatemsg, &name);
  1561. dns_message_puttemprdata(updatemsg, &rdata);
  1562. return (STATUS_SYNTAX);
  1563. }
  1564. static isc_uint16_t
  1565. evaluate_update(char *cmdline) {
  1566. char *word;
  1567. isc_boolean_t isdelete;
  1568. ddebug("evaluate_update()");
  1569. word = nsu_strsep(&cmdline, " \t\r\n");
  1570. if (*word == 0) {
  1571. fprintf(stderr, "could not read operation code\n");
  1572. return (STATUS_SYNTAX);
  1573. }
  1574. if (strcasecmp(word, "delete") == 0)
  1575. isdelete = ISC_TRUE;
  1576. else if (strcasecmp(word, "add") == 0)
  1577. isdelete = ISC_FALSE;
  1578. else {
  1579. fprintf(stderr, "incorrect operation code: %s\n", word);
  1580. return (STATUS_SYNTAX);
  1581. }
  1582. return (update_addordelete(cmdline, isdelete));
  1583. }
  1584. static void
  1585. setzone(dns_name_t *zonename) {
  1586. isc_result_t result;
  1587. dns_name_t *name = NULL;
  1588. dns_rdataset_t *rdataset = NULL;
  1589. result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
  1590. if (result == ISC_R_SUCCESS) {
  1591. dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
  1592. dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
  1593. for (rdataset = ISC_LIST_HEAD(name->list);
  1594. rdataset != NULL;
  1595. rdataset = ISC_LIST_HEAD(name->list)) {
  1596. ISC_LIST_UNLINK(name->list, rdataset, link);
  1597. dns_rdataset_disassociate(rdataset);
  1598. dns_message_puttemprdataset(updatemsg, &rdataset);
  1599. }
  1600. dns_message_puttempname(updatemsg, &name);
  1601. }
  1602. if (zonename != NULL) {
  1603. result = dns_message_gettempname(updatemsg, &name);
  1604. check_result(result, "dns_message_gettempname");
  1605. dns_name_init(name, NULL);
  1606. dns_name_clone(zonename, name);
  1607. result = dns_message_gettemprdataset(updatemsg, &rdataset);
  1608. check_result(result, "dns_message_gettemprdataset");
  1609. dns_rdataset_makequestion(rdataset, getzoneclass(),
  1610. dns_rdatatype_soa);
  1611. ISC_LIST_INIT(name->list);
  1612. ISC_LIST_APPEND(name->list, rdataset, link);
  1613. dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
  1614. }
  1615. }
  1616. static void
  1617. show_message(FILE *stream, dns_message_t *msg, const char *description) {
  1618. isc_result_t result;
  1619. isc_buffer_t *buf = NULL;
  1620. int bufsz;
  1621. ddebug("show_message()");
  1622. setzone(userzone);
  1623. bufsz = INITTEXT;
  1624. do {
  1625. if (bufsz > MAXTEXT) {
  1626. fprintf(stderr, "could not allocate large enough "
  1627. "buffer to display message\n");
  1628. exit(1);
  1629. }
  1630. if (buf != NULL)
  1631. isc_buffer_free(&buf);
  1632. result = isc_buffer_allocate(mctx, &buf, bufsz);
  1633. check_result(result, "isc_buffer_allocate");
  1634. result = dns_message_totext(msg, style, 0, buf);
  1635. bufsz *= 2;
  1636. } while (result == ISC_R_NOSPACE);
  1637. if (result != ISC_R_SUCCESS) {
  1638. fprintf(stderr, "could not convert message to text format.\n");
  1639. isc_buffer_free(&buf);
  1640. return;
  1641. }
  1642. fprintf(stream, "%s\n%.*s", description,
  1643. (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
  1644. isc_buffer_free(&buf);
  1645. }
  1646. static isc_uint16_t
  1647. get_next_command(void) {
  1648. char cmdlinebuf[MAXCMD];
  1649. char *cmdline;
  1650. char *word;
  1651. ddebug("get_next_command()");
  1652. if (interactive) {
  1653. fprintf(stdout, "> ");
  1654. fflush(stdout);
  1655. }
  1656. isc_app_block();
  1657. cmdline = fgets(cmdlinebuf, MAXCMD, input);
  1658. isc_app_unblock();
  1659. if (cmdline == NULL)
  1660. return (STATUS_QUIT);
  1661. word = nsu_strsep(&cmdline, " \t\r\n");
  1662. if (feof(input))
  1663. return (STATUS_QUIT);
  1664. if (*word == 0)
  1665. return (STATUS_SEND);
  1666. if (word[0] == ';')
  1667. return (STATUS_MORE);
  1668. if (strcasecmp(word, "quit") == 0)
  1669. return (STATUS_QUIT);
  1670. if (strcasecmp(word, "prereq") == 0)
  1671. return (evaluate_prereq(cmdline));
  1672. if (strcasecmp(word, "update") == 0)
  1673. return (evaluate_update(cmdline));
  1674. if (strcasecmp(word, "server") == 0)
  1675. return (evaluate_server(cmdline));
  1676. if (strcasecmp(word, "local") == 0)
  1677. return (evaluate_local(cmdline));
  1678. if (strcasecmp(word, "zone") == 0)
  1679. return (evaluate_zone(cmdline));
  1680. if (strcasecmp(word, "class") == 0)
  1681. return (evaluate_class(cmdline));
  1682. if (strcasecmp(word, "send") == 0)
  1683. return (STATUS_SEND);
  1684. if (strcasecmp(word, "debug") == 0) {
  1685. if (debugging)
  1686. ddebugging = ISC_TRUE;
  1687. else
  1688. debugging = ISC_TRUE;
  1689. return (STATUS_MORE);
  1690. }
  1691. if (strcasecmp(word, "ttl") == 0)
  1692. return (evaluate_ttl(cmdline));
  1693. if (strcasecmp(word, "show") == 0) {
  1694. show_message(stdout, updatemsg, "Outgoing update query:");
  1695. return (STATUS_MORE);
  1696. }