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