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