aca5967c26bc86be0b83f959ab469911c67a75eb
[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 * help for dumm root shell
44 */
45 static void help()
46 {
47 printf("create name=<name> start a guest named <name>\n");
48 printf(" [master=<dir>] read only master root filesystem\n");
49 printf(" [memory=<MB>] guest main memory in megabyte\n");
50 printf("list list running guests\n");
51 printf("guest <name> open guest menu for <name>\n");
52 printf("help show this help\n");
53 printf("quit kill quests and exit\n");
54 }
55
56 /**
57 * help for guest shell
58 */
59 static void help_guest()
60 {
61 printf("start [kernel=<uml-kernel>] start a stopped guest\n");
62 printf("stop stop a started guest\n");
63 printf("addif <name> add an interface to the guest\n");
64 printf("delif <name> remove the interface\n");
65 printf("listif list guests interfaces\n");
66 printf("help show this help\n");
67 printf("quit quit the guest menu\n");
68 }
69
70 /**
71 * add an iface to a guest
72 */
73 static void add_if(guest_t *guest, char *name)
74 {
75 iface_t *iface;
76
77 iface = guest->create_iface(guest, name);
78 if (iface)
79 {
80 printf("created guest interface '%s' connected to '%s'\n",
81 iface->get_guestif(iface), iface->get_hostif(iface));
82 }
83 else
84 {
85 printf("failed to create guest interface\n");
86 }
87 }
88
89 /**
90 * delete an iface from a guest
91 */
92 static void del_if(guest_t *guest, char *name)
93 {
94 iface_t *iface;
95 iterator_t *iterator;
96 bool found = FALSE;
97
98 iterator = guest->create_iface_iterator(guest);
99 while (iterator->iterate(iterator, (void**)&iface))
100 {
101 if (streq(name, iface->get_guestif(iface)))
102 {
103 iterator->remove(iterator);
104 printf("removing interface '%s' ('%s') from %s\n",
105 iface->get_guestif(iface), iface->get_hostif(iface),
106 guest->get_name(guest));
107 iface->destroy(iface);
108 found = TRUE;
109 break;
110 }
111 }
112 iterator->destroy(iterator);
113 if (!found)
114 {
115 printf("guest '%s' has no interface named '%s'\n",
116 guest->get_name(guest), name);
117 }
118 }
119
120 /**
121 * list interfaces on a guest
122 */
123 static void list_if(guest_t *guest)
124 {
125 iface_t *iface;
126 iterator_t *iterator;
127
128 iterator = guest->create_iface_iterator(guest);
129 while (iterator->iterate(iterator, (void**)&iface))
130 {
131 printf("'%s' => '%s'\n", iface->get_guestif(iface), iface->get_hostif(iface));
132
133 }
134 iterator->destroy(iterator);
135 }
136
137 /**
138 * start an UML guest
139 */
140 static void start_guest(guest_t *guest, char *line)
141 {
142 enum {
143 KERNEL = 0,
144 };
145 char *const opts[] = {
146 [KERNEL] = "kernel",
147 NULL
148 };
149 char *value;
150 char *kernel = NULL;
151
152 while (TRUE)
153 {
154 switch (getsubopt(&line, opts, &value))
155 {
156 case KERNEL:
157 kernel = value;
158 continue;
159 default:
160 break;
161 }
162 break;
163 }
164 if (kernel == NULL)
165 {
166 kernel = "./linux";
167 }
168
169 printf("starting guest '%s'... \n", guest->get_name(guest));
170 if (guest->start(guest, kernel))
171 {
172 printf("guest '%s' is up\n", guest->get_name(guest));
173 }
174 else
175 {
176 printf("failed to start guest '%s'!\n", guest->get_name(guest));
177 }
178 }
179
180 /**
181 * stop (kill) an UML guest
182 */
183 static void stop_guest(guest_t *guest, char *line)
184 {
185 printf("stopping guest '%s'...\n", guest->get_name(guest));
186 guest->stop(guest);
187 printf("guest '%s' is down\n", guest->get_name(guest));
188 }
189
190 /**
191 * subshell for guests
192 */
193 static void guest(char *name)
194 {
195 char *line = NULL;
196 char prompt[32];
197 int len;
198 iterator_t *iterator;
199 guest_t *guest;
200 bool found = FALSE;
201
202 iterator = dumm->create_guest_iterator(dumm);
203 while (iterator->iterate(iterator, (void**)&guest))
204 {
205 if (streq(name, guest->get_name(guest)))
206 {
207 found = TRUE;
208 break;
209 }
210 }
211 iterator->destroy(iterator);
212 if (!found)
213 {
214 printf("guest '%s' not found\n", name);
215 return;
216 }
217
218 len = snprintf(prompt, sizeof(prompt), "dumm@%s# ", name);
219 if (len < 0 || len >= sizeof(prompt))
220 {
221 return;
222 }
223
224 while (TRUE)
225 {
226 enum {
227 QUIT = 0,
228 HELP,
229 START,
230 STOP,
231 ADDIF,
232 DELIF,
233 LISTIF,
234 };
235 char *const opts[] = {
236 [QUIT] = "quit",
237 [HELP] = "help",
238 [START] = "start",
239 [STOP] = "stop",
240 [ADDIF] = "addif",
241 [DELIF] = "delif",
242 [LISTIF] = "listif",
243 NULL
244 };
245 char *pos, *value;
246
247 free(line);
248 line = readline(prompt);
249 if (line == NULL || *line == '\0')
250 {
251 continue;
252 }
253 add_history(line);
254 pos = line;
255 while (*pos != '\0')
256 {
257 if (*pos == ' ')
258 {
259 *pos = ',';
260 }
261 pos++;
262 }
263 pos = line;
264 switch (getsubopt(&pos, opts, &value))
265 {
266 case QUIT:
267 free(line);
268 break;
269 case HELP:
270 help_guest();
271 continue;
272 case START:
273 start_guest(guest, pos);
274 continue;
275 case STOP:
276 stop_guest(guest, pos);
277 continue;
278 case ADDIF:
279 add_if(guest, pos);
280 continue;
281 case DELIF:
282 del_if(guest, pos);
283 continue;
284 case LISTIF:
285 list_if(guest);
286 continue;
287 default:
288 printf("command unknown: '%s'\n", line);
289 continue;
290 }
291 break;
292 }
293 }
294
295
296 /**
297 * create an bridge
298 */
299 static void create_bridge(char *name)
300 {
301 dumm->create_bridge(dumm, name);
302
303 }
304
305 /**
306 * create an UML guest
307 */
308 static void create_guest(char *line)
309 {
310 enum {
311 NAME = 0,
312 KERNEL,
313 MASTER,
314 MEMORY,
315 };
316 char *const opts[] = {
317 [NAME] = "name",
318 [KERNEL] = "kernel",
319 [MASTER] = "master",
320 [MEMORY] = "memory",
321 NULL
322 };
323 char *value;
324 char *name = NULL;
325 char *master = NULL;
326 char *kernel = NULL;
327 int mem = 128;
328
329 while (TRUE)
330 {
331 switch (getsubopt(&line, opts, &value))
332 {
333 case NAME:
334 name = value;
335 continue;
336 case KERNEL:
337 kernel = value;
338 continue;
339 case MASTER:
340 master = value;
341 continue;
342 case MEMORY:
343 if (value)
344 {
345 mem = atoi(value);
346 }
347 continue;
348 default:
349 break;
350 }
351 break;
352 }
353 if (name == NULL || master == NULL || kernel == NULL)
354 {
355 printf("too few arguments!\n");
356 help();
357 return;
358 }
359 if (mem == 0)
360 {
361 mem = 128;
362 }
363 if (dumm->create_guest(dumm, name, kernel, master, mem))
364 {
365 printf("guest '%s' created\n", name);
366 guest(name);
367 }
368 else
369 {
370 printf("failed to create guest '%s'!\n", name);
371 }
372 }
373
374 /**
375 * list running UML guests
376 */
377 static void list()
378 {
379 iterator_t *guests, *ifaces;
380 guest_t *guest;
381 iface_t *iface;
382
383 guests = dumm->create_guest_iterator(dumm);
384 while (guests->iterate(guests, (void**)&guest))
385 {
386 printf("%s (%N)\n", guest->get_name(guest),
387 guest_state_names, guest->get_state(guest));
388 ifaces = guest->create_iface_iterator(guest);
389 while (ifaces->iterate(ifaces, (void**)&iface))
390 {
391 printf(" '%s' => '%s'\n",
392 iface->get_guestif(iface), iface->get_hostif(iface));
393 }
394 ifaces->destroy(ifaces);
395 }
396 guests->destroy(guests);
397 }
398
399 /**
400 * Signal handler
401 */
402 void signal_action(int sig, siginfo_t *info, void *ucontext)
403 {
404 printf("\nuse 'quit'\ndumm# ");
405 }
406
407 /**
408 * main routine, parses args and reads from console
409 */
410 int main(int argc, char *argv[])
411 {
412 char *line = NULL;
413 struct sigaction action;
414 char *dir = ".";
415
416 while (TRUE)
417 {
418 struct option options[] = {
419 {"dir", 1, 0, 0},
420 {"help", 0, 0, 0},
421 {0, 0, 0, 0}
422 };
423
424 switch (getopt_long(argc, argv, "d:h", options, NULL))
425 {
426 case -1:
427 break;
428 case 'd':
429 dir = optarg;
430 continue;
431 case 'h':
432 usage();
433 return 0;
434 default:
435 usage();
436 return 1;
437 }
438 break;
439 }
440
441 dumm = dumm_create(dir);
442
443 memset(&action, 0, sizeof(action));
444 action.sa_sigaction = signal_action;
445 action.sa_flags = SA_SIGINFO;
446 if (sigaction(SIGINT, &action, NULL) != 0 ||
447 sigaction(SIGQUIT, &action, NULL) != 0 ||
448 sigaction(SIGTERM, &action, NULL) != 0)
449 {
450 printf("signal handler setup failed: %m.\n");
451 return 1;
452 }
453
454 while (TRUE)
455 {
456 enum {
457 QUIT = 0,
458 HELP,
459 CREATE,
460 BRIDGE,
461 LIST,
462 GUEST,
463 };
464 char *const opts[] = {
465 [QUIT] = "quit",
466 [HELP] = "help",
467 [CREATE] = "create",
468 [BRIDGE] = "bridge",
469 [LIST] = "list",
470 [GUEST] = "guest",
471 NULL
472 };
473 char *pos, *value;
474
475 free(line);
476 line = readline("dumm# ");
477 if (line == NULL || *line == '\0')
478 {
479 continue;
480 }
481
482 add_history(line);
483 pos = line;
484 while (*pos != '\0')
485 {
486 if (*pos == ' ')
487 {
488 *pos = ',';
489 }
490 pos++;
491 }
492 pos = line;
493 switch (getsubopt(&pos, opts, &value))
494 {
495 case QUIT:
496 free(line);
497 break;
498 case HELP:
499 help();
500 continue;
501 case CREATE:
502 create_guest(pos);
503 continue;
504 case BRIDGE:
505 create_bridge(pos);
506 continue;
507 case LIST:
508 list();
509 continue;
510 case GUEST:
511 guest(pos);
512 continue;
513 default:
514 printf("command unknown: '%s'\n", line);
515 continue;
516 }
517 break;
518 }
519 dumm->destroy(dumm);
520 clear_history();
521 return 0;
522 }
523