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
| @@ -9,6 +9,7 @@ version 0.6.1: | @@ -9,6 +9,7 @@ version 0.6.1: | ||
| 9 | - VMware 3 and 4 read-only disk image support (untested) | 9 | - VMware 3 and 4 read-only disk image support (untested) |
| 10 | - Support for up to 4 serial ports | 10 | - Support for up to 4 serial ports |
| 11 | - TFTP server support (Magnus Damm) | 11 | - TFTP server support (Magnus Damm) |
| 12 | + - Port redirection support in user mode networking | ||
| 12 | 13 | ||
| 13 | version 0.6.0: | 14 | version 0.6.0: |
| 14 | 15 |
qemu-doc.texi
| @@ -228,6 +228,44 @@ example of its use. | @@ -228,6 +228,44 @@ example of its use. | ||
| 228 | Use the user mode network stack. This is the default if no tun/tap | 228 | Use the user mode network stack. This is the default if no tun/tap |
| 229 | network init script is found. | 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 | @item -dummy-net | 269 | @item -dummy-net |
| 232 | Use the dummy network stack: no packet will be received by the network | 270 | Use the dummy network stack: no packet will be received by the network |
| 233 | cards. | 271 | cards. |
| @@ -652,7 +690,12 @@ Note that @code{ping} is not supported reliably to the internet as it | @@ -652,7 +690,12 @@ Note that @code{ping} is not supported reliably to the internet as it | ||
| 652 | would require root priviledges. It means you can only ping the local | 690 | would require root priviledges. It means you can only ping the local |
| 653 | router (10.0.2.2). | 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 | @node direct_linux_boot | 700 | @node direct_linux_boot |
| 658 | @section Direct Linux Boot | 701 | @section Direct Linux Boot |
slirp/libslirp.h
| @@ -3,8 +3,10 @@ | @@ -3,8 +3,10 @@ | ||
| 3 | 3 | ||
| 4 | #ifdef _WIN32 | 4 | #ifdef _WIN32 |
| 5 | #include <winsock2.h> | 5 | #include <winsock2.h> |
| 6 | +int inet_aton(const char *cp, struct in_addr *ia); | ||
| 6 | #else | 7 | #else |
| 7 | #include <sys/select.h> | 8 | #include <sys/select.h> |
| 9 | +#include <arpa/inet.h> | ||
| 8 | #endif | 10 | #endif |
| 9 | 11 | ||
| 10 | void slirp_init(void); | 12 | void slirp_init(void); |
| @@ -20,4 +22,9 @@ void slirp_input(const uint8_t *pkt, int pkt_len); | @@ -20,4 +22,9 @@ void slirp_input(const uint8_t *pkt, int pkt_len); | ||
| 20 | int slirp_can_output(void); | 22 | int slirp_can_output(void); |
| 21 | void slirp_output(const uint8_t *pkt, int pkt_len); | 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 | #endif | 30 | #endif |
slirp/slirp.c
| @@ -617,3 +617,18 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) | @@ -617,3 +617,18 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) | ||
| 617 | memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); | 617 | memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); |
| 618 | slirp_output(buf, ip_data_len + ETH_HLEN); | 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
| @@ -36,7 +36,7 @@ struct tftp_session { | @@ -36,7 +36,7 @@ struct tftp_session { | ||
| 36 | 36 | ||
| 37 | struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; | 37 | struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; |
| 38 | 38 | ||
| 39 | -char *tftp_prefix; | 39 | +const char *tftp_prefix; |
| 40 | 40 | ||
| 41 | static void tftp_session_update(struct tftp_session *spt) | 41 | static void tftp_session_update(struct tftp_session *spt) |
| 42 | { | 42 | { |
slirp/tftp.h
vl.c
| @@ -1382,6 +1382,78 @@ static int net_slirp_init(NetDriverState *nd) | @@ -1382,6 +1382,78 @@ static int net_slirp_init(NetDriverState *nd) | ||
| 1382 | return 0; | 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 | #endif /* CONFIG_SLIRP */ | 1457 | #endif /* CONFIG_SLIRP */ |
| 1386 | 1458 | ||
| 1387 | #if !defined(_WIN32) | 1459 | #if !defined(_WIN32) |
| @@ -2334,7 +2406,9 @@ void help(void) | @@ -2334,7 +2406,9 @@ void help(void) | ||
| 2334 | "-tun-fd fd use this fd as already opened tap/tun interface\n" | 2406 | "-tun-fd fd use this fd as already opened tap/tun interface\n" |
| 2335 | #ifdef CONFIG_SLIRP | 2407 | #ifdef CONFIG_SLIRP |
| 2336 | "-user-net use user mode network stack [default if no tap/tun script]\n" | 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 | #endif | 2412 | #endif |
| 2339 | "-dummy-net use dummy network stack\n" | 2413 | "-dummy-net use dummy network stack\n" |
| 2340 | "\n" | 2414 | "\n" |
| @@ -2410,6 +2484,7 @@ enum { | @@ -2410,6 +2484,7 @@ enum { | ||
| 2410 | QEMU_OPTION_tun_fd, | 2484 | QEMU_OPTION_tun_fd, |
| 2411 | QEMU_OPTION_user_net, | 2485 | QEMU_OPTION_user_net, |
| 2412 | QEMU_OPTION_tftp, | 2486 | QEMU_OPTION_tftp, |
| 2487 | + QEMU_OPTION_redir, | ||
| 2413 | QEMU_OPTION_dummy_net, | 2488 | QEMU_OPTION_dummy_net, |
| 2414 | 2489 | ||
| 2415 | QEMU_OPTION_kernel, | 2490 | QEMU_OPTION_kernel, |
| @@ -2463,6 +2538,7 @@ const QEMUOption qemu_options[] = { | @@ -2463,6 +2538,7 @@ const QEMUOption qemu_options[] = { | ||
| 2463 | #ifdef CONFIG_SLIRP | 2538 | #ifdef CONFIG_SLIRP |
| 2464 | { "user-net", 0, QEMU_OPTION_user_net }, | 2539 | { "user-net", 0, QEMU_OPTION_user_net }, |
| 2465 | { "tftp", HAS_ARG, QEMU_OPTION_tftp }, | 2540 | { "tftp", HAS_ARG, QEMU_OPTION_tftp }, |
| 2541 | + { "redir", HAS_ARG, QEMU_OPTION_redir }, | ||
| 2466 | #endif | 2542 | #endif |
| 2467 | { "dummy-net", 0, QEMU_OPTION_dummy_net }, | 2543 | { "dummy-net", 0, QEMU_OPTION_dummy_net }, |
| 2468 | 2544 | ||
| @@ -2756,14 +2832,14 @@ int main(int argc, char **argv) | @@ -2756,14 +2832,14 @@ int main(int argc, char **argv) | ||
| 2756 | break; | 2832 | break; |
| 2757 | #ifdef CONFIG_SLIRP | 2833 | #ifdef CONFIG_SLIRP |
| 2758 | case QEMU_OPTION_tftp: | 2834 | case QEMU_OPTION_tftp: |
| 2759 | - { | ||
| 2760 | - extern const char *tftp_prefix; | ||
| 2761 | tftp_prefix = optarg; | 2835 | tftp_prefix = optarg; |
| 2762 | - } | ||
| 2763 | - break; | 2836 | + break; |
| 2764 | case QEMU_OPTION_user_net: | 2837 | case QEMU_OPTION_user_net: |
| 2765 | net_if_type = NET_IF_USER; | 2838 | net_if_type = NET_IF_USER; |
| 2766 | break; | 2839 | break; |
| 2840 | + case QEMU_OPTION_redir: | ||
| 2841 | + net_slirp_redir(optarg); | ||
| 2842 | + break; | ||
| 2767 | #endif | 2843 | #endif |
| 2768 | case QEMU_OPTION_dummy_net: | 2844 | case QEMU_OPTION_dummy_net: |
| 2769 | net_if_type = NET_IF_DUMMY; | 2845 | net_if_type = NET_IF_DUMMY; |