Commit 9bf05444b24f10616b9e9b9f296bcfdcba4ff0df
1 parent
a3504c87
port redirection support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1054 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
149 additions
and
9 deletions
Changelog
qemu-doc.texi
... | ... | @@ -228,6 +228,44 @@ example of its use. |
228 | 228 | Use the user mode network stack. This is the default if no tun/tap |
229 | 229 | network init script is found. |
230 | 230 | |
231 | +@item -tftp prefix | |
232 | +When using the user mode network stack, activate a built-in TFTP | |
233 | +server. All filenames beginning with @var{prefix} can be downloaded | |
234 | +from the host to the guest using a TFTP client. The TFTP client on the | |
235 | +guest must be configured in binary mode (use the command @code{bin} of | |
236 | +the Unix TFTP client). The host IP address on the guest is as usual | |
237 | +10.0.2.2. | |
238 | + | |
239 | +@item -redir [tcp|udp]:host-port:[guest-host]:guest-port | |
240 | + | |
241 | +When using the user mode network stack, redirect incoming TCP or UDP | |
242 | +connections to the host port @var{host-port} to the guest | |
243 | +@var{guest-host} on guest port @var{guest-port}. If @var{guest-host} | |
244 | +is not specified, its value is 10.0.2.15 (default address given by the | |
245 | +built-in DHCP server). | |
246 | + | |
247 | +For example, to redirect host X11 connection from screen 1 to guest | |
248 | +screen 0, use the following: | |
249 | + | |
250 | +@example | |
251 | +# on the host | |
252 | +qemu -redir tcp:6001::6000 [...] | |
253 | +# this host xterm should open in the guest X11 server | |
254 | +xterm -display :1 | |
255 | +@end example | |
256 | + | |
257 | +To redirect telnet connections from host port 5555 to telnet port on | |
258 | +the guest, use the following: | |
259 | + | |
260 | +@example | |
261 | +# on the host | |
262 | +qemu -redir tcp:5555::23 [...] | |
263 | +telnet localhost 5555 | |
264 | +@end example | |
265 | + | |
266 | +Then when you use on the host @code{telnet localhost 5555}, you | |
267 | +connect to the guest telnet server. | |
268 | + | |
231 | 269 | @item -dummy-net |
232 | 270 | Use the dummy network stack: no packet will be received by the network |
233 | 271 | cards. |
... | ... | @@ -652,7 +690,12 @@ Note that @code{ping} is not supported reliably to the internet as it |
652 | 690 | would require root priviledges. It means you can only ping the local |
653 | 691 | router (10.0.2.2). |
654 | 692 | |
655 | -The user mode network is currently only supported on a Unix host. | |
693 | +When using the built-in TFTP server, the router is also the TFTP | |
694 | +server. | |
695 | + | |
696 | +When using the @option{-redir} option, TCP or UDP connections can be | |
697 | +redirected from the host to the guest. It allows for example to | |
698 | +redirect X11, telnet or SSH connections. | |
656 | 699 | |
657 | 700 | @node direct_linux_boot |
658 | 701 | @section Direct Linux Boot | ... | ... |
slirp/libslirp.h
... | ... | @@ -3,8 +3,10 @@ |
3 | 3 | |
4 | 4 | #ifdef _WIN32 |
5 | 5 | #include <winsock2.h> |
6 | +int inet_aton(const char *cp, struct in_addr *ia); | |
6 | 7 | #else |
7 | 8 | #include <sys/select.h> |
9 | +#include <arpa/inet.h> | |
8 | 10 | #endif |
9 | 11 | |
10 | 12 | void slirp_init(void); |
... | ... | @@ -20,4 +22,9 @@ void slirp_input(const uint8_t *pkt, int pkt_len); |
20 | 22 | int slirp_can_output(void); |
21 | 23 | void slirp_output(const uint8_t *pkt, int pkt_len); |
22 | 24 | |
25 | +int slirp_redir(int is_udp, int host_port, | |
26 | + struct in_addr guest_addr, int guest_port); | |
27 | + | |
28 | +extern const char *tftp_prefix; | |
29 | + | |
23 | 30 | #endif | ... | ... |
slirp/slirp.c
... | ... | @@ -617,3 +617,18 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) |
617 | 617 | memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); |
618 | 618 | slirp_output(buf, ip_data_len + ETH_HLEN); |
619 | 619 | } |
620 | + | |
621 | +int slirp_redir(int is_udp, int host_port, | |
622 | + struct in_addr guest_addr, int guest_port) | |
623 | +{ | |
624 | + if (is_udp) { | |
625 | + if (!udp_listen(htons(host_port), guest_addr.s_addr, | |
626 | + htons(guest_port), 0)) | |
627 | + return -1; | |
628 | + } else { | |
629 | + if (!solisten(htons(host_port), guest_addr.s_addr, | |
630 | + htons(guest_port), 0)) | |
631 | + return -1; | |
632 | + } | |
633 | + return 0; | |
634 | +} | ... | ... |
slirp/tftp.c
slirp/tftp.h
vl.c
... | ... | @@ -1382,6 +1382,78 @@ static int net_slirp_init(NetDriverState *nd) |
1382 | 1382 | return 0; |
1383 | 1383 | } |
1384 | 1384 | |
1385 | +static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) | |
1386 | +{ | |
1387 | + const char *p, *p1; | |
1388 | + int len; | |
1389 | + p = *pp; | |
1390 | + p1 = strchr(p, sep); | |
1391 | + if (!p1) | |
1392 | + return -1; | |
1393 | + len = p1 - p; | |
1394 | + p1++; | |
1395 | + if (buf_size > 0) { | |
1396 | + if (len > buf_size - 1) | |
1397 | + len = buf_size - 1; | |
1398 | + memcpy(buf, p, len); | |
1399 | + buf[len] = '\0'; | |
1400 | + } | |
1401 | + *pp = p1; | |
1402 | + return 0; | |
1403 | +} | |
1404 | + | |
1405 | +static void net_slirp_redir(const char *redir_str) | |
1406 | +{ | |
1407 | + int is_udp; | |
1408 | + char buf[256], *r; | |
1409 | + const char *p; | |
1410 | + struct in_addr guest_addr; | |
1411 | + int host_port, guest_port; | |
1412 | + | |
1413 | + if (!slirp_inited) { | |
1414 | + slirp_inited = 1; | |
1415 | + slirp_init(); | |
1416 | + } | |
1417 | + | |
1418 | + p = redir_str; | |
1419 | + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) | |
1420 | + goto fail; | |
1421 | + if (!strcmp(buf, "tcp")) { | |
1422 | + is_udp = 0; | |
1423 | + } else if (!strcmp(buf, "udp")) { | |
1424 | + is_udp = 1; | |
1425 | + } else { | |
1426 | + goto fail; | |
1427 | + } | |
1428 | + | |
1429 | + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) | |
1430 | + goto fail; | |
1431 | + host_port = strtol(buf, &r, 0); | |
1432 | + if (r == buf) | |
1433 | + goto fail; | |
1434 | + | |
1435 | + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) | |
1436 | + goto fail; | |
1437 | + if (buf[0] == '\0') { | |
1438 | + pstrcpy(buf, sizeof(buf), "10.0.2.15"); | |
1439 | + } | |
1440 | + if (!inet_aton(buf, &guest_addr)) | |
1441 | + goto fail; | |
1442 | + | |
1443 | + guest_port = strtol(p, &r, 0); | |
1444 | + if (r == p) | |
1445 | + goto fail; | |
1446 | + | |
1447 | + if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) { | |
1448 | + fprintf(stderr, "qemu: could not set up redirection\n"); | |
1449 | + exit(1); | |
1450 | + } | |
1451 | + return; | |
1452 | + fail: | |
1453 | + fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n"); | |
1454 | + exit(1); | |
1455 | +} | |
1456 | + | |
1385 | 1457 | #endif /* CONFIG_SLIRP */ |
1386 | 1458 | |
1387 | 1459 | #if !defined(_WIN32) |
... | ... | @@ -2334,7 +2406,9 @@ void help(void) |
2334 | 2406 | "-tun-fd fd use this fd as already opened tap/tun interface\n" |
2335 | 2407 | #ifdef CONFIG_SLIRP |
2336 | 2408 | "-user-net use user mode network stack [default if no tap/tun script]\n" |
2337 | - "-tftp prefix allow tftp access to files starting with prefix [only with -user-net enabled]\n" | |
2409 | + "-tftp prefix allow tftp access to files starting with prefix [-user-net]\n" | |
2410 | + "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" | |
2411 | + " redirect TCP or UDP connections from host to guest [-user-net]\n" | |
2338 | 2412 | #endif |
2339 | 2413 | "-dummy-net use dummy network stack\n" |
2340 | 2414 | "\n" |
... | ... | @@ -2410,6 +2484,7 @@ enum { |
2410 | 2484 | QEMU_OPTION_tun_fd, |
2411 | 2485 | QEMU_OPTION_user_net, |
2412 | 2486 | QEMU_OPTION_tftp, |
2487 | + QEMU_OPTION_redir, | |
2413 | 2488 | QEMU_OPTION_dummy_net, |
2414 | 2489 | |
2415 | 2490 | QEMU_OPTION_kernel, |
... | ... | @@ -2463,6 +2538,7 @@ const QEMUOption qemu_options[] = { |
2463 | 2538 | #ifdef CONFIG_SLIRP |
2464 | 2539 | { "user-net", 0, QEMU_OPTION_user_net }, |
2465 | 2540 | { "tftp", HAS_ARG, QEMU_OPTION_tftp }, |
2541 | + { "redir", HAS_ARG, QEMU_OPTION_redir }, | |
2466 | 2542 | #endif |
2467 | 2543 | { "dummy-net", 0, QEMU_OPTION_dummy_net }, |
2468 | 2544 | |
... | ... | @@ -2756,14 +2832,14 @@ int main(int argc, char **argv) |
2756 | 2832 | break; |
2757 | 2833 | #ifdef CONFIG_SLIRP |
2758 | 2834 | case QEMU_OPTION_tftp: |
2759 | - { | |
2760 | - extern const char *tftp_prefix; | |
2761 | 2835 | tftp_prefix = optarg; |
2762 | - } | |
2763 | - break; | |
2836 | + break; | |
2764 | 2837 | case QEMU_OPTION_user_net: |
2765 | 2838 | net_if_type = NET_IF_USER; |
2766 | 2839 | break; |
2840 | + case QEMU_OPTION_redir: | |
2841 | + net_slirp_redir(optarg); | |
2842 | + break; | |
2767 | 2843 | #endif |
2768 | 2844 | case QEMU_OPTION_dummy_net: |
2769 | 2845 | net_if_type = NET_IF_DUMMY; | ... | ... |