b4c435256956e2f53d5abe0812451eb0be8ca109
[strongswan.git] / src / dumm / main.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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 #define _GNU_SOURCE
17
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <getopt.h>
21 #include <library.h>
22 #include <readline/readline.h>
23 #include <readline/history.h>
24
25 #include "dumm.h"
26
27 /**
28 * global set of UMLs guests
29 */
30 dumm_t *dumm;
31
32 /**
33 * show usage information (program arguments)
34 */
35 static void usage()
36 {
37 printf("Usage:\n");
38 printf(" --dir|-d <path> set working dir to <path>\n");
39 printf(" --help|-h show this help\n");
40 }
41
42 /**
43 * readline() wrapper
44 */
45 static char* get_line(char *format, ...)
46 {
47 char *line = NULL;
48 char *prompt = "";
49 va_list args;
50
51 va_start(args, format);
52 vasprintf(&prompt, format, args);
53 va_end(args);
54
55 while (TRUE)
56 {
57 line = readline(prompt);
58 if (line == NULL)
59 {
60 printf("quit\n");
61 dumm->destroy(dumm);
62 clear_history();
63 exit(0);
64 }
65 if (*line == '\0')
66 {
67 free(line);
68 continue;
69 }
70 add_history(line);
71 break;
72 }
73 free(prompt);
74 return line;
75 }
76
77 /**
78 * get a guest by name
79 */
80 static guest_t* get_guest(char *name)
81 {
82 iterator_t *iterator;
83 guest_t *guest = NULL;
84
85 iterator = dumm->create_guest_iterator(dumm);
86 while (iterator->iterate(iterator, (void**)&guest))
87 {
88 if (streq(guest->get_name(guest), name))
89 {
90 break;
91 }
92 guest = NULL;
93 }
94 iterator->destroy(iterator);
95 return guest;
96 }
97
98 /**
99 * get a bridge by name
100 */
101 static bridge_t* get_bridge(char *name)
102 {
103 iterator_t *iterator;
104 bridge_t *bridge = NULL;
105
106 iterator = dumm->create_bridge_iterator(dumm);
107 while (iterator->iterate(iterator, (void**)&bridge))
108 {
109 if (streq(bridge->get_name(bridge), name))
110 {
111 break;
112 }
113 bridge = NULL;
114 }
115 iterator->destroy(iterator);
116 return bridge;
117 }
118
119 /**
120 * get an interface by guest name
121 */
122 static iface_t* get_iface(char *name, char *ifname)
123 {
124 iterator_t *guests, *ifaces;
125 guest_t *guest;
126 iface_t *iface;
127
128 guests = dumm->create_guest_iterator(dumm);
129 while (guests->iterate(guests, (void**)&guest))
130 {
131 if (streq(guest->get_name(guest), name))
132 {
133 iface = NULL;
134 ifaces = guest->create_iface_iterator(guest);
135 while (ifaces->iterate(ifaces, (void**)&iface))
136 {
137 if (streq(iface->get_guestif(iface), ifname))
138 {
139 break;
140 }
141 iface = NULL;
142 }
143 ifaces->destroy(ifaces);
144 if (iface)
145 {
146 break;
147 }
148 }
149 }
150 guests->destroy(guests);
151 return iface;
152 }
153
154 static void guest_addif_menu(guest_t *guest)
155 {
156 char *name;
157
158 name = get_line("interface name: ");
159
160 if (!guest->create_iface(guest, name))
161 {
162 printf("creating interface failed\n");
163 }
164 free(name);
165 }
166
167 static void guest_delif_menu(guest_t *guest)
168 {
169 char *name;
170 iface_t *iface;
171 iterator_t *iterator;
172 bool found = FALSE;
173
174 name = get_line("interface name: ");
175
176 iterator = guest->create_iface_iterator(guest);
177 while (iterator->iterate(iterator, (void**)&iface))
178 {
179 if (streq(iface->get_guestif(iface), name))
180 {
181 iterator->remove(iterator);
182 iface->destroy(iface);
183 found = TRUE;
184 break;
185 }
186 }
187 iterator->destroy(iterator);
188
189 if (!found)
190 {
191 printf("interface '%s' not found\n");
192 }
193 free(name);
194 }
195
196 static void guest_console(guest_t *guest)
197 {
198 int con;
199
200 for (con = 1; con <= 6; con++)
201 {
202 char *pts = guest->get_console(guest, con);
203 if (pts)
204 {
205 printf("%d: %s\n", con, pts);
206 free(pts);
207 }
208 }
209 }
210
211 static void guest_menu(guest_t *guest)
212 {
213 while (TRUE)
214 {
215 char *line = get_line("guest/%s# ", guest->get_name(guest));
216
217 if (streq(line, "back"))
218 {
219 free(line);
220 break;
221 }
222 else if (streq(line, "start"))
223 {
224 if (guest->start(guest))
225 {
226 printf("guest '%s' is running\n", guest->get_name(guest));
227 }
228 else
229 {
230 printf("failed to start guest '%s'\n", guest->get_name(guest));
231 }
232 }
233 else if (streq(line, "stop"))
234 {
235 printf("stopping guest '%s'...\n", guest->get_name(guest));
236 guest->stop(guest);
237 printf("guest '%s' is down\n", guest->get_name(guest));
238 }
239 else if (streq(line, "addif"))
240 {
241 guest_addif_menu(guest);
242 }
243 else if (streq(line, "delif"))
244 {
245 guest_delif_menu(guest);
246 }
247 else if (streq(line, "console"))
248 {
249 guest_console(guest);
250 }
251 else
252 {
253 printf("back|start|stop|addif|delif|console\n");
254 }
255 free(line);
256 }
257 }
258
259 static void guest_create_menu()
260 {
261 char *name, *kernel, *master, *mem;
262 guest_t *guest;
263
264 name = get_line("guest name: ");
265 kernel = get_line("kernel image: ");
266 master = get_line("master filesystem: ");
267 mem = get_line("amount of memory in MB: ");
268
269 guest = dumm->create_guest(dumm, name, kernel, master, atoi(mem));
270 if (guest)
271 {
272 printf("guest '%s' created\n", guest->get_name(guest));
273 guest_menu(guest);
274 }
275 else
276 {
277 printf("failed to create guest '%s'\n", name);
278 }
279 free(name);
280 free(kernel);
281 free(master);
282 free(mem);
283 }
284
285 static void guest_list_menu()
286 {
287 while (TRUE)
288 {
289 iterator_t *iterator;
290 guest_t *guest;
291 char *line = get_line("guest# ");
292
293 if (streq(line, "back"))
294 {
295 free(line);
296 break;
297 }
298 else if (streq(line, "list"))
299 {
300 iterator = dumm->create_guest_iterator(dumm);
301 while (iterator->iterate(iterator, (void**)&guest))
302 {
303 printf("%s\n", guest->get_name(guest));
304 }
305 iterator->destroy(iterator);
306 }
307 else if (streq(line, "create"))
308 {
309 guest_create_menu();
310 }
311 else
312 {
313 guest = get_guest(line);
314 if (guest)
315 {
316 guest_menu(guest);
317 }
318 else
319 {
320 printf("back|list|create|<guest>\n");
321 }
322 }
323 free(line);
324 }
325 }
326
327 static void bridge_addif_menu(bridge_t *bridge)
328 {
329 char *name, *ifname;
330 iface_t *iface;
331
332 name = get_line("guest name: ");
333 ifname = get_line("interface name: ");
334
335 iface = get_iface(name, ifname);
336 if (!iface)
337 {
338 printf("guest '%s' has no interface named '%s'\n", name, ifname);
339 }
340 else if (!bridge->connect_iface(bridge, iface))
341 {
342 printf("failed to add interface '%s' to bridge '%s'\n", ifname,
343 bridge->get_name(bridge));
344 }
345 free(name);
346 free(ifname);
347 }
348
349 static void bridge_delif_menu(bridge_t *bridge)
350 {
351 char *name, *ifname;
352 iface_t *iface;
353
354 name = get_line("guest name: ");
355 ifname = get_line("interface name: ");
356
357 iface = get_iface(name, ifname);
358 if (!iface)
359 {
360 printf("guest '%s' has no interface named '%s'\n", name, ifname);
361 }
362 else if (!bridge->disconnect_iface(bridge, iface))
363 {
364 printf("failed to remove interface '%s' from bridge '%s'\n", ifname,
365 bridge->get_name(bridge));
366 }
367 free(name);
368 free(ifname);
369 }
370
371 static void bridge_menu(bridge_t *bridge)
372 {
373 while (TRUE)
374 {
375 char *line = get_line("bridge/%s# ", bridge->get_name(bridge));
376
377 if (streq(line, "back"))
378 {
379 free(line);
380 break;
381 }
382 else if (streq(line, "list"))
383 {
384 iterator_t *iterator;
385 iface_t *iface;
386
387 iterator = bridge->create_iface_iterator(bridge);
388 while (iterator->iterate(iterator, (void**)&iface))
389 {
390 printf("%s (%s)\n", iface->get_guestif(iface), iface->get_hostif(iface));
391 }
392 iterator->destroy(iterator);
393 }
394 else if (streq(line, "addif"))
395 {
396 bridge_addif_menu(bridge);
397 }
398 else if (streq(line, "delif"))
399 {
400 bridge_delif_menu(bridge);
401 }
402 else
403 {
404 printf("back|list|addif|delif\n");
405 }
406 free(line);
407 }
408 }
409
410 static void bridge_create_menu()
411 {
412 char *name;
413 bridge_t *bridge;
414
415 name = get_line("bridge name: ");
416
417 bridge = dumm->create_bridge(dumm, name);
418 if (bridge)
419 {
420 printf("bridge '%s' created\n", bridge->get_name(bridge));
421 bridge_menu(bridge);
422 }
423 else
424 {
425 printf("failed to create bridge '%s'\n", name);
426 }
427 free(name);
428 }
429
430 static void bridge_list_menu()
431 {
432 while (TRUE)
433 {
434 iterator_t *iterator;
435 bridge_t *bridge;
436 char *line = get_line("bridge# ");
437
438 if (streq(line, "back"))
439 {
440 free(line);
441 break;
442 }
443 else if (streq(line, "list"))
444 {
445 iterator = dumm->create_bridge_iterator(dumm);
446 while (iterator->iterate(iterator, (void**)&bridge))
447 {
448 printf("%s\n", bridge->get_name(bridge));
449 }
450 iterator->destroy(iterator);
451 }
452 else if (streq(line, "create"))
453 {
454 bridge_create_menu();
455 }
456 else
457 {
458 bridge = get_bridge(line);
459 if (bridge)
460 {
461 bridge_menu(bridge);
462 }
463 else
464 {
465 printf("back|list|create|<bridge>\n");
466 }
467 }
468 free(line);
469 }
470 }
471
472 static void scenario_menu()
473 {
474 char *name;
475
476 name = get_line("scenario name (or 'none'): ");
477
478 dumm->load_scenario(dumm, streq(name, "none") ? NULL : name);
479
480 free(name);
481 }
482
483 /**
484 * Signal handler
485 */
486 void signal_action(int sig, siginfo_t *info, void *ucontext)
487 {
488 dumm->destroy(dumm);
489 clear_history();
490 exit(0);
491 }
492
493 /**
494 * main routine, parses args and reads from console
495 */
496 int main(int argc, char *argv[])
497 {
498 struct sigaction action;
499 char *dir = ".";
500
501 while (TRUE)
502 {
503 struct option options[] = {
504 {"dir", 1, 0, 0},
505 {"help", 0, 0, 0},
506 {0, 0, 0, 0}
507 };
508
509 switch (getopt_long(argc, argv, "d:h", options, NULL))
510 {
511 case -1:
512 break;
513 case 'd':
514 dir = optarg;
515 continue;
516 case 'h':
517 usage();
518 return 0;
519 default:
520 usage();
521 return 1;
522 }
523 break;
524 }
525
526 memset(&action, 0, sizeof(action));
527 action.sa_sigaction = signal_action;
528 action.sa_flags = SA_SIGINFO;
529 if (sigaction(SIGINT, &action, NULL) != 0 ||
530 sigaction(SIGQUIT, &action, NULL) != 0 ||
531 sigaction(SIGTERM, &action, NULL) != 0)
532 {
533 printf("signal handler setup failed: %m.\n");
534 return 1;
535 }
536
537 dumm = dumm_create(dir);
538 while (TRUE)
539 {
540 char *line = get_line("# ");
541
542 if (streq(line, "quit"))
543 {
544 free(line);
545 break;
546 }
547 else if (streq(line, "guest"))
548 {
549 guest_list_menu();
550 }
551 else if (streq(line, "bridge"))
552 {
553 bridge_list_menu();
554 }
555 else if (streq(line, "scenario"))
556 {
557 scenario_menu();
558 }
559 else
560 {
561 printf("quit|guest|bridge|scenario\n");
562 }
563 free(line);
564 }
565 dumm->destroy(dumm);
566 clear_history();
567 return 0;
568 }
569