| Submitter | Alexander Graf |
|---|---|
| Date | June 3, 2012, 7:45 a.m. |
| Message ID | <1338709501-7740-1-git-send-email-agraf@suse.de> |
| Download | mbox | patch |
| Permalink | /patch/162794/ |
| State | New |
| Headers | show |
Comments
On 2012-06-03 09:45, Alexander Graf wrote: > When using guestfwd=, Qemu only connects the virtual server's TCP port > to a single chardev. This is useless in most cases, as we usually want > to have more than a single connection from the guest to the outside world. > > This patch adds a new cmd: target to guestfwd= that allows for execution > of a command on every TCP connection. This leverages the same code as > the -smb parameter, just that here the command is user defined. > > Reported-by: Sascha Wilde <wilde@intevation.de> > Signed-off-by: Alexander Graf <agraf@suse.de> > > --- > > v1 -> v2: > > - rebase to current master > - fix documentation > --- > net/slirp.c | 44 +++++++++++++++++++++++++++----------------- > qemu-options.hx | 22 +++++++++++++++++++++- > 2 files changed, 48 insertions(+), 18 deletions(-) > > diff --git a/net/slirp.c b/net/slirp.c > index 96f5032..41cd058 100644 > --- a/net/slirp.c > +++ b/net/slirp.c > @@ -616,25 +616,35 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, > > fwd = g_malloc(sizeof(struct GuestFwd)); > snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port); > - fwd->hd = qemu_chr_new(buf, p, NULL); > - if (!fwd->hd) { > - error_report("could not open guest forwarding device '%s'", buf); > - g_free(fwd); > - return -1; > - } > > - if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) { > - error_report("conflicting/invalid host:port in guest forwarding " > - "rule '%s'", config_str); > - g_free(fwd); > - return -1; > - } > - fwd->server = server; > - fwd->port = port; > - fwd->slirp = s->slirp; > + if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) { > + if (slirp_add_exec(s->slirp, 0, &p[4], &server, port) < 0) { > + error_report("conflicting/invalid host:port in guest forwarding " > + "rule '%s'", config_str); > + g_free(fwd); > + return -1; > + } > + } else { > + fwd->hd = qemu_chr_new(buf, p, NULL); > + if (!fwd->hd) { > + error_report("could not open guest forwarding device '%s'", buf); > + g_free(fwd); > + return -1; > + } > + > + if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) { > + error_report("conflicting/invalid host:port in guest forwarding " > + "rule '%s'", config_str); > + g_free(fwd); > + return -1; > + } > + fwd->server = server; > + fwd->port = port; > + fwd->slirp = s->slirp; > > - qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, > - NULL, fwd); > + qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, > + NULL, fwd); > + } > return 0; > > fail_syntax: > diff --git a/qemu-options.hx b/qemu-options.hx > index 8b66264..ecf7ca1 100644 > --- a/qemu-options.hx > +++ b/qemu-options.hx > @@ -1421,8 +1421,28 @@ Then when you use on the host @code{telnet localhost 5555}, you > connect to the guest telnet server. > > @item guestfwd=[tcp]:@var{server}:@var{port}-@var{dev} > +@item guestfwd=[tcp]:@var{server}:@var{port}-@var{cmd:command} > Forward guest TCP connections to the IP address @var{server} on port @var{port} > -to the character device @var{dev}. This option can be given multiple times. > +to the character device @var{dev} or to a program executed by @var{cmd:command} > +which gets spawned for each connection. This option can be given multiple times. > + > +You can either use a chardev directly and have that one used throughout Qemu's > +lifetime, like in the following example: > + > +@example > +# open 10.10.1.1:4321 on bootup, connect 10.0.2.100:1234 to it whenever > +# the guest accesses it > +qemu -net user,guestfwd=tcp:10.0.2.100:1234-tcp:10.10.1.1:4321 [...] > +@end example > + > +Or you can execute a command on every TCP connection established by the guest, > +so that Qemu behaves similar to an inetd process for that virtual server: > + > +@example > +# call "netcat 10.10.1.1 4321" on every TCP connection to 10.0.2.100:1234 > +# and connect the TCP stream to its stdin/stdout > +qemu -net 'user,guestfwd=tcp:10.0.2.100:1234-cmd:netcat 10.10.1.1 4321' > +@end example > > @end table > > Thanks, queued. Jan
Patch
diff --git a/net/slirp.c b/net/slirp.c index 96f5032..41cd058 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -616,25 +616,35 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, fwd = g_malloc(sizeof(struct GuestFwd)); snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port); - fwd->hd = qemu_chr_new(buf, p, NULL); - if (!fwd->hd) { - error_report("could not open guest forwarding device '%s'", buf); - g_free(fwd); - return -1; - } - if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) { - error_report("conflicting/invalid host:port in guest forwarding " - "rule '%s'", config_str); - g_free(fwd); - return -1; - } - fwd->server = server; - fwd->port = port; - fwd->slirp = s->slirp; + if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) { + if (slirp_add_exec(s->slirp, 0, &p[4], &server, port) < 0) { + error_report("conflicting/invalid host:port in guest forwarding " + "rule '%s'", config_str); + g_free(fwd); + return -1; + } + } else { + fwd->hd = qemu_chr_new(buf, p, NULL); + if (!fwd->hd) { + error_report("could not open guest forwarding device '%s'", buf); + g_free(fwd); + return -1; + } + + if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) { + error_report("conflicting/invalid host:port in guest forwarding " + "rule '%s'", config_str); + g_free(fwd); + return -1; + } + fwd->server = server; + fwd->port = port; + fwd->slirp = s->slirp; - qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, - NULL, fwd); + qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, + NULL, fwd); + } return 0; fail_syntax: diff --git a/qemu-options.hx b/qemu-options.hx index 8b66264..ecf7ca1 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1421,8 +1421,28 @@ Then when you use on the host @code{telnet localhost 5555}, you connect to the guest telnet server. @item guestfwd=[tcp]:@var{server}:@var{port}-@var{dev} +@item guestfwd=[tcp]:@var{server}:@var{port}-@var{cmd:command} Forward guest TCP connections to the IP address @var{server} on port @var{port} -to the character device @var{dev}. This option can be given multiple times. +to the character device @var{dev} or to a program executed by @var{cmd:command} +which gets spawned for each connection. This option can be given multiple times. + +You can either use a chardev directly and have that one used throughout Qemu's +lifetime, like in the following example: + +@example +# open 10.10.1.1:4321 on bootup, connect 10.0.2.100:1234 to it whenever +# the guest accesses it +qemu -net user,guestfwd=tcp:10.0.2.100:1234-tcp:10.10.1.1:4321 [...] +@end example + +Or you can execute a command on every TCP connection established by the guest, +so that Qemu behaves similar to an inetd process for that virtual server: + +@example +# call "netcat 10.10.1.1 4321" on every TCP connection to 10.0.2.100:1234 +# and connect the TCP stream to its stdin/stdout +qemu -net 'user,guestfwd=tcp:10.0.2.100:1234-cmd:netcat 10.10.1.1 4321' +@end example @end table
When using guestfwd=, Qemu only connects the virtual server's TCP port to a single chardev. This is useless in most cases, as we usually want to have more than a single connection from the guest to the outside world. This patch adds a new cmd: target to guestfwd= that allows for execution of a command on every TCP connection. This leverages the same code as the -smb parameter, just that here the command is user defined. Reported-by: Sascha Wilde <wilde@intevation.de> Signed-off-by: Alexander Graf <agraf@suse.de> --- v1 -> v2: - rebase to current master - fix documentation --- net/slirp.c | 44 +++++++++++++++++++++++++++----------------- qemu-options.hx | 22 +++++++++++++++++++++- 2 files changed, 48 insertions(+), 18 deletions(-)