48 #include <ldns/ldns.h>
53 #include <sys/select.h>
54 #include <sys/socket.h>
55 #ifdef HAVE_SYS_TYPES_H
56 # include <sys/types.h>
61 #include <sys/types.h>
63 #define SE_CMDH_CMDLEN 7
66 #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
70 static char* cmdh_str =
"cmdhandler";
78 cmdhandler_handle_cmd_help(
int sockfd)
80 char buf[ODS_SE_MAXLINE];
82 (void) snprintf(buf, ODS_SE_MAXLINE,
84 "zones show the currently known zones.\n"
85 "sign <zone> [--serial <nr>] read zone and schedule for immediate "
87 " If a serial is given, that serial is used "
88 "in the output zone.\n"
89 "sign --all read all zones and schedule all for "
90 "immediate (re-)sign.\n"
91 "clear <zone> delete the internal storage of this zone.\n"
92 " All signatures will be regenerated on the "
97 (void) snprintf(buf, ODS_SE_MAXLINE,
98 "queue show the current task queue.\n"
99 "debug-locks show locking information (for debugging "
101 "flush execute all scheduled tasks immediately.\n"
102 "update <zone> update this zone signer configurations.\n"
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"
111 (void) snprintf(buf, ODS_SE_MAXLINE,
112 "stop stop the engine.\n"
113 "verbosity <nr> set verbosity.\n"
127 char buf[ODS_SE_MAXLINE];
129 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
135 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no zones configured\n");
143 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have %i zones configured\n",
149 while (node && node != LDNS_RBTREE_NULL) {
151 for (i=0; i < ODS_SE_MAXLINE; i++) {
154 (void)snprintf(buf, ODS_SE_MAXLINE,
"- %s\n", zone->
name);
156 node = ldns_rbtree_next(node);
172 char buf[ODS_SE_MAXLINE];
191 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has not changed."
192 " Signer configurations updated.\n");
196 ods_log_debug(
"[%s] signer configurations updated", cmdh_str);
198 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list updated: %i "
199 "removed, %i added, %i updated.\n",
213 ods_log_debug(
"[%s] signer configurations updated", cmdh_str);
217 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has errors.\n");
235 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
239 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
264 "signconf as soon as possible", cmdh_str, zone->
name);
276 ods_log_crit(
"[%s] cannot schedule task for zone %s: %s",
284 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s config being updated.\n",
293 max(uint32_t a, uint32_t b)
304 cmdhandler_handle_cmd_sign(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
309 char buf[ODS_SE_MAXLINE];
323 (void)snprintf(buf, ODS_SE_MAXLINE,
"All zones scheduled for "
324 "immediate re-sign.\n");
330 char* delim1 = strchr(tbd,
' ');
332 int force_serial = 0;
337 if (strncmp(delim1+1,
"--serial ", 9) != 0) {
338 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting <zone> "
339 "--serial <nr>, got %s.\n", tbd);
343 delim2 = strchr(delim1+1,
' ');
345 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial.\n");
349 serial = (uint32_t) strtol(delim2+1, &end, 10);
351 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial, "
352 "got %s.\n", delim2+1);
374 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
388 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to enforce "
389 "serial %u for zone %s.\n", serial, tbd);
412 "zone input as soon as possible", cmdh_str, zone->
name);
425 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Cannot schedule task for "
428 ods_log_crit(
"[%s] cannot schedule task for zone %s: %s",
433 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s scheduled for immediate "
450 unlink_backup_file(
const char* filename,
const char* extension)
455 free((
void*)tmpname);
464 cmdhandler_handle_cmd_clear(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
466 char buf[ODS_SE_MAXLINE];
469 uint32_t inbound_serial = 0;
470 uint32_t internal_serial = 0;
471 uint32_t outbound_serial = 0;
478 unlink_backup_file(tbd,
".inbound");
479 unlink_backup_file(tbd,
".backup");
511 " reloading signconf", cmdh_str, zone->
name);
517 " zone %s, reloading signconf", cmdh_str, zone->
name);
524 " for zone %s, reloading signconf", cmdh_str, zone->
name);
530 (void)snprintf(buf, ODS_SE_MAXLINE,
"Internal zone information about "
531 "%s cleared", tbd?tbd:
"(null)");
532 ods_log_info(
"[%s] internal zone information about %s cleared",
533 cmdh_str, tbd?tbd:
"(null)");
535 (void)snprintf(buf, ODS_SE_MAXLINE,
"Cannot clear zone %s, zone not "
536 "found", tbd?tbd:
"(null)");
538 cmdh_str, tbd?tbd:
"(null)");
553 char* strtime = NULL;
554 char buf[ODS_SE_MAXLINE];
557 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
563 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no tasks scheduled.\n");
572 strtime = ctime(&now);
573 (void)snprintf(buf, ODS_SE_MAXLINE,
"It is now %s",
574 strtime?strtime:
"(null)");
581 (void)snprintf(buf, ODS_SE_MAXLINE,
"Working with task %s on "
590 (void)snprintf(buf, ODS_SE_MAXLINE,
"\nI have %i tasks scheduled.\n",
596 while (node && node != LDNS_RBTREE_NULL) {
598 for (i=0; i < ODS_SE_MAXLINE; i++) {
601 (void)
task2str(task, (
char*) &buf[0]);
603 node = ldns_rbtree_next(node);
618 char* strtime = NULL;
619 char buf[ODS_SE_MAXLINE];
622 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
630 strtime = ctime(&now);
631 (void)snprintf(buf, ODS_SE_MAXLINE,
"It is now %s",
632 strtime?strtime:
"(null)");
635 (void)snprintf(buf, ODS_SE_MAXLINE,
"- signal is %s[%i]\n",
639 (void)snprintf(buf, ODS_SE_MAXLINE,
"- zone list is %s[%i]\n",
643 (void)snprintf(buf, ODS_SE_MAXLINE,
"- task schedule is %s[%i]\n",
647 (void)snprintf(buf, ODS_SE_MAXLINE,
"- rrset queue is %s[%i]\n",
653 (void)snprintf(buf, ODS_SE_MAXLINE,
"- worker[%i] is %s[%i]\n",
661 (void)snprintf(buf, ODS_SE_MAXLINE,
"- drudger[%i] is %s[%i]\n",
670 while (node && node != LDNS_RBTREE_NULL) {
672 memset(buf, 0, ODS_SE_MAXLINE);
673 (void)snprintf(buf, ODS_SE_MAXLINE,
"- %s is %s[%i], stats is %s[%i]\n",
680 node = ldns_rbtree_next(node);
694 char buf[ODS_SE_MAXLINE];
708 (void)snprintf(buf, ODS_SE_MAXLINE,
"All tasks scheduled immediately.\n");
722 char buf[ODS_SE_MAXLINE];
735 (void)snprintf(buf, ODS_SE_MAXLINE,
"Reloading engine.\n");
748 char buf[ODS_SE_MAXLINE];
761 (void)snprintf(buf, ODS_SE_MAXLINE, ODS_SE_STOP_RESPONSE);
772 cmdhandler_handle_cmd_start(
int sockfd)
774 char buf[ODS_SE_MAXLINE];
776 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine already running.\n");
787 cmdhandler_handle_cmd_running(
int sockfd)
789 char buf[ODS_SE_MAXLINE];
791 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine running.\n");
802 cmdhandler_handle_cmd_verbosity(
int sockfd,
cmdhandler_type* cmdc,
int val)
804 char buf[ODS_SE_MAXLINE];
813 (void)snprintf(buf, ODS_SE_MAXLINE,
"Verbosity level set to %i.\n", val);
823 cmdhandler_handle_cmd_error(
int sockfd,
const char* str)
825 char buf[ODS_SE_MAXLINE];
826 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: %s.\n", str?str:
"(null)");
837 cmdhandler_handle_cmd_unknown(
int sockfd,
const char* str)
839 char buf[ODS_SE_MAXLINE];
840 (void)snprintf(buf, ODS_SE_MAXLINE,
"Unknown command %s.\n",
870 char buf[ODS_SE_MAXLINE];
876 while ((n = read(sockfd, buf, ODS_SE_MAXLINE)) > 0) {
884 if (n == 4 && strncmp(buf,
"help", n) == 0) {
886 cmdhandler_handle_cmd_help(sockfd);
887 }
else if (n == 5 && strncmp(buf,
"zones", n) == 0) {
889 cmdhandler_handle_cmd_zones(sockfd, cmdc);
890 }
else if (n >= 4 && strncmp(buf,
"sign", 4) == 0) {
892 if (buf[4] ==
'\0') {
894 cmdhandler_handle_cmd_error(sockfd,
"sign command needs "
895 "an argument (either '--all' or a zone name)");
896 }
else if (buf[4] !=
' ') {
897 cmdhandler_handle_cmd_unknown(sockfd, buf);
899 cmdhandler_handle_cmd_sign(sockfd, cmdc, &buf[5]);
901 }
else if (n >= 5 && strncmp(buf,
"clear", 5) == 0) {
903 if (buf[5] ==
'\0') {
904 cmdhandler_handle_cmd_error(sockfd,
"clear command needs "
906 }
else if (buf[5] !=
' ') {
907 cmdhandler_handle_cmd_unknown(sockfd, buf);
909 cmdhandler_handle_cmd_clear(sockfd, cmdc, &buf[6]);
911 }
else if (n == 5 && strncmp(buf,
"queue", n) == 0) {
913 cmdhandler_handle_cmd_queue(sockfd, cmdc);
914 }
else if (n == 11 && strncmp(buf,
"debug-locks", n) == 0) {
916 cmdhandler_handle_cmd_debuglocks(sockfd, cmdc);
917 }
else if (n == 5 && strncmp(buf,
"flush", n) == 0) {
919 cmdhandler_handle_cmd_flush(sockfd, cmdc);
920 }
else if (n >= 6 && strncmp(buf,
"update", 6) == 0) {
922 if (buf[6] ==
'\0') {
923 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
924 }
else if (buf[6] !=
' ') {
925 cmdhandler_handle_cmd_unknown(sockfd, buf);
927 cmdhandler_handle_cmd_update(sockfd, cmdc, &buf[7]);
929 }
else if (n == 4 && strncmp(buf,
"stop", n) == 0) {
931 cmdhandler_handle_cmd_stop(sockfd, cmdc);
933 }
else if (n == 5 && strncmp(buf,
"start", n) == 0) {
935 cmdhandler_handle_cmd_start(sockfd);
936 }
else if (n == 6 && strncmp(buf,
"reload", n) == 0) {
938 cmdhandler_handle_cmd_reload(sockfd, cmdc);
939 }
else if (n == 7 && strncmp(buf,
"running", n) == 0) {
941 cmdhandler_handle_cmd_running(sockfd);
942 }
else if (n >= 9 && strncmp(buf,
"verbosity", 9) == 0) {
944 if (buf[9] ==
'\0') {
945 cmdhandler_handle_cmd_error(sockfd,
"verbosity command "
946 "an argument (verbosity level)");
947 }
else if (buf[9] !=
' ') {
948 cmdhandler_handle_cmd_unknown(sockfd, buf);
950 cmdhandler_handle_cmd_verbosity(sockfd, cmdc, atoi(&buf[10]));
954 cmdhandler_handle_cmd_unknown(sockfd, buf);
957 ods_log_debug(
"[%s] done handling command %s[%i]", cmdh_str, buf, n);
962 if (n < 0 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) ) {
964 }
else if (n < 0 && errno == ECONNRESET) {
968 ods_log_error(
"[%s] read error: %s", cmdh_str, strerror(errno));
979 cmdhandler_accept_client(
void* arg)
987 cmdhandler_handle_cmd(cmdc);
1006 struct sockaddr_un servaddr;
1012 ods_log_error(
"[%s] unable to create: no allocator", cmdh_str);
1018 ods_log_error(
"[%s] unable to create: no socket filename", cmdh_str);
1025 listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
1026 if (listenfd <= 0) {
1027 ods_log_error(
"[%s] unable to create, socket() failed: %s", cmdh_str,
1032 flags = fcntl(listenfd, F_GETFL, 0);
1034 ods_log_error(
"[%s] unable to create, fcntl(F_GETFL) failed: %s",
1035 cmdh_str, strerror(errno));
1039 flags |= O_NONBLOCK;
1040 if (fcntl(listenfd, F_SETFL, flags) < 0) {
1041 ods_log_error(
"[%s] unable to create, fcntl(F_SETFL) failed: %s",
1042 cmdh_str, strerror(errno));
1051 bzero(&servaddr,
sizeof(servaddr));
1052 servaddr.sun_family = AF_UNIX;
1053 strncpy(servaddr.sun_path, filename,
sizeof(servaddr.sun_path) - 1);
1056 ret = bind(listenfd, (
const struct sockaddr*) &servaddr,
1059 ods_log_error(
"[%s] unable to create, bind() failed: %s", cmdh_str,
1066 ods_log_error(
"[%s] unable to create, listen() failed: %s", cmdh_str,
1094 struct sockaddr_un cliaddr;
1106 engine = cmdhandler->
engine;
1110 clilen =
sizeof(cliaddr);
1112 ret = select(cmdhandler->
listen_fd+1, &rset, NULL, NULL, NULL);
1114 if (errno != EINTR && errno != EWOULDBLOCK) {
1120 if (FD_ISSET(cmdhandler->
listen_fd, &rset)) {
1122 (
struct sockaddr *) &cliaddr, &clilen);
1124 if (errno != EINTR && errno != EWOULDBLOCK) {
1133 ods_log_crit(
"[%s] unable to create thread for client: "
1134 "malloc failed", cmdh_str);
1146 ods_log_debug(
"[%s] %i clients in progress...", cmdh_str, count);
1151 engine = cmdhandler->
engine;