45 #include <ldns/ldns.h>
50 #include <sys/select.h>
51 #include <sys/socket.h>
52 #ifdef HAVE_SYS_TYPES_H
53 # include <sys/types.h>
58 #include <sys/types.h>
60 #define SE_CMDH_CMDLEN 7
63 #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
67 static char* cmdh_str =
"cmdhandler";
75 cmdhandler_handle_cmd_help(
int sockfd)
77 char buf[ODS_SE_MAXLINE];
79 (void) snprintf(buf, ODS_SE_MAXLINE,
81 "zones Show the currently known zones.\n"
82 "sign <zone> [--serial <nr>] Read zone and schedule for immediate "
84 " If a serial is given, that serial is used "
85 "in the output zone.\n"
86 "sign --all Read all zones and schedule all for "
87 "immediate (re-)sign.\n"
91 (void) snprintf(buf, ODS_SE_MAXLINE,
92 "clear <zone> Delete the internal storage of this "
94 " All signatures will be regenerated "
95 "on the next re-sign.\n"
96 "queue Show the current task queue.\n"
97 "flush Execute all scheduled tasks "
102 (void) snprintf(buf, ODS_SE_MAXLINE,
103 "update <zone> Update this zone signer "
105 "update [--all] Update zone list and all signer "
107 "start Start the engine.\n"
108 "running Check if the engine is running.\n"
109 "reload Reload the engine.\n"
110 "stop Stop the engine.\n"
111 "verbosity <nr> Set verbosity.\n"
126 char buf[ODS_SE_MAXLINE];
128 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
134 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no zones configured\n");
140 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have %i zones configured\n",
145 while (node && node != LDNS_RBTREE_NULL) {
147 for (i=0; i < ODS_SE_MAXLINE; i++) {
150 (void)snprintf(buf, ODS_SE_MAXLINE,
"- %s\n", zone->
name);
152 node = ldns_rbtree_next(node);
168 char buf[ODS_SE_MAXLINE];
182 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has not changed."
183 " Signer configurations updated.\n");
186 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list updated: %i "
187 "removed, %i added, %i updated.\n",
194 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has errors.\n");
223 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
227 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
236 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
237 "task for zone %s.\n", tbd);
239 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
242 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s config being updated.\n",
245 ods_log_verbose(
"[%s] zone %s scheduled for immediate update signconf",
255 max(uint32_t a, uint32_t b)
266 cmdhandler_handle_cmd_sign(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
271 char buf[ODS_SE_MAXLINE];
283 (void)snprintf(buf, ODS_SE_MAXLINE,
"All zones scheduled for "
284 "immediate re-sign.\n");
290 char* delim1 = strchr(tbd,
' ');
292 int force_serial = 0;
297 if (strncmp(delim1+1,
"--serial ", 9) != 0) {
298 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting <zone> "
299 "--serial <nr>, got %s.\n", tbd);
303 delim2 = strchr(delim1+1,
' ');
305 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial.\n");
309 serial = (uint32_t) strtol(delim2+1, &end, 10);
311 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial, "
312 "got %s.\n", delim2+1);
331 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
343 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to enforce "
344 "serial %u for zone %s.\n", serial, tbd);
355 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
356 "task for zone %s.\n", tbd);
358 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
361 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s scheduled for "
362 "immediate re-sign.\n", tbd);
378 unlink_backup_file(
const char* filename,
const char* extension)
384 free((
void*)tmpname);
394 cmdhandler_handle_cmd_clear(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
398 char buf[ODS_SE_MAXLINE];
401 uint32_t inbserial = 0;
402 uint32_t intserial = 0;
403 uint32_t outserial = 0;
408 unlink_backup_file(tbd,
".inbound");
409 unlink_backup_file(tbd,
".backup");
410 unlink_backup_file(tbd,
".axfr");
411 unlink_backup_file(tbd,
".ixfr");
431 "signconf, ixfr of db structure (out of memory?)", cmdh_str, tbd);
444 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
445 "task for zone %s.\n", tbd);
446 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
449 (void)snprintf(buf, ODS_SE_MAXLINE,
"Internal zone information about "
450 "%s cleared", tbd?tbd:
"(null)");
451 ods_log_info(
"[%s] internal zone information about %s cleared",
452 cmdh_str, tbd?tbd:
"(null)");
455 (void)snprintf(buf, ODS_SE_MAXLINE,
"Cannot clear zone %s, zone not "
456 "found", tbd?tbd:
"(null)");
458 cmdh_str, tbd?tbd:
"(null)");
473 char* strtime = NULL;
474 char buf[ODS_SE_MAXLINE];
477 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
483 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no tasks scheduled.\n");
489 strtime = ctime(&now);
490 (void)snprintf(buf, ODS_SE_MAXLINE,
"It is now %s",
491 strtime?strtime:
"(null)");
498 (void)snprintf(buf, ODS_SE_MAXLINE,
"Working with task %s on "
506 (void)snprintf(buf, ODS_SE_MAXLINE,
"\nI have %i tasks scheduled.\n",
510 node = ldns_rbtree_first(engine->
taskq->
tasks);
511 while (node && node != LDNS_RBTREE_NULL) {
513 for (i=0; i < ODS_SE_MAXLINE; i++) {
516 (void)
task2str(task, (
char*) &buf[0]);
518 node = ldns_rbtree_next(node);
533 char buf[ODS_SE_MAXLINE];
542 (void)snprintf(buf, ODS_SE_MAXLINE,
"All tasks scheduled immediately.\n");
557 char buf[ODS_SE_MAXLINE];
565 (void)snprintf(buf, ODS_SE_MAXLINE,
"Reloading engine.\n");
579 char buf[ODS_SE_MAXLINE];
587 (void)snprintf(buf, ODS_SE_MAXLINE, ODS_SE_STOP_RESPONSE);
598 cmdhandler_handle_cmd_start(
int sockfd)
600 char buf[ODS_SE_MAXLINE];
601 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine already running.\n");
612 cmdhandler_handle_cmd_running(
int sockfd)
614 char buf[ODS_SE_MAXLINE];
615 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine running.\n");
626 cmdhandler_handle_cmd_verbosity(
int sockfd,
cmdhandler_type* cmdc,
int val)
629 char buf[ODS_SE_MAXLINE];
636 (void)snprintf(buf, ODS_SE_MAXLINE,
"Verbosity level set to %i.\n", val);
647 cmdhandler_handle_cmd_error(
int sockfd,
const char* str)
649 char buf[ODS_SE_MAXLINE];
650 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: %s.\n", str?str:
"(null)");
661 cmdhandler_handle_cmd_unknown(
int sockfd,
const char* str)
663 char buf[ODS_SE_MAXLINE];
664 (void)snprintf(buf, ODS_SE_MAXLINE,
"Unknown command %s.\n",
694 char buf[ODS_SE_MAXLINE];
700 while ((n = read(sockfd, buf, ODS_SE_MAXLINE)) > 0) {
708 if (n == 4 && strncmp(buf,
"help", n) == 0) {
710 cmdhandler_handle_cmd_help(sockfd);
711 }
else if (n == 5 && strncmp(buf,
"zones", n) == 0) {
713 cmdhandler_handle_cmd_zones(sockfd, cmdc);
714 }
else if (n >= 4 && strncmp(buf,
"sign", 4) == 0) {
716 if (buf[4] ==
'\0') {
718 cmdhandler_handle_cmd_error(sockfd,
"sign command needs "
719 "an argument (either '--all' or a zone name)");
720 }
else if (buf[4] !=
' ') {
721 cmdhandler_handle_cmd_unknown(sockfd, buf);
723 cmdhandler_handle_cmd_sign(sockfd, cmdc, &buf[5]);
725 }
else if (n >= 5 && strncmp(buf,
"clear", 5) == 0) {
727 if (buf[5] ==
'\0') {
728 cmdhandler_handle_cmd_error(sockfd,
"clear command needs "
730 }
else if (buf[5] !=
' ') {
731 cmdhandler_handle_cmd_unknown(sockfd, buf);
733 cmdhandler_handle_cmd_clear(sockfd, cmdc, &buf[6]);
735 }
else if (n == 5 && strncmp(buf,
"queue", n) == 0) {
737 cmdhandler_handle_cmd_queue(sockfd, cmdc);
738 }
else if (n == 5 && strncmp(buf,
"flush", n) == 0) {
740 cmdhandler_handle_cmd_flush(sockfd, cmdc);
741 }
else if (n >= 6 && strncmp(buf,
"update", 6) == 0) {
743 if (buf[6] ==
'\0') {
744 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
745 }
else if (buf[6] !=
' ') {
746 cmdhandler_handle_cmd_unknown(sockfd, buf);
748 cmdhandler_handle_cmd_update(sockfd, cmdc, &buf[7]);
750 }
else if (n == 4 && strncmp(buf,
"stop", n) == 0) {
752 cmdhandler_handle_cmd_stop(sockfd, cmdc);
754 }
else if (n == 5 && strncmp(buf,
"start", n) == 0) {
756 cmdhandler_handle_cmd_start(sockfd);
757 }
else if (n == 6 && strncmp(buf,
"reload", n) == 0) {
759 cmdhandler_handle_cmd_reload(sockfd, cmdc);
760 }
else if (n == 7 && strncmp(buf,
"running", n) == 0) {
762 cmdhandler_handle_cmd_running(sockfd);
763 }
else if (n >= 9 && strncmp(buf,
"verbosity", 9) == 0) {
765 if (buf[9] ==
'\0') {
766 cmdhandler_handle_cmd_error(sockfd,
"verbosity command "
767 "an argument (verbosity level)");
768 }
else if (buf[9] !=
' ') {
769 cmdhandler_handle_cmd_unknown(sockfd, buf);
771 cmdhandler_handle_cmd_verbosity(sockfd, cmdc, atoi(&buf[10]));
775 cmdhandler_handle_cmd_unknown(sockfd, buf);
777 ods_log_debug(
"[%s] done handling command %s[%i]", cmdh_str, buf, n);
782 if (n < 0 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) ) {
784 }
else if (n < 0 && errno == ECONNRESET) {
788 ods_log_error(
"[%s] read error: %s", cmdh_str, strerror(errno));
799 cmdhandler_accept_client(
void* arg)
807 cmdhandler_handle_cmd(cmdc);
826 struct sockaddr_un servaddr;
831 if (!allocator || !filename) {
836 listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
839 "socket() failed (%s)", cmdh_str, strerror(errno));
843 flags = fcntl(listenfd, F_GETFL, 0);
846 "fcntl(F_GETFL) failed (%s)", cmdh_str, strerror(errno));
851 if (fcntl(listenfd, F_SETFL, flags) < 0) {
853 "fcntl(F_SETFL) failed (%s)", cmdh_str, strerror(errno));
859 (void)unlink(filename);
861 bzero(&servaddr,
sizeof(servaddr));
862 servaddr.sun_family = AF_UNIX;
863 strncpy(servaddr.sun_path, filename,
sizeof(servaddr.sun_path) - 1);
864 #ifdef HAVE_SOCKADDR_SUN_LEN
865 servaddr.sun_len = strlen(servaddr.sun_path);
868 ret = bind(listenfd, (
const struct sockaddr*) &servaddr,
872 "bind() failed (%s)", cmdh_str, strerror(errno));
879 "listen() failed (%s)", cmdh_str, strerror(errno));
888 "allocator_alloc() failed", cmdh_str);
907 struct sockaddr_un cliaddr;
921 clilen =
sizeof(cliaddr);
923 ret = select(cmdhandler->
listen_fd+1, &rset, NULL, NULL, NULL);
925 if (errno != EINTR && errno != EWOULDBLOCK) {
931 if (FD_ISSET(cmdhandler->
listen_fd, &rset)) {
933 (
struct sockaddr *) &cliaddr, &clilen);
935 if (errno != EINTR && errno != EWOULDBLOCK) {
944 ods_log_crit(
"[%s] unable to create thread for client: "
945 "malloc() failed", cmdh_str);
957 ods_log_debug(
"[%s] %i clients in progress...", cmdh_str, count);
961 engine = cmdhandler->
engine;
signconf_type * signconf_create(void)
void ixfr_cleanup(ixfr_type *ixfr)
void ods_thread_blocksigs(void)
void engine_wakeup_workers(engine_type *engine)
void ods_log_debug(const char *format,...)
cond_basic_type signal_cond
void * allocator_alloc(allocator_type *allocator, size_t size)
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)
cmdhandler_type * cmdhandler_create(allocator_type *allocator, const char *filename)
void ods_fatal_exit(const char *format,...)
void ods_log_info(const char *format,...)
const char * task_who2str(task_type *task)
enum ods_enum_status ods_status
lock_basic_type zone_lock
void schedule_flush(schedule_type *schedule, task_id override)
ods_thread_type thread_id
void ods_log_error(const char *format,...)
const char * ods_status2str(ods_status status)
int ods_strcmp(const char *s1, const char *s2)
void cmdhandler_start(cmdhandler_type *cmdhandler)
struct sockaddr_un listen_addr
int util_serial_gt(uint32_t serial_new, uint32_t serial_old)
#define ODS_SE_MAX_HANDLERS
void ods_log_crit(const char *format,...)
const char * log_filename
lock_basic_type signal_lock
#define lock_basic_lock(lock)
void ods_str_trim(char *str)
engineconfig_type * config
ssize_t ods_writen(int fd, const void *vptr, size_t n)
allocator_type * allocator
ods_status zone_reschedule_task(zone_type *zone, schedule_type *taskq, task_id what)
namedb_type * namedb_create(void *zone)
char * ods_build_path(const char *file, const char *suffix, int dir, int no_slash)
#define ods_thread_detach(thr)
void ods_log_verbose(const char *format,...)
zone_type * zonelist_lookup_zone_by_name(zonelist_type *zonelist, const char *name, ldns_rr_class klass)
void allocator_deallocate(allocator_type *allocator, void *data)
ods_status zonelist_update(zonelist_type *zl, const char *zlfile)
char * task2str(task_type *task, char *buftask)
lock_basic_type schedule_lock
#define ods_log_assert(x)
#define ods_thread_create(thr, func, arg)
void ods_log_init(const char *filename, int use_syslog, int verbosity)
ixfr_type * ixfr_create(void *zone)
#define lock_basic_alarm(cond)
#define lock_basic_unlock(lock)
void ods_log_warning(const char *format,...)
void cmdhandler_cleanup(cmdhandler_type *cmdhandler)
const char * task_what2str(task_id what)