43 #include <ldns/ldns.h> 48 #include <sys/select.h> 49 #include <sys/socket.h> 50 #ifdef HAVE_SYS_TYPES_H 51 # include <sys/types.h> 56 #include <sys/types.h> 58 #define SE_CMDH_CMDLEN 7 61 static char const * cmdh_str =
"cmdhandler";
69 cmdhandler_handle_cmd_help(
int sockfd)
71 char buf[ODS_SE_MAXLINE];
73 (void) snprintf(buf, ODS_SE_MAXLINE,
75 "zones Show the currently known zones.\n" 76 "sign <zone> [--serial <nr>] Read zone and schedule for immediate " 78 " If a serial is given, that serial is used " 79 "in the output zone.\n" 80 "sign --all Read all zones and schedule all for " 81 "immediate (re-)sign.\n" 83 ods_writen(sockfd, buf, strlen(buf));
85 (void) snprintf(buf, ODS_SE_MAXLINE,
86 "clear <zone> Delete the internal storage of this " 88 " All signatures will be regenerated " 89 "on the next re-sign.\n" 90 "queue Show the current task queue.\n" 91 "flush Execute all scheduled tasks " 94 ods_writen(sockfd, buf, strlen(buf));
96 (void) snprintf(buf, ODS_SE_MAXLINE,
97 "update <zone> Update this zone signer " 99 "update [--all] Update zone list and all signer " 101 "retransfer <zone> Retransfer the zone from the master.\n" 102 "start Start the engine.\n" 103 "running Check if the engine is running.\n" 104 "reload Reload the engine.\n" 105 "stop Stop the engine.\n" 106 "verbosity <nr> Set verbosity.\n" 108 ods_writen(sockfd, buf, strlen(buf));
120 char buf[ODS_SE_MAXLINE];
122 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
124 ods_log_assert(cmdc);
125 ods_log_assert(cmdc->
engine);
128 (void)snprintf(buf, ODS_SE_MAXLINE,
"There are no zones configured\n");
129 ods_writen(sockfd, buf, strlen(buf));
134 (void)snprintf(buf, ODS_SE_MAXLINE,
"There are %i zones configured\n",
136 ods_writen(sockfd, buf, strlen(buf));
139 while (node && node != LDNS_RBTREE_NULL) {
141 for (i=0; i < ODS_SE_MAXLINE; i++) {
144 (void)snprintf(buf, ODS_SE_MAXLINE,
"- %s\n", zone->
name);
145 ods_writen(sockfd, buf, strlen(buf));
146 node = ldns_rbtree_next(node);
161 char buf[ODS_SE_MAXLINE];
162 ods_status status = ODS_STATUS_OK;
164 ods_status zl_changed = ODS_STATUS_OK;
166 ods_log_assert(cmdc);
167 ods_log_assert(cmdc->
engine);
169 ods_log_assert(engine->
taskq);
170 if (ods_strcmp(tbd,
"--all") == 0) {
174 if (zl_changed == ODS_STATUS_UNCHANGED) {
175 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has not changed." 176 " Signer configurations updated.\n");
177 ods_writen(sockfd, buf, strlen(buf));
178 }
else if (zl_changed == ODS_STATUS_OK) {
179 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list updated: %i " 180 "removed, %i added, %i updated.\n",
184 ods_writen(sockfd, buf, strlen(buf));
187 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has errors.\n");
188 ods_writen(sockfd, buf, strlen(buf));
190 if (zl_changed == ODS_STATUS_OK ||
191 zl_changed == ODS_STATUS_UNCHANGED) {
215 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
217 ods_writen(sockfd, buf, strlen(buf));
219 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
227 if (status != ODS_STATUS_OK) {
228 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule " 229 "task for zone %s.\n", tbd);
230 ods_writen(sockfd, buf, strlen(buf));
231 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
232 cmdh_str, zone->
name, ods_status2str(status));
234 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s config being updated.\n",
236 ods_writen(sockfd, buf, strlen(buf));
237 ods_log_verbose(
"[%s] zone %s scheduled for immediate update signconf",
250 cmdhandler_handle_cmd_retransfer(
int sockfd,
cmdhandler_type* cmdc,
char* tbd)
253 char buf[ODS_SE_MAXLINE];
256 ods_log_assert(cmdc);
257 ods_log_assert(cmdc->
engine);
259 ods_log_assert(engine->
taskq);
272 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
274 ods_writen(sockfd, buf, strlen(buf));
276 (void)snprintf(buf, ODS_SE_MAXLINE,
277 "Error: Zone %s not configured to use DNS input adapter.\n",
279 ods_writen(sockfd, buf, strlen(buf));
283 ods_log_debug(
"[%s] forward a notify", cmdh_str);
286 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s being retransferred.\n", tbd);
287 ods_writen(sockfd, buf, strlen(buf));
288 ods_log_verbose(
"[%s] zone %s being retransferred", cmdh_str, tbd);
294 max(uint32_t a, uint32_t b)
305 cmdhandler_handle_cmd_sign(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
309 ods_status status = ODS_STATUS_OK;
310 char buf[ODS_SE_MAXLINE];
313 ods_log_assert(cmdc);
314 ods_log_assert(cmdc->
engine);
316 ods_log_assert(engine->
taskq);
317 if (ods_strcmp(tbd,
"--all") == 0) {
322 (void)snprintf(buf, ODS_SE_MAXLINE,
"All zones scheduled for " 323 "immediate re-sign.\n");
324 ods_writen(sockfd, buf, strlen(buf));
325 ods_log_verbose(
"[%s] all zones scheduled for immediate re-sign",
328 char* delim1 = strchr(tbd,
' ');
330 int force_serial = 0;
335 if (strncmp(delim1+1,
"--serial ", 9) != 0) {
336 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting <zone> " 337 "--serial <nr>, got %s.\n", tbd);
338 ods_writen(sockfd, buf, strlen(buf));
341 delim2 = strchr(delim1+1,
' ');
343 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial.\n");
344 ods_writen(sockfd, buf, strlen(buf));
347 serial = (uint32_t) strtol(delim2+1, &end, 10);
349 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial, " 350 "got %s.\n", delim2+1);
351 ods_writen(sockfd, buf, strlen(buf));
369 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
371 ods_writen(sockfd, buf, strlen(buf));
377 ods_log_assert(zone->
db);
378 if (!util_serial_gt(serial, max(zone->
db->
outserial,
381 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to enforce " 382 "serial %u for zone %s.\n", serial, tbd);
383 ods_writen(sockfd, buf, strlen(buf));
392 if (status != ODS_STATUS_OK) {
393 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule " 394 "task for zone %s.\n", tbd);
395 ods_writen(sockfd, buf, strlen(buf));
396 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
397 cmdh_str, zone->
name, ods_status2str(status));
399 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s scheduled for " 400 "immediate re-sign.\n", tbd);
401 ods_writen(sockfd, buf, strlen(buf));
402 ods_log_verbose(
"[%s] zone %s scheduled for immediate re-sign",
415 unlink_backup_file(
const char* filename,
const char* extension)
417 char* tmpname = ods_build_path(filename, extension, 0, 1);
419 ods_log_debug(
"[%s] unlink file %s", cmdh_str, tmpname);
421 free((
void*)tmpname);
430 cmdhandler_handle_cmd_clear(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
432 ods_status status = ODS_STATUS_OK;
434 char buf[ODS_SE_MAXLINE];
436 uint32_t inbserial = 0;
437 uint32_t intserial = 0;
438 uint32_t outserial = 0;
440 ods_log_assert(cmdc);
441 ods_log_assert(cmdc->
engine);
443 unlink_backup_file(tbd,
".inbound");
444 unlink_backup_file(tbd,
".backup");
445 unlink_backup_file(tbd,
".axfr");
446 unlink_backup_file(tbd,
".ixfr");
465 ods_fatal_exit(
"[%s] unable to clear zone %s: failed to recreate" 466 "signconf, ixfr of db structure (out of memory?)", cmdh_str, tbd);
478 if (status != ODS_STATUS_OK) {
479 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule " 480 "task for zone %s.\n", tbd);
481 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
482 cmdh_str, zone->
name, ods_status2str(status));
484 (void)snprintf(buf, ODS_SE_MAXLINE,
"Internal zone information about " 485 "%s cleared", tbd?tbd:
"(null)");
486 ods_log_info(
"[%s] internal zone information about %s cleared",
487 cmdh_str, tbd?tbd:
"(null)");
490 (void)snprintf(buf, ODS_SE_MAXLINE,
"Cannot clear zone %s, zone not " 491 "found", tbd?tbd:
"(null)");
492 ods_log_warning(
"[%s] cannot clear zone %s, zone not found",
493 cmdh_str, tbd?tbd:
"(null)");
495 ods_writen(sockfd, buf, strlen(buf));
507 char* strtime = NULL;
508 char buf[ODS_SE_MAXLINE];
511 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
513 ods_log_assert(cmdc);
514 ods_log_assert(cmdc->
engine);
517 (void)snprintf(buf, ODS_SE_MAXLINE,
"There are no tasks scheduled.\n");
518 ods_writen(sockfd, buf, strlen(buf));
523 strtime = ctime(&now);
524 (void)snprintf(buf, ODS_SE_MAXLINE,
"It is now %s",
525 strtime?strtime:
"(null)");
526 ods_writen(sockfd, buf, strlen(buf));
532 (void)snprintf(buf, ODS_SE_MAXLINE,
"Working with task %s on " 536 ods_writen(sockfd, buf, strlen(buf));
540 (void)snprintf(buf, ODS_SE_MAXLINE,
"\nThere are %i tasks scheduled.\n",
542 ods_writen(sockfd, buf, strlen(buf));
544 node = ldns_rbtree_first(engine->
taskq->
tasks);
545 while (node && node != LDNS_RBTREE_NULL) {
547 for (i=0; i < ODS_SE_MAXLINE; i++) {
550 (void)
task2str(task, (
char*) &buf[0]);
551 ods_writen(sockfd, buf, strlen(buf));
552 node = ldns_rbtree_next(node);
566 char buf[ODS_SE_MAXLINE];
567 ods_log_assert(cmdc);
568 ods_log_assert(cmdc->
engine);
570 ods_log_assert(engine->
taskq);
575 (void)snprintf(buf, ODS_SE_MAXLINE,
"All tasks scheduled immediately.\n");
576 ods_writen(sockfd, buf, strlen(buf));
577 ods_log_verbose(
"[%s] all tasks scheduled immediately", cmdh_str);
589 char buf[ODS_SE_MAXLINE];
590 ods_log_assert(cmdc);
591 ods_log_assert(cmdc->
engine);
593 ods_log_error(
"signer instructed to reload due to explicit command");
598 (void)snprintf(buf, ODS_SE_MAXLINE,
"Reloading engine.\n");
599 ods_writen(sockfd, buf, strlen(buf));
611 char buf[ODS_SE_MAXLINE];
612 ods_log_assert(cmdc);
613 ods_log_assert(cmdc->
engine);
619 (void)snprintf(buf, ODS_SE_MAXLINE, ODS_SE_STOP_RESPONSE);
620 ods_writen(sockfd, buf, strlen(buf));
629 cmdhandler_handle_cmd_start(
int sockfd)
631 char buf[ODS_SE_MAXLINE];
632 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine already running.\n");
633 ods_writen(sockfd, buf, strlen(buf));
642 cmdhandler_handle_cmd_running(
int sockfd)
644 char buf[ODS_SE_MAXLINE];
645 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine running.\n");
646 ods_writen(sockfd, buf, strlen(buf));
655 cmdhandler_handle_cmd_verbosity(
int sockfd,
cmdhandler_type* cmdc,
int val)
658 char buf[ODS_SE_MAXLINE];
659 ods_log_assert(cmdc);
660 ods_log_assert(cmdc->
engine);
662 ods_log_assert(engine->
config);
664 (void)snprintf(buf, ODS_SE_MAXLINE,
"Verbosity level set to %i.\n", val);
665 ods_writen(sockfd, buf, strlen(buf));
674 cmdhandler_handle_cmd_error(
int sockfd,
const char* str)
676 char buf[ODS_SE_MAXLINE];
677 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: %s.\n", str?str:
"(null)");
678 ods_writen(sockfd, buf, strlen(buf));
687 cmdhandler_handle_cmd_unknown(
int sockfd,
const char* str)
689 char buf[ODS_SE_MAXLINE];
690 (void)snprintf(buf, ODS_SE_MAXLINE,
"Unknown command %s.\n",
692 ods_writen(sockfd, buf, strlen(buf));
718 char buf[ODS_SE_MAXLINE];
720 ods_log_assert(cmdc);
724 while ((n = read(sockfd, buf, ODS_SE_MAXLINE)) > 0) {
728 ods_log_verbose(
"[%s] received command %s[%ld]", cmdh_str, buf, (
long)n);
732 if (n == 4 && strncmp(buf,
"help", n) == 0) {
733 ods_log_debug(
"[%s] help command", cmdh_str);
734 cmdhandler_handle_cmd_help(sockfd);
735 }
else if (n == 5 && strncmp(buf,
"zones", n) == 0) {
736 ods_log_debug(
"[%s] list zones command", cmdh_str);
737 cmdhandler_handle_cmd_zones(sockfd, cmdc);
738 }
else if (n >= 4 && strncmp(buf,
"sign", 4) == 0) {
739 ods_log_debug(
"[%s] sign zone command", cmdh_str);
740 if (n == 4 || buf[4] ==
'\0') {
742 cmdhandler_handle_cmd_error(sockfd,
"sign command needs " 743 "an argument (either '--all' or a zone name)");
744 }
else if (buf[4] !=
' ') {
745 cmdhandler_handle_cmd_unknown(sockfd, buf);
747 cmdhandler_handle_cmd_sign(sockfd, cmdc, &buf[5]);
749 }
else if (n >= 5 && strncmp(buf,
"clear", 5) == 0) {
750 ods_log_debug(
"[%s] clear zone command", cmdh_str);
751 if (n == 5 || buf[5] ==
'\0') {
752 cmdhandler_handle_cmd_error(sockfd,
"clear command needs " 754 }
else if (buf[5] !=
' ') {
755 cmdhandler_handle_cmd_unknown(sockfd, buf);
757 cmdhandler_handle_cmd_clear(sockfd, cmdc, &buf[6]);
759 }
else if (n == 5 && strncmp(buf,
"queue", n) == 0) {
760 ods_log_debug(
"[%s] list tasks command", cmdh_str);
761 cmdhandler_handle_cmd_queue(sockfd, cmdc);
762 }
else if (n == 5 && strncmp(buf,
"flush", n) == 0) {
763 ods_log_debug(
"[%s] flush tasks command", cmdh_str);
764 cmdhandler_handle_cmd_flush(sockfd, cmdc);
765 }
else if (n >= 6 && strncmp(buf,
"update", 6) == 0) {
766 ods_log_debug(
"[%s] update command", cmdh_str);
767 if (n == 6 || buf[6] ==
'\0') {
768 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
769 }
else if (buf[6] !=
' ') {
770 cmdhandler_handle_cmd_unknown(sockfd, buf);
772 cmdhandler_handle_cmd_update(sockfd, cmdc, &buf[7]);
774 }
else if (n == 4 && strncmp(buf,
"stop", n) == 0) {
775 ods_log_debug(
"[%s] shutdown command", cmdh_str);
776 cmdhandler_handle_cmd_stop(sockfd, cmdc);
778 }
else if (n == 5 && strncmp(buf,
"start", n) == 0) {
779 ods_log_debug(
"[%s] start command", cmdh_str);
780 cmdhandler_handle_cmd_start(sockfd);
781 }
else if (n == 6 && strncmp(buf,
"reload", n) == 0) {
782 ods_log_debug(
"[%s] reload command", cmdh_str);
783 cmdhandler_handle_cmd_reload(sockfd, cmdc);
784 }
else if (n == 7 && strncmp(buf,
"running", n) == 0) {
785 ods_log_debug(
"[%s] running command", cmdh_str);
786 cmdhandler_handle_cmd_running(sockfd);
787 }
else if (n >= 9 && strncmp(buf,
"verbosity", 9) == 0) {
788 ods_log_debug(
"[%s] verbosity command", cmdh_str);
789 if (n == 9 || buf[9] ==
'\0') {
790 cmdhandler_handle_cmd_error(sockfd,
"verbosity command " 791 "an argument (verbosity level)");
792 }
else if (buf[9] !=
' ') {
793 cmdhandler_handle_cmd_unknown(sockfd, buf);
795 cmdhandler_handle_cmd_verbosity(sockfd, cmdc, atoi(&buf[10]));
797 }
else if (n >= 10 && strncmp(buf,
"retransfer", 10) == 0) {
798 ods_log_debug(
"[%s] retransfer zone command", cmdh_str);
799 if (n == 10 || buf[10] ==
'\0') {
800 cmdhandler_handle_cmd_error(sockfd,
"retransfer command needs " 801 "an argument (a zone name)");
802 }
else if (buf[10] !=
' ') {
803 cmdhandler_handle_cmd_unknown(sockfd, buf);
805 cmdhandler_handle_cmd_retransfer(sockfd, cmdc, &buf[11]);
808 ods_log_debug(
"[%s] unknown command", cmdh_str);
809 cmdhandler_handle_cmd_unknown(sockfd, buf);
811 ods_log_debug(
"[%s] done handling command %s[%ld]", cmdh_str, buf, (
long)n);
813 ods_writen(sockfd, buf, strlen(buf));
816 if (n < 0 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) ) {
818 }
else if (n < 0 && errno == ECONNRESET) {
819 ods_log_debug(
"[%s] done handling client: %s", cmdh_str,
822 ods_log_error(
"[%s] read error: %s", cmdh_str, strerror(errno));
832 cmdhandler_accept_client(
void* arg)
836 ods_thread_blocksigs();
839 ods_log_debug(
"[%s] accept client %i", cmdh_str, cmdc->
client_fd);
840 cmdhandler_handle_cmd(cmdc);
859 struct sockaddr_un servaddr;
868 ods_log_debug(
"[%s] create socket %s", cmdh_str, filename);
869 listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
871 ods_log_error(
"[%s] unable to create cmdhandler: " 872 "socket() failed (%s)", cmdh_str, strerror(errno));
876 flags = fcntl(listenfd, F_GETFL, 0);
878 ods_log_error(
"[%s] unable to create cmdhandler: " 879 "fcntl(F_GETFL) failed (%s)", cmdh_str, strerror(errno));
884 if (fcntl(listenfd, F_SETFL, flags) < 0) {
885 ods_log_error(
"[%s] unable to create cmdhandler: " 886 "fcntl(F_SETFL) failed (%s)", cmdh_str, strerror(errno));
892 (void)unlink(filename);
894 bzero(&servaddr,
sizeof(servaddr));
895 servaddr.sun_family = AF_UNIX;
896 strncpy(servaddr.sun_path, filename,
sizeof(servaddr.sun_path) - 1);
897 #ifdef HAVE_SOCKADDR_SUN_LEN 898 servaddr.sun_len = strlen(servaddr.sun_path);
901 ret = bind(listenfd, (
const struct sockaddr*) &servaddr,
sizeof(
struct sockaddr_un));
903 ods_log_error(
"[%s] unable to create cmdhandler: " 904 "bind() failed (%s)", cmdh_str, strerror(errno));
910 ods_log_error(
"[%s] unable to create cmdhandler: " 911 "listen() failed (%s)", cmdh_str, strerror(errno));
931 struct sockaddr_un cliaddr;
938 ods_log_assert(cmdhandler);
939 ods_log_assert(cmdhandler->
engine);
940 ods_log_debug(
"[%s] start", cmdh_str);
941 engine = cmdhandler->
engine;
942 ods_thread_detach(cmdhandler->
thread_id);
945 clilen =
sizeof(cliaddr);
947 ret = select(cmdhandler->
listen_fd+1, &rset, NULL, NULL, NULL);
949 if (errno != EINTR && errno != EWOULDBLOCK) {
950 ods_log_warning(
"[%s] select() error: %s", cmdh_str,
955 if (FD_ISSET(cmdhandler->
listen_fd, &rset)) {
957 (
struct sockaddr *) &cliaddr, &clilen);
959 if (errno != EINTR && errno != EWOULDBLOCK) {
960 ods_log_warning(
"[%s] accept() error: %s", cmdh_str,
968 ods_log_crit(
"[%s] unable to create thread for client: " 969 "malloc() failed", cmdh_str);
978 ods_thread_create(&cmdc->
thread_id, &cmdhandler_accept_client,
981 ods_log_debug(
"[%s] %i clients in progress...", cmdh_str, count);
984 ods_log_debug(
"[%s] shutdown", cmdh_str);
985 engine = cmdhandler->
engine;
signconf_type * signconf_create(void)
void ixfr_cleanup(ixfr_type *ixfr)
#define ODS_SE_NOTIFY_CMD
void engine_wakeup_workers(engine_type *engine)
cond_basic_type signal_cond
const char * zonelist_filename
void engine_update_zones(engine_type *engine, ods_status zl_changed)
void signconf_cleanup(signconf_type *sc)
void namedb_cleanup(namedb_type *db)
ixfr_type * ixfr_create(zone_type *zone)
const char * task_who2str(task_type *task)
lock_basic_type zone_lock
void schedule_flush(schedule_type *schedule, task_id override)
ods_thread_type thread_id
void cmdhandler_start(cmdhandler_type *cmdhandler)
struct sockaddr_un listen_addr
#define ODS_SE_MAX_HANDLERS
const char * log_filename
lock_basic_type signal_lock
engineconfig_type * config
ods_status zone_reschedule_task(zone_type *zone, schedule_type *taskq, task_id what)
namedb_type * namedb_create(void *zone)
zone_type * zonelist_lookup_zone_by_name(zonelist_type *zonelist, const char *name, ldns_rr_class klass)
void xfrd_set_timer_now(xfrd_type *xfrd)
uint8_t serial_retransfer
cmdhandler_type * cmdhandler_create(const char *filename)
ods_status zonelist_update(zonelist_type *zl, const char *zlfile)
char * task2str(task_type *task, char *buftask)
lock_basic_type schedule_lock
void dnshandler_fwd_notify(dnshandler_type *dnshandler, uint8_t *pkt, size_t len)
void cmdhandler_cleanup(cmdhandler_type *cmdhandler)
const char * task_what2str(task_id what)
dnshandler_type * dnshandler