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",
285 (void)snprintf(buf, ODS_SE_MAXLINE,
286 "Error: Zone %s not configured to use DNS input adapter.\n",
296 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s being retransferred.\n", tbd);
304 max(uint32_t a, uint32_t b)
315 cmdhandler_handle_cmd_sign(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
320 char buf[ODS_SE_MAXLINE];
332 (void)snprintf(buf, ODS_SE_MAXLINE,
"All zones scheduled for " 333 "immediate re-sign.\n");
339 char* delim1 = strchr(tbd,
' ');
341 int force_serial = 0;
346 if (strncmp(delim1+1,
"--serial ", 9) != 0) {
347 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting <zone> " 348 "--serial <nr>, got %s.\n", tbd);
352 delim2 = strchr(delim1+1,
' ');
354 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial.\n");
358 serial = (uint32_t) strtol(delim2+1, &end, 10);
360 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Expecting serial, " 361 "got %s.\n", delim2+1);
380 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Zone %s not found.\n",
392 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to enforce " 393 "serial %u for zone %s.\n", serial, tbd);
404 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule " 405 "task for zone %s.\n", tbd);
407 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
410 (void)snprintf(buf, ODS_SE_MAXLINE,
"Zone %s scheduled for " 411 "immediate re-sign.\n", tbd);
427 unlink_backup_file(
const char* filename,
const char* extension)
433 free((
void*)tmpname);
443 cmdhandler_handle_cmd_clear(
int sockfd,
cmdhandler_type* cmdc,
const char* tbd)
447 char buf[ODS_SE_MAXLINE];
449 uint32_t inbserial = 0;
450 uint32_t intserial = 0;
451 uint32_t outserial = 0;
456 unlink_backup_file(tbd,
".inbound");
457 unlink_backup_file(tbd,
".backup");
458 unlink_backup_file(tbd,
".axfr");
459 unlink_backup_file(tbd,
".ixfr");
479 "signconf, ixfr of db structure (out of memory?)", cmdh_str, tbd);
492 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: Unable to reschedule " 493 "task for zone %s.\n", tbd);
494 ods_log_crit(
"[%s] unable to reschedule task for zone %s: %s",
497 (void)snprintf(buf, ODS_SE_MAXLINE,
"Internal zone information about " 498 "%s cleared", tbd?tbd:
"(null)");
499 ods_log_info(
"[%s] internal zone information about %s cleared",
500 cmdh_str, tbd?tbd:
"(null)");
503 (void)snprintf(buf, ODS_SE_MAXLINE,
"Cannot clear zone %s, zone not " 504 "found", tbd?tbd:
"(null)");
506 cmdh_str, tbd?tbd:
"(null)");
521 char* strtime = NULL;
522 char buf[ODS_SE_MAXLINE];
525 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
531 (void)snprintf(buf, ODS_SE_MAXLINE,
"I have no tasks scheduled.\n");
537 strtime = ctime(&now);
538 (void)snprintf(buf, ODS_SE_MAXLINE,
"It is now %s",
539 strtime?strtime:
"(null)");
546 (void)snprintf(buf, ODS_SE_MAXLINE,
"Working with task %s on " 554 (void)snprintf(buf, ODS_SE_MAXLINE,
"\nI have %i tasks scheduled.\n",
558 node = ldns_rbtree_first(engine->
taskq->
tasks);
559 while (node && node != LDNS_RBTREE_NULL) {
561 for (i=0; i < ODS_SE_MAXLINE; i++) {
564 (void)
task2str(task, (
char*) &buf[0]);
566 node = ldns_rbtree_next(node);
581 char buf[ODS_SE_MAXLINE];
590 (void)snprintf(buf, ODS_SE_MAXLINE,
"All tasks scheduled immediately.\n");
605 char buf[ODS_SE_MAXLINE];
609 ods_log_error(
"signer instructed to reload due to explicit command");
614 (void)snprintf(buf, ODS_SE_MAXLINE,
"Reloading engine.\n");
628 char buf[ODS_SE_MAXLINE];
636 (void)snprintf(buf, ODS_SE_MAXLINE, ODS_SE_STOP_RESPONSE);
647 cmdhandler_handle_cmd_start(
int sockfd)
649 char buf[ODS_SE_MAXLINE];
650 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine already running.\n");
661 cmdhandler_handle_cmd_running(
int sockfd)
663 char buf[ODS_SE_MAXLINE];
664 (void)snprintf(buf, ODS_SE_MAXLINE,
"Engine running.\n");
675 cmdhandler_handle_cmd_verbosity(
int sockfd,
cmdhandler_type* cmdc,
int val)
678 char buf[ODS_SE_MAXLINE];
685 (void)snprintf(buf, ODS_SE_MAXLINE,
"Verbosity level set to %i.\n", val);
696 cmdhandler_handle_cmd_error(
int sockfd,
const char* str)
698 char buf[ODS_SE_MAXLINE];
699 (void)snprintf(buf, ODS_SE_MAXLINE,
"Error: %s.\n", str?str:
"(null)");
710 cmdhandler_handle_cmd_unknown(
int sockfd,
const char* str)
712 char buf[ODS_SE_MAXLINE];
713 (void)snprintf(buf, ODS_SE_MAXLINE,
"Unknown command %s.\n",
743 char buf[ODS_SE_MAXLINE];
749 while ((n = read(sockfd, buf, ODS_SE_MAXLINE)) > 0) {
757 if (n == 4 && strncmp(buf,
"help", n) == 0) {
759 cmdhandler_handle_cmd_help(sockfd);
760 }
else if (n == 5 && strncmp(buf,
"zones", n) == 0) {
762 cmdhandler_handle_cmd_zones(sockfd, cmdc);
763 }
else if (n >= 4 && strncmp(buf,
"sign", 4) == 0) {
765 if (n == 4 || buf[4] ==
'\0') {
767 cmdhandler_handle_cmd_error(sockfd,
"sign command needs " 768 "an argument (either '--all' or a zone name)");
769 }
else if (buf[4] !=
' ') {
770 cmdhandler_handle_cmd_unknown(sockfd, buf);
772 cmdhandler_handle_cmd_sign(sockfd, cmdc, &buf[5]);
774 }
else if (n >= 5 && strncmp(buf,
"clear", 5) == 0) {
776 if (n == 5 || buf[5] ==
'\0') {
777 cmdhandler_handle_cmd_error(sockfd,
"clear command needs " 779 }
else if (buf[5] !=
' ') {
780 cmdhandler_handle_cmd_unknown(sockfd, buf);
782 cmdhandler_handle_cmd_clear(sockfd, cmdc, &buf[6]);
784 }
else if (n == 5 && strncmp(buf,
"queue", n) == 0) {
786 cmdhandler_handle_cmd_queue(sockfd, cmdc);
787 }
else if (n == 5 && strncmp(buf,
"flush", n) == 0) {
789 cmdhandler_handle_cmd_flush(sockfd, cmdc);
790 }
else if (n >= 6 && strncmp(buf,
"update", 6) == 0) {
792 if (n == 6 || buf[6] ==
'\0') {
793 cmdhandler_handle_cmd_update(sockfd, cmdc,
"--all");
794 }
else if (buf[6] !=
' ') {
795 cmdhandler_handle_cmd_unknown(sockfd, buf);
797 cmdhandler_handle_cmd_update(sockfd, cmdc, &buf[7]);
799 }
else if (n == 4 && strncmp(buf,
"stop", n) == 0) {
801 cmdhandler_handle_cmd_stop(sockfd, cmdc);
803 }
else if (n == 5 && strncmp(buf,
"start", n) == 0) {
805 cmdhandler_handle_cmd_start(sockfd);
806 }
else if (n == 6 && strncmp(buf,
"reload", n) == 0) {
808 cmdhandler_handle_cmd_reload(sockfd, cmdc);
809 }
else if (n == 7 && strncmp(buf,
"running", n) == 0) {
811 cmdhandler_handle_cmd_running(sockfd);
812 }
else if (n >= 9 && strncmp(buf,
"verbosity", 9) == 0) {
814 if (n == 9 || buf[9] ==
'\0') {
815 cmdhandler_handle_cmd_error(sockfd,
"verbosity command " 816 "an argument (verbosity level)");
817 }
else if (buf[9] !=
' ') {
818 cmdhandler_handle_cmd_unknown(sockfd, buf);
820 cmdhandler_handle_cmd_verbosity(sockfd, cmdc, atoi(&buf[10]));
822 }
else if (n >= 10 && strncmp(buf,
"retransfer", 10) == 0) {
824 if (n == 10 || buf[10] ==
'\0') {
825 cmdhandler_handle_cmd_error(sockfd,
"retransfer command needs " 826 "an argument (a zone name)");
827 }
else if (buf[10] !=
' ') {
828 cmdhandler_handle_cmd_unknown(sockfd, buf);
830 cmdhandler_handle_cmd_retransfer(sockfd, cmdc, &buf[11]);
834 cmdhandler_handle_cmd_unknown(sockfd, buf);
836 ods_log_debug(
"[%s] done handling command %s[%i]", cmdh_str, buf, n);
841 if (n < 0 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) ) {
843 }
else if (n < 0 && errno == ECONNRESET) {
847 ods_log_error(
"[%s] read error: %s", cmdh_str, strerror(errno));
858 cmdhandler_accept_client(
void* arg)
866 cmdhandler_handle_cmd(cmdc);
885 struct sockaddr_un servaddr;
890 if (!allocator || !filename) {
895 listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
898 "socket() failed (%s)", cmdh_str, strerror(errno));
902 flags = fcntl(listenfd, F_GETFL, 0);
905 "fcntl(F_GETFL) failed (%s)", cmdh_str, strerror(errno));
910 if (fcntl(listenfd, F_SETFL, flags) < 0) {
912 "fcntl(F_SETFL) failed (%s)", cmdh_str, strerror(errno));
918 (void)unlink(filename);
920 bzero(&servaddr,
sizeof(servaddr));
921 servaddr.sun_family = AF_UNIX;
922 strncpy(servaddr.sun_path, filename,
sizeof(servaddr.sun_path) - 1);
923 #ifdef HAVE_SOCKADDR_SUN_LEN 924 servaddr.sun_len = strlen(servaddr.sun_path);
927 ret = bind(listenfd, (
const struct sockaddr*) &servaddr,
931 "bind() failed (%s)", cmdh_str, strerror(errno));
938 "listen() failed (%s)", cmdh_str, strerror(errno));
947 "allocator_alloc() failed", cmdh_str);
966 struct sockaddr_un cliaddr;
980 clilen =
sizeof(cliaddr);
982 ret = select(cmdhandler->
listen_fd+1, &rset, NULL, NULL, NULL);
984 if (errno != EINTR && errno != EWOULDBLOCK) {
990 if (FD_ISSET(cmdhandler->
listen_fd, &rset)) {
992 (
struct sockaddr *) &cliaddr, &clilen);
994 if (errno != EINTR && errno != EWOULDBLOCK) {
1003 ods_log_crit(
"[%s] unable to create thread for client: " 1004 "malloc() failed", cmdh_str);
1016 ods_log_debug(
"[%s] %i clients in progress...", cmdh_str, count);
1020 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