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 "retransfer <zone> Retransfer the zone from the master.\n"
106 "start Start the engine.\n"
107 "running Check if the engine is running.\n"
108 "reload Reload the engine.\n"
109 "stop Stop the engine.\n"
110 "verbosity <nr> Set verbosity.\n"
125 char buf[ODS_SE_MAXLINE];
127 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
133 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no zones configured\n");
139 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have %i zones configured\n",
144 while (node && node != LDNS_RBTREE_NULL) {
146 for (i=0; i < ODS_SE_MAXLINE; i++) {
149 (void)snprintf(buf, ODS_SE_MAXLINE,
"- %s\n", zone->
name);
151 node = ldns_rbtree_next(node);
167 char buf[ODS_SE_MAXLINE];
181 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has not changed."
182 " Signer configurations updated.\n");
185 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list updated: %i "
186 "removed, %i added, %i updated.\n",
193 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone list has errors.\n");
222 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
226 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
235 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
236 "task for zone %s.\n", tbd);
238 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
241 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s config being updated.\n",
244 ods_log_verbose(
"[%s] zone %s scheduled for immediate update signconf",
258 cmdhandler_handle_cmd_retransfer(
int sockfd,
cmdhandler_type* cmdc,
char* tbd)
261 char buf[ODS_SE_MAXLINE];
280 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
290 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s being retransferred.\n", tbd);
298 max(uint32_t a, uint32_t b)
309 cmdhandler_handle_cmd_sign(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
314 char buf[ODS_SE_MAXLINE];
326 (void)snprintf(buf, ODS_SE_MAXLINE,
"All zones scheduled for "
327 "immediate re-sign.\n");
333 char* delim1 = strchr(tbd,
' ');
335 int force_serial = 0;
340 if (strncmp(delim1+1,
"--serial ", 9) != 0) {
341 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting <zone> "
342 "--serial <nr>, got %s.\n", tbd);
346 delim2 = strchr(delim1+1,
' ');
348 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial.\n");
352 serial = (uint32_t) strtol(delim2+1, &end, 10);
354 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial, "
355 "got %s.\n", delim2+1);
374 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
386 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to enforce "
387 "serial %u for zone %s.\n", serial, tbd);
398 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
399 "task for zone %s.\n", tbd);
401 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
404 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s scheduled for "
405 "immediate re-sign.\n", tbd);
421 unlink_backup_file(
const char* filename,
const char* extension)
427 free((
void*)tmpname);
437 cmdhandler_handle_cmd_clear(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
441 char buf[ODS_SE_MAXLINE];
443 uint32_t inbserial = 0;
444 uint32_t intserial = 0;
445 uint32_t outserial = 0;
450 unlink_backup_file(tbd,
".inbound");
451 unlink_backup_file(tbd,
".backup");
452 unlink_backup_file(tbd,
".axfr");
453 unlink_backup_file(tbd,
".ixfr");
473 "signconf, ixfr of db structure (out of memory?)", cmdh_str, tbd);
486 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule "
487 "task for zone %s.\n", tbd);
488 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
491 (void)snprintf(buf, ODS_SE_MAXLINE,
"Internal zone information about "
492 "%s cleared", tbd?tbd:
"(null)");
493 ods_log_info(
"[%s] internal zone information about %s cleared",
494 cmdh_str, tbd?tbd:
"(null)");
497 (void)snprintf(buf, ODS_SE_MAXLINE,
"Cannot clear zone %s, zone not "
498 "found", tbd?tbd:
"(null)");
500 cmdh_str, tbd?tbd:
"(null)");
515 char* strtime = NULL;
516 char buf[ODS_SE_MAXLINE];
519 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
525 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no tasks scheduled.\n");
531 strtime = ctime(&now);
532 (void)snprintf(buf, ODS_SE_MAXLINE,
"It is now %s",
533 strtime?strtime:
"(null)");
540 (void)snprintf(buf, ODS_SE_MAXLINE,
"Working with task %s on "
548 (void)snprintf(buf, ODS_SE_MAXLINE,
"\nI have %i tasks scheduled.\n",
552 node = ldns_rbtree_first(engine->
taskq->
tasks);
553 while (node && node != LDNS_RBTREE_NULL) {
555 for (i=0; i < ODS_SE_MAXLINE; i++) {
558 (void)
task2str(task, (
char*) &buf[0]);
560 node = ldns_rbtree_next(node);
575 char buf[ODS_SE_MAXLINE];
584 (void)snprintf(buf, ODS_SE_MAXLINE,
"All tasks scheduled immediately.\n");
599 char buf[ODS_SE_MAXLINE];
607 (void)snprintf(buf, ODS_SE_MAXLINE,
"Reloading engine.\n");
621 char buf[ODS_SE_MAXLINE];
629 (void)snprintf(buf, ODS_SE_MAXLINE, ODS_SE_STOP_RESPONSE);
640 cmdhandler_handle_cmd_start(
int sockfd)
642 char buf[ODS_SE_MAXLINE];
643 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine already running.\n");
654 cmdhandler_handle_cmd_running(
int sockfd)
656 char buf[ODS_SE_MAXLINE];
657 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine running.\n");
668 cmdhandler_handle_cmd_verbosity(
int sockfd,
cmdhandler_type* cmdc,
int val)
671 char buf[ODS_SE_MAXLINE];
678 (void)snprintf(buf, ODS_SE_MAXLINE,
"Verbosity level set to %i.\n", val);
689 cmdhandler_handle_cmd_error(
int sockfd,
const char* str)
691 char buf[ODS_SE_MAXLINE];
692 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: %s.\n", str?str:
"(null)");
703 cmdhandler_handle_cmd_unknown(
int sockfd,
const char* str)
705 char buf[ODS_SE_MAXLINE];
706 (void)snprintf(buf, ODS_SE_MAXLINE,
"Unknown command %s.\n",
736 char buf[ODS_SE_MAXLINE];
742 while ((n = read(sockfd, buf, ODS_SE_MAXLINE)) > 0) {
750 if (n == 4 && strncmp(buf,
"help", n) == 0) {
752 cmdhandler_handle_cmd_help(sockfd);
753 }
else if (n == 5 && strncmp(buf,
"zones", n) == 0) {
755 cmdhandler_handle_cmd_zones(sockfd, cmdc);
756 }
else if (n >= 4 && strncmp(buf,
"sign", 4) == 0) {
758 if (n == 4 || buf[4] ==
'\0') {
760 cmdhandler_handle_cmd_error(sockfd,
"sign command needs "
761 "an argument (either '--all' or a zone name)");
762 }
else if (buf[4] !=
' ') {
763 cmdhandler_handle_cmd_unknown(sockfd, buf);
765 cmdhandler_handle_cmd_sign(sockfd, cmdc, &buf[5]);
767 }
else if (n >= 5 && strncmp(buf,
"clear", 5) == 0) {
769 if (n == 5 || buf[5] ==
'\0') {
770 cmdhandler_handle_cmd_error(sockfd,
"clear command needs "
772 }
else if (buf[5] !=
' ') {
773 cmdhandler_handle_cmd_unknown(sockfd, buf);
775 cmdhandler_handle_cmd_clear(sockfd, cmdc, &buf[6]);
777 }
else if (n == 5 && strncmp(buf,
"queue", n) == 0) {
779 cmdhandler_handle_cmd_queue(sockfd, cmdc);
780 }
else if (n == 5 && strncmp(buf,
"flush", n) == 0) {
782 cmdhandler_handle_cmd_flush(sockfd, cmdc);
783 }
else if (n >= 6 && strncmp(buf,
"update", 6) == 0) {
785 if (n == 6 || buf[6] ==
'\0') {
786 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
787 }
else if (buf[6] !=
' ') {
788 cmdhandler_handle_cmd_unknown(sockfd, buf);
790 cmdhandler_handle_cmd_update(sockfd, cmdc, &buf[7]);
792 }
else if (n == 4 && strncmp(buf,
"stop", n) == 0) {
794 cmdhandler_handle_cmd_stop(sockfd, cmdc);
796 }
else if (n == 5 && strncmp(buf,
"start", n) == 0) {
798 cmdhandler_handle_cmd_start(sockfd);
799 }
else if (n == 6 && strncmp(buf,
"reload", n) == 0) {
801 cmdhandler_handle_cmd_reload(sockfd, cmdc);
802 }
else if (n == 7 && strncmp(buf,
"running", n) == 0) {
804 cmdhandler_handle_cmd_running(sockfd);
805 }
else if (n >= 9 && strncmp(buf,
"verbosity", 9) == 0) {
807 if (n == 9 || buf[9] ==
'\0') {
808 cmdhandler_handle_cmd_error(sockfd,
"verbosity command "
809 "an argument (verbosity level)");
810 }
else if (buf[9] !=
' ') {
811 cmdhandler_handle_cmd_unknown(sockfd, buf);
813 cmdhandler_handle_cmd_verbosity(sockfd, cmdc, atoi(&buf[10]));
815 }
else if (n >= 10 && strncmp(buf,
"retransfer", 10) == 0) {
817 if (n == 10 || buf[10] ==
'\0') {
818 cmdhandler_handle_cmd_error(sockfd,
"retransfer command needs "
819 "an argument (a zone name)");
820 }
else if (buf[10] !=
' ') {
821 cmdhandler_handle_cmd_unknown(sockfd, buf);
823 cmdhandler_handle_cmd_retransfer(sockfd, cmdc, &buf[11]);
827 cmdhandler_handle_cmd_unknown(sockfd, buf);
829 ods_log_debug(
"[%s] done handling command %s[%i]", cmdh_str, buf, n);
834 if (n < 0 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) ) {
836 }
else if (n < 0 && errno == ECONNRESET) {
840 ods_log_error(
"[%s] read error: %s", cmdh_str, strerror(errno));
851 cmdhandler_accept_client(
void* arg)
859 cmdhandler_handle_cmd(cmdc);
878 struct sockaddr_un servaddr;
883 if (!allocator || !filename) {
888 listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
891 "socket() failed (%s)", cmdh_str, strerror(errno));
895 flags = fcntl(listenfd, F_GETFL, 0);
898 "fcntl(F_GETFL) failed (%s)", cmdh_str, strerror(errno));
903 if (fcntl(listenfd, F_SETFL, flags) < 0) {
905 "fcntl(F_SETFL) failed (%s)", cmdh_str, strerror(errno));
911 (void)unlink(filename);
913 bzero(&servaddr,
sizeof(servaddr));
914 servaddr.sun_family = AF_UNIX;
915 strncpy(servaddr.sun_path, filename,
sizeof(servaddr.sun_path) - 1);
916 #ifdef HAVE_SOCKADDR_SUN_LEN
917 servaddr.sun_len = strlen(servaddr.sun_path);
920 ret = bind(listenfd, (
const struct sockaddr*) &servaddr,
924 "bind() failed (%s)", cmdh_str, strerror(errno));
931 "listen() failed (%s)", cmdh_str, strerror(errno));
940 "allocator_alloc() failed", cmdh_str);
959 struct sockaddr_un cliaddr;
973 clilen =
sizeof(cliaddr);
975 ret = select(cmdhandler->
listen_fd+1, &rset, NULL, NULL, NULL);
977 if (errno != EINTR && errno != EWOULDBLOCK) {
983 if (FD_ISSET(cmdhandler->
listen_fd, &rset)) {
985 (
struct sockaddr *) &cliaddr, &clilen);
987 if (errno != EINTR && errno != EWOULDBLOCK) {
996 ods_log_crit(
"[%s] unable to create thread for client: "
997 "malloc() failed", cmdh_str);
1009 ods_log_debug(
"[%s] %i clients in progress...", cmdh_str, count);
1013 engine = cmdhandler->
engine;
signconf_type * signconf_create(void)
void ixfr_cleanup(ixfr_type *ixfr)
#define ODS_SE_NOTIFY_CMD
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 xfrd_set_timer_now(xfrd_type *xfrd)
uint8_t serial_retransfer
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)
void dnshandler_fwd_notify(dnshandler_type *dnshandler, uint8_t *pkt, size_t len)
#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)
dnshandler_type * dnshandler