Added a Suite B conftest utility skeleton using libcharon
[strongswan.git] / src / conftest / conftest.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <unistd.h>
17 #include <stdio.h>
18 #include <errno.h>
19 #include <signal.h>
20 #include <getopt.h>
21
22 #include "conftest.h"
23
24 #include <threading/thread.h>
25
26 /**
27 * Conftest globals struct
28 */
29 conftest_t *conftest;
30
31 /**
32 * Print usage information
33 */
34 static void usage(char *error)
35 {
36 FILE *out = stdout;
37
38 if (error)
39 {
40 out = stderr;
41 fprintf(out, "%s\n", error);
42 }
43 else
44 {
45 fprintf(out, "strongSwan %s conftest\n", VERSION);
46 }
47 fprintf(out, "Usage:\n");
48 fprintf(out, " --help show usage information\n");
49 fprintf(out, " --version show conftest version\n");
50 fprintf(out, " --suite <file> global testsuite configuration "
51 "(default: ./suite.conf)\n");
52 fprintf(out, " --test <file> test specific configuration\n");
53 }
54
55 /**
56 * Handle SIGSEGV/SIGILL signals raised by threads
57 */
58 static void segv_handler(int signal)
59 {
60 fprintf(stderr, "thread %u received %d", thread_current_id(), signal);
61 abort();
62 }
63
64 /**
65 * Load suite and test specific configurations
66 */
67 static bool load_configs(char *suite_file, char *test_file)
68 {
69 if (!test_file)
70 {
71 fprintf(stderr, "Missing test configuration file.\n");
72 return FALSE;
73 }
74 if (access(suite_file, R_OK) != 0)
75 {
76 fprintf(stderr, "Reading suite configuration file '%s' failed: %s.\n",
77 suite_file, strerror(errno));
78 return FALSE;
79 }
80 if (access(test_file, R_OK) != 0)
81 {
82 fprintf(stderr, "Reading test configuration file '%s' failed: %s.\n",
83 test_file, strerror(errno));
84 return FALSE;
85 }
86 conftest->suite = settings_create(suite_file);
87 conftest->test = settings_create(test_file);
88 return TRUE;
89 }
90
91 /**
92 * atexit() cleanup handler
93 */
94 static void cleanup()
95 {
96 DESTROY_IF(conftest->suite);
97 DESTROY_IF(conftest->test);
98 free(conftest);
99 libcharon_deinit();
100 libhydra_deinit();
101 library_deinit();
102 }
103
104 /**
105 * Main function, starts the conftest daemon.
106 */
107 int main(int argc, char *argv[])
108 {
109 struct sigaction action;
110 int status = 0;
111 sigset_t set;
112 int sig;
113 char *suite_file = "suite.conf", *test_file = NULL;
114 file_logger_t *logger;
115
116 if (!library_init(NULL))
117 {
118 library_deinit();
119 return SS_RC_LIBSTRONGSWAN_INTEGRITY;
120 }
121 if (!libhydra_init("conftest"))
122 {
123 libhydra_deinit();
124 library_deinit();
125 return SS_RC_INITIALIZATION_FAILED;
126 }
127 if (!libcharon_init())
128 {
129 libcharon_deinit();
130 libhydra_deinit();
131 library_deinit();
132 return SS_RC_INITIALIZATION_FAILED;
133 }
134
135 INIT(conftest,
136 );
137 logger = file_logger_create(stdout, NULL, FALSE);
138 logger->set_level(logger, DBG_ANY, LEVEL_CTRL);
139 charon->bus->add_listener(charon->bus, &logger->listener);
140 charon->file_loggers->insert_last(charon->file_loggers, logger);
141
142 atexit(cleanup);
143
144 while (TRUE)
145 {
146 struct option long_opts[] = {
147 { "help", no_argument, NULL, 'h' },
148 { "version", no_argument, NULL, 'v' },
149 { "suite", required_argument, NULL, 's' },
150 { "test", required_argument, NULL, 't' },
151 { 0,0,0,0 }
152 };
153 switch (getopt_long(argc, argv, "", long_opts, NULL))
154 {
155 case EOF:
156 break;
157 case 'h':
158 usage(NULL);
159 return 0;
160 case 'v':
161 printf("strongSwan %s conftest\n", VERSION);
162 return 0;
163 case 's':
164 suite_file = optarg;
165 continue;
166 case 't':
167 test_file = optarg;
168 continue;
169 default:
170 usage("Invalid option.");
171 return 1;
172 }
173 break;
174 }
175
176 if (!load_configs(suite_file, test_file))
177 {
178 return 1;
179 }
180
181 if (!charon->initialize(charon))
182 {
183 return 1;
184 }
185
186 /* set up thread specific handlers */
187 action.sa_handler = segv_handler;
188 action.sa_flags = 0;
189 sigemptyset(&action.sa_mask);
190 sigaddset(&action.sa_mask, SIGINT);
191 sigaddset(&action.sa_mask, SIGTERM);
192 sigaddset(&action.sa_mask, SIGHUP);
193 sigaction(SIGSEGV, &action, NULL);
194 sigaction(SIGILL, &action, NULL);
195 sigaction(SIGBUS, &action, NULL);
196 action.sa_handler = SIG_IGN;
197 sigaction(SIGPIPE, &action, NULL);
198 pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
199
200 /* start thread pool */
201 charon->start(charon);
202
203 /* handle SIGINT/SIGTERM in main thread */
204 sigemptyset(&set);
205 sigaddset(&set, SIGINT);
206 sigaddset(&set, SIGHUP);
207 sigaddset(&set, SIGTERM);
208 sigprocmask(SIG_BLOCK, &set, NULL);
209
210 while (sigwait(&set, &sig) == 0)
211 {
212 switch (sig)
213 {
214 case SIGINT:
215 case SIGTERM:
216 fprintf(stderr, "\nshutting down...\n");
217 break;
218 default:
219 continue;
220 }
221 break;
222 }
223 return status;
224 }