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; | ... | ... |