Commit 9bf05444b24f10616b9e9b9f296bcfdcba4ff0df

Authored by bellard
1 parent a3504c87

port redirection support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1054 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
... ... @@ -9,6 +9,7 @@ version 0.6.1:
9 9 - VMware 3 and 4 read-only disk image support (untested)
10 10 - Support for up to 4 serial ports
11 11 - TFTP server support (Magnus Damm)
  12 + - Port redirection support in user mode networking
12 13  
13 14 version 0.6.0:
14 15  
... ...
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
... ... @@ -36,7 +36,7 @@ struct tftp_session {
36 36  
37 37 struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
38 38  
39   -char *tftp_prefix;
  39 +const char *tftp_prefix;
40 40  
41 41 static void tftp_session_update(struct tftp_session *spt)
42 42 {
... ...
slirp/tftp.h
... ... @@ -29,6 +29,4 @@ struct tftp_t {
29 29 } x;
30 30 };
31 31  
32   -extern char *tftp_prefix;
33   -
34 32 void tftp_input(struct mbuf *m);
... ...
... ... @@ -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;
... ...