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"
88 "clear <zone> Delete the internal storage of this "
90 " All signatures will be regenerated "
91 "on the next re-sign.\n"
92 "queue Show the current task queue.\n"
96 (void) snprintf(buf, ODS_SE_MAXLINE,
97 "flush Execute all scheduled tasks "
99 "update <zone> Update this zone signer "
101 "update [--all] Update zone list and all signer "
103 "start Start the engine.\n"
104 "running Check if the engine is running.\n"
105 "reload Reload the engine.\n"
106 "stop Stop the engine.\n"
107 "verbosity <nr> Set verbosity.\n"
122 char buf[ODS_SE_MAXLINE];
124 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
130 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no zones configured\n");
136 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have %i zones configured\n",
141 while (node && node != LDNS_RBTREE_NULL) {
143 for (i=0; i < ODS_SE_MAXLINE; i++) {
146 (void)snprintf(buf, ODS_SE_MAXLINE,
"- %s\n", zone->
name);
148 node = ldns_rbtree_next(node);
164 char buf[ODS_SE_MAXLINE];
178 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has not changed."
179 " Signer configurations updated.\n");
182 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list updated: %i "
183 "removed, %i added, %i updated.\n",
190 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has errors.\n");
219 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
223 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
232 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
233 "task for zone %s.\n", tbd);
235 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",
249 max(uint32_t a, uint32_t b)
260 cmdhandler_handle_cmd_sign(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
265 char buf[ODS_SE_MAXLINE];
277 (void)snprintf(buf, ODS_SE_MAXLINE,
"All zones scheduled for "
278 "immediate re-sign.\n");
284 char* delim1 = strchr(tbd,
' ');
286 int force_serial = 0;
291 if (strncmp(delim1+1,
"--serial ", 9) != 0) {
292 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting <zone> "
293 "--serial <nr>, got %s.\n", tbd);
297 delim2 = strchr(delim1+1,
' ');
299 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial.\n");
303 serial = (uint32_t) strtol(delim2+1, &end, 10);
305 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial, "
306 "got %s.\n", delim2+1);
325 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
337 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to enforce "
338 "serial %u for zone %s.\n", serial, tbd);
349 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
350 "task for zone %s.\n", tbd);
352 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
355 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s scheduled for "
356 "immediate re-sign.\n", tbd);
372 unlink_backup_file(
const char* filename,
const char* extension)
378 free((
void*)tmpname);
388 cmdhandler_handle_cmd_clear(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
391 char buf[ODS_SE_MAXLINE];
394 uint32_t inbserial = 0;
395 uint32_t intserial = 0;
396 uint32_t outserial = 0;
401 unlink_backup_file(tbd,
".inbound");
402 unlink_backup_file(tbd,
".backup");
403 unlink_backup_file(tbd,
".axfr");
404 unlink_backup_file(tbd,
".ixfr");
424 "signconf, ixfr of db structure (out of memory?)", cmdh_str, tbd);
436 (void)snprintf(buf, ODS_SE_MAXLINE,
"Internal zone information about "
437 "%s cleared", tbd?tbd:
"(null)");
438 ods_log_info(
"[%s] internal zone information about %s cleared",
439 cmdh_str, tbd?tbd:
"(null)");
441 (void)snprintf(buf, ODS_SE_MAXLINE,
"Cannot clear zone %s, zone not "
442 "found", tbd?tbd:
"(null)");
444 cmdh_str, tbd?tbd:
"(null)");
459 char* strtime = NULL;
460 char buf[ODS_SE_MAXLINE];
463 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
469 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no tasks scheduled.\n");
475 strtime = ctime(&now);
476 (void)snprintf(buf, ODS_SE_MAXLINE,
"It is now %s",
477 strtime?strtime:
"(null)");
484 (void)snprintf(buf, ODS_SE_MAXLINE,
"Working with task %s on "
492 (void)snprintf(buf, ODS_SE_MAXLINE,
"\nI have %i tasks scheduled.\n",
496 node = ldns_rbtree_first(engine->
taskq->
tasks);
497 while (node && node != LDNS_RBTREE_NULL) {
499 for (i=0; i < ODS_SE_MAXLINE; i++) {
502 (void)
task2str(task, (
char*) &buf[0]);
504 node = ldns_rbtree_next(node);
519 char buf[ODS_SE_MAXLINE];
528 (void)snprintf(buf, ODS_SE_MAXLINE,
"All tasks scheduled immediately.\n");
543 char buf[ODS_SE_MAXLINE];
551 (void)snprintf(buf, ODS_SE_MAXLINE,
"Reloading engine.\n");
565 char buf[ODS_SE_MAXLINE];
573 (void)snprintf(buf, ODS_SE_MAXLINE, ODS_SE_STOP_RESPONSE);
584 cmdhandler_handle_cmd_start(
int sockfd)
586 char buf[ODS_SE_MAXLINE];
587 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine already running.\n");
598 cmdhandler_handle_cmd_running(
int sockfd)
600 char buf[ODS_SE_MAXLINE];
601 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine running.\n");
612 cmdhandler_handle_cmd_verbosity(
int sockfd,
cmdhandler_type* cmdc,
int val)
615 char buf[ODS_SE_MAXLINE];
622 (void)snprintf(buf, ODS_SE_MAXLINE,
"Verbosity level set to %i.\n", val);
633 cmdhandler_handle_cmd_error(
int sockfd,
const char* str)
635 char buf[ODS_SE_MAXLINE];
636 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: %s.\n", str?str:
"(null)");
647 cmdhandler_handle_cmd_unknown(
int sockfd,
const char* str)
649 char buf[ODS_SE_MAXLINE];
650 (void)snprintf(buf, ODS_SE_MAXLINE,
"Unknown command %s.\n",
680 char buf[ODS_SE_MAXLINE];
686 while ((n = read(sockfd, buf, ODS_SE_MAXLINE)) > 0) {
694 if (n == 4 && strncmp(buf,
"help", n) == 0) {
696 cmdhandler_handle_cmd_help(sockfd);
697 }
else if (n == 5 && strncmp(buf,
"zones", n) == 0) {
699 cmdhandler_handle_cmd_zones(sockfd, cmdc);
700 }
else if (n >= 4 && strncmp(buf,
"sign", 4) == 0) {
702 if (buf[4] ==
'\0') {
704 cmdhandler_handle_cmd_error(sockfd,
"sign command needs "
705 "an argument (either '--all' or a zone name)");
706 }
else if (buf[4] !=
' ') {
707 cmdhandler_handle_cmd_unknown(sockfd, buf);
709 cmdhandler_handle_cmd_sign(sockfd, cmdc, &buf[5]);
711 }
else if (n >= 5 && strncmp(buf,
"clear", 5) == 0) {
713 if (buf[5] ==
'\0') {
714 cmdhandler_handle_cmd_error(sockfd,
"clear command needs "
716 }
else if (buf[5] !=
' ') {
717 cmdhandler_handle_cmd_unknown(sockfd, buf);
719 cmdhandler_handle_cmd_clear(sockfd, cmdc, &buf[6]);
721 }
else if (n == 5 && strncmp(buf,
"queue", n) == 0) {
723 cmdhandler_handle_cmd_queue(sockfd, cmdc);
724 }
else if (n == 5 && strncmp(buf,
"flush", n) == 0) {
726 cmdhandler_handle_cmd_flush(sockfd, cmdc);
727 }
else if (n >= 6 && strncmp(buf,
"update", 6) == 0) {
729 if (buf[6] ==
'\0') {
730 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
731 }
else if (buf[6] !=
' ') {
732 cmdhandler_handle_cmd_unknown(sockfd, buf);
734 cmdhandler_handle_cmd_update(sockfd, cmdc, &buf[7]);
736 }
else if (n == 4 && strncmp(buf,
"stop", n) == 0) {
738 cmdhandler_handle_cmd_stop(sockfd, cmdc);
740 }
else if (n == 5 && strncmp(buf,
"start", n) == 0) {
742 cmdhandler_handle_cmd_start(sockfd);
743 }
else if (n == 6 && strncmp(buf,
"reload", n) == 0) {
745 cmdhandler_handle_cmd_reload(sockfd, cmdc);
746 }
else if (n == 7 && strncmp(buf,
"running", n) == 0) {
748 cmdhandler_handle_cmd_running(sockfd);
749 }
else if (n >= 9 && strncmp(buf,
"verbosity", 9) == 0) {
751 if (buf[9] ==
'\0') {
752 cmdhandler_handle_cmd_error(sockfd,
"verbosity command "
753 "an argument (verbosity level)");
754 }
else if (buf[9] !=
' ') {
755 cmdhandler_handle_cmd_unknown(sockfd, buf);
757 cmdhandler_handle_cmd_verbosity(sockfd, cmdc, atoi(&buf[10]));
761 cmdhandler_handle_cmd_unknown(sockfd, buf);
763 ods_log_debug(
"[%s] done handling command %s[%i]", cmdh_str, buf, n);
768 if (n < 0 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) ) {
770 }
else if (n < 0 && errno == ECONNRESET) {
774 ods_log_error(
"[%s] read error: %s", cmdh_str, strerror(errno));
785 cmdhandler_accept_client(
void* arg)
793 cmdhandler_handle_cmd(cmdc);
812 struct sockaddr_un servaddr;
817 if (!allocator || !filename) {
822 listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
825 "socket() failed (%s)", cmdh_str, strerror(errno));
829 flags = fcntl(listenfd, F_GETFL, 0);
832 "fcntl(F_GETFL) failed (%s)", cmdh_str, strerror(errno));
837 if (fcntl(listenfd, F_SETFL, flags) < 0) {
839 "fcntl(F_SETFL) failed (%s)", cmdh_str, strerror(errno));
845 (void)unlink(filename);
847 bzero(&servaddr,
sizeof(servaddr));
848 servaddr.sun_family = AF_UNIX;
849 strncpy(servaddr.sun_path, filename,
sizeof(servaddr.sun_path) - 1);
850 #ifdef HAVE_SOCKADDR_SUN_LEN
851 servaddr.sun_len = strlen(servaddr.sun_path);
854 ret = bind(listenfd, (
const struct sockaddr*) &servaddr,
858 "bind() failed (%s)", cmdh_str, strerror(errno));
865 "listen() failed (%s)", cmdh_str, strerror(errno));
874 "allocator_alloc() failed", cmdh_str);
893 struct sockaddr_un cliaddr;
907 clilen =
sizeof(cliaddr);
909 ret = select(cmdhandler->
listen_fd+1, &rset, NULL, NULL, NULL);
911 if (errno != EINTR && errno != EWOULDBLOCK) {
917 if (FD_ISSET(cmdhandler->
listen_fd, &rset)) {
919 (
struct sockaddr *) &cliaddr, &clilen);
921 if (errno != EINTR && errno != EWOULDBLOCK) {
930 ods_log_crit(
"[%s] unable to create thread for client: "
931 "malloc() failed", cmdh_str);
943 ods_log_debug(
"[%s] %i clients in progress...", cmdh_str, count);
947 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)