OpenDNSSEC-enforcer  2.0.3
time_leap_cmd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 NLNet Labs
3  * Copyright (c) 2014 OpenDNSSEC AB (svb)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
29 #include "config.h"
30 
31 #include "file.h"
32 #include "duration.h"
33 #include "log.h"
34 #include "str.h"
35 #include "daemon/cmdhandler.h"
36 #include "daemon/engine.h"
37 #include "clientpipe.h"
38 #include "hsmkey/hsm_key_factory.h"
39 
40 #include "daemon/time_leap_cmd.h"
41 
42 #define MAX_ARGS 5
43 
44 static const char *module_str = "time_leap_cmd";
45 
46 static void
47 usage(int sockfd)
48 {
49  client_printf(sockfd,
50  "time leap\n"
51  " --time <time> aka -t \n"
52  " --attach aka -a\n"
53  );
54 }
55 
56 static void
57 help(int sockfd)
58 {
59  client_printf(sockfd,
60  "*WARNING* time leap is a debugging/testing tool, it should NEVER be used\n"
61  "in production! Without arguments the daemon inspects the first task in the\n"
62  "schedule and sets its internal time to the time of the task. This allows for\n"
63  "a quick replay of a test scenario. With the --time or -t switch the daemon\n"
64  "sets its time to the argument given as: \"YYYY-MM-DD-HH:MM:SS\"."
65  "\n"
66  "\nOptions:\n"
67  "time leap to this exact time\n"
68  "attach Perform 1 task and stay attached, use only when workerthreads=0\n\n"
69  );
70 }
71 
72 static int
73 handles(const char *cmd, ssize_t n)
74 {
75  return ods_check_command(cmd, n, time_leap_funcblock()->cmdname)?1:0;
76 }
77 
78 static int
79 run(int sockfd, engine_type* engine, const char *cmd, ssize_t n,
80  db_connection_t *dbconn)
81 {
82  struct tm strtime_struct;
83  char strtime[64]; /* at least 26 according to docs plus a long integer */
84  char buf[ODS_SE_MAXLINE];
85  time_t now = time_now();
86  const char *time = NULL;
87  time_t time_leap = 0;
88  struct tm tm;
89  const int NARGV = MAX_ARGS;
90  const char *argv[MAX_ARGS];
91  int argc, attach, cont;
92  task_type* task = NULL, *newtask;
93  (void)n; (void)dbconn;
94 
95  ods_log_debug("[%s] %s command", module_str, time_leap_funcblock()->cmdname);
96 
97  strncpy(buf, cmd, sizeof(buf));
98  buf[sizeof(buf)-1] = '\0';
99  argc = ods_str_explode(buf, NARGV, argv);
100  if (argc > NARGV) {
101  ods_log_error_and_printf(sockfd, module_str, "too many arguments");
102  return -1;
103  }
104  (void)ods_find_arg_and_param(&argc, argv, "time", "t", &time);
105  if (time) {
106  if (strptime(time, "%Y-%m-%d-%H:%M:%S", &tm)) {
107  tm.tm_isdst = -1;
108  time_leap = mktime(&tm);
109  client_printf(sockfd,
110  "Using %s parameter value as time to leap to\n", time);
111  } else {
112  client_printf_err(sockfd,
113  "Time leap: Error - could not convert '%s' to a time. "
114  "Format is YYYY-MM-DD-HH:MM:SS \n", time);
115  return -1;
116  }
117  }
118  attach = ods_find_arg(&argc,argv,"attach","a") != -1;
119 
120  if (argc > 2){
121  ods_log_error_and_printf(sockfd, module_str, "unknown arguments");
122  return -1;
123  }
124 
125  ods_log_assert(engine);
126  if (!engine->taskq || !engine->taskq->tasks) {
127  client_printf(sockfd, "There are no tasks scheduled.\n");
128  return 1;
129  }
130 
131  /* how many tasks */
132  now = time_now();
133  strftime(strtime, sizeof(strtime), "%c", localtime_r(&now, &strtime_struct));
134  client_printf(sockfd,
135  "There are %i tasks scheduled.\nIt is now %s (%ld seconds since epoch)\n",
136  (int) schedule_taskcount(engine->taskq), strtime, (long)now);
137  cont = 1;
138  while (cont) {
139  if (! time)
140  time_leap = schedule_time_first(engine->taskq);
141  if (time_leap < 0) break;
142  if (now > time_leap) {
143  time_leap = now;
144  }
145 
146  set_time_now(time_leap);
147  strftime(strtime, sizeof(strtime), "%c", localtime_r(&time_leap, &strtime_struct));
148 
149  client_printf(sockfd, "Leaping to time %s (%ld seconds since epoch)\n",
150  (strtime[0]?strtime:"(null)"), (long)time_leap);
151  ods_log_info("Time leap: Leaping to time %s\n", strtime);
152  /* Wake up all workers and let them reevaluate wether their
153  tasks need to be executed */
154  client_printf(sockfd, "Waking up workers\n");
155  engine_wakeup_workers(engine);
156  if (!attach)
157  break;
158  if (!(task = schedule_pop_first_task(engine->taskq)))
159  break;
160  client_printf(sockfd, "[timeleap] attaching to job %s\n", task_what2str(task->what));
161  if (strcmp(task_what2str(task->what), "enforce") == 0)
162  cont = 0;
163  task->dbconn = dbconn;
164  newtask = task_perform(task);
165  ods_log_debug("[timeleap] finished working");
166  if (newtask) {
167  newtask->dbconn = NULL;
168  (void) schedule_task(engine->taskq, newtask); /* TODO unchecked error code */
169  }
170  hsm_key_factory_generate_all(engine, dbconn, 0);
171  }
172  return 0;
173 }
174 
175 
176 static struct cmd_func_block funcblock = {
177  "time leap", &usage, &help, &handles, &run
178 };
179 
180 struct cmd_func_block*
182 {
183  return &funcblock;
184 }
#define NARGV
void engine_wakeup_workers(engine_type *engine)
Definition: engine.c:255
void(* help)(int sockfd)
Definition: cmdhandler.h:64
void ods_log_debug(const char *format,...)
Definition: log.c:41
task_type * schedule_pop_first_task(schedule_type *schedule)
Definition: schedule.c:390
void ods_log_info(const char *format,...)
Definition: log.c:55
int(* run)(int sockfd, struct engine_struct *engine, const char *cmd, ssize_t n, db_connection_t *dbconn)
Definition: cmdhandler.h:79
ods_status schedule_task(schedule_type *schedule, task_type *task)
Definition: schedule.c:401
#define MAX_ARGS
Definition: time_leap_cmd.c:42
void(* usage)(int sockfd)
Definition: cmdhandler.h:61
time_t schedule_time_first(schedule_type *schedule)
Definition: schedule.c:246
task_type * task_perform(task_type *task)
Definition: task.c:292
db_connection_t * dbconn
Definition: task.h:71
const char * task_what2str(int what)
Definition: task.c:212
struct cmd_func_block * time_leap_funcblock(void)
task_id what
Definition: task.h:60
ldns_rbtree_t * tasks
Definition: schedule.h:49
schedule_type * taskq
Definition: engine.h:55
void hsm_key_factory_generate_all(engine_type *engine, const db_connection_t *connection, time_t duration)
int(* handles)(const char *cmd, ssize_t n)
Definition: cmdhandler.h:67
size_t schedule_taskcount(schedule_type *schedule)
Definition: schedule.c:266