437e4ed0eda8eb2600752dc6d0e92b743f5c4964
[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_guestif(iface), iface->get_hostif(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_guestif(iface)))
175 {
176 iterator->remove(iterator);
177 printf("removing interface '%s' ('%s') from %s\n",
178 iface->get_guestif(iface), iface->get_hostif(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_guestif(iface), iface->get_hostif(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 break;
229 }
230 }
231 iterator->destroy(iterator);
232 if (!found)
233 {
234 printf("guest '%s' not found\n", name);
235 return;
236 }
237
238 len = snprintf(prompt, sizeof(prompt), "dumm@%s# ", name);
239 if (len < 0 || len >= sizeof(prompt))
240 {
241 return;
242 }
243
244 while (TRUE)
245 {
246 enum {
247 QUIT = 0,
248 HELP,
249 ADDIF,
250 DELIF,
251 LISTIF,
252 };
253 char *const opts[] = {
254 [QUIT] = "quit",
255 [HELP] = "help",
256 [ADDIF] = "addif",
257 [DELIF] = "delif",
258 [LISTIF] = "listif",
259 NULL
260 };
261 char *pos, *value;
262
263 free(line);
264 line = readline(prompt);
265 if (line == NULL || *line == '\0')
266 {
267 continue;
268 }
269 add_history(line);
270 pos = line;
271 while (*pos != '\0')
272 {
273 if (*pos == ' ')
274 {
275 *pos = ',';
276 }
277 pos++;
278 }
279 pos = line;
280 switch (getsubopt(&pos, opts, &value))
281 {
282 case QUIT:
283 free(line);
284 break;
285 case HELP:
286 help_guest();
287 continue;
288 case ADDIF:
289 add_if(guest, pos);
290 continue;
291 case DELIF:
292 del_if(guest, pos);
293 continue;
294 case LISTIF:
295 list_if(guest);
296 continue;
297 default:
298 printf("command unknown: '%s'\n", line);
299 continue;
300 }
301 break;
302 }
303 }
304
305 /**
306 * list running UML guests
307 */
308 static void list(dumm_t *dumm)
309 {
310 iterator_t *guests, *ifaces;
311 guest_t *guest;
312 iface_t *iface;
313
314 guests = dumm->create_guest_iterator(dumm);
315 while (guests->iterate(guests, (void**)&guest))
316 {
317 printf("%s\n", guest->get_name(guest));
318 ifaces = guest->create_iface_iterator(guest);
319 while (ifaces->iterate(ifaces, (void**)&iface))
320 {
321 printf(" '%s' => '%s'\n",
322 iface->get_guestif(iface), iface->get_hostif(iface));
323 }
324 ifaces->destroy(ifaces);
325 }
326 guests->destroy(guests);
327 }
328
329 /**
330 * main routine, parses args and reads from console
331 */
332 int main(int argc, char *argv[])
333 {
334 dumm_t *dumm;
335 char *line = NULL;
336
337 while (TRUE)
338 {
339 struct option options[] = {
340 {"dir", 1, 0, 0},
341 {"help", 0, 0, 0},
342 {0, 0, 0, 0}
343 };
344
345 switch (getopt_long(argc, argv, "d:h", options, NULL))
346 {
347 case -1:
348 break;
349 case 'd':
350 if (chdir(optarg))
351 {
352 printf("changing to directory '%s' failed.\n", optarg);
353 return 1;
354 }
355 continue;
356 case 'h':
357 usage();
358 return 0;
359 default:
360 usage();
361 return 1;
362 }
363 break;
364 }
365
366 dumm = dumm_create();
367
368 while (TRUE)
369 {
370 enum {
371 QUIT = 0,
372 HELP,
373 START,
374 LIST,
375 GUEST,
376 };
377 char *const opts[] = {
378 [QUIT] = "quit",
379 [HELP] = "help",
380 [START] = "start",
381 [LIST] = "list",
382 [GUEST] = "guest",
383 NULL
384 };
385 char *pos, *value;
386
387 free(line);
388 line = readline("dumm# ");
389 if (line == NULL || *line == '\0')
390 {
391 continue;
392 }
393
394 add_history(line);
395 pos = line;
396 while (*pos != '\0')
397 {
398 if (*pos == ' ')
399 {
400 *pos = ',';
401 }
402 pos++;
403 }
404 pos = line;
405 switch (getsubopt(&pos, opts, &value))
406 {
407 case QUIT:
408 free(line);
409 break;
410 case HELP:
411 help();
412 continue;
413 case START:
414 start(dumm, pos);
415 continue;
416 case LIST:
417 list(dumm);
418 continue;
419 case GUEST:
420 guest(dumm, pos);
421 continue;
422 default:
423 printf("command unknown: '%s'\n", line);
424 continue;
425 }
426 break;
427 }
428 dumm->destroy(dumm);
429 clear_history();
430 return 0;
431 }
432