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 #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
65 static char* cmdh_str =
"cmdhandler";
73 cmdhandler_handle_cmd_help(
int sockfd)
75 char buf[ODS_SE_MAXLINE];
77 (void) snprintf(buf, ODS_SE_MAXLINE,
79 "zones Show the currently known zones.\n"
80 "sign <zone> [--serial <nr>] Read zone and schedule for immediate "
82 " If a serial is given, that serial is used "
83 "in the output zone.\n"
84 "sign --all Read all zones and schedule all for "
85 "immediate (re-)sign.\n"
89 (void) snprintf(buf, ODS_SE_MAXLINE,
90 "clear <zone> Delete the internal storage of this "
92 " All signatures will be regenerated "
93 "on the next re-sign.\n"
94 "queue Show the current task queue.\n"
95 "flush Execute all scheduled tasks "
100 (void) snprintf(buf, ODS_SE_MAXLINE,
101 "update <zone> Update this zone signer "
103 "update [--all] Update zone list and all signer "
105 "start Start the engine.\n"
106 "running Check if the engine is running.\n"
107 "reload Reload the engine.\n"
108 "stop Stop the engine.\n"
109 "verbosity <nr> Set verbosity.\n"
124 char buf[ODS_SE_MAXLINE];
126 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
132 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no zones configured\n");
138 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have %i zones configured\n",
143 while (node && node != LDNS_RBTREE_NULL) {
145 for (i=0; i < ODS_SE_MAXLINE; i++) {
148 (void)snprintf(buf, ODS_SE_MAXLINE,
"- %s\n", zone->
name);
150 node = ldns_rbtree_next(node);
166 char buf[ODS_SE_MAXLINE];
180 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has not changed."
181 " Signer configurations updated.\n");
184 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list updated: %i "
185 "removed, %i added, %i updated.\n",
192 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has errors.\n");
221 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
225 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
234 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
235 "task for zone %s.\n", tbd);
237 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
240 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s config being updated.\n",
243 ods_log_verbose(
"[%s] zone %s scheduled for immediate update signconf",
253 max(uint32_t a, uint32_t b)
264 cmdhandler_handle_cmd_sign(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
269 char buf[ODS_SE_MAXLINE];
281 (void)snprintf(buf, ODS_SE_MAXLINE,
"All zones scheduled for "
282 "immediate re-sign.\n");
288 char* delim1 = strchr(tbd,
' ');
290 int force_serial = 0;
295 if (strncmp(delim1+1,
"--serial ", 9) != 0) {
296 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting <zone> "
297 "--serial <nr>, got %s.\n", tbd);
301 delim2 = strchr(delim1+1,
' ');
303 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial.\n");
307 serial = (uint32_t) strtol(delim2+1, &end, 10);
309 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial, "
310 "got %s.\n", delim2+1);
329 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
341 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to enforce "
342 "serial %u for zone %s.\n", serial, tbd);
353 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
354 "task for zone %s.\n", tbd);
356 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
359 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s scheduled for "
360 "immediate re-sign.\n", tbd);
376 unlink_backup_file(
const char* filename,
const char* extension)
382 free((
void*)tmpname);
392 cmdhandler_handle_cmd_clear(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
396 char buf[ODS_SE_MAXLINE];
399 uint32_t inbserial = 0;
400 uint32_t intserial = 0;
401 uint32_t outserial = 0;
406 unlink_backup_file(tbd,
".inbound");
407 unlink_backup_file(tbd,
".backup");
408 unlink_backup_file(tbd,
".axfr");
409 unlink_backup_file(tbd,
".ixfr");
429 "signconf, ixfr of db structure (out of memory?)", cmdh_str, tbd);
442 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
443 "task for zone %s.\n", tbd);
444 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
447 (void)snprintf(buf, ODS_SE_MAXLINE,
"Internal zone information about "
448 "%s cleared", tbd?tbd:
"(null)");
449 ods_log_info(
"[%s] internal zone information about %s cleared",
450 cmdh_str, tbd?tbd:
"(null)");
453 (void)snprintf(buf, ODS_SE_MAXLINE,
"Cannot clear zone %s, zone not "
454 "found", tbd?tbd:
"(null)");
456 cmdh_str, tbd?tbd:
"(null)");
471 char* strtime = NULL;
472 char buf[ODS_SE_MAXLINE];
475 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
481 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no tasks scheduled.\n");
487 strtime = ctime(&now);
488 (void)snprintf(buf, ODS_SE_MAXLINE,
"It is now %s",
489 strtime?strtime:
"(null)");
496 (void)snprintf(buf, ODS_SE_MAXLINE,
"Working with task %s on "
504 (void)snprintf(buf, ODS_SE_MAXLINE,
"\nI have %i tasks scheduled.\n",
508 node = ldns_rbtree_first(engine->
taskq->
tasks);
509 while (node && node != LDNS_RBTREE_NULL) {
511 for (i=0; i < ODS_SE_MAXLINE; i++) {
514 (void)
task2str(task, (
char*) &buf[0]);
516 node = ldns_rbtree_next(node);
531 char buf[ODS_SE_MAXLINE];
540 (void)snprintf(buf, ODS_SE_MAXLINE,
"All tasks scheduled immediately.\n");
555 char buf[ODS_SE_MAXLINE];
563 (void)snprintf(buf, ODS_SE_MAXLINE,
"Reloading engine.\n");
577 char buf[ODS_SE_MAXLINE];
585 (void)snprintf(buf, ODS_SE_MAXLINE, ODS_SE_STOP_RESPONSE);
596 cmdhandler_handle_cmd_start(
int sockfd)
598 char buf[ODS_SE_MAXLINE];
599 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine already running.\n");
610 cmdhandler_handle_cmd_running(
int sockfd)
612 char buf[ODS_SE_MAXLINE];
613 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine running.\n");
624 cmdhandler_handle_cmd_verbosity(
int sockfd,
cmdhandler_type* cmdc,
int val)
627 char buf[ODS_SE_MAXLINE];
634 (void)snprintf(buf, ODS_SE_MAXLINE,
"Verbosity level set to %i.\n", val);
645 cmdhandler_handle_cmd_error(
int sockfd,
const char* str)
647 char buf[ODS_SE_MAXLINE];
648 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: %s.\n", str?str:
"(null)");
659 cmdhandler_handle_cmd_unknown(
int sockfd,
const char* str)
661 char buf[ODS_SE_MAXLINE];
662 (void)snprintf(buf, ODS_SE_MAXLINE,
"Unknown command %s.\n",
692 char buf[ODS_SE_MAXLINE];
698 while ((n = read(sockfd, buf, ODS_SE_MAXLINE)) > 0) {
706 if (n == 4 && strncmp(buf,
"help", n) == 0) {
708 cmdhandler_handle_cmd_help(sockfd);
709 }
else if (n == 5 && strncmp(buf,
"zones", n) == 0) {
711 cmdhandler_handle_cmd_zones(sockfd, cmdc);
712 }
else if (n >= 4 && strncmp(buf,
"sign", 4) == 0) {
714 if (buf[4] ==
'\0') {
716 cmdhandler_handle_cmd_error(sockfd,
"sign command needs "
717 "an argument (either '--all' or a zone name)");
718 }
else if (buf[4] !=
' ') {
719 cmdhandler_handle_cmd_unknown(sockfd, buf);
721 cmdhandler_handle_cmd_sign(sockfd, cmdc, &buf[5]);
723 }
else if (n >= 5 && strncmp(buf,
"clear", 5) == 0) {
725 if (buf[5] ==
'\0') {
726 cmdhandler_handle_cmd_error(sockfd,
"clear command needs "
728 }
else if (buf[5] !=
' ') {
729 cmdhandler_handle_cmd_unknown(sockfd, buf);
731 cmdhandler_handle_cmd_clear(sockfd, cmdc, &buf[6]);
733 }
else if (n == 5 && strncmp(buf,
"queue", n) == 0) {
735 cmdhandler_handle_cmd_queue(sockfd, cmdc);
736 }
else if (n == 5 && strncmp(buf,
"flush", n) == 0) {
738 cmdhandler_handle_cmd_flush(sockfd, cmdc);
739 }
else if (n >= 6 && strncmp(buf,
"update", 6) == 0) {
741 if (buf[6] ==
'\0') {
742 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
743 }
else if (buf[6] !=
' ') {
744 cmdhandler_handle_cmd_unknown(sockfd, buf);
746 cmdhandler_handle_cmd_update(sockfd, cmdc, &buf[7]);
748 }
else if (n == 4 && strncmp(buf,
"stop", n) == 0) {
750 cmdhandler_handle_cmd_stop(sockfd, cmdc);
752 }
else if (n == 5 && strncmp(buf,
"start", n) == 0) {
754 cmdhandler_handle_cmd_start(sockfd);
755 }
else if (n == 6 && strncmp(buf,
"reload", n) == 0) {
757 cmdhandler_handle_cmd_reload(sockfd, cmdc);
758 }
else if (n == 7 && strncmp(buf,
"running", n) == 0) {
760 cmdhandler_handle_cmd_running(sockfd);
761 }
else if (n >= 9 && strncmp(buf,
"verbosity", 9) == 0) {
763 if (buf[9] ==
'\0') {
764 cmdhandler_handle_cmd_error(sockfd,
"verbosity command "
765 "an argument (verbosity level)");
766 }
else if (buf[9] !=
' ') {
767 cmdhandler_handle_cmd_unknown(sockfd, buf);
769 cmdhandler_handle_cmd_verbosity(sockfd, cmdc, atoi(&buf[10]));
773 cmdhandler_handle_cmd_unknown(sockfd, buf);
775 ods_log_debug(
"[%s] done handling command %s[%i]", cmdh_str, buf, n);
780 if (n < 0 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) ) {
782 }
else if (n < 0 && errno == ECONNRESET) {
786 ods_log_error(
"[%s] read error: %s", cmdh_str, strerror(errno));
797 cmdhandler_accept_client(
void* arg)
805 cmdhandler_handle_cmd(cmdc);
824 struct sockaddr_un servaddr;
829 if (!allocator || !filename) {
834 listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
837 "socket() failed (%s)", cmdh_str, strerror(errno));
841 flags = fcntl(listenfd, F_GETFL, 0);
844 "fcntl(F_GETFL) failed (%s)", cmdh_str, strerror(errno));
849 if (fcntl(listenfd, F_SETFL, flags) < 0) {
851 "fcntl(F_SETFL) failed (%s)", cmdh_str, strerror(errno));
857 (void)unlink(filename);
859 bzero(&servaddr,
sizeof(servaddr));
860 servaddr.sun_family = AF_UNIX;
861 strncpy(servaddr.sun_path, filename,
sizeof(servaddr.sun_path) - 1);
862 #ifdef HAVE_SOCKADDR_SUN_LEN
863 servaddr.sun_len = strlen(servaddr.sun_path);
866 ret = bind(listenfd, (
const struct sockaddr*) &servaddr,
870 "bind() failed (%s)", cmdh_str, strerror(errno));
877 "listen() failed (%s)", cmdh_str, strerror(errno));
886 "allocator_alloc() failed", cmdh_str);
905 struct sockaddr_un cliaddr;
919 clilen =
sizeof(cliaddr);
921 ret = select(cmdhandler->
listen_fd+1, &rset, NULL, NULL, NULL);
923 if (errno != EINTR && errno != EWOULDBLOCK) {
929 if (FD_ISSET(cmdhandler->
listen_fd, &rset)) {
931 (
struct sockaddr *) &cliaddr, &clilen);
933 if (errno != EINTR && errno != EWOULDBLOCK) {
942 ods_log_crit(
"[%s] unable to create thread for client: "
943 "malloc() failed", cmdh_str);
955 ods_log_debug(
"[%s] %i clients in progress...", cmdh_str, count);
959 engine = cmdhandler->
engine;